video enrichment: keyless workers read 'Disabled' (not 'Not configured') when off
AniList defaults off (anime opt-in), so it showed 'Not configured' — implying a missing API key, when it's keyless and just toggled off in Settings > Community Data (No Key). Workers now report needs_key in get_stats (True for the key-gated fanart/opensubtitles/trakt + all matchers; False for the keyless toggles). The manager rail/pill + dashboard-header tooltip show 'Disabled' / 'Off — enable in Settings' for a disabled keyless worker, and keep 'Not configured' only for ones that genuinely need a key. (The AniList on/off toggle already exists in the collapsed 'Community Data (No Key)' settings frame — this just makes the status honest about what's needed.)
This commit is contained in:
parent
f98ceecd68
commit
8c2f66bea9
5 changed files with 14 additions and 4 deletions
|
|
@ -99,6 +99,7 @@ def _norm_title(s):
|
||||||
# ── base worker (lifecycle + loop + status; mirrors VideoEnrichmentWorker) ────
|
# ── base worker (lifecycle + loop + status; mirrors VideoEnrichmentWorker) ────
|
||||||
class VideoBackfillWorker:
|
class VideoBackfillWorker:
|
||||||
is_ratings = False
|
is_ratings = False
|
||||||
|
requires_key = False # True for workers gated on an API key (vs a keyless toggle)
|
||||||
|
|
||||||
def __init__(self, db, service, display_name, interval=1.0):
|
def __init__(self, db, service, display_name, interval=1.0):
|
||||||
self.db = db
|
self.db = db
|
||||||
|
|
@ -259,6 +260,7 @@ class VideoBackfillWorker:
|
||||||
"percent": round(done / total * 100) if total else 0}
|
"percent": round(done / total * 100) if total else 0}
|
||||||
return {
|
return {
|
||||||
"enabled": self.enabled,
|
"enabled": self.enabled,
|
||||||
|
"needs_key": self.requires_key, # key-gated → "Not configured"; keyless → "Disabled"
|
||||||
"running": running,
|
"running": running,
|
||||||
"paused": self.paused or cooling,
|
"paused": self.paused or cooling,
|
||||||
"idle": idle,
|
"idle": idle,
|
||||||
|
|
@ -379,6 +381,7 @@ def _fa_first(j, *keys):
|
||||||
|
|
||||||
class FanartWorker(VideoBackfillWorker):
|
class FanartWorker(VideoBackfillWorker):
|
||||||
BASE = "https://webservice.fanart.tv/v3"
|
BASE = "https://webservice.fanart.tv/v3"
|
||||||
|
requires_key = True
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, db):
|
||||||
super().__init__(db, "fanart", "fanart.tv", interval=1.0)
|
super().__init__(db, "fanart", "fanart.tv", interval=1.0)
|
||||||
|
|
@ -451,6 +454,7 @@ class FanartWorker(VideoBackfillWorker):
|
||||||
# ── OpenSubtitles (free key) — subtitle-language availability ─────────────────
|
# ── OpenSubtitles (free key) — subtitle-language availability ─────────────────
|
||||||
class OpenSubtitlesWorker(VideoBackfillWorker):
|
class OpenSubtitlesWorker(VideoBackfillWorker):
|
||||||
BASE = "https://api.opensubtitles.com/api/v1"
|
BASE = "https://api.opensubtitles.com/api/v1"
|
||||||
|
requires_key = True
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, db):
|
||||||
super().__init__(db, "opensubtitles", "OpenSubtitles", interval=1.5)
|
super().__init__(db, "opensubtitles", "OpenSubtitles", interval=1.5)
|
||||||
|
|
@ -521,6 +525,7 @@ class OpenSubtitlesWorker(VideoBackfillWorker):
|
||||||
# ── Trakt (free API key) — community audience rating + vote count ─────────────
|
# ── Trakt (free API key) — community audience rating + vote count ─────────────
|
||||||
class TraktWorker(VideoBackfillWorker):
|
class TraktWorker(VideoBackfillWorker):
|
||||||
BASE = "https://api.trakt.tv"
|
BASE = "https://api.trakt.tv"
|
||||||
|
requires_key = True
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, db):
|
||||||
super().__init__(db, "trakt", "Trakt", interval=1.0)
|
super().__init__(db, "trakt", "Trakt", interval=1.0)
|
||||||
|
|
|
||||||
|
|
@ -290,6 +290,7 @@ class VideoEnrichmentWorker:
|
||||||
"percent": round(done / total * 100) if total else 0}
|
"percent": round(done / total * 100) if total else 0}
|
||||||
return {
|
return {
|
||||||
"enabled": self.enabled,
|
"enabled": self.enabled,
|
||||||
|
"needs_key": True, # matchers (TMDB/TVDB/OMDb) always require an API key
|
||||||
"running": running,
|
"running": running,
|
||||||
"paused": self.paused or cooling, # cooldown reads as paused in the UI
|
"paused": self.paused or cooling, # cooldown reads as paused in the UI
|
||||||
"idle": idle,
|
"idle": idle,
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,7 @@ def test_nokey_workers_enabled_by_default_and_toggle(db):
|
||||||
def test_get_stats_shape_matches_matcher_worker(db):
|
def test_get_stats_shape_matches_matcher_worker(db):
|
||||||
_seed_video(db)
|
_seed_video(db)
|
||||||
stats = RydWorker(db).get_stats()
|
stats = RydWorker(db).get_stats()
|
||||||
assert set(stats) == {"enabled", "running", "paused", "idle", "current_item",
|
assert set(stats) == {"enabled", "needs_key", "running", "paused", "idle", "current_item",
|
||||||
"note", "cooldown", "stats", "progress", "breakdown"}
|
"note", "cooldown", "stats", "progress", "breakdown"}
|
||||||
assert set(stats["stats"]) == {"matched", "not_found", "errors", "pending"}
|
assert set(stats["stats"]) == {"matched", "not_found", "errors", "pending"}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function statusInfo(s) {
|
function statusInfo(s) {
|
||||||
if (!s || !s.enabled) return { cls: 'disabled', label: 'Not configured' };
|
// Keyless workers that are simply toggled off read "Disabled", not the
|
||||||
|
// key-implying "Not configured".
|
||||||
|
if (!s || !s.enabled) {
|
||||||
|
return { cls: 'disabled', label: (s && s.needs_key === false) ? 'Disabled' : 'Not configured' };
|
||||||
|
}
|
||||||
if (s.running && !s.paused && !s.idle) return { cls: 'running', label: 'Running' };
|
if (s.running && !s.paused && !s.idle) return { cls: 'running', label: 'Running' };
|
||||||
if (s.paused) return { cls: 'paused', label: 'Paused' };
|
if (s.paused) return { cls: 'paused', label: 'Paused' };
|
||||||
if (s.idle) return { cls: 'idle', label: 'Complete' };
|
if (s.idle) return { cls: 'idle', label: 'Complete' };
|
||||||
|
|
@ -106,7 +110,7 @@
|
||||||
return t ? Math.round(m / t * 100) : 0;
|
return t ? Math.round(m / t * 100) : 0;
|
||||||
}
|
}
|
||||||
function railSub(s, id) {
|
function railSub(s, id) {
|
||||||
if (!s || !s.enabled) return 'Not configured';
|
if (!s || !s.enabled) return (s && s.needs_key === false) ? 'Off — enable in Settings' : 'Not configured';
|
||||||
if (id === 'youtube') {
|
if (id === 'youtube') {
|
||||||
if (s.running && s.current_item && s.current_item.name) return s.current_item.name;
|
if (s.running && s.current_item && s.current_item.name) return s.current_item.name;
|
||||||
if (s.queued) return s.queued + ' queued';
|
if (s.queued) return s.queued + ' queued';
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
var tip = document.querySelector('[data-video-enrich-tooltip="' + svc + '"]');
|
var tip = document.querySelector('[data-video-enrich-tooltip="' + svc + '"]');
|
||||||
if (!tip) return;
|
if (!tip) return;
|
||||||
var status = !d.enabled ? 'Not configured'
|
var status = !d.enabled ? (d.needs_key === false ? 'Disabled' : 'Not configured')
|
||||||
: d.idle ? 'Complete'
|
: d.idle ? 'Complete'
|
||||||
: (d.running && !d.paused) ? 'Running'
|
: (d.running && !d.paused) ? 'Running'
|
||||||
: d.paused ? 'Paused' : 'Idle';
|
: d.paused ? 'Paused' : 'Idle';
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue