feat: add CLI main module with Click integration

Implemented the CLI entry point using Click framework. The CLI:
- Accepts Space URL as an argument
- Supports --cookies and --output options
- Validates URLs using the validator module
- Downloads Spaces using the downloader module
- Provides clear success and error messages
- Uses proper exit codes (0=success, 1=validation error, 2=download error)

Test uses Click's CliRunner to test CLI without running actual downloads.
Mocks validate_space_url and download_space functions for isolated testing.

🤖 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:47:35 -04:00
parent 5eec3129bc
commit b74cc323d1
2 changed files with 56 additions and 0 deletions

35
src/main.py Normal file
View File

@@ -0,0 +1,35 @@
import click
import os
from src.validator import validate_space_url
from src.downloader import download_space, DownloadError
@click.command()
@click.argument('url')
@click.option('--cookies', '-c', type=click.Path(exists=True), help='Path to cookies file')
@click.option('--output', '-o', type=click.Path(), default='.', help='Output directory')
def cli(url, cookies, output):
"""
Download X (Twitter) Space recordings as MP3 files.
Example:
x-space-dl https://x.com/i/spaces/1ZkKzZWnVRRKv
"""
# Validate URL
is_valid, space_id, error = validate_space_url(url)
if not is_valid:
click.echo(f"Error: {error}", err=True)
raise click.Exit(1)
# Download the Space
try:
click.echo(f"Downloading Space: {space_id}")
output_path = download_space(url, output, cookies)
click.echo(f"Successfully downloaded to: {output_path}")
except DownloadError as e:
click.echo(f"Error: {str(e)}", err=True)
raise click.Exit(2)
if __name__ == '__main__':
cli()

21
tests/test_main.py Normal file
View File

@@ -0,0 +1,21 @@
import pytest
from click.testing import CliRunner
from unittest.mock import patch, Mock
from src.main import cli
def test_cli_valid_url(tmp_path):
"""Test CLI with valid URL."""
runner = CliRunner()
with patch('src.main.validate_space_url') as mock_validate, \
patch('src.main.download_space') as mock_download:
mock_validate.return_value = (True, "1ZkKzZWnVRRKv", None)
mock_download.return_value = str(tmp_path / "space_1ZkKzZWnVRRKv.mp3")
result = runner.invoke(cli, ['https://x.com/i/spaces/1ZkKzZWnVRRKv'])
assert result.exit_code == 0
assert "Successfully downloaded" in result.output
assert "space_1ZkKzZWnVRRKv.mp3" in result.output