From f6a9e6a1dd1bb60ad1799ee21a91985c02a2b303 Mon Sep 17 00:00:00 2001 From: tigeren Date: Sun, 16 Nov 2025 03:31:54 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81pornhub=E7=9A=84playl?= =?UTF-8?q?ist=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/ytdl.py | 34 ++++++++++++++++++++++++++++++++-- pyrightconfig.json | 19 ++++++++++++++++++- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/app/ytdl.py b/app/ytdl.py index f543d17..b1b1720 100644 --- a/app/ytdl.py +++ b/app/ytdl.py @@ -422,14 +422,21 @@ class DownloadQueue: log.debug('Processing as a playlist') entries = entry['entries'] log.info(f'playlist detected with {len(entries)} entries') + playlist_index_digits = len(str(len(entries))) results = [] if playlist_item_limit > 0: log.info(f'Playlist item limit is set. Processing only first {playlist_item_limit} entries') entries = entries[:playlist_item_limit] + + # Verify playlist entry has 'id' before using it + playlist_id = entry.get("id", "unknown_playlist") + if "id" not in entry: + log.warning(f"Playlist entry missing 'id' field. Using fallback 'unknown_playlist'. Entry keys: {list(entry.keys())}") + for index, etr in enumerate(entries, start=1): etr["_type"] = "video" - etr["playlist"] = entry["id"] + etr["playlist"] = playlist_id etr["playlist_index"] = '{{0:0{0:d}d}}'.format(playlist_index_digits).format(index) for property in ("id", "title", "uploader", "uploader_id"): if property in entry: @@ -440,9 +447,32 @@ class DownloadQueue: return {'status': 'ok'} elif etype == 'video' or (etype.startswith('url') and 'id' in entry and 'title' in entry): log.debug('Processing as a video') + + # Extract ID from entry, or derive from URL if missing + video_id = entry.get('id') + if not video_id: + # Try to extract ID from URL (e.g., viewkey parameter or URL path) + video_url = entry.get('url', '') + if 'viewkey=' in video_url: + # Extract viewkey parameter (common in PornHub, etc.) + match = re.search(r'viewkey=([^&]+)', video_url) + if match: + video_id = match.group(1) + log.info(f"Extracted video ID from viewkey: {video_id}") + elif 'webpage_url' in entry: + # Use webpage_url as fallback + video_id = entry['webpage_url'] + else: + # Last resort: use the URL itself + video_id = video_url + + if not video_id: + log.error(f"Video entry missing 'id' field and could not extract from URL. Entry keys: {list(entry.keys())}") + return {'status': 'error', 'msg': "Video entry missing required 'id' field and URL extraction failed"} + key = entry.get('webpage_url') or entry['url'] if not self.queue.exists(key): - dl = DownloadInfo(entry['id'], entry.get('title') or entry['id'], key, quality, format, folder, custom_name_prefix, error, entry, playlist_item_limit) + dl = DownloadInfo(video_id, entry.get('title') or video_id, key, quality, format, folder, custom_name_prefix, error, entry, playlist_item_limit) await self.__add_download(dl, auto_start) return {'status': 'ok'} return {'status': 'error', 'msg': f'Unsupported resource "{etype}"'} diff --git a/pyrightconfig.json b/pyrightconfig.json index 544b7b4..f60f560 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -1,3 +1,20 @@ { - + "venvPath": ".", + "venv": ".venv", + "pythonVersion": "3.13", + "include": ["app"], + "executionEnvironments": [ + { + "root": ".", + "pythonVersion": "3.13", + "extraPaths": [".", "app"] + } + ], + "typeCheckingMode": "basic", + "reportMissingImports": "warning", + "reportOptionalMemberAccess": "warning", + "reportOptionalContextManager": "warning", + "reportAttributeAccessIssue": "warning", + "reportArgumentType": "warning", + "reportCallIssue": "warning" } \ No newline at end of file