The video side gets its OWN automations at music-side parity, kept separate so
nothing on the music side breaks. First twin: Scan Video Library — tells the media
server to rescan the user's SELECTED video sections (movies/TV, never music), then
reads the result into video.db so freshly-downloaded media shows as owned.
Architecture (scope tags + video twins on the shared engine):
- Handler core/automation/handlers/video_scan_library.py — pure function with
injected I/O (server_refresh / run_video_scan); production lazily binds
refresh_video_server_sections() + the video scanner. Owns its own progress.
Lives on the SHARED automation side so it may import core.video (isolation only
forbids core/video & api/video from importing music, not the reverse).
- blocks.py gains a 'scope' tag ('both' generic / 'video' video-only / absent=music)
+ blocks_for_scope(). The music /api/automations/blocks now filters out video
blocks; new isolated /api/video/automations/blocks serves the video palette.
- automation_engine seeds 'Scan Video Library' (owned_by='video', schedule 6h) so
it appears ONLY on the video Automations page; ensure_system_automations now
honours owned_by + action_config. Music page excludes owned_by='video' rows.
kettui: seam-level tests for every handler path (happy/no-server/scan-error/never-
raises/mode), scope filtering (music excludes video, video gets generics, music
parity preserved), seeding (owned_by + mode), registration drift guard. 39 new
tests; full automation suite (288) + isolation guards green.
28 lines
1 KiB
Python
28 lines
1 KiB
Python
"""Video automation builder support (isolated /api/video routes).
|
|
|
|
The automation ENGINE is app-wide (shared with the music side), but the
|
|
builder block palette is scoped: the video builder must only ever offer
|
|
video + generic blocks, never music-only ones. This endpoint returns that
|
|
scoped slice via ``core.automation.blocks.blocks_for_scope('video')``.
|
|
|
|
ISOLATION: imports only the shared automation block definitions (which
|
|
themselves import nothing music-specific) — no music API / music DB.
|
|
Reading/running/toggling video automations goes through the shared
|
|
``/api/automations`` endpoints (owned_by='video' rows); only the scoped
|
|
block palette lives here.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from flask import jsonify
|
|
|
|
from utils.logging_config import get_logger
|
|
|
|
logger = get_logger("video_api.automations")
|
|
|
|
|
|
def register_routes(bp):
|
|
@bp.route("/automations/blocks", methods=["GET"])
|
|
def video_automation_blocks():
|
|
from core.automation.blocks import blocks_for_scope
|
|
return jsonify(blocks_for_scope("video"))
|