kryten-webqueue 0.3.0__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/PKG-INFO +1 -1
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/catalog/images.py +24 -7
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/catalog/sync.py +2 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/pyproject.toml +1 -1
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/.github/workflows/python-publish.yml +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/.github/workflows/release.yml +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/.gitignore +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/README.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/config.example.json +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/deploy/kryten-webqueue.service +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/deploy/nginx-queue.conf +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/docs/IMPLEMENTATION_SPEC.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/docs/IMPL_API_GATE.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/docs/IMPL_ECONOMY.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/docs/IMPL_KRYTEN_PY.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/docs/IMPL_ROBOT.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/docs/PRE_PLAN_GAPS.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/docs/PRODUCT_PLAN.md +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/__main__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/api_gate/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/api_gate/client.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/app.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/auth/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/auth/otp.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/auth/rate_limit.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/auth/session.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/catalog/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/catalog/db.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/config.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/playlists/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/playlists/fire.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/playlists/importer.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/playlists/scheduler.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/queue/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/queue/ordering.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/queue/poller.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/queue/shadow.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/admin_playlists.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/admin_queue.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/admin_schedules.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/auth.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/catalog.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/pages.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/queue.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/routes/user.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/static/css/main.css +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/static/js/main.js +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/admin/index.html +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/auth/login.html +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/base.html +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/catalog/browse.html +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/queue/index.html +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/user/dashboard.html +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/ws/__init__.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/ws/handler.py +0 -0
- {kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/ws/manager.py +0 -0
|
@@ -33,15 +33,27 @@ class CoverArtResolver:
|
|
|
33
33
|
if existing and existing.get("cover_art_path"):
|
|
34
34
|
return existing["cover_art_path"]
|
|
35
35
|
|
|
36
|
+
if not self._tmdb_key and not self._omdb_key:
|
|
37
|
+
logger.warning("No TMDB or OMDB API keys configured — cover art lookup skipped")
|
|
38
|
+
return None
|
|
39
|
+
|
|
36
40
|
# Try TMDB first
|
|
37
41
|
image_url = None
|
|
38
42
|
source = None
|
|
39
43
|
if self._tmdb_key:
|
|
40
44
|
image_url = await self._search_tmdb(title)
|
|
41
|
-
|
|
45
|
+
if image_url:
|
|
46
|
+
source = "tmdb"
|
|
47
|
+
logger.debug(f"TMDB found art for {friendly_token!r}: {title!r}")
|
|
48
|
+
else:
|
|
49
|
+
logger.debug(f"TMDB found no art for {friendly_token!r}: {title!r}")
|
|
42
50
|
if not image_url and self._omdb_key:
|
|
43
51
|
image_url = await self._search_omdb(title)
|
|
44
|
-
|
|
52
|
+
if image_url:
|
|
53
|
+
source = "omdb"
|
|
54
|
+
logger.debug(f"OMDB found art for {friendly_token!r}: {title!r}")
|
|
55
|
+
else:
|
|
56
|
+
logger.debug(f"OMDB found no art for {friendly_token!r}: {title!r}")
|
|
45
57
|
|
|
46
58
|
if not image_url:
|
|
47
59
|
return None
|
|
@@ -50,8 +62,11 @@ class CoverArtResolver:
|
|
|
50
62
|
try:
|
|
51
63
|
resp = await self._client.get(image_url)
|
|
52
64
|
if resp.status_code != 200:
|
|
65
|
+
logger.warning(f"Cover art download failed for {friendly_token!r}: HTTP {resp.status_code} {image_url}")
|
|
53
66
|
return None
|
|
54
|
-
|
|
67
|
+
path = await self._save_responsive(friendly_token, resp.content, source, db)
|
|
68
|
+
logger.info(f"Cover art saved for {friendly_token!r} ({source}): {path}")
|
|
69
|
+
return path
|
|
55
70
|
except Exception as e:
|
|
56
71
|
logger.warning(f"Failed to download cover art for {friendly_token}: {e}")
|
|
57
72
|
return None
|
|
@@ -63,14 +78,15 @@ class CoverArtResolver:
|
|
|
63
78
|
params={"api_key": self._tmdb_key, "query": title},
|
|
64
79
|
)
|
|
65
80
|
if resp.status_code != 200:
|
|
81
|
+
logger.warning(f"TMDB API returned {resp.status_code} for {title!r}")
|
|
66
82
|
return None
|
|
67
83
|
results = resp.json().get("results", [])
|
|
68
84
|
if results:
|
|
69
85
|
poster = results[0].get("poster_path")
|
|
70
86
|
if poster:
|
|
71
87
|
return f"https://image.tmdb.org/t/p/w500{poster}"
|
|
72
|
-
except Exception:
|
|
73
|
-
|
|
88
|
+
except Exception as e:
|
|
89
|
+
logger.warning(f"TMDB search error for {title!r}: {e}")
|
|
74
90
|
return None
|
|
75
91
|
|
|
76
92
|
async def _search_omdb(self, title: str) -> str | None:
|
|
@@ -80,13 +96,14 @@ class CoverArtResolver:
|
|
|
80
96
|
params={"apikey": self._omdb_key, "t": title},
|
|
81
97
|
)
|
|
82
98
|
if resp.status_code != 200:
|
|
99
|
+
logger.warning(f"OMDB API returned {resp.status_code} for {title!r}")
|
|
83
100
|
return None
|
|
84
101
|
data = resp.json()
|
|
85
102
|
poster = data.get("Poster")
|
|
86
103
|
if poster and poster != "N/A":
|
|
87
104
|
return poster
|
|
88
|
-
except Exception:
|
|
89
|
-
|
|
105
|
+
except Exception as e:
|
|
106
|
+
logger.warning(f"OMDB search error for {title!r}: {e}")
|
|
90
107
|
return None
|
|
91
108
|
|
|
92
109
|
async def _save_responsive(self, friendly_token: str, data: bytes, source: str, db) -> str:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import httpx
|
|
2
3
|
import logging
|
|
3
4
|
from datetime import datetime, UTC
|
|
@@ -134,6 +135,7 @@ class CatalogSync:
|
|
|
134
135
|
await self._cover_art.resolve(token, row["title"], self._db)
|
|
135
136
|
except Exception as e:
|
|
136
137
|
logger.debug(f"Cover art resolve failed for {token}: {e}")
|
|
138
|
+
await asyncio.sleep(0.25)
|
|
137
139
|
|
|
138
140
|
def _build_manifest_url(self, media: dict) -> str:
|
|
139
141
|
# Use the MediaCMS watch page URL (e.g. https://www.dropsugar.co/view?m=TOKEN)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/catalog/browse.html
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.3.0 → kryten_webqueue-0.3.2}/kryten_webqueue/templates/user/dashboard.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|