-
-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy patharr_import.py
More file actions
163 lines (132 loc) · 6 KB
/
Copy patharr_import.py
File metadata and controls
163 lines (132 loc) · 6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
"""Bulk import from existing Radarr/Sonarr instances into Mycelium.
For each Radarr movie: kick off processor.process() to find a release and add
to TorBox (skips if already in our request history).
For each Sonarr series: upsert into monitored_series so the regular monitor
will pull all (monitored) seasons + episodes.
"""
import logging
import threading
import time
import db
import processor
import radarr
import settings as _settings
import sonarr
import tmdb
from config import RADARR_API_KEY, RADARR_URL, SONARR_API_KEY, SONARR_URL
from webhook_parser import MediaRequest
def _radarr_url() -> str:
return _settings.get("RADARR_URL", RADARR_URL) or ""
def _radarr_key() -> str:
return _settings.get("RADARR_API_KEY", RADARR_API_KEY) or ""
def _sonarr_url() -> str:
return _settings.get("SONARR_URL", SONARR_URL) or ""
def _sonarr_key() -> str:
return _settings.get("SONARR_API_KEY", SONARR_API_KEY) or ""
log = logging.getLogger(__name__)
_import_lock = threading.Lock()
_status: dict = {"running": False, "kind": None, "total": 0, "done": 0,
"added": 0, "skipped": 0, "errors": 0, "started": None,
"finished": None, "message": ""}
def get_status() -> dict:
return dict(_status)
def _set(**kw):
_status.update(kw)
def import_radarr(only_monitored: bool = True, throttle_sec: float = 1.0) -> dict:
"""Pull all (monitored) Radarr movies and queue them for processing."""
url, key = _radarr_url(), _radarr_key()
if not (url and key):
raise RuntimeError("RADARR_URL/RADARR_API_KEY not configured")
with _import_lock:
if _status["running"]:
raise RuntimeError(f"Another import is already running: {_status['kind']}")
_set(running=True, kind="radarr", total=0, done=0, added=0, skipped=0,
errors=0, started=time.time(), finished=None, message="Fetching from Radarr…")
try:
movies = radarr.list_movies(url, key)
if only_monitored:
movies = [m for m in movies if m.get("monitored")]
_set(total=len(movies), message=f"Importing {len(movies)} movie(s)")
existing = {r["imdb_id"] for r in db.get_recent(5000)
if r.get("media_type") == "movie"}
for idx, m in enumerate(movies, start=1):
imdb_id = m.get("imdb_id") or ""
title = m.get("title") or ""
if not imdb_id and m.get("tmdb_id"):
imdb_id = tmdb.tmdb_to_imdb(m["tmdb_id"], media_type="movie") or ""
if not imdb_id:
log.warning("Radarr import: no imdb_id for %s - skipping", title)
_status["skipped"] += 1
_status["done"] = idx
continue
if imdb_id in existing:
log.debug("Radarr import: %s already known (%s) - skipping", title, imdb_id)
_status["skipped"] += 1
_status["done"] = idx
continue
try:
req = MediaRequest(title=title, media_type="movie", imdb_id=imdb_id, seasons=[])
processor.process(req)
existing.add(imdb_id)
_status["added"] += 1
except Exception as exc:
log.warning("Radarr import: processor failed for %s: %s", title, exc)
_status["errors"] += 1
_status["done"] = idx
time.sleep(throttle_sec)
_set(message=f"Done - added {_status['added']}, skipped {_status['skipped']},"
f" errors {_status['errors']}")
return get_status()
finally:
_set(running=False, finished=time.time())
def import_sonarr(only_monitored: bool = True) -> dict:
"""Pull all (monitored) Sonarr series and add them to monitored_series."""
url, key = _sonarr_url(), _sonarr_key()
if not (url and key):
raise RuntimeError("SONARR_URL/SONARR_API_KEY not configured")
with _import_lock:
if _status["running"]:
raise RuntimeError(f"Another import is already running: {_status['kind']}")
_set(running=True, kind="sonarr", total=0, done=0, added=0, skipped=0,
errors=0, started=time.time(), finished=None, message="Fetching from Sonarr…")
try:
series = sonarr.list_series(url, key)
if only_monitored:
series = [s for s in series if s.get("monitored")]
_set(total=len(series), message=f"Importing {len(series)} series")
existing = {s["imdb_id"] for s in db.get_all_monitored_series()}
for idx, s in enumerate(series, start=1):
imdb_id = s.get("imdb_id") or ""
title = s.get("title") or ""
tmdb_id = s.get("tmdb_id")
if not imdb_id and tmdb_id:
imdb_id = tmdb.tmdb_to_imdb(tmdb_id, media_type="tv") or ""
if not imdb_id:
log.warning("Sonarr import: no imdb_id for %s - skipping", title)
_status["skipped"] += 1
_status["done"] = idx
continue
if imdb_id in existing:
_status["skipped"] += 1
_status["done"] = idx
continue
try:
seasons = s.get("seasons") or []
if not seasons:
if tmdb_id:
show = tmdb.get_show_info(tmdb_id) or {}
seasons = list(range(1, (show.get("number_of_seasons") or 1) + 1))
else:
seasons = [1]
db.upsert_monitored_series(imdb_id, tmdb_id, title, seasons)
existing.add(imdb_id)
_status["added"] += 1
except Exception as exc:
log.warning("Sonarr import: upsert failed for %s: %s", title, exc)
_status["errors"] += 1
_status["done"] = idx
_set(message=f"Done - added {_status['added']}, skipped {_status['skipped']},"
f" errors {_status['errors']}")
return get_status()
finally:
_set(running=False, finished=time.time())