video enrichment 1d: wire TMDB/TVDB API keys (workers turn on)
- GET/POST /api/video/enrichment/config saves the keys into video_settings; POST rebuilds the engine (stop old workers, rebuild clients with new keys) so they pick up the change live. - video-settings.js loads the saved keys into the TMDB/TVDB fields on the Connections tab and saves them on change (workers enable once a key is set). Backend is now end-to-end: key -> client.enabled -> worker matches the library to TMDB/TVDB and fills ids + metadata. 91 tests green; real DB untouched.
This commit is contained in:
parent
80679b02ba
commit
65ff84aa6a
4 changed files with 96 additions and 1 deletions
|
|
@ -38,6 +38,31 @@ def register_routes(bp):
|
|||
logger.exception("video enrichment services failed")
|
||||
return jsonify({"services": []})
|
||||
|
||||
@bp.route("/enrichment/config", methods=["GET"])
|
||||
def video_enrichment_config():
|
||||
from . import get_video_db
|
||||
db = get_video_db()
|
||||
return jsonify({
|
||||
"tmdb_api_key": db.get_setting("tmdb_api_key") or "",
|
||||
"tvdb_api_key": db.get_setting("tvdb_api_key") or "",
|
||||
})
|
||||
|
||||
@bp.route("/enrichment/config", methods=["POST"])
|
||||
def video_enrichment_config_save():
|
||||
from . import get_video_db
|
||||
db = get_video_db()
|
||||
body = request.get_json(silent=True) or {}
|
||||
if "tmdb_api_key" in body:
|
||||
db.set_setting("tmdb_api_key", body.get("tmdb_api_key") or "")
|
||||
if "tvdb_api_key" in body:
|
||||
db.set_setting("tvdb_api_key", body.get("tvdb_api_key") or "")
|
||||
try:
|
||||
from core.video.enrichment.engine import rebuild_video_enrichment_engine
|
||||
rebuild_video_enrichment_engine()
|
||||
except Exception:
|
||||
logger.exception("video enrichment: engine rebuild after key change failed")
|
||||
return jsonify({"status": "saved"})
|
||||
|
||||
@bp.route("/enrichment/<service>/status", methods=["GET"])
|
||||
def video_enrichment_status(service):
|
||||
w = engine().worker(service)
|
||||
|
|
|
|||
|
|
@ -58,3 +58,17 @@ def get_video_enrichment_engine():
|
|||
eng.start_all()
|
||||
_engine = eng
|
||||
return _engine
|
||||
|
||||
|
||||
def rebuild_video_enrichment_engine():
|
||||
"""Rebuild the engine so workers pick up changed API keys (stops the old
|
||||
workers first so threads don't leak)."""
|
||||
global _engine
|
||||
with _lock:
|
||||
if _engine is not None:
|
||||
try:
|
||||
_engine.stop_all()
|
||||
except Exception:
|
||||
logger.exception("video enrichment: stopping old engine failed")
|
||||
_engine = None
|
||||
return get_video_enrichment_engine()
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ def test_blueprint_exposes_dashboard_route():
|
|||
assert "/api/video/enrichment/services" in rules
|
||||
assert "/api/video/enrichment/<service>/status" in rules
|
||||
assert "/api/video/enrichment/<service>/unmatched" in rules
|
||||
assert "/api/video/enrichment/config" in rules
|
||||
|
||||
|
||||
def test_dashboard_endpoint_returns_zeroed_json(tmp_path):
|
||||
|
|
@ -130,6 +131,29 @@ def test_enrichment_endpoints(tmp_path):
|
|||
eng_mod._engine = None
|
||||
|
||||
|
||||
def test_enrichment_config_save_load(tmp_path, monkeypatch):
|
||||
import api.video as videoapi
|
||||
from database.video_database import VideoDatabase
|
||||
import core.video.enrichment.engine as eng_mod
|
||||
# Don't build a real engine (would open the default-path DB + start threads).
|
||||
monkeypatch.setattr(eng_mod, "rebuild_video_enrichment_engine", lambda: None)
|
||||
|
||||
db = VideoDatabase(database_path=str(tmp_path / "video_library.db"))
|
||||
videoapi._video_db = db
|
||||
app = Flask(__name__)
|
||||
app.register_blueprint(videoapi.create_video_blueprint(), url_prefix="/api/video")
|
||||
client = app.test_client()
|
||||
try:
|
||||
assert client.get("/api/video/enrichment/config").get_json() == {
|
||||
"tmdb_api_key": "", "tvdb_api_key": ""}
|
||||
client.post("/api/video/enrichment/config", json={"tmdb_api_key": "abc", "tvdb_api_key": "xyz"})
|
||||
assert client.get("/api/video/enrichment/config").get_json() == {
|
||||
"tmdb_api_key": "abc", "tvdb_api_key": "xyz"}
|
||||
assert db.get_setting("tmdb_api_key") == "abc"
|
||||
finally:
|
||||
videoapi._video_db = None
|
||||
|
||||
|
||||
def test_video_api_imports_nothing_from_music():
|
||||
base = Path(__file__).resolve().parent.parent / "api" / "video"
|
||||
for py in base.glob("*.py"):
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
var PAGE_ID = 'video-settings';
|
||||
var URL = '/api/video/libraries';
|
||||
var CONFIG_URL = '/api/video/enrichment/config';
|
||||
|
||||
function status(text) {
|
||||
var n = document.querySelector('[data-video-lib-status]');
|
||||
|
|
@ -62,8 +63,34 @@
|
|||
.catch(function () { status('Save failed'); });
|
||||
}
|
||||
|
||||
// ── Enrichment API keys (TMDB / TVDB) ───────────────────────────────────
|
||||
function loadKeys() {
|
||||
fetch(CONFIG_URL, { headers: { 'Accept': 'application/json' } })
|
||||
.then(function (r) { return r.ok ? r.json() : null; })
|
||||
.then(function (d) {
|
||||
if (!d) return;
|
||||
var t = document.getElementById('tmdb-api-key');
|
||||
var v = document.getElementById('tvdb-api-key');
|
||||
if (t && d.tmdb_api_key != null) t.value = d.tmdb_api_key;
|
||||
if (v && d.tvdb_api_key != null) v.value = d.tvdb_api_key;
|
||||
})
|
||||
.catch(function () { /* ignore */ });
|
||||
}
|
||||
|
||||
function saveKeys() {
|
||||
var t = document.getElementById('tmdb-api-key');
|
||||
var v = document.getElementById('tvdb-api-key');
|
||||
fetch(CONFIG_URL, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
|
||||
body: JSON.stringify({ tmdb_api_key: t ? t.value : '', tvdb_api_key: v ? v.value : '' })
|
||||
}).catch(function () { /* ignore */ });
|
||||
}
|
||||
|
||||
function onPageShown(e) {
|
||||
if (e && e.detail === PAGE_ID) load();
|
||||
if (e && e.detail !== PAGE_ID) return;
|
||||
load();
|
||||
loadKeys();
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
|
@ -73,6 +100,11 @@
|
|||
for (var i = 0; i < selects.length; i++) {
|
||||
selects[i].addEventListener('change', save);
|
||||
}
|
||||
// Enrichment keys save on blur/change (turns the workers on).
|
||||
['tmdb-api-key', 'tvdb-api-key'].forEach(function (id) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) el.addEventListener('change', saveKeys);
|
||||
});
|
||||
document.addEventListener('soulsync:video-page-shown', onPageShown);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue