kryten-webqueue 0.20.0__tar.gz → 0.21.0__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.
Files changed (105) hide show
  1. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/CHANGELOG.md +17 -0
  2. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/PKG-INFO +1 -1
  3. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/app.py +4 -1
  4. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/static/css/main.css +15 -8
  5. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/admin/index.html +1 -1
  6. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/pyproject.toml +1 -1
  7. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/.github/workflows/python-publish.yml +0 -0
  8. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/.github/workflows/release.yml +0 -0
  9. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/.gitignore +0 -0
  10. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/README.md +0 -0
  11. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/config.example.json +0 -0
  12. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/deploy/kryten-webqueue.service +0 -0
  13. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/deploy/nginx-queue.conf +0 -0
  14. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/IMPLEMENTATION_SPEC.md +0 -0
  15. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/IMPL_API_GATE.md +0 -0
  16. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/IMPL_ECONOMY.md +0 -0
  17. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/IMPL_KRYTEN_PY.md +0 -0
  18. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/IMPL_ROBOT.md +0 -0
  19. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/PLAN_PRESENCE_AND_PROMOS.md +0 -0
  20. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/PRE_PLAN_GAPS.md +0 -0
  21. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/PRODUCT_PLAN.md +0 -0
  22. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/SPEC_JOBS_AND_BROWSE.md +0 -0
  23. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/docs/UX_POLISH_PLAN.md +0 -0
  24. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/__init__.py +0 -0
  25. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/__main__.py +0 -0
  26. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/api_gate/__init__.py +0 -0
  27. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/api_gate/client.py +0 -0
  28. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/auth/__init__.py +0 -0
  29. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/auth/otp.py +0 -0
  30. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/auth/rate_limit.py +0 -0
  31. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/auth/session.py +0 -0
  32. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/catalog/__init__.py +0 -0
  33. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/catalog/db.py +0 -0
  34. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/catalog/images.py +0 -0
  35. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/catalog/mediacms.py +0 -0
  36. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/catalog/sync.py +0 -0
  37. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/config.py +0 -0
  38. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/__init__.py +0 -0
  39. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/cmsutils/__init__.py +0 -0
  40. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/cmsutils/_common.py +0 -0
  41. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/cmsutils/enrichmeta.py +0 -0
  42. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/cmsutils/enrichtitles.py +0 -0
  43. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/cmsutils/enrichtv.py +0 -0
  44. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/cmsutils/fetchurls.py +0 -0
  45. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/ytpipe/__init__.py +0 -0
  46. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/integrations/ytpipe/downloader.py +0 -0
  47. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/jobs/__init__.py +0 -0
  48. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/jobs/fetchurls_auth.py +0 -0
  49. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/jobs/manager.py +0 -0
  50. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/jobs/tasks.py +0 -0
  51. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/logging_config.py +0 -0
  52. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/playlists/__init__.py +0 -0
  53. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/playlists/bulk_add.py +0 -0
  54. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/playlists/fire.py +0 -0
  55. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/playlists/importer.py +0 -0
  56. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/playlists/ordering.py +0 -0
  57. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/playlists/scheduler.py +0 -0
  58. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/promos/__init__.py +0 -0
  59. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/promos/director.py +0 -0
  60. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/queue/__init__.py +0 -0
  61. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/queue/ordering.py +0 -0
  62. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/queue/poller.py +0 -0
  63. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/queue/presence.py +0 -0
  64. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/queue/shadow.py +0 -0
  65. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/__init__.py +0 -0
  66. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/admin_catalog.py +0 -0
  67. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/admin_jobs.py +0 -0
  68. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/admin_playlists.py +0 -0
  69. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/admin_promos.py +0 -0
  70. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/admin_queue.py +0 -0
  71. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/admin_schedules.py +0 -0
  72. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/auth.py +0 -0
  73. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/catalog.py +0 -0
  74. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/pages.py +0 -0
  75. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/queue.py +0 -0
  76. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/routes/user.py +0 -0
  77. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/static/js/main.js +0 -0
  78. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/admin/playlists.html +0 -0
  79. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/admin/promos.html +0 -0
  80. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/admin/queue_mgmt.html +0 -0
  81. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/admin/schedules.html +0 -0
  82. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/auth/login.html +0 -0
  83. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/base.html +0 -0
  84. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/catalog/browse.html +0 -0
  85. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/catalog/item_detail.html +0 -0
  86. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/catalog/item_not_found.html +0 -0
  87. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/queue/index.html +0 -0
  88. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/templates/user/dashboard.html +0 -0
  89. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/ws/__init__.py +0 -0
  90. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/ws/handler.py +0 -0
  91. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/kryten_webqueue/ws/manager.py +0 -0
  92. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/__init__.py +0 -0
  93. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_config_persistence.py +0 -0
  94. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_fetchurls_sharepoint.py +0 -0
  95. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_phase1.py +0 -0
  96. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_phase2_jobs.py +0 -0
  97. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_phase3_jobs.py +0 -0
  98. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_phase4_live_fixes.py +0 -0
  99. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_playlist_import.py +0 -0
  100. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_presence_refund.py +0 -0
  101. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_promo_director.py +0 -0
  102. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_promo_pool_exclusion.py +0 -0
  103. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_queue_announce.py +0 -0
  104. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_save_results_to_playlist.py +0 -0
  105. {kryten_webqueue-0.20.0 → kryten_webqueue-0.21.0}/tests/test_search_facets.py +0 -0
