An automated solution for extracting nested archives (zip/rar) from completed qBittorrent downloads.
"No files found are eligible for import" - Every Readarr user, probably
Finally, a tool that ensures your *arr apps actually find the files hidden inside those pesky nested archives!
- Automatically extracts ZIP files from completed torrent downloads
- Handles nested RAR archives within ZIP files (because BitBook loves their archive-ception)
- Integrates with qBittorrent's "Run external program on torrent completion" feature
- Comprehensive logging (so you know exactly why Readarr is happy now)
- Preserves original archives (keep seeding, friends!)
- Error handling and reporting (no more silent failures)
- Makes your *arr apps actually see those EPUB files buried in
Chuck.Palahniuk.-.Fight.Club.2011.Retail.EPUB.eBook-BitBook.zip
# Clone the repository
git clone https://github.com/ggfevans/qbit-torrent-extract.git
cd qbit-torrent-extract
# Create and activate virtual environment
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install the package
pip install -e .
qbit-torrent-extract /path/to/torrent/folder
- Open qBittorrent Settings (Tools → Options)
- Navigate to Downloads tab
- Enable "Run external program on torrent completion"
- Add the extraction command:
/path/to/venv/bin/python -m qbit_torrent_extract "%F"
With Verbose Logging:
/path/to/venv/bin/python -m qbit_torrent_extract "%F" --verbose --torrent-name "%N"
With Custom Configuration:
/path/to/venv/bin/python -m qbit_torrent_extract "%F" --config /path/to/config.json --torrent-name "%N"
With Statistics Tracking:
/path/to/venv/bin/python -m qbit_torrent_extract "%F" --stats-file /path/to/stats.json --show-stats
%F
- Torrent content path (file or root directory)%N
- Torrent name%R
- Root directory of the torrent%D
- Save directory%C
- Number of files in the torrent%Z
- Torrent size (bytes)%T
- Torrent category%I
- Torrent hash
For best results, use this command which includes torrent name for logging:
/path/to/venv/bin/python -m qbit_torrent_extract "%F" --torrent-name "%N" --preserve
The tool supports both command-line options and JSON configuration files.
qbit-torrent-extract [OPTIONS] DIRECTORY
Options:
--preserve / --no-preserve Preserve original archives after extraction [default: preserve]
--verbose / --quiet Increase output verbosity [default: quiet]
--config PATH Path to configuration file
--max-ratio FLOAT Maximum extraction ratio for zipbomb protection [default: 100.0]
--max-depth INTEGER Maximum nested archive depth [default: 3]
--log-dir PATH Directory for log files [default: ~/.qbit-torrent-extract/logs]
--torrent-name TEXT Name of the torrent for per-torrent logging
--stats-file PATH Path to statistics file [default: ~/.qbit-torrent-extract/stats.json]
--show-stats Show aggregated statistics after extraction
--export-stats PATH Export statistics to file
--version Show the version and exit
--help Show this message and exit
Create a JSON configuration file for consistent settings:
{
"max_extraction_ratio": 100.0,
"max_nested_depth": 3,
"supported_extensions": [".zip", ".rar", ".7z", ".tar.gz", ".tgz"],
"log_level": "INFO",
"log_dir": "~/.qbit-torrent-extract/logs",
"log_rotation_size": 10485760,
"log_rotation_count": 5,
"preserve_originals": true,
"skip_on_error": true,
"progress_indicators": true,
"stats_file": "~/.qbit-torrent-extract/stats.json"
}
max_extraction_ratio
: Prevents zipbomb attacks by limiting extraction size vs archive sizemax_nested_depth
: Limits recursive extraction depth to prevent infinite loopsskip_on_error
: Continues processing other files when one archive fails
Problem: PermissionError: [Errno 13] Permission denied
Solution:
- Ensure qBittorrent runs with appropriate permissions
- Check that the download directory is writable
- On Linux/macOS, verify file ownership:
chown -R user:group /download/path
Problem: FileNotFoundError: [Errno 2] No such file or directory
Solution:
- Verify the Python path in qBittorrent settings is correct
- Use absolute paths for the script location
- Test the command manually:
python -m qbit_torrent_extract /test/path
Problem: ModuleNotFoundError: No module named 'rarfile'
Solution:
# Reinstall with all dependencies
pip install -e .
# Or install missing dependencies manually
pip install rarfile py7zr tqdm click
Problem: Archives are found but not extracted Solutions:
- Check if archives are password-protected (not supported)
- Verify archive integrity:
unrar t archive.rar
orunzip -t archive.zip
- Increase verbosity to see detailed logs:
--verbose
- Check zipbomb protection limits:
--max-ratio 200
Problem: Extraction stops or times out on large archives Solutions:
- Increase system resources (RAM, disk space)
- Check available disk space before extraction
- Use
--verbose
to monitor progress - Consider splitting large archives
-
Test manually first:
python -m qbit_torrent_extract /path/to/torrent --verbose
-
Check logs:
# View main log cat ~/.qbit-torrent-extract/logs/qbit-torrent-extract.log # View torrent-specific log cat ~/.qbit-torrent-extract/logs/TorrentName.log
-
Verify qBittorrent setup:
- Test with a simple command first:
echo "%F" > /tmp/qbit-test.txt
- Check if qBittorrent variables are being passed correctly
- Test with a simple command first:
-
Check statistics:
python -m qbit_torrent_extract /any/path --show-stats
2023-XX-XX 12:00:00 | INFO | Starting qbit-torrent-extract v0.1.0
2023-XX-XX 12:00:00 | INFO | Processing directory: /downloads/TorrentName
2023-XX-XX 12:00:00 | INFO | Found 3 archives to process
2023-XX-XX 12:00:01 | INFO | Successfully extracted: archive1.zip
2023-XX-XX 12:00:02 | INFO | Extraction completed - Processed: 3, Successful: 3, Failed: 0
ERROR | Zipbomb detected in archive.zip (ratio: 1500.0 > 100.0)
ERROR | Password-protected archive detected: secret.rar
ERROR | Corrupted archive detected: broken.zip
WARNING | Maximum nested depth reached (3) for nested.zip
- Always use zipbomb protection (default: enabled)
- Set reasonable depth limits (default: 3 levels)
- Monitor disk space before processing large torrents
- Use dedicated user account for qBittorrent with limited permissions
- Allocate sufficient RAM for large archive extraction
- Use SSD storage for extraction operations when possible
- Monitor system resources during heavy extraction periods
- Enable log rotation to prevent log files from growing too large
- Use per-torrent logging with
--torrent-name "%N"
- Enable statistics tracking to monitor success rates
- Regular log cleanup using built-in rotation features
- Backup important configuration files
- Test extraction manually before setting up automation
- Start with conservative settings (low max-ratio, shallow depth)
- Use absolute paths in qBittorrent configuration
- Monitor logs regularly for issues or patterns
- Keep extraction and seed directories separate when possible
# Production setup with comprehensive logging and stats
/path/to/venv/bin/python -m qbit_torrent_extract "%F" \
--torrent-name "%N" \
--config /etc/qbit-extract/config.json \
--log-dir /var/log/qbit-extract \
--stats-file /var/lib/qbit-extract/stats.json \
--preserve
Consider setting up monitoring for:
- Extraction failure rates (via statistics export)
- Disk space usage in download directories
- Log file sizes and rotation
- Unusual extraction patterns or errors
Comprehensive documentation is available in the docs/
directory:
- Installation Guide - Detailed installation instructions for all platforms
- Configuration Reference - Complete configuration options and examples
- API Documentation - Full API reference for developers
- Troubleshooting Guide - Common issues and solutions
- Platform-specific installation
- qBittorrent integration setup
- Configuration file format
- Security settings
- Performance optimization
- Common errors and solutions
# Clone repository
git clone https://github.com/yourusername/qbit-torrent-extract.git
cd qbit-torrent-extract
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install development dependencies
pip install -e ".[dev]"
# Run all tests
pytest
# Run with coverage
pytest --cov=src --cov-report=html
# Run specific test categories
pytest tests/test_security.py # Security tests
pytest tests/test_performance.py -m performance # Performance tests
pytest tests/test_integration.py # Integration tests
# Run tests with verbose output
pytest -v --tb=short
# Format code
black src/ tests/
# Lint code
flake8 src/ tests/
# Type checking
mypy src/
# Run all quality checks
black --check src/ tests/ && flake8 src/ tests/ && mypy src/
qbit-torrent-extract/
├── src/qbit_torrent_extract/ # Main package
│ ├── __init__.py
│ ├── main.py # CLI entry point
│ ├── config.py # Configuration management
│ ├── extractor.py # Archive extraction logic
│ ├── validator.py # Archive validation
│ ├── logger.py # Logging system
│ └── statistics.py # Statistics tracking
├── tests/ # Test suite (148 tests)
│ ├── test_main.py # CLI tests
│ ├── test_config.py # Configuration tests
│ ├── test_extractor.py # Extraction tests
│ ├── test_validator.py # Validation tests
│ ├── test_logger.py # Logging tests
│ ├── test_statistics.py # Statistics tests
│ ├── test_security.py # Security tests
│ ├── test_performance.py # Performance tests
│ └── test_integration.py # Integration tests
├── docs/ # Documentation
│ ├── installation.md # Installation guide
│ ├── configuration.md # Configuration reference
│ ├── api.md # API documentation
│ └── troubleshooting.md # Troubleshooting guide
├── setup.py # Package configuration
├── requirements.txt # Dependencies
└── README.md # This file
- Fork the repository and create a feature branch
- Install development dependencies:
pip install -e ".[dev]"
- Write tests for new functionality
- Run the test suite:
pytest
- Check code quality:
black --check . && flake8 . && mypy src/
- Update documentation if needed
- Submit a pull request with a clear description
- Unit tests: Test individual components in isolation
- Integration tests: Test component interactions and workflows
- Security tests: Test security features and edge cases
- Performance tests: Benchmark and regression testing
- All tests should pass: Never commit failing tests
- Aim for high coverage: Target >90% code coverage
MIT License - see LICENSE file for details.
- Documentation: See docs/ directory
- Issues: Report bugs on GitHub Issues
- Discussions: Join discussions on GitHub Discussions
- Security: Report security issues privately via email
See CHANGELOG.md for version history and release notes.