b3b167c075
New service types: - backups: BackupsConfig(ingestion_label), no secrets, summary widget kind. Modeled as a service so it can be named/multi-instanced like others. - authentik: AuthentikConfig(base_url, timeout_seconds), api_token secret (required). Directory source for the upcoming Users tab. Jellyseerr absorption: - JellyfinConfig gains optional jellyseerr_url + jellyseerr_api_key fields. - integrations/jellyseerr.py deleted; registry entry removed. - clients/jellyseerr.py stays (JellyseerrClient still used by enrichment). - One-time idempotent migration in settings_store.ensure_defaults(): jellyseerr service rows merge into a paired Jellyfin (exactly-one merges; multiple picks first unpaired; none/all-paired drops with a logged warning). The api_key is decrypted from secrets before moving to config. Registry is now 8 types: alertmanager, authentik, backups, grafana, jellyfin, nextcloud, prometheus, ssh_tasks. Tests: registry count updated to 8, jellyseerr-absent assertion, new-type definition assertions, and migration tests (single-jellyfin merge, no- jellyfin drop, idempotency). 256 backend tests pass; ruff clean. Refs openspec/changes/services-as-hub-ia/ (spec R6, tasks slice 1).
58 lines
1.5 KiB
Python
58 lines
1.5 KiB
Python
"""Jellyfin service definition."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from media_library_viewer_api.integrations.base import (
|
|
SecretField,
|
|
ServiceBaseUrl,
|
|
ServiceConfigBase,
|
|
ServiceDefinition,
|
|
WidgetConfigBase,
|
|
widget_kind,
|
|
)
|
|
|
|
|
|
class JellyfinConfig(ServiceConfigBase):
|
|
"""Non-secret Jellyfin connection config.
|
|
|
|
The optional ``jellyseerr_url`` / ``jellyseerr_api_key`` fields carry the
|
|
paired Jellyseerr companion config, absorbed from the former standalone
|
|
``jellyseerr`` service type (see OpenSpec change ``services-as-hub-ia``).
|
|
When both are set, the Jellyfin service page renders a Requests tab backed
|
|
by Jellyseerr.
|
|
"""
|
|
|
|
base_url: ServiceBaseUrl
|
|
user_id: str = ""
|
|
timeout_seconds: int = 10
|
|
jellyseerr_url: str = ""
|
|
jellyseerr_api_key: str = ""
|
|
|
|
|
|
class JellyfinActivityWidgetConfig(WidgetConfigBase):
|
|
"""Live Jellyfin session activity."""
|
|
|
|
# No user-overridable fields; the service record carries user_id.
|
|
pass
|
|
|
|
|
|
DEFINITION = ServiceDefinition(
|
|
service_type="jellyfin",
|
|
name="Jellyfin",
|
|
description="Media server with live session activity.",
|
|
config_model=JellyfinConfig,
|
|
secret_fields=[
|
|
SecretField(key="api_key", label="API key", required=True),
|
|
],
|
|
widget_kinds=[
|
|
widget_kind(
|
|
kind="activity",
|
|
name="Activity",
|
|
description="Live sessions and idle users.",
|
|
model_cls=JellyfinActivityWidgetConfig,
|
|
default_config={},
|
|
refresh_interval_ms=30_000,
|
|
),
|
|
],
|
|
)
|