mirror of
https://github.com/Dasemu/x-space-downloader.git
synced 2026-10-13 13:39:45 +00:00
189 lines
5.3 KiB
Markdown
189 lines
5.3 KiB
Markdown
# X Space Downloader - Design Document
|
|
|
|
**Date:** 2025-10-26
|
|
**Status:** Approved
|
|
|
|
## Overview
|
|
|
|
A Python CLI tool that downloads X (Twitter) Space recordings and outputs them as MP3 files. Takes a Space URL as input and produces an audio file.
|
|
|
|
## Requirements
|
|
|
|
- **Input:** X Space recording URL (e.g., `https://x.com/i/spaces/1ZkKzZWnVRRKv`)
|
|
- **Output:** MP3 audio file
|
|
- **Interface:** Command-line tool
|
|
- **Authentication:** Supports X account credentials via cookies
|
|
- **Scope:** Recordings only (not live Spaces)
|
|
- **Error Handling:** Clear error messages for invalid or non-recording URLs
|
|
|
|
## Architecture Overview
|
|
|
|
### Technology Choices
|
|
|
|
- **Language:** Python
|
|
- **Core Engine:** yt-dlp (handles X authentication and media extraction)
|
|
- **CLI Framework:** Click (argument parsing and user interface)
|
|
- **Pattern:** Thin wrapper around yt-dlp
|
|
|
|
### Project Structure
|
|
|
|
```
|
|
x-space-downloader/
|
|
├── src/
|
|
│ ├── __init__.py
|
|
│ ├── main.py # CLI entry point with argument parsing
|
|
│ ├── downloader.py # Wraps yt-dlp functionality
|
|
│ └── validator.py # URL validation and error handling
|
|
├── tests/
|
|
│ ├── test_validator.py
|
|
│ └── test_downloader.py
|
|
├── requirements.txt # Dependencies: yt-dlp, click
|
|
├── setup.py # Makes it installable
|
|
└── README.md
|
|
```
|
|
|
|
### User Workflow
|
|
|
|
```bash
|
|
x-space-dl --cookies cookies.txt https://x.com/i/spaces/1ZkKzZWnVRRKv
|
|
# Output: space_1ZkKzZWnVRRKv.mp3
|
|
```
|
|
|
|
## Component Design
|
|
|
|
### validator.py
|
|
|
|
**Responsibilities:**
|
|
- Validate URL format (must match X Spaces pattern: `https://x.com/i/spaces/{SPACE_ID}`)
|
|
- Check if URL points to a recording vs live Space
|
|
- Return clear error messages for invalid inputs
|
|
|
|
**Key Interface:**
|
|
```python
|
|
def validate_space_url(url: str) -> Tuple[bool, Optional[str], Optional[str]]:
|
|
"""
|
|
Validates X Space URL.
|
|
|
|
Returns:
|
|
(is_valid, space_id, error_message)
|
|
"""
|
|
```
|
|
|
|
### downloader.py
|
|
|
|
**Responsibilities:**
|
|
- Configure yt-dlp options (format: mp3, quality, output template)
|
|
- Pass cookie file to yt-dlp for authentication
|
|
- Translate yt-dlp output/errors to user-friendly messages
|
|
- Show download progress
|
|
|
|
**Key Interface:**
|
|
```python
|
|
def download_space(
|
|
space_url: str,
|
|
output_dir: str,
|
|
cookies_file: Optional[str]
|
|
) -> str:
|
|
"""
|
|
Downloads Space recording using yt-dlp.
|
|
|
|
Returns:
|
|
Path to downloaded MP3 file
|
|
"""
|
|
```
|
|
|
|
**yt-dlp Configuration:**
|
|
- Output format: mp3 (audio only)
|
|
- Output template: `space_{space_id}.mp3`
|
|
- Post-processing: convert to mp3 if needed
|
|
- Progress hooks for user feedback
|
|
|
|
### main.py
|
|
|
|
**Responsibilities:**
|
|
- CLI argument parsing with Click
|
|
- Orchestrate validation → download flow
|
|
- Handle and display errors appropriately
|
|
- Exit with appropriate status codes
|
|
|
|
**CLI Arguments:**
|
|
- `URL` (required): X Space URL
|
|
- `--cookies` (optional): Path to cookies file
|
|
- `--output` (optional): Output directory (default: current directory)
|
|
|
|
**Exit Codes:**
|
|
- `0`: Success
|
|
- `1`: Invalid URL
|
|
- `2`: Download failed
|
|
- `3`: Authentication required
|
|
|
|
## Data Flow
|
|
|
|
1. User provides URL + optional cookies file
|
|
2. **Validator** checks URL format → extracts space_id
|
|
3. **Downloader** configures yt-dlp with:
|
|
- Output format: mp3 (audio only)
|
|
- Output template: `space_{space_id}.mp3`
|
|
- Cookies file if provided
|
|
- Post-processing: convert to mp3 if needed
|
|
4. yt-dlp fetches metadata, downloads audio stream, converts to mp3
|
|
5. Return file path to user
|
|
|
|
## Error Handling
|
|
|
|
| Error Scenario | Detection | User Message |
|
|
|----------------|-----------|--------------|
|
|
| Invalid URL format | Validator regex check | "Invalid URL format. Expected: https://x.com/i/spaces/{SPACE_ID}" |
|
|
| Space doesn't exist | yt-dlp 404 error | "Recording not found. Check URL or Space may be deleted." |
|
|
| Authentication required | yt-dlp auth error | "Authentication required. Please provide cookies file with --cookies" |
|
|
| Network errors | yt-dlp timeout/connection | "Network error. Check connection and try again." |
|
|
| Space is live | Validator metadata check | "Error: This is a live Space, not a recording." |
|
|
| Disk space/permissions | File system errors | "Cannot write to output directory. Check permissions and disk space." |
|
|
|
|
## Authentication
|
|
|
|
**Cookie-based Authentication:**
|
|
- User exports cookies from logged-in X session
|
|
- Provides cookie file path via `--cookies` flag
|
|
- yt-dlp uses cookies for authenticated requests
|
|
|
|
**Cookie Export Instructions:**
|
|
- Browser extensions: "Get cookies.txt", "cookies.txt"
|
|
- Manual: Export via browser DevTools
|
|
- Instructions included in README
|
|
|
|
## Testing Strategy
|
|
|
|
**Unit Tests:**
|
|
- Validator: Test various URL formats, valid/invalid patterns
|
|
- Error message generation
|
|
|
|
**Integration Tests:**
|
|
- Full download flow with yt-dlp
|
|
- Use test Space URLs or mock yt-dlp calls
|
|
- Cookie authentication flow
|
|
|
|
**Error Scenario Tests:**
|
|
- Invalid URLs
|
|
- Missing cookies
|
|
- Network failures
|
|
- Live Space detection
|
|
|
|
## Dependencies
|
|
|
|
**Core:**
|
|
- `yt-dlp`: Media downloading and extraction
|
|
- `click`: CLI framework
|
|
|
|
**Development:**
|
|
- `pytest`: Testing framework
|
|
- `pytest-mock`: Mocking for tests
|
|
|
|
## Future Considerations (Out of Scope)
|
|
|
|
- Live Space recording
|
|
- Batch downloading multiple Spaces
|
|
- GUI interface
|
|
- Format options beyond MP3
|
|
- Metadata extraction (speakers, title, description)
|