diff --git a/apps/musicseerr/tasks.py b/apps/musicseerr/tasks.py index 97e3ab1..1e648a8 100644 --- a/apps/musicseerr/tasks.py +++ b/apps/musicseerr/tasks.py @@ -227,6 +227,31 @@ def send_telegram_notification(chat_id: int, text: str): logger.error(f"Failed to send Telegram notification: {e}") +def symlink_existing_tracks(temp_dir: str): + """ + Finds all MP3 files recursively in /remote-music/music and creates symlinks to them + in the temp_dir so spotDL and yt-dlp skip downloading duplicates. + """ + remote_base = "/remote-music/music" + if not os.path.isdir(remote_base): + return + + logger.info(f"Scanning {remote_base} to symlink existing tracks in {temp_dir}...") + count = 0 + for root, dirs, files in os.walk(remote_base): + for file in files: + if file.endswith(".mp3"): + src_path = os.path.join(root, file) + dest_path = os.path.join(temp_dir, file) + if not os.path.exists(dest_path): + try: + os.symlink(src_path, dest_path) + count += 1 + except Exception as e: + logger.warning(f"Failed to create symlink for {file}: {e}") + logger.info(f"Created {count} symlinks for existing tracks.") + + def run_download_task(task_id: str, query: str, proxy_url: str, jobs_dict: dict, chat_id: int = None): """ Core download manager task that runs in the background. @@ -235,6 +260,7 @@ def run_download_task(task_id: str, query: str, proxy_url: str, jobs_dict: dict, temp_dir = f"/tmp/downloads/{task_id}" os.makedirs(temp_dir, exist_ok=True) + symlink_existing_tracks(temp_dir) # Resolve proxy hostname to IP address for spotDL compatibility (spotDL requires IP in proxy URL) resolved_proxy_url = proxy_url @@ -389,17 +415,27 @@ def run_download_task(task_id: str, query: str, proxy_url: str, jobs_dict: dict, # Verify files and move to /remote-music/music downloaded_files = os.listdir(temp_dir) - if not downloaded_files: - raise Exception("Ingestion finished but no files were found in local temp folder.") + actual_files = [f for f in downloaded_files if not os.path.islink(os.path.join(temp_dir, f))] + + if not actual_files: + if downloaded_files: + logger.info(f"[{task_id}] All tracks in this query were already downloaded (skipped duplicates).") + jobs_dict[task_id]["files"] = [] + jobs_dict[task_id]["status"] = "completed" + if chat_id: + send_telegram_notification(chat_id, f"✅ Successfully ingested request: '{query}'\n\n(All tracks already existed - skipped duplicates)") + return + else: + raise Exception("Ingestion finished but no files were found in local temp folder.") os.makedirs("/remote-music/music", exist_ok=True) moved_files = [] - for file_name in downloaded_files: + for file_name in actual_files: src_file = os.path.join(temp_dir, file_name) dest_file = os.path.join("/remote-music/music", file_name) - logger.info(f"[{task_id}] Moving '{file_name}' to remote Seedbox directory") + logger.info(f"[{task_id}] Moving new file '{file_name}' to remote Seedbox directory") shutil.move(src_file, dest_file) moved_files.append(file_name)