@@ -6,6 +6,23 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.21.0] — 2026-06-17
10
+
11
+ ### Changed
12
+
13
+ - **Catalog sync no longer runs on startup.** The background sync loop now waits a full interval before its first run instead of syncing immediately when the process starts, so a restart won't kick off a sync. Admins can still trigger it on demand with the "Sync Catalog" button.
14
+ - **Friendlier job buttons.** Jobs that open a parameter dialog before running now show **"Begin…"** instead of "Run…", signalling that a dialog (with a Cancel) comes next rather than an immediate action. One-click jobs keep the plain **"Run"** label.
15
+
16
+ [0.21.0]: https://github.com/grobertson/kryten-webqueue/releases/tag/v0.21.0
17
+
18
+ ## [0.20.1] — 2026-06-17
19
+
20
+ ### Fixed
21
+
22
+ - **Z-Coin dashboard layout polish.** The left account column is now a fixed 320px width (was a flexible 280–360px range that shifted with content), and the tab strip has proper folder-tab styling — filled inactive tabs with hover feedback and an active tab that visually connects to its panel — instead of the previous near-invisible underline.
23
+
24
+ [0.20.1]: https://github.com/grobertson/kryten-webqueue/releases/tag/v0.20.1
25
+
9
26
  ## [0.20.0] — 2026-06-17
10
27
 
11
28
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kryten-webqueue
3
- Version: 0.20.0
3
+ Version: 0.21.0
4
4
  Summary: Netflix/Tubi-style catalog browser and pay-to-play queue management for CyTube
5
5
  Author: grobertson
6
6
  License-Expression: MIT
@@ -163,12 +163,15 @@ async def lifespan(app: FastAPI):
163
163
  # Background workers
164
164
  async def _catalog_sync_loop():
165
165
  interval = config.catalog_sync_interval_hours * 3600
166
+ # Sync on the interval, NOT immediately on startup — a restart should
167
+ # not trigger a catalog sync. Admins can run it on demand from the
168
+ # "Sync Catalog" button.
166
169
  while True:
170
+ await asyncio.sleep(interval)
167
171
  try:
168
172
  await catalog_sync.sync()
169
173
  except Exception as e:
170
174
  logger.exception(f"Catalog sync error: {type(e).__name__}: {e}")
171
- await asyncio.sleep(interval)
172
175
 
173
176
  async def _otp_cleanup_loop():
174
177
  while True:
@@ -797,7 +797,7 @@ a.np-chip {
797
797
  }
798
798
  .dashboard-grid {
799
799
  display: grid;
800
- grid-template-columns: minmax(280px, 360px) 1fr;
800
+ grid-template-columns: 320px minmax(0, 1fr);
801
801
  gap: 1.5rem;
802
802
  margin-top: 1.5rem;
803
803
  align-items: start;
@@ -816,27 +816,34 @@ a.np-chip {
816
816
  /* Dashboard tabbed container */
817
817
  .tabs {
818
818
  display: flex;
819
- gap: 0.25rem;
819
+ gap: 0.35rem;
820
820
  border-bottom: 1px solid var(--border);
821
- margin-bottom: 1rem;
821
+ margin-bottom: 1.25rem;
822
822
  }
823
823
  .tab-btn {
824
- background: transparent;
825
- border: none;
826
- border-bottom: 2px solid transparent;
824
+ appearance: none;
825
+ background: var(--bg-secondary);
826
+ border: 1px solid var(--border);
827
+ border-bottom: none;
828
+ border-radius: var(--radius) var(--radius) 0 0;
827
829
  color: var(--text-secondary);
828
830
  cursor: pointer;
831
+ font-family: inherit;
829
832
  font-size: 0.95rem;
830
833
  font-weight: 600;
831
- padding: 0.6rem 0.9rem;
834
+ padding: 0.6rem 1.1rem;
832
835
  margin-bottom: -1px;
836
+ transition: color 0.15s, background 0.15s;
833
837
  }
834
838
  .tab-btn:hover {
835
839
  color: var(--text-primary);
840
+ background: var(--bg-hover);
836
841
  }
837
842
  .tab-btn.active {
838
843
  color: var(--accent);
839
- border-bottom-color: var(--accent);
844
+ background: var(--bg-card);
845
+ border-color: var(--border);
846
+ border-bottom: 1px solid var(--bg-card);
840
847
  }
841
848
  .tab-panel[hidden] {
842
849
  display: none;
@@ -199,7 +199,7 @@ async function loadJobs() {
199
199
  <span class="job-label">${escapeHtml(j.label)}${hasParams ? ' <span class="job-badge">params</span>' : ''}</span>
200
200
  ${summary}
201
201
  <button class="btn btn-sm" onclick="startJob('${j.name}')" ${j.running ? 'disabled' : ''}>
202
- ${j.running ? 'Running…' : (hasParams ? 'Run…' : 'Run')}
202
+ ${j.running ? 'Running…' : (hasParams ? 'Begin…' : 'Run')}
203
203
  </button>
204
204
  </div>`;
205
205
  }).join('')
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryten-webqueue"
3
- version = "0.20.0"
3
+ version = "0.21.0"
4
4
  description = "Netflix/Tubi-style catalog browser and pay-to-play queue management for CyTube"
5
5
  readme = "README.md"
6
6
  license = "MIT"