feat: Add series TV support with Vidzy HLS downloads and duplicate prevention
Major improvements: - Series TV support via FS7 provider with dedicated search endpoint - Vidzy downloader now uses Playwright for JS obfuscation and ffmpeg for HLS streams - Episode filenames properly named (Series Title - Episode X) instead of master.m3u8.mp4 - Duplicate download prevention: checks existing tasks before creating new ones - Removed host preference system in favor of intelligent URL-based detection Technical changes: - Vidzy: Added Playwright extraction and M3U8→MP4 conversion with ffmpeg - FS7: Episodes now use pipe format (video_url|series_url|episode_title) - DownloadManager: Extract target_filename from pipe URL and prevent duplicates - UI: New Series tab with search, recommendations, and releases sections - Anime-Sama: Removed hardcoded host preferences, uses site's URL order Generated with [Claude Code](https://claude.com/claude-code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
+30
-1
@@ -30,6 +30,25 @@ class DownloadManager:
|
||||
return list(self.tasks.values())
|
||||
|
||||
def create_task(self, request: DownloadRequest) -> DownloadTask:
|
||||
# Check for existing tasks with the same URL
|
||||
# Extract actual URL from pipe-separated format
|
||||
url_to_check = request.url.split('|')[0] if '|' in request.url else request.url
|
||||
|
||||
# Look for existing non-failed tasks with the same URL
|
||||
for existing_task in self.tasks.values():
|
||||
existing_url = existing_task.url.split('|')[0] if '|' in existing_task.url else existing_task.url
|
||||
|
||||
# If same URL and task is not failed/cancelled/completed
|
||||
if existing_url == url_to_check and existing_task.status not in [
|
||||
DownloadStatus.FAILED,
|
||||
DownloadStatus.CANCELLED,
|
||||
DownloadStatus.COMPLETED
|
||||
]:
|
||||
logger.info(f"Duplicate download detected: {url_to_check[:80]}...")
|
||||
logger.info(f"Returning existing task: {existing_task.id}")
|
||||
return existing_task
|
||||
|
||||
# No duplicate found, create new task
|
||||
task_id = str(uuid.uuid4())
|
||||
task = DownloadTask(
|
||||
id=task_id,
|
||||
@@ -103,7 +122,17 @@ class DownloadManager:
|
||||
|
||||
# Get downloader and extract link
|
||||
downloader = get_downloader(task.url)
|
||||
download_url, filename = await downloader.get_download_link(task.url)
|
||||
|
||||
# Extract episode title from pipe-separated URL if present
|
||||
# Format: video_url|anime_page_url|episode_title
|
||||
target_filename = None
|
||||
if '|' in task.url:
|
||||
parts = task.url.split('|')
|
||||
if len(parts) >= 3:
|
||||
target_filename = parts[2].strip()
|
||||
logger.debug(f"Extracted target filename from pipe: {target_filename}")
|
||||
|
||||
download_url, filename = await downloader.get_download_link(task.url, target_filename)
|
||||
|
||||
logger.info(f"Download URL: {download_url[:100] if len(download_url) > 100 else download_url}")
|
||||
logger.debug(f"Downloader filename: {filename}")
|
||||
|
||||
Reference in New Issue
Block a user