feat: 支持pornhub的playlist下载
This commit is contained in:
parent
424c9c6f3c
commit
f6a9e6a1dd
34
app/ytdl.py
34
app/ytdl.py
|
|
@ -422,14 +422,21 @@ class DownloadQueue:
|
||||||
log.debug('Processing as a playlist')
|
log.debug('Processing as a playlist')
|
||||||
entries = entry['entries']
|
entries = entry['entries']
|
||||||
log.info(f'playlist detected with {len(entries)} entries')
|
log.info(f'playlist detected with {len(entries)} entries')
|
||||||
|
|
||||||
playlist_index_digits = len(str(len(entries)))
|
playlist_index_digits = len(str(len(entries)))
|
||||||
results = []
|
results = []
|
||||||
if playlist_item_limit > 0:
|
if playlist_item_limit > 0:
|
||||||
log.info(f'Playlist item limit is set. Processing only first {playlist_item_limit} entries')
|
log.info(f'Playlist item limit is set. Processing only first {playlist_item_limit} entries')
|
||||||
entries = entries[:playlist_item_limit]
|
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):
|
for index, etr in enumerate(entries, start=1):
|
||||||
etr["_type"] = "video"
|
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)
|
etr["playlist_index"] = '{{0:0{0:d}d}}'.format(playlist_index_digits).format(index)
|
||||||
for property in ("id", "title", "uploader", "uploader_id"):
|
for property in ("id", "title", "uploader", "uploader_id"):
|
||||||
if property in entry:
|
if property in entry:
|
||||||
|
|
@ -440,9 +447,32 @@ class DownloadQueue:
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
elif etype == 'video' or (etype.startswith('url') and 'id' in entry and 'title' in entry):
|
elif etype == 'video' or (etype.startswith('url') and 'id' in entry and 'title' in entry):
|
||||||
log.debug('Processing as a video')
|
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']
|
key = entry.get('webpage_url') or entry['url']
|
||||||
if not self.queue.exists(key):
|
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)
|
await self.__add_download(dl, auto_start)
|
||||||
return {'status': 'ok'}
|
return {'status': 'ok'}
|
||||||
return {'status': 'error', 'msg': f'Unsupported resource "{etype}"'}
|
return {'status': 'error', 'msg': f'Unsupported resource "{etype}"'}
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue