Skip to content

Development Guide

Christian Blank edited this page Nov 8, 2024 · 1 revision

Development Guide

Setting Up Development Environment

Prerequisites

  • Python 3.7 or higher
  • Git
  • pip
  • Virtual environment (recommended)

Initial Setup

  1. Fork and clone the repository:
git clone https://github.com/YOUR-USERNAME/Addarr.git
cd Addarr
  1. Create and activate virtual environment:
python -m venv venv
source venv/bin/activate  # Linux/Mac
# or
.\venv\Scripts\activate  # Windows
  1. Install development dependencies:
pip install -r requirements.txt
pip install -r requirements-dev.txt

Project Structure

Addarr/
├── addarr/
│   ├── __init__.py
│   ├── bot.py           # Main bot logic
│   ├── config.py        # Configuration handling
│   ├── sonarr.py        # Sonarr integration
│   ├── radarr.py        # Radarr integration
│   └── utils/           # Utility functions
├── tests/               # Test files
├── docs/                # Documentation
├── requirements.txt     # Production dependencies
└── requirements-dev.txt # Development dependencies

Development Workflow

1. Create a New Branch

git checkout -b feature/your-feature-name
# or
git checkout -b bugfix/issue-number

2. Code Style

  • Follow PEP 8 guidelines
  • Use meaningful variable names
  • Add docstrings to functions
  • Comment complex logic

Example:

def search_media(query: str, media_type: str) -> List[Dict]:
    """
    Search for media in Sonarr or Radarr.

    Args:
        query (str): Search term
        media_type (str): Either 'movie' or 'tv'

    Returns:
        List[Dict]: List of search results
    """
    # Implementation

3. Testing

Running Tests

# Run all tests
pytest

# Run specific test file
pytest tests/test_bot.py

# Run with coverage
pytest --cov=addarr

Writing Tests

def test_search_media():
    """Test media search functionality."""
    result = search_media("Breaking Bad", "tv")
    assert isinstance(result, list)
    assert len(result) > 0
    assert "title" in result[0]

API Integration

Sonarr API Example

def add_series(title: str, tvdb_id: int) -> Dict:
    """Add a new series to Sonarr."""
    payload = {
        "title": title,
        "tvdbId": tvdb_id,
        "qualityProfileId": 1,
        "rootFolderPath": "/tv",
        "monitored": True
    }
    response = requests.post(f"{SONARR_URL}/api/series", json=payload)
    return response.json()

Radarr API Example

def add_movie(title: str, tmdb_id: int) -> Dict:
    """Add a new movie to Radarr."""
    payload = {
        "title": title,
        "tmdbId": tmdb_id,
        "qualityProfileId": 1,
        "rootFolderPath": "/movies",
        "monitored": True
    }
    response = requests.post(f"{RADARR_URL}/api/movie", json=payload)
    return response.json()

Telegram Bot Development

Command Handler Example

@bot.message_handler(commands=['tv'])
def handle_tv_search(message):
    """Handle TV show search command."""
    query = message.text.replace('/tv', '').strip()
    if not query:
        bot.reply_to(message, "Please provide a show name")
        return
    
    results = search_media(query, 'tv')
    # Process results and send response

Documentation

Adding Documentation

  1. Update relevant wiki pages
  2. Add docstrings to new functions
  3. Update README.md if needed
  4. Document configuration changes

Documentation Style

class MediaManager:
    """
    Manages media operations for Sonarr and Radarr.

    Attributes:
        config (Config): Configuration instance
        sonarr (SonarrAPI): Sonarr API client
        radarr (RadarrAPI): Radarr API client
    """

    def __init__(self, config: Config):
        """
        Initialize MediaManager.

        Args:
            config (Config): Configuration instance
        """
        self.config = config

Pull Request Process

  1. Update Documentation
  2. Add/Update Tests
  3. Run Tests Locally
  4. Create Pull Request
    • Describe changes
    • Reference issues
    • Add screenshots if UI changes

Debug Tools

Logging

import logging

logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)

logger = logging.getLogger(__name__)

Debug Configuration

[general]
debug = true
log_level = DEBUG

Common Development Tasks

Adding a New Command

  1. Create command handler
  2. Add to help message
  3. Document in wiki
  4. Add tests
  5. Update README

Fixing a Bug

  1. Create regression test
  2. Fix the bug
  3. Verify fix
  4. Update documentation

Getting Help

  • Check existing issues
  • Join development discussions
  • Read the wiki
  • Ask questions in pull requests

Clone this wiki locally