kryten-webqueue 0.36.0__tar.gz → 0.36.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.36.0 → kryten_webqueue-0.36.2}/CHANGELOG.md +30 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/PKG-INFO +1 -1
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/tags.py +53 -12
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/catalog/browse.html +7 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/pyproject.toml +1 -1
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/.github/workflows/gitleaks.yml +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/.github/workflows/python-publish.yml +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/.github/workflows/release.yml +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/.gitignore +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/.gitleaks.toml +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/.pre-commit-config.yaml +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/AGENT-WORKFLOW-GUIDE.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/README.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/config.example.json +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/deploy/kryten-webqueue.service +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/deploy/nginx-queue.conf +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/IMPLEMENTATION_SPEC.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/IMPL_API_GATE.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/IMPL_ECONOMY.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/IMPL_KRYTEN_PY.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/IMPL_ROBOT.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/Kryten-Economy Service Quality Survey Report at v0.13.0.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/Kryten-Webqueue Service Quality Survey Report at v0.27.1.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/Log for incorrect promo insertion problem.txt +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/PLAN_PRESENCE_AND_PROMOS.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/PRE_PLAN_GAPS.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/PRODUCT_PLAN.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/SPEC_CATALOG_ENRICHMENT_PIPELINE.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/SPEC_EMOTE_REHOST.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/SPEC_JOBS_AND_BROWSE.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/docs/UX_POLISH_PLAN.md +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/__main__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/api_gate/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/api_gate/client.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/app.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/auth/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/auth/otp.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/auth/rate_limit.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/auth/session.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_catalog.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_connection.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_enrichment.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_feedback.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_people.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_playlists.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_queue.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/db/_watchlist.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/classify.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/normalise.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/pipeline.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/providers.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/report.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/art.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/categories.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/meta.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/sync.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/title.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/images.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/mediacms.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/sync.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/config.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/_common.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/enrichmeta.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/enrichtitles.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/enrichtv.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/fetchurls.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/motdposters.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/playedmovies.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/ytpipe/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/ytpipe/downloader.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/jobs/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/jobs/fetchurls_auth.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/jobs/job_scheduler.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/jobs/manager.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/jobs/rehost_emotes.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/jobs/tasks.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/logging_config.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/playlists/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/playlists/bulk_add.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/playlists/fire.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/playlists/importer.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/playlists/ordering.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/playlists/scheduler.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/promos/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/promos/director.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/queue/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/queue/completion.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/queue/ordering.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/queue/poller.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/queue/presence.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/queue/race_poller.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/queue/shadow.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_catalog.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_feedback.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_job_schedules.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_jobs.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_moderation.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_playlists.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_promos.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_queue.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_schedules.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/auth.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/catalog.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/feedback.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/pages.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/queue.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/user.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/css/main.css +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin-playlists.js +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin-promos.js +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin-queue-mgmt.js +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin-schedules.js +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin.js +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/main.js +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/index.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/playlists.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/promos.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/queue_mgmt.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/schedules.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/auth/login.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/base.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/catalog/item_detail.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/catalog/item_not_found.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/feedback/index.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/queue/index.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/race.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/user/dashboard.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/user/my_list.html +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/ws/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/ws/handler.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/ws/manager.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/__init__.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_classify.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_config_persistence.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_feedback.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_fetchurls_sharepoint.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_people_facets.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_phase1.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_phase2_jobs.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_phase3_jobs.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_phase4_live_fixes.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_playlist_import.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_presence_refund.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_promo_director.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_promo_pool_exclusion.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_providers.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_queue_announce.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_race_poller.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_recently_played_hide.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_save_results_to_playlist.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_schedule_lock.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_search_facets.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_title_normalization.py +0 -0
- {kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/tests/test_watchlist.py +0 -0
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.36.2] - 2026-08-14
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Stop flooding MediaCMS with futile tag-push 400s.** The tags step attempted
|
|
10
|
+
`POST /media/user/bulk_actions` (`add_tags`) for every enriched item, but that
|
|
11
|
+
endpoint filters `Media.objects.filter(user=request.user, ...)` with no manager
|
|
12
|
+
or superuser bypass, so pushes against media owned by other users always return
|
|
13
|
+
400 "No matching media found". The step now looks up the API token's username
|
|
14
|
+
once via `/whoami` and only attempts the CMS push for media that user actually
|
|
15
|
+
owns. Local `catalog_tags` remains the source of truth for derived
|
|
16
|
+
genre/MPAA/hosted tags, so tags still display regardless.
|
|
17
|
+
|
|
18
|
+
## [0.36.1] - 2026-08-14
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- **Tags now appear on item detail pages.** The tags enrichment step pushed tags to
|
|
23
|
+
MediaCMS via `PUT /media/{token}`, but that endpoint only accepts title/description
|
|
24
|
+
and silently ignores a `tags` field — so tags never landed in CMS and thus never
|
|
25
|
+
reverse-synced into the local catalog. Tag pushes now use the correct
|
|
26
|
+
`POST /media/user/bulk_actions` (`action: add_tags`) endpoint, and computed
|
|
27
|
+
genre/MPAA/hosted-show tags are also written directly to the local `catalog_tags`
|
|
28
|
+
table so they display regardless of CMS write success.
|
|
29
|
+
- **Person and Studio facet links now work.** Clicking a person or studio chip on an
|
|
30
|
+
item detail page dropped the filter and landed on the unfiltered browse page whenever
|
|
31
|
+
the user had a saved sort or hide-short preference: the `applyFacets()` redirect
|
|
32
|
+
rebuilt the URL from the dropdowns only and discarded the `person`/`studio` query
|
|
33
|
+
params. It now preserves them.
|
|
34
|
+
|
|
5
35
|
## [0.36.0] - 2026-08-14
|
|
6
36
|
|
|
7
37
|
### Added
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/tags.py
RENAMED
|
@@ -42,6 +42,22 @@ class TagsStep:
|
|
|
42
42
|
)
|
|
43
43
|
self._headers = {"Authorization": f"Token {config.mediacms_token}"}
|
|
44
44
|
|
|
45
|
+
async def _get_api_username(self, client: httpx.AsyncClient) -> str | None:
|
|
46
|
+
"""Return the API token's username, or None.
|
|
47
|
+
|
|
48
|
+
MediaCMS ``/media/user/bulk_actions`` filters ``Media.objects.filter(
|
|
49
|
+
user=request.user, ...)`` with no manager/superuser bypass, so tag
|
|
50
|
+
pushes only succeed on media this user owns. We use this to skip futile
|
|
51
|
+
pushes against media owned by others instead of flooding CMS with 400s.
|
|
52
|
+
"""
|
|
53
|
+
try:
|
|
54
|
+
resp = await client.get(f"{self._base}/api/v1/whoami")
|
|
55
|
+
if resp.status_code != 200:
|
|
56
|
+
return None
|
|
57
|
+
return resp.json().get("username")
|
|
58
|
+
except (httpx.HTTPError, json.JSONDecodeError, ValueError):
|
|
59
|
+
return None
|
|
60
|
+
|
|
45
61
|
async def run(
|
|
46
62
|
self,
|
|
47
63
|
*,
|
|
@@ -54,6 +70,7 @@ class TagsStep:
|
|
|
54
70
|
now = datetime.now(UTC).isoformat()
|
|
55
71
|
|
|
56
72
|
async with httpx.AsyncClient(headers=self._headers, timeout=_TIMEOUT) as client:
|
|
73
|
+
api_user = None if dry_run else await self._get_api_username(client)
|
|
57
74
|
for cls in classifications:
|
|
58
75
|
result.processed += 1
|
|
59
76
|
try:
|
|
@@ -83,10 +100,17 @@ class TagsStep:
|
|
|
83
100
|
continue
|
|
84
101
|
|
|
85
102
|
if not dry_run:
|
|
103
|
+
# Persist computed tags locally first so item detail shows
|
|
104
|
+
# them even if the CMS write below fails (owner/permission).
|
|
105
|
+
for tag in desired:
|
|
106
|
+
await self._db.add_catalog_tag(cls.friendly_token, tag)
|
|
86
107
|
changed = await self._push_tags(
|
|
87
|
-
client,
|
|
108
|
+
client,
|
|
109
|
+
cls.friendly_token,
|
|
110
|
+
desired,
|
|
111
|
+
api_user=api_user,
|
|
88
112
|
)
|
|
89
|
-
# Reverse sync: pull CMS tags back to local DB
|
|
113
|
+
# Reverse sync: pull any CMS-only tags back to local DB
|
|
90
114
|
await self._reverse_sync(client, cls.friendly_token)
|
|
91
115
|
if changed:
|
|
92
116
|
result.changed += 1
|
|
@@ -106,15 +130,31 @@ class TagsStep:
|
|
|
106
130
|
return result
|
|
107
131
|
|
|
108
132
|
async def _push_tags(
|
|
109
|
-
self,
|
|
133
|
+
self,
|
|
134
|
+
client: httpx.AsyncClient,
|
|
135
|
+
token: str,
|
|
136
|
+
new_tags: list[str],
|
|
137
|
+
*,
|
|
138
|
+
api_user: str | None = None,
|
|
110
139
|
) -> bool:
|
|
111
|
-
|
|
140
|
+
"""Add tags to a CMS media item via the bulk_actions ``add_tags`` action.
|
|
141
|
+
|
|
142
|
+
The ``PUT /media/{token}`` endpoint only accepts title/description/media_file
|
|
143
|
+
and silently ignores a ``tags`` field, so tag changes must go through
|
|
144
|
+
``POST /media/user/bulk_actions`` with ``action: add_tags``. That endpoint
|
|
145
|
+
filters ``Media.objects.filter(user=request.user, ...)`` with no manager or
|
|
146
|
+
superuser bypass, so we skip the push unless the API user owns the media
|
|
147
|
+
rather than flooding CMS with 400s.
|
|
148
|
+
"""
|
|
149
|
+
detail_url = f"{self._base}/api/v1/media/{token}"
|
|
112
150
|
try:
|
|
113
|
-
resp = await client.get(
|
|
151
|
+
resp = await client.get(detail_url)
|
|
114
152
|
if resp.status_code != 200:
|
|
115
153
|
return False
|
|
116
154
|
data = resp.json()
|
|
117
155
|
owner = data.get("user")
|
|
156
|
+
if api_user is None or owner != api_user:
|
|
157
|
+
return False
|
|
118
158
|
current = {
|
|
119
159
|
(t.get("title") if isinstance(t, dict) else t)
|
|
120
160
|
for t in (data.get("tags_info") or [])
|
|
@@ -122,13 +162,14 @@ class TagsStep:
|
|
|
122
162
|
to_add = [t for t in new_tags if t not in current]
|
|
123
163
|
if not to_add:
|
|
124
164
|
return False
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
165
|
+
put = await client.post(
|
|
166
|
+
f"{self._base}/api/v1/media/user/bulk_actions",
|
|
167
|
+
json={
|
|
168
|
+
"action": "add_tags",
|
|
169
|
+
"media_ids": [token],
|
|
170
|
+
"tag_titles": to_add,
|
|
171
|
+
},
|
|
172
|
+
)
|
|
132
173
|
return put.status_code in (200, 201)
|
|
133
174
|
except (httpx.HTTPError, json.JSONDecodeError, ValueError):
|
|
134
175
|
return False
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/catalog/browse.html
RENAMED
|
@@ -203,6 +203,13 @@ function applyFacets() {
|
|
|
203
203
|
}
|
|
204
204
|
if (cat) params.set('category', cat);
|
|
205
205
|
if (tag) params.set('tag', tag);
|
|
206
|
+
// Preserve person/studio facets — these come from the URL, not the dropdowns,
|
|
207
|
+
// and must survive a sort/hide_short change or the filter is silently dropped.
|
|
208
|
+
const current = new URLSearchParams(window.location.search);
|
|
209
|
+
const person = current.get('person');
|
|
210
|
+
const studio = current.get('studio');
|
|
211
|
+
if (person) params.set('person', person);
|
|
212
|
+
if (studio) params.set('studio', studio);
|
|
206
213
|
if (sort && sort !== 'default') params.set('sort', sort);
|
|
207
214
|
// Only include hide_short in URL when non-default (default = 1, hide).
|
|
208
215
|
if (!hideShort) params.set('hide_short', '0');
|
|
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.36.0 → kryten_webqueue-0.36.2}/docs/Log for incorrect promo insertion problem.txt
RENAMED
|
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.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/__init__.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/classify.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/normalise.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/pipeline.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/providers.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/report.py
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/art.py
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/meta.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/sync.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/catalog/enrichment/steps/title.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/__init__.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/_common.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/enrichtv.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/cmsutils/fetchurls.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/ytpipe/__init__.py
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/integrations/ytpipe/downloader.py
RENAMED
|
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.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_job_schedules.py
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/routes/admin_moderation.py
RENAMED
|
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.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin-playlists.js
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin-queue-mgmt.js
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/static/js/admin-schedules.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/index.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/playlists.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/promos.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/queue_mgmt.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/admin/schedules.html
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/catalog/item_detail.html
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/feedback/index.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/queue/index.html
RENAMED
|
File without changes
|
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/user/dashboard.html
RENAMED
|
File without changes
|
{kryten_webqueue-0.36.0 → kryten_webqueue-0.36.2}/kryten_webqueue/templates/user/my_list.html
RENAMED
|
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
|