From 0a6a2ffd7149d92aaa3fb23d836e5cd17d1cc88e Mon Sep 17 00:00:00 2001 From: synapz-org Date: Sun, 26 Oct 2025 09:40:11 -0400 Subject: [PATCH] feat: add downloader module with yt-dlp integration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- src/downloader.py | 46 ++++++++++++++++++++++++++++++++++++++++ tests/test_downloader.py | 27 +++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/downloader.py create mode 100644 tests/test_downloader.py diff --git a/src/downloader.py b/src/downloader.py new file mode 100644 index 0000000..518952f --- /dev/null +++ b/src/downloader.py @@ -0,0 +1,46 @@ +import os +import yt_dlp +from typing import Optional + + +def download_space( + space_url: str, + output_dir: str, + cookies_file: Optional[str] = None +) -> str: + """ + Downloads X Space recording using yt-dlp. + + Args: + space_url: URL of the X Space recording + output_dir: Directory to save the MP3 file + cookies_file: Optional path to cookies file for authentication + + Returns: + Path to the downloaded MP3 file + """ + # Extract space ID from URL for filename + space_id = space_url.split('/')[-1] + + # Configure yt-dlp options + ydl_opts = { + 'format': 'bestaudio/best', + 'outtmpl': os.path.join(output_dir, f'space_{space_id}.%(ext)s'), + 'postprocessors': [{ + 'key': 'FFmpegExtractAudio', + 'preferredcodec': 'mp3', + }], + 'quiet': False, + 'no_warnings': False, + } + + # Add cookies if provided + if cookies_file: + ydl_opts['cookiefile'] = cookies_file + + # Download with yt-dlp + with yt_dlp.YoutubeDL(ydl_opts) as ydl: + ydl.extract_info(space_url, download=True) + + # Return the expected output path + return os.path.join(output_dir, f'space_{space_id}.mp3') diff --git a/tests/test_downloader.py b/tests/test_downloader.py new file mode 100644 index 0000000..d960cda --- /dev/null +++ b/tests/test_downloader.py @@ -0,0 +1,27 @@ +import pytest +from unittest.mock import Mock, patch +from src.downloader import download_space + + +def test_download_space_basic(tmp_path): + """Test basic download functionality.""" + space_url = "https://x.com/i/spaces/1ZkKzZWnVRRKv" + + with patch('src.downloader.yt_dlp.YoutubeDL') as mock_ytdl_class: + # Mock the YoutubeDL instance + mock_ytdl = Mock() + mock_ytdl_class.return_value.__enter__.return_value = mock_ytdl + mock_ytdl.extract_info.return_value = {'id': '1ZkKzZWnVRRKv'} + + # Call download_space + result = download_space( + space_url=space_url, + output_dir=str(tmp_path), + cookies_file=None + ) + + # Verify YoutubeDL was called + mock_ytdl.extract_info.assert_called_once_with(space_url, download=True) + + # Verify result contains expected filename + assert "space_1ZkKzZWnVRRKv" in result