Files
LXC-Dispatcharr-modificado-…/apps/vod/catalog_settings.py
T
root f56b088643
Base Image Build / prepare (push) Has been cancelled
Build and Push Multi-Arch Docker Image / build-and-push (push) Has been cancelled
Frontend Tests / test (push) Has been cancelled
Base Image Build / docker (amd64, ubuntu-24.04) (push) Has been cancelled
Base Image Build / docker (arm64, ubuntu-24.04-arm) (push) Has been cancelled
Base Image Build / create-manifest (push) Has been cancelled
Proyecto LCX Dispatcharr multicuenta
2026-05-09 21:24:50 +02:00

150 lines
4.9 KiB
Python

"""VOD catalog: optional single M3U account for library listings (env DISPATCHARR_VOD_CATALOG_ACCOUNT_ID).
Plus per-user playback / catalog policies stored in User.custom_properties:
custom_properties = {
"vod_playback_mode": "strict" | "prefer" | "auto",
"vod_playback_account_ids": [10, 11],
"allowed_movie_category_ids": [3, 7, 12], # empty/missing = all
"allowed_series_category_ids": [4, 9], # empty/missing = all
}
"""
import os
def get_vod_catalog_account_id():
raw = (os.environ.get("DISPATCHARR_VOD_CATALOG_ACCOUNT_ID") or "").strip()
if raw.isdigit():
return int(raw)
return None
def get_vod_playback_allowed_account_ids():
"""
Optional comma-separated M3U account IDs used only for VOD stream selection (failover).
Example: DISPATCHARR_VOD_PLAYBACK_ACCOUNT_IDS=10,11,12
When unset, any active M3U account with a relation may be used (default).
"""
raw = (os.environ.get("DISPATCHARR_VOD_PLAYBACK_ACCOUNT_IDS") or "").strip()
if not raw:
return None
out = []
for part in raw.split(","):
part = part.strip()
if part.isdigit():
out.append(int(part))
return out if out else None
def filter_m3u_relation_queryset_for_playback(qs):
"""
Apply DISPATCHARR_VOD_PLAYBACK_ACCOUNT_IDS allowlist to an M3U relation queryset.
Used by VOD proxy and Xtream stream redirects so failover matches playback policy.
"""
allowed = get_vod_playback_allowed_account_ids()
if allowed is not None:
return qs.filter(m3u_account_id__in=allowed, m3u_account__is_active=True)
return qs.filter(m3u_account__is_active=True)
def _coerce_int_list(raw):
out = []
if not raw:
return out
if isinstance(raw, (list, tuple)):
items = raw
elif isinstance(raw, str):
items = raw.split(",")
else:
return out
for x in items:
try:
out.append(int(str(x).strip()))
except (TypeError, ValueError):
continue
return out
def get_user_vod_prefs(user):
"""Return a normalized dict of per-user VOD policies. Safe with None / anonymous user."""
if not user or not getattr(user, "is_authenticated", False):
return {
"playback_mode": "auto",
"playback_account_ids": [],
"allowed_movie_category_ids": None,
"allowed_series_category_ids": None,
}
cp = getattr(user, "custom_properties", None) or {}
accounts = _coerce_int_list(cp.get("vod_playback_account_ids"))
mode = (cp.get("vod_playback_mode") or "").strip().lower()
if mode not in ("strict", "prefer", "auto"):
mode = "auto"
movie_cats = _coerce_int_list(cp.get("allowed_movie_category_ids"))
series_cats = _coerce_int_list(cp.get("allowed_series_category_ids"))
return {
"playback_mode": mode,
"playback_account_ids": accounts,
"allowed_movie_category_ids": movie_cats or None,
"allowed_series_category_ids": series_cats or None,
}
def filter_relation_qs_for_user_playback(qs, user):
"""Restrict a relation queryset based on the user's playback prefs.
Returns (queryset, prefer_account_id).
- mode=strict: only the user's accounts (queryset further restricted).
- mode=prefer: queryset unchanged, returns the first account as preference for tie-breaking.
- mode=auto (or no accounts): no per-user filter; the global allowlist already applies upstream.
"""
prefs = get_user_vod_prefs(user)
accounts = prefs.get("playback_account_ids") or []
mode = prefs.get("playback_mode") or "auto"
if accounts and mode == "strict":
qs = qs.filter(m3u_account_id__in=accounts)
prefer = accounts[0]
elif accounts and mode == "prefer":
prefer = accounts[0]
else:
prefer = None
return qs, prefer
def get_user_allowed_movie_category_ids(user):
return get_user_vod_prefs(user).get("allowed_movie_category_ids")
def get_user_allowed_series_category_ids(user):
return get_user_vod_prefs(user).get("allowed_series_category_ids")
def filter_movie_qs_for_user(qs, user):
"""Restrict a Movie queryset to only categories the user is allowed to see."""
cats = get_user_allowed_movie_category_ids(user)
if cats:
return qs.filter(m3u_relations__category_id__in=cats).distinct()
return qs
def filter_series_qs_for_user(qs, user):
"""Restrict a Series queryset to only categories the user is allowed to see."""
cats = get_user_allowed_series_category_ids(user)
if cats:
return qs.filter(m3u_relations__category_id__in=cats).distinct()
return qs
def filter_m3u_movie_relation_qs_for_user(qs, user):
cats = get_user_allowed_movie_category_ids(user)
if cats:
return qs.filter(category_id__in=cats)
return qs
def filter_m3u_series_relation_qs_for_user(qs, user):
cats = get_user_allowed_series_category_ids(user)
if cats:
return qs.filter(category_id__in=cats)
return qs