mirror of
https://github.com/nirvana-7777/script.service.ultimate.git
synced 2026-10-07 00:12:29 +02:00
Merge pull request #15 from mltobi/fix-delete-recording-magenta2
merci!
This commit is contained in:
@@ -1 +1,3 @@
|
||||
.aider*
|
||||
*.pyc
|
||||
__pycache__/
|
||||
@@ -43,9 +43,10 @@ def generate_qr_code_png(data: str, size: int = 512) -> Optional[bytes]:
|
||||
# Generate image using pure Python PNG backend
|
||||
img = qr.make_image(image_factory=PyPNGImage, fill_color="black", back_color="white")
|
||||
|
||||
# Convert to PNG bytes
|
||||
# Convert to PNG bytes. PyPNGImage.save() always writes PNG and does
|
||||
# not accept a `format` kwarg (unlike PIL), so it must be omitted here.
|
||||
buffer = io.BytesIO()
|
||||
img.save(buffer, format="PNG")
|
||||
img.save(buffer)
|
||||
png_data = buffer.getvalue()
|
||||
|
||||
return png_data
|
||||
|
||||
@@ -373,6 +373,10 @@ VOD_PREFIX_MOVIE_SH = "GN_SH"
|
||||
PVR_GET_RECORDINGS_PATH = "/get-recordings"
|
||||
PVR_RECORDINGS_PATH = "/recordings"
|
||||
|
||||
# recordings are deleted with HTTP DELETE on this listing-GUID-based path (returns 202 Accepted),
|
||||
# NOT via DELETE /recordings/{id} (which 404s for every identifier).
|
||||
PVR_DELETE_RECORDING_FOR_LISTING_PATH = "/delete-recording-for-listing"
|
||||
|
||||
# Default and maximum page sizes for the nPVR get-recordings endpoint
|
||||
PVR_DEFAULT_PAGE_LIMIT = 500
|
||||
PVR_MAX_PAGE_LIMIT = 500
|
||||
|
||||
@@ -44,6 +44,7 @@ from ...base.utils.logger import logger
|
||||
|
||||
from .constants import (
|
||||
PVR_DEFAULT_PAGE_LIMIT,
|
||||
PVR_DELETE_RECORDING_FOR_LISTING_PATH,
|
||||
PVR_GET_RECORDINGS_PATH,
|
||||
PVR_MAX_PAGE_LIMIT,
|
||||
PVR_RECORDINGS_PATH,
|
||||
@@ -144,23 +145,69 @@ class RecordingsManager(PvrHttpMixin):
|
||||
"""
|
||||
Permanently delete a recording on the nPVR backend.
|
||||
|
||||
The recording_id received from the PVR client is the MPX playback GUID
|
||||
(content_id). Deletion is performed with HTTP DELETE on
|
||||
``/delete-recording-for-listing/{listingGuid}`` (confirmed to return
|
||||
202 Accepted) - the documented ``/recordings/{id}`` path 404s for every
|
||||
known identifier.
|
||||
|
||||
Args:
|
||||
recording_id: The recording's ``id`` field (not externalRecordingId).
|
||||
recording_id: The recording's content_id (MPX GUID).
|
||||
|
||||
Raises:
|
||||
RuntimeError: When the API returns a non-200/204 status or the
|
||||
``auth_headers_callback`` is not configured.
|
||||
KeyError: When the recording does not exist (404).
|
||||
RuntimeError: When the recording cannot be resolved or the API
|
||||
returns a non-success status.
|
||||
"""
|
||||
pvr_base_url = self._get_pvr_base_url()
|
||||
url = f"{pvr_base_url}{PVR_RECORDINGS_PATH}/{recording_id}"
|
||||
|
||||
listing_guid = self._resolve_listing_guid(recording_id)
|
||||
if not listing_guid:
|
||||
raise RuntimeError(
|
||||
f"{self._provider}: cannot delete recording '{recording_id}' - "
|
||||
"no matching listing GUID found"
|
||||
)
|
||||
|
||||
url = f"{pvr_base_url}{PVR_DELETE_RECORDING_FOR_LISTING_PATH}/{listing_guid}"
|
||||
status_code = self._delete(url)
|
||||
logger.info(
|
||||
f"{self._provider}: Deleted recording '{recording_id}' "
|
||||
f"[HTTP {status_code}]"
|
||||
f"(listing '{listing_guid}') [HTTP {status_code}]"
|
||||
)
|
||||
|
||||
def _resolve_listing_guid(self, recording_id: str) -> str:
|
||||
"""
|
||||
Resolve the listing GUID for the recording the PVR client refers to.
|
||||
|
||||
The client sends content_id (MPX playback GUID); the delete endpoint
|
||||
needs the recording's ``listing.guid``. Fetch the raw recordings and
|
||||
match on the playback GUID (or the internal/external recording ids).
|
||||
"""
|
||||
try:
|
||||
pvr_base_url = self._get_pvr_base_url()
|
||||
url = f"{pvr_base_url}{PVR_GET_RECORDINGS_PATH}"
|
||||
params = {
|
||||
"limit": PVR_MAX_PAGE_LIMIT,
|
||||
"offset": 1,
|
||||
"byRecordingStatus": "|".join(PVR_RECORDING_STATUSES_ALL),
|
||||
}
|
||||
data = self._get(url, params) or {}
|
||||
for raw in data.get("recordings", []):
|
||||
if not raw:
|
||||
continue
|
||||
internal_id = raw.get("id", "")
|
||||
external_id = raw.get("externalRecordingId", "")
|
||||
mpx_guid = PvrHelpers.extract_mpx_guid(raw.get("playbackUrl"))
|
||||
if recording_id in (internal_id, external_id, mpx_guid):
|
||||
listing = raw.get("listing") or {}
|
||||
if isinstance(listing, dict):
|
||||
return listing.get("guid") or ""
|
||||
except Exception as exc:
|
||||
logger.warning(
|
||||
f"{self._provider}: could not resolve listing guid for "
|
||||
f"'{recording_id}': {exc}"
|
||||
)
|
||||
return ""
|
||||
|
||||
def get_recording_manifest(self, recording_id: str) -> Optional[str]:
|
||||
"""
|
||||
Return the playback URL for a recording.
|
||||
@@ -320,7 +367,6 @@ class RecordingsManager(PvrHttpMixin):
|
||||
content_id=effective_content_id,
|
||||
name=title,
|
||||
provider=self._provider,
|
||||
# descriptions
|
||||
description=description,
|
||||
plot=plot,
|
||||
plot_outline=plot_outline,
|
||||
|
||||
@@ -14,7 +14,7 @@ from urllib.parse import parse_qs, unquote, urlparse
|
||||
from ...base.network import HTTPManager
|
||||
from ...base.ui import NotificationFactory, NotificationInterface, NotificationResult
|
||||
from ...base.utils.logger import logger
|
||||
from .constants import DEFAULT_PLATFORM, DEFAULT_REQUEST_TIMEOUT, GRANT_TYPES, MAGENTA2_PLATFORMS
|
||||
from .constants import DEFAULT_PLATFORM, DEFAULT_REQUEST_TIMEOUT, GRANT_TYPES, MAGENTA2_PLATFORMS, render_user_agent
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -73,7 +73,9 @@ class RemoteLoginHandler:
|
||||
|
||||
# FIX: Get platform config correctly
|
||||
self.platform_config = MAGENTA2_PLATFORMS[DEFAULT_PLATFORM]
|
||||
self.user_agent = self.platform_config["user_agent"]
|
||||
# The platform config has no static "user_agent" key - the UA is
|
||||
# rendered from the platform's templates via render_user_agent().
|
||||
self.user_agent = render_user_agent(DEFAULT_PLATFORM)
|
||||
|
||||
# Get or create notifier with http_manager
|
||||
if notifier:
|
||||
|
||||
@@ -17,6 +17,12 @@ requests~=2.32.5
|
||||
Unidecode~=1.3.7
|
||||
PyYAML~=6.0.3
|
||||
|
||||
# QR-code login (magenta2 SAM3 remote login). pypng provides qrcode's pure
|
||||
# Python PNG backend so no Pillow/system image libs are required in the
|
||||
# standalone/Docker runtime.
|
||||
qrcode>=7.4
|
||||
pypng>=0.0.21
|
||||
|
||||
# Optional but recommended
|
||||
aiohttp>=3.8.5
|
||||
cryptography>=41.0.4
|
||||
|
||||
Reference in New Issue
Block a user