feat: add downloader module with yt-dlp integration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
synapz-org
2025-10-26 09:40:11 -04:00
parent 21b3dfd8b2
commit 0a6a2ffd71
2 changed files with 73 additions and 0 deletions

46
src/downloader.py Normal file
View File

@@ -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')

27
tests/test_downloader.py Normal file
View File

@@ -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