kryten-webqueue 0.34.0__tar.gz → 0.34.1__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 (139) hide show
  1. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/CHANGELOG.md +13 -0
  2. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/PKG-INFO +1 -1
  3. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/jobs/job_scheduler.py +44 -16
  4. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_job_schedules.py +24 -18
  5. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/pyproject.toml +1 -1
  6. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/.github/workflows/gitleaks.yml +0 -0
  7. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/.github/workflows/python-publish.yml +0 -0
  8. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/.github/workflows/release.yml +0 -0
  9. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/.gitignore +0 -0
  10. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/.gitleaks.toml +0 -0
  11. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/.pre-commit-config.yaml +0 -0
  12. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/AGENT-WORKFLOW-GUIDE.md +0 -0
  13. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/README.md +0 -0
  14. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/config.example.json +0 -0
  15. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/deploy/kryten-webqueue.service +0 -0
  16. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/deploy/nginx-queue.conf +0 -0
  17. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/IMPLEMENTATION_SPEC.md +0 -0
  18. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/IMPL_API_GATE.md +0 -0
  19. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/IMPL_ECONOMY.md +0 -0
  20. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/IMPL_KRYTEN_PY.md +0 -0
  21. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/IMPL_ROBOT.md +0 -0
  22. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/Kryten-Economy Service Quality Survey Report at v0.13.0.md +0 -0
  23. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/Kryten-Webqueue Service Quality Survey Report at v0.27.1.md +0 -0
  24. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/Log for incorrect promo insertion problem.txt +0 -0
  25. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/PLAN_PRESENCE_AND_PROMOS.md +0 -0
  26. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/PRE_PLAN_GAPS.md +0 -0
  27. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/PRODUCT_PLAN.md +0 -0
  28. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/SPEC_EMOTE_REHOST.md +0 -0
  29. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/SPEC_JOBS_AND_BROWSE.md +0 -0
  30. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/docs/UX_POLISH_PLAN.md +0 -0
  31. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/__init__.py +0 -0
  32. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/__main__.py +0 -0
  33. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/api_gate/__init__.py +0 -0
  34. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/api_gate/client.py +0 -0
  35. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/app.py +0 -0
  36. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/auth/__init__.py +0 -0
  37. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/auth/otp.py +0 -0
  38. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/auth/rate_limit.py +0 -0
  39. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/auth/session.py +0 -0
  40. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/__init__.py +0 -0
  41. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/db/__init__.py +0 -0
  42. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/db/_catalog.py +0 -0
  43. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/db/_connection.py +0 -0
  44. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/db/_feedback.py +0 -0
  45. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/db/_playlists.py +0 -0
  46. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/db/_queue.py +0 -0
  47. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/images.py +0 -0
  48. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/mediacms.py +0 -0
  49. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/catalog/sync.py +0 -0
  50. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/config.py +0 -0
  51. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/__init__.py +0 -0
  52. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/__init__.py +0 -0
  53. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/_common.py +0 -0
  54. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/enrichmeta.py +0 -0
  55. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/enrichtitles.py +0 -0
  56. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/enrichtv.py +0 -0
  57. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/fetchurls.py +0 -0
  58. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/motdposters.py +0 -0
  59. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/cmsutils/playedmovies.py +0 -0
  60. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/ytpipe/__init__.py +0 -0
  61. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/integrations/ytpipe/downloader.py +0 -0
  62. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/jobs/__init__.py +0 -0
  63. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/jobs/fetchurls_auth.py +0 -0
  64. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/jobs/manager.py +0 -0
  65. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/jobs/rehost_emotes.py +0 -0
  66. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/jobs/tasks.py +0 -0
  67. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/logging_config.py +0 -0
  68. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/playlists/__init__.py +0 -0
  69. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/playlists/bulk_add.py +0 -0
  70. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/playlists/fire.py +0 -0
  71. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/playlists/importer.py +0 -0
  72. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/playlists/ordering.py +0 -0
  73. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/playlists/scheduler.py +0 -0
  74. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/promos/__init__.py +0 -0
  75. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/promos/director.py +0 -0
  76. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/queue/__init__.py +0 -0
  77. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/queue/completion.py +0 -0
  78. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/queue/ordering.py +0 -0
  79. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/queue/poller.py +0 -0
  80. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/queue/presence.py +0 -0
  81. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/queue/race_poller.py +0 -0
  82. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/queue/shadow.py +0 -0
  83. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/__init__.py +0 -0
  84. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_catalog.py +0 -0
  85. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_feedback.py +0 -0
  86. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_jobs.py +0 -0
  87. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_moderation.py +0 -0
  88. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_playlists.py +0 -0
  89. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_promos.py +0 -0
  90. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_queue.py +0 -0
  91. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/admin_schedules.py +0 -0
  92. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/auth.py +0 -0
  93. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/catalog.py +0 -0
  94. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/feedback.py +0 -0
  95. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/pages.py +0 -0
  96. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/queue.py +0 -0
  97. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/routes/user.py +0 -0
  98. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/static/css/main.css +0 -0
  99. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/static/js/admin-playlists.js +0 -0
  100. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/static/js/admin-promos.js +0 -0
  101. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/static/js/admin-queue-mgmt.js +0 -0
  102. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/static/js/admin-schedules.js +0 -0
  103. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/static/js/admin.js +0 -0
  104. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/static/js/main.js +0 -0
  105. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/admin/index.html +0 -0
  106. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/admin/playlists.html +0 -0
  107. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/admin/promos.html +0 -0
  108. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/admin/queue_mgmt.html +0 -0
  109. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/admin/schedules.html +0 -0
  110. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/auth/login.html +0 -0
  111. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/base.html +0 -0
  112. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/catalog/browse.html +0 -0
  113. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/catalog/item_detail.html +0 -0
  114. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/catalog/item_not_found.html +0 -0
  115. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/feedback/index.html +0 -0
  116. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/queue/index.html +0 -0
  117. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/race.html +0 -0
  118. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/templates/user/dashboard.html +0 -0
  119. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/ws/__init__.py +0 -0
  120. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/ws/handler.py +0 -0
  121. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/kryten_webqueue/ws/manager.py +0 -0
  122. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/__init__.py +0 -0
  123. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_config_persistence.py +0 -0
  124. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_feedback.py +0 -0
  125. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_fetchurls_sharepoint.py +0 -0
  126. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_phase1.py +0 -0
  127. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_phase2_jobs.py +0 -0
  128. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_phase3_jobs.py +0 -0
  129. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_phase4_live_fixes.py +0 -0
  130. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_playlist_import.py +0 -0
  131. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_presence_refund.py +0 -0
  132. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_promo_director.py +0 -0
  133. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_promo_pool_exclusion.py +0 -0
  134. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_queue_announce.py +0 -0
  135. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_race_poller.py +0 -0
  136. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_recently_played_hide.py +0 -0
  137. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_save_results_to_playlist.py +0 -0
  138. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_schedule_lock.py +0 -0
  139. {kryten_webqueue-0.34.0 → kryten_webqueue-0.34.1}/tests/test_search_facets.py +0 -0
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.34.1] - 2026-08-12
4
+
5
+ ### Fixed
6
+
7
+ - `JobScheduler._register()`: bad cron expressions in the DB (e.g. hour=27)
8
+ are now logged at WARNING and skipped rather than raising `ValueError` during
9
+ startup and preventing the service from starting.
10
+ - `JobScheduler.upsert()`: validates the cron expression via APScheduler before
11
+ persisting; raises `ValueError` with a clear message so the API route can
12
+ return HTTP 400 instead of saving an unrunnable schedule.
13
+ - `/admin/job-schedules` POST and PUT: APScheduler validation errors now surface
14
+ as HTTP 400 with the rejection reason.
15
+
3
16
  ## [0.34.0] - 2026-08-11
4
17
 
5
18
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: kryten-webqueue
3
- Version: 0.34.0
3
+ Version: 0.34.1
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
@@ -57,21 +57,30 @@ class JobScheduler:
57
57
  )
58
58
  return False
59
59
  minute, hour, day, month, day_of_week = parts
60
- trigger = CronTrigger(
61
- minute=minute,
62
- hour=hour,
63
- day=day,
64
- month=month,
65
- day_of_week=day_of_week,
66
- timezone="UTC",
67
- )
68
- self._aps.add_job(
69
- self._fire,
70
- trigger=trigger,
71
- args=[job_name],
72
- id=f"jsch_{job_name}",
73
- replace_existing=True,
74
- )
60
+ try:
61
+ trigger = CronTrigger(
62
+ minute=minute,
63
+ hour=hour,
64
+ day=day,
65
+ month=month,
66
+ day_of_week=day_of_week,
67
+ timezone="UTC",
68
+ )
69
+ self._aps.add_job(
70
+ self._fire,
71
+ trigger=trigger,
72
+ args=[job_name],
73
+ id=f"jsch_{job_name}",
74
+ replace_existing=True,
75
+ )
76
+ except (ValueError, Exception) as exc: # noqa: BLE001 - bad stored cron must not crash startup
77
+ logger.warning(
78
+ "JobScheduler: skipping invalid cron %r for %r: %s",
79
+ cron_expression,
80
+ job_name,
81
+ exc,
82
+ )
83
+ return False
75
84
  logger.info("JobScheduler: registered %r cron=%r", job_name, cron_expression)
76
85
  return True
77
86
 
@@ -134,7 +143,26 @@ class JobScheduler:
134
143
  is_active: bool = True,
135
144
  created_by: str | None = None,
136
145
  ) -> None:
137
- """Persist a schedule and (re)register it with APScheduler."""
146
+ """Persist a schedule and (re)register it with APScheduler.
147
+
148
+ Raises ValueError if cron_expression is rejected by APScheduler.
149
+ """
150
+ # Validate before persisting so a bad expression is rejected at save time.
151
+ if is_active:
152
+ parts = (cron_expression or "").strip().split()
153
+ if len(parts) != 5:
154
+ raise ValueError(
155
+ f"cron_expression must have exactly 5 fields (min hour dom mon dow), got: {cron_expression!r}"
156
+ )
157
+ minute, hour, day, month, day_of_week = parts
158
+ try:
159
+ CronTrigger(
160
+ minute=minute, hour=hour, day=day,
161
+ month=month, day_of_week=day_of_week, timezone="UTC",
162
+ )
163
+ except Exception as exc:
164
+ raise ValueError(f"Invalid cron expression {cron_expression!r}: {exc}") from exc
165
+
138
166
  params_json = json.dumps(params) if params is not None else None
139
167
  await self._db.upsert_job_schedule(
140
168
  job_name,
@@ -40,15 +40,18 @@ async def upsert_job_schedule(request: Request, user: dict = Depends(require_adm
40
40
  raise HTTPException(400, "cron_expression must have exactly 5 fields (min hour dom mon dow)")
41
41
 
42
42
  job_scheduler = request.app.state.job_scheduler
43
- await job_scheduler.upsert(
44
- job_name,
45
- cron_expression,
46
- params=body.get("params") or None,
47
- label=body.get("label") or None,
48
- run_next_job=body.get("run_next_job") or None,
49
- is_active=bool(body.get("is_active", True)),
50
- created_by=user["username"],
51
- )
43
+ try:
44
+ await job_scheduler.upsert(
45
+ job_name,
46
+ cron_expression,
47
+ params=body.get("params") or None,
48
+ label=body.get("label") or None,
49
+ run_next_job=body.get("run_next_job") or None,
50
+ is_active=bool(body.get("is_active", True)),
51
+ created_by=user["username"],
52
+ )
53
+ except ValueError as exc:
54
+ raise HTTPException(400, str(exc))
52
55
  return {"success": True}
53
56
 
54
57
 
@@ -65,15 +68,18 @@ async def update_job_schedule(
65
68
  raise HTTPException(400, "cron_expression must have exactly 5 fields (min hour dom mon dow)")
66
69
 
67
70
  job_scheduler = request.app.state.job_scheduler
68
- await job_scheduler.upsert(
69
- job_name,
70
- cron_expression,
71
- params=body.get("params") or None,
72
- label=body.get("label") or None,
73
- run_next_job=body.get("run_next_job") or None,
74
- is_active=bool(body.get("is_active", True)),
75
- created_by=user["username"],
76
- )
71
+ try:
72
+ await job_scheduler.upsert(
73
+ job_name,
74
+ cron_expression,
75
+ params=body.get("params") or None,
76
+ label=body.get("label") or None,
77
+ run_next_job=body.get("run_next_job") or None,
78
+ is_active=bool(body.get("is_active", True)),
79
+ created_by=user["username"],
80
+ )
81
+ except ValueError as exc:
82
+ raise HTTPException(400, str(exc))
77
83
  return {"success": True}
78
84
 
79
85
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kryten-webqueue"
3
- version = "0.34.0"
3
+ version = "0.34.1"
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"