mirror of
https://github.com/magnus919/agent-skills.git
synced 2026-09-12 12:06:29 +03:00
393 lines
21 KiB
Python
Executable File
393 lines
21 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""lidarr-cli — Lidarr music management from the terminal."""
|
|
|
|
import argparse, json, os, sys, warnings
|
|
from typing import Any, Dict, List, Optional, Tuple
|
|
warnings.simplefilter("ignore")
|
|
import requests
|
|
|
|
ENV_SERVER = os.getenv("ARR_SERVER_LIDARR", "http://localhost:8686")
|
|
ENV_KEY = os.getenv("ARR_KEY_LIDARR", "")
|
|
|
|
QUIET = False
|
|
GLOBAL_FLAGS: Dict[str, Any] = {"json": False, "dry_run": False, "quiet": False, "verbose": False}
|
|
def log(m): global QUIET; G = GLOBAL_FLAGS; (not QUIET and not G.get("json")) and print(m)
|
|
def warn(m): print(f"Warning: {m}", file=sys.stderr)
|
|
def die(m, c=1): print(f"Error: {m}", file=sys.stderr); sys.exit(c)
|
|
def emit(h, d):
|
|
if GLOBAL_FLAGS.get("json"): print(json.dumps(d, default=str))
|
|
else: print(h)
|
|
|
|
def _preparse(argv):
|
|
BOOLS = {"--json","--dry-run","--force","--quiet","--verbose"}
|
|
f, fl = {}, [argv[0]]
|
|
i = 1
|
|
while i < len(argv):
|
|
a = argv[i]
|
|
if a in BOOLS: f[a.lstrip("-").replace("-","_")] = True; i += 1
|
|
elif a in ("--help","-h"): return f, argv
|
|
elif a == "--": fl.extend(argv[i:]); break
|
|
else: fl.append(a); i += 1
|
|
return f, fl
|
|
|
|
class LidarrClient:
|
|
def __init__(self, server="", key="", dry_run=False):
|
|
self.server = (server or ENV_SERVER).rstrip("/"); self.key = key or ENV_KEY; self.dry_run = dry_run
|
|
def _get(self, path, params=None):
|
|
url = f"{self.server}/api/v1{path}"
|
|
if self.dry_run: return {"dry_run":True, "url":url, "params":params}
|
|
if not self.key: die("ARR_KEY_LIDARR not set. Get one from Lidarr → Settings → General → API Key.")
|
|
try:
|
|
r = requests.get(url, params=params, headers={"X-Api-Key": self.key, "Accept":"application/json"}, timeout=30)
|
|
except ConnectionError as e: die(f"Cannot connect: {e}")
|
|
if r.status_code == 401: die("Auth failed (401). Check ARR_KEY_LIDARR.")
|
|
if r.status_code >= 400:
|
|
try: d = r.json()
|
|
except: d = r.text[:200]
|
|
die(f"API error ({r.status_code}): {d}")
|
|
return r.json()
|
|
def _post(self, path, data):
|
|
url = f"{self.server}/api/v1{path}"
|
|
if self.dry_run: return {"dry_run":True, "url":url, "json":data}
|
|
if not self.key: die("ARR_KEY_LIDARR not set.")
|
|
try:
|
|
r = requests.post(url, json=data, headers={"X-Api-Key":self.key,"Content-Type":"application/json"}, timeout=30)
|
|
except ConnectionError as e: die(f"Cannot connect: {e}")
|
|
if r.status_code >= 400:
|
|
try: d = r.json()
|
|
except: d = r.text[:200]
|
|
die(f"API error ({r.status_code}): {d}")
|
|
return r.json()
|
|
def status(self): return self._get("/system/status")
|
|
def artists(self): return self._get("/artist")
|
|
def artist(self, aid): return self._get(f"/artist/{aid}")
|
|
def lookup_artist(self, term): return self._get("/artist/lookup", {"term": term})
|
|
def lookup_album(self, term): return self._get("/album/lookup", {"term": term})
|
|
def albums(self, artist_id): return self._get("/album", {"artistId": artist_id})
|
|
def album(self, alb_id): return self._get(f"/album/{alb_id}")
|
|
def tracks(self, album_id): return self._get("/track", {"albumId": album_id})
|
|
def track_files(self, album_id): return self._get("/trackfile", {"albumId": album_id})
|
|
def quality_profiles(self): return self._get("/qualityprofile")
|
|
def quality_profile(self, pid): return self._get(f"/qualityprofile/{pid}")
|
|
def metadata_profiles(self): return self._get("/metadataprofile")
|
|
def root_folders(self): return self._get("/rootfolder")
|
|
def calendar(self, start="", end=""):
|
|
p = {}
|
|
if start: p["start"] = start
|
|
if end: p["end"] = end
|
|
return self._get("/calendar", p)
|
|
def queue(self, page=1, limit=20): return self._get("/queue", {"page":page, "pageSize":limit})
|
|
def history(self, page=1, limit=20): return self._get("/history", {"page":page, "pageSize":limit})
|
|
def wanted_missing(self, page=1, limit=20): return self._get("/wanted/missing", {"page":page, "pageSize":limit})
|
|
def disk_space(self): return self._get("/diskSpace")
|
|
def health(self): return self._get("/health")
|
|
def add_artist(self, mb_id, quality_profile=4, metadata_profile=1, root_folder_path="",
|
|
monitored=True, search=True):
|
|
return self._post("/artist", {"foreignArtistId":mb_id, "qualityProfileId":quality_profile,
|
|
"metadataProfileId":metadata_profile,
|
|
"rootFolderPath":root_folder_path, "monitored":monitored,
|
|
"addOptions":{"searchForNewAlbum":search}})
|
|
def command(self, name, **kwargs):
|
|
return self._post("/command", {"name":name, **kwargs})
|
|
|
|
def cmd_status(client, args):
|
|
if client.dry_run: return emit("[dry-run] Get system status", {"dry_run":True})
|
|
d = client.status() or {}
|
|
emit(f"🎵 Lidarr v{d.get('version','?')} OS: {d.get('osName','?')} DB: {d.get('databaseVersion','?')}",
|
|
{"version":d.get("version"),"osName":d.get("osName")})
|
|
|
|
def cmd_artists(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli artists")
|
|
p.add_argument("--limit", type=int, default=50)
|
|
p.add_argument("--status", help="Filter by status (continue, ended, etc.)")
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit("[dry-run] List artists", {"dry_run":True})
|
|
data = client.artists() or []
|
|
if parsed.status: data = [a for a in data if a.get("status") == parsed.status]
|
|
data = data[:parsed.limit]
|
|
if not data: return emit("No artists found.", {"artists":[]})
|
|
lines, out = [], []
|
|
for a in data:
|
|
title = a.get("artistName","?"); mon = a.get("monitored",False)
|
|
alb_count = a.get("statistics",{}).get("albumCount",0)
|
|
icon = "✅" if alb_count > 0 else ("👁️" if mon else "🚫")
|
|
lines.append(f" {icon} {title:45} {alb_count} albums")
|
|
out.append({"artistName":title,"monitored":mon,"albumCount":alb_count,"id":a.get("id"),"foreignArtistId":a.get("foreignArtistId")})
|
|
emit(f"{len(data)} artist(s):\n"+"\n".join(lines), {"artists":out})
|
|
|
|
def cmd_lookup(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli lookup")
|
|
p.add_argument("--term", "-t", required=True)
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit(f"[dry-run] Lookup: {parsed.term}", {"dry_run":True})
|
|
data = client.lookup_artist(parsed.term) or []
|
|
if not data: return emit("No results.", {"results":[]})
|
|
lines, out = [], []
|
|
for a in data[:20]:
|
|
name = a.get("artistName","?"); mbid = a.get("foreignArtistId","?")
|
|
lines.append(f" {name:45} mb={mbid}")
|
|
out.append({"artistName":name,"foreignArtistId":mbid,"overview":(a.get("overview") or "")[:120]})
|
|
emit(f"{len(data)} result(s):\n"+"\n".join(lines), {"results":out})
|
|
|
|
def cmd_lookup_album(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli lookup-album")
|
|
p.add_argument("--term", "-t", required=True)
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit(f"[dry-run] Lookup album: {parsed.term}", {"dry_run":True})
|
|
data = client.lookup_album(parsed.term) or []
|
|
if not data: return emit("No results.", {"results":[]})
|
|
lines, out = [], []
|
|
for alb in data[:20]:
|
|
title = alb.get("title","?"); artist = alb.get("artist",{}).get("artistName","?")
|
|
date = (alb.get("releaseDate") or "")[:10]
|
|
lines.append(f" {title:45} {artist:25} {date}")
|
|
out.append({"title":title,"artist":artist,"releaseDate":date,"id":alb.get("id")})
|
|
emit(f"{len(data)} result(s):\n"+"\n".join(lines), {"results":out})
|
|
|
|
def cmd_add(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli add")
|
|
p.add_argument("--mb-id", required=True, help="MusicBrainz ID (UUID)")
|
|
p.add_argument("--root", required=True, help="Root folder path (e.g. /music)")
|
|
p.add_argument("--quality-profile", type=int, default=4, help="Quality profile ID (default: 4)")
|
|
p.add_argument("--metadata-profile", type=int, default=1, help="Metadata profile ID (default: 1)")
|
|
p.add_argument("--unmonitored", action="store_true", help="Add unmonitored")
|
|
p.add_argument("--search", action="store_true", help="Search for albums after adding")
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run:
|
|
return emit(f"[dry-run] Add artist mb={parsed.mb_id} profile={parsed.quality_profile}",
|
|
{"dry_run":True, "foreignArtistId":parsed.mb_id, "qualityProfileId":parsed.quality_profile,
|
|
"metadataProfileId":parsed.metadata_profile, "rootFolderPath":parsed.root,
|
|
"monitored":not parsed.unmonitored})
|
|
data = client.add_artist(parsed.mb_id, quality_profile=parsed.quality_profile,
|
|
metadata_profile=parsed.metadata_profile, root_folder_path=parsed.root,
|
|
monitored=not parsed.unmonitored, search=parsed.search)
|
|
emit(f"Added: #{data.get('id')} {data.get('artistName')}",
|
|
{"id":data.get("id"), "artistName":data.get("artistName")})
|
|
|
|
def cmd_albums(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli albums")
|
|
p.add_argument("--artist-id", type=int, required=True)
|
|
p.add_argument("--limit", type=int, default=50)
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit(f"[dry-run] List albums for artist {parsed.artist_id}", {"dry_run":True})
|
|
data = client.albums(parsed.artist_id) or []
|
|
data = data[:parsed.limit]
|
|
if not data: return emit("No albums found.", {"albums":[]})
|
|
lines, out = [], []
|
|
for alb in data:
|
|
title = alb.get("title","?"); date = (alb.get("releaseDate") or "")[:10]
|
|
mon = alb.get("monitored",False); tracks = alb.get("statistics",{}).get("trackCount",0)
|
|
icon = "✅" if alb.get("statistics",{}).get("trackFileCount",0) > 0 else ("👁️" if mon else "🚫")
|
|
lines.append(f" {icon} {title:45} {date} {tracks} tracks")
|
|
out.append({"title":title,"releaseDate":date,"monitored":mon,"trackCount":tracks,"id":alb.get("id")})
|
|
emit(f"{len(data)} album(s):\n"+"\n".join(lines), {"albums":out})
|
|
|
|
def cmd_tracks(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli tracks")
|
|
p.add_argument("--album-id", type=int, required=True)
|
|
p.add_argument("--limit", type=int, default=50)
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit(f"[dry-run] List tracks for album {parsed.album_id}", {"dry_run":True})
|
|
data = client.tracks(parsed.album_id) or []
|
|
data = data[:parsed.limit]
|
|
if not data: return emit("No tracks found.", {"tracks":[]})
|
|
lines, out = [], []
|
|
for t in data:
|
|
tn = t.get("trackNumber"); title = t.get("title","?")
|
|
had = t.get("hasFile",False); mon = t.get("monitored",False)
|
|
dur = t.get("duration",0)//1000
|
|
tn_str = f"{tn:3d}" if isinstance(tn, int) else " ?"
|
|
mins = f"{dur//60}:{dur%60:02d}" if dur else "?"
|
|
icon = "✅" if had else ("👁️" if mon else "🚫")
|
|
lines.append(f" {icon} {tn_str} {title:45} {mins}")
|
|
out.append({"trackNumber":tn,"title":title,"hasFile":had,"monitored":mon,"duration":dur})
|
|
emit(f"{len(data)} track(s):\n"+"\n".join(lines), {"tracks":out})
|
|
|
|
def cmd_track_files(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli track-files")
|
|
p.add_argument("--album-id", type=int, required=True)
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit(f"[dry-run] List track files for album {parsed.album_id}", {"dry_run":True})
|
|
data = client.track_files(parsed.album_id) or []
|
|
if not data: return emit("No track files found.", {"trackFiles":[]})
|
|
lines, out = [], []
|
|
for f in data:
|
|
qual = f.get("quality",{}).get("quality",{}).get("name","?")
|
|
size = (f.get("size") or 0)//1048576
|
|
lines.append(f" {qual:25} {size}MB")
|
|
out.append({"quality":qual,"size":size,"id":f.get("id")})
|
|
emit(f"{len(data)} track file(s):\n"+"\n".join(lines), {"trackFiles":out})
|
|
|
|
def cmd_quality_profile(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli quality-profile")
|
|
p.add_argument("id", nargs="?", type=int, help="Profile ID (omit to list all)")
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit(f"[dry-run] Quality profile: {parsed.id or 'all'}", {"dry_run":True})
|
|
if parsed.id:
|
|
qp = client.quality_profile(parsed.id) or {}
|
|
items = qp.get("items",[])
|
|
lines = [f" {qp.get('name','?')} (id={qp.get('id','?')}) cutoff={qp.get('cutoff',{}).get('name','?')}"]
|
|
for item in items:
|
|
name = item.get("quality",{}).get("name","?")
|
|
allowed = "✓" if item.get("allowed") else "✗"
|
|
lines.append(f" {allowed} {name}")
|
|
emit("\n".join(lines), qp)
|
|
else:
|
|
profiles = client.quality_profiles() or []
|
|
lines = [f" {p.get('id')}: {p.get('name','?')}" for p in profiles]
|
|
emit(f"{len(profiles)} quality profile(s):\n"+"\n".join(lines), {"profiles":profiles})
|
|
|
|
def cmd_metadata_profile(client, args):
|
|
if client.dry_run: return emit("[dry-run] List metadata profiles", {"dry_run":True})
|
|
profiles = client.metadata_profiles() or []
|
|
if not profiles: return emit("No metadata profiles.", {"metadataProfiles":[]})
|
|
lines = [f" {p.get('id')}: {p.get('name','?')}" for p in profiles]
|
|
emit(f"{len(profiles)} metadata profile(s):\n"+"\n".join(lines), {"metadataProfiles":profiles})
|
|
|
|
def cmd_calendar(client, args):
|
|
if client.dry_run: return emit("[dry-run] Get calendar", {"dry_run":True})
|
|
data = client.calendar() or []
|
|
if not data: return emit("No upcoming releases.", {"albums":[]})
|
|
lines, out = [], []
|
|
for alb in data[:30]:
|
|
title = alb.get("title","?"); artist = alb.get("artist",{}).get("artistName","?")
|
|
date = (alb.get("releaseDate") or "")[:10]
|
|
lines.append(f" {date} {artist:30} — {title:45}")
|
|
out.append({"title":title,"artist":artist,"releaseDate":date})
|
|
emit(f"Upcoming:\n"+"\n".join(lines), {"albums":out})
|
|
|
|
def cmd_queue(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli queue")
|
|
p.add_argument("--limit", type=int, default=20)
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit("[dry-run] List queue", {"dry_run":True})
|
|
data = client.queue(limit=parsed.limit) or []
|
|
if not data: return emit("Queue is empty.", {"queue":[]})
|
|
lines, out = [], []
|
|
for item in data:
|
|
title = item.get("title","?"); status = item.get("status","?")
|
|
pct = item.get("sizeleft",0) and item.get("size",1) and f"{100-item.get('sizeleft',0)*100//item.get('size',1):2d}%" or "?"
|
|
lines.append(f" {title:45} [{status:10}] {pct}")
|
|
out.append({"title":title,"status":status,"progress":pct})
|
|
emit(f"{len(data)} in queue:\n"+"\n".join(lines), {"queue":out})
|
|
|
|
def cmd_history(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli history")
|
|
p.add_argument("--limit", type=int, default=20)
|
|
p.add_argument("--event-type", help="Filter by event type (grabbed, importFailed, etc.)")
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit("[dry-run] List history", {"dry_run":True})
|
|
data = client.history(limit=parsed.limit) or {}
|
|
records = data.get("records",[]) if isinstance(data,dict) else data[:parsed.limit]
|
|
if not records: return emit("No history.", {"history":[]})
|
|
lines, out = [], []
|
|
for e in records[:parsed.limit]:
|
|
title = e.get("artist",{}).get("artistName","?") if isinstance(e.get("artist"),dict) else e.get("artistName","?")
|
|
evt = e.get("eventType","?"); date = (e.get("date") or "")[:10]
|
|
lines.append(f" {date} {title:45} {evt}")
|
|
out.append({"date":date,"title":title,"eventType":evt})
|
|
emit(f"History:\n"+"\n".join(lines), {"history":out})
|
|
|
|
def cmd_wanted(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli wanted")
|
|
p.add_argument("--limit", type=int, default=20)
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run: return emit("[dry-run] List wanted", {"dry_run":True})
|
|
data = client.wanted_missing(limit=parsed.limit) or {}
|
|
records = data.get("records",[])
|
|
if not records: return emit("No missing albums.", {"wanted":[]})
|
|
lines, out = [], []
|
|
for alb in records:
|
|
title = alb.get("title","?"); artist = alb.get("artist",{}).get("artistName","?")
|
|
date = (alb.get("releaseDate") or "")[:10]
|
|
lines.append(f" {artist:30} — {title:45} {date}")
|
|
out.append({"artist":artist,"title":title,"releaseDate":date})
|
|
total = data.get("totalRecords", len(records))
|
|
emit(f"{total} missing album(s):\n"+"\n".join(lines), {"total":total,"wanted":out})
|
|
|
|
def cmd_search(client, args):
|
|
p = argparse.ArgumentParser(prog="lidarr-cli search")
|
|
p.add_argument("--artist-id", type=int, required=True, help="Lidarr artist ID")
|
|
parsed, _ = p.parse_known_args(args)
|
|
if client.dry_run:
|
|
return emit(f"[dry-run] Search artist id={parsed.artist_id}", {"dry_run":True, "name":"ArtistSearch", "artistIds":[parsed.artist_id]})
|
|
data = client.command("ArtistSearch", artistIds=[parsed.artist_id])
|
|
emit(f"Search triggered: command #{data.get('id')} — {data.get('status','?')}",
|
|
{"id":data.get("id"), "status":data.get("status"), "name":data.get("name")})
|
|
|
|
def cmd_root_folder(client, args):
|
|
if client.dry_run: return emit("[dry-run] List root folders", {"dry_run":True})
|
|
data = client.root_folders() or []
|
|
if not data: return emit("No root folders configured.", {"rootFolders":[]})
|
|
lines = [f" {r.get('path','?')} ({r.get('freeSpace',0)//1073741824}GB free)" for r in data]
|
|
emit(f"{len(data)} root folder(s):\n"+"\n".join(lines), {"rootFolders":data})
|
|
|
|
def cmd_disk_space(client, args):
|
|
if client.dry_run: return emit("[dry-run] List disk space", {"dry_run":True})
|
|
data = client.disk_space() or []
|
|
if not data: return emit("No disk space info.", {"diskSpace":[]})
|
|
lines = []
|
|
for d in data:
|
|
path = d.get("path","?"); free = d.get("freeSpace",0)//1073741824
|
|
total = d.get("totalSpace",0)//1073741824
|
|
lines.append(f" {path:30} {free}/{total} GB free")
|
|
emit(f"Disk space:\n"+"\n".join(lines), {"diskSpace":data})
|
|
|
|
def cmd_health(client, args):
|
|
if client.dry_run: return emit("[dry-run] Get health", {"dry_run":True})
|
|
data = client.health() or []
|
|
if not data: return emit("All healthy.", {"health":[]})
|
|
lines = [f" {h.get('type','?'):20} — {h.get('message','?')}" for h in data]
|
|
emit(f"{len(data)} warning(s):\n"+"\n".join(lines), {"health":data})
|
|
|
|
def main():
|
|
global GLOBAL_FLAGS, QUIET
|
|
GLOBAL_FLAGS, filtered_argv = _preparse(sys.argv)
|
|
if GLOBAL_FLAGS.get("quiet"): QUIET = True
|
|
if GLOBAL_FLAGS.get("json"): warnings.simplefilter("ignore")
|
|
parser = argparse.ArgumentParser(prog="lidarr-cli", description="Lidarr music management.",
|
|
epilog="Set ARR_SERVER_LIDARR and ARR_KEY_LIDARR.")
|
|
sub = parser.add_subparsers(dest="command")
|
|
sub.add_parser("status")
|
|
sub.add_parser("artists", help="List artists").add_argument("--limit", type=int, default=50)
|
|
sub.add_parser("lookup", help="Search for artists").add_argument("--term","-t",required=True)
|
|
sub.add_parser("lookup-album", help="Search for albums").add_argument("--term","-t",required=True)
|
|
p_add = sub.add_parser("add", help="Add an artist to library")
|
|
p_add.add_argument("--mb-id", required=True)
|
|
p_add.add_argument("--root", required=True)
|
|
p_add.add_argument("--quality-profile", type=int, default=4)
|
|
p_add.add_argument("--metadata-profile", type=int, default=1)
|
|
p_add.add_argument("--unmonitored", action="store_true")
|
|
p_add.add_argument("--search", action="store_true")
|
|
sub.add_parser("albums", help="List albums").add_argument("--artist-id", type=int, required=True)
|
|
sub.add_parser("tracks", help="List tracks").add_argument("--album-id", type=int, required=True)
|
|
sub.add_parser("track-files", help="List track files").add_argument("--album-id", type=int, required=True)
|
|
sub.add_parser("quality-profile", help="List or inspect quality profiles").add_argument("id", nargs="?", type=int)
|
|
sub.add_parser("metadata-profile", help="List metadata profiles")
|
|
sub.add_parser("root-folder", help="List root folders")
|
|
sub.add_parser("calendar")
|
|
sub.add_parser("queue")
|
|
sub.add_parser("history")
|
|
sub.add_parser("wanted")
|
|
sub.add_parser("search", help="Trigger automatic search").add_argument("--artist-id", type=int, required=True)
|
|
sub.add_parser("disk-space", help="Show disk usage")
|
|
sub.add_parser("health", help="Show health warnings")
|
|
args = parser.parse_args(filtered_argv[1:])
|
|
if not args.command: parser.print_help(); sys.exit(1)
|
|
client = LidarrClient(dry_run=GLOBAL_FLAGS.get("dry_run",False))
|
|
handlers = {
|
|
"status":cmd_status, "artists":cmd_artists, "lookup":cmd_lookup,
|
|
"lookup-album":cmd_lookup_album, "add":cmd_add, "albums":cmd_albums,
|
|
"tracks":cmd_tracks, "track-files":cmd_track_files,
|
|
"quality-profile":cmd_quality_profile, "metadata-profile":cmd_metadata_profile,
|
|
"root-folder":cmd_root_folder, "calendar":cmd_calendar,
|
|
"queue":cmd_queue, "history":cmd_history, "wanted":cmd_wanted,
|
|
"search":cmd_search, "disk-space":cmd_disk_space, "health":cmd_health,
|
|
}
|
|
h = handlers.get(args.command)
|
|
if not h: parser.print_help(); sys.exit(1)
|
|
r = filtered_argv[filtered_argv.index(args.command)+1:]
|
|
h(client, r)
|
|
|
|
if __name__ == "__main__": main()
|