GoAnime

repository·main·Indexed 21 days ago

https://github.com/alvarorichard/goanime

A terminal-based user interface (TUI) and Go library for searching, streaming, and downloading anime episodes using the mpv media player. It scrapes data from multiple sources, including AllAnime and AnimeFire, supporting subbed and dubbed content in English and Portuguese.

Tokens
18.4K
Snippets
84
Records
103
Agent score
76%

What's inside GoAnime

  1. Project directory structure and data flow

    main

    Understanding the directory layout is essential for navigating the codebase:

    • cmd/: Main application entry points (executables).
    • internal/: Private application code (encapsulated).
    • internal/api/: External API communications (databases, streaming services).
    • internal/player/: Core video player (platform-specific Unix/Windows).
    • internal/models/: Core data structures (anime, skip times, URLs).
    • internal/tracking/: Watch history and progress tracking.
    • internal/discord/: Discord Rich Presence integration.
    • internal/playback/: Media playback logic.
    • internal/appflow/: Application workflow and data flow management.
    • build/: Platform-specific build scripts.
    • test/: Functional test suite.

    Data Flow Pattern

    The application typically follows this sequence:

    1. API Layer (internal/api/) fetches data.
    2. Models (internal/models/) structure the data.
    3. Appflow (internal/appflow/) manages the flow.
    4. Playback (internal/playback/) handles media logic.
    5. Player (internal/player/) manages video playback.
    6. Tracking (internal/tracking/) records progress.
    7. Discord (internal/discord/) updates status.
  2. Understand circuit breaker and log messages

    main

    GoAnime uses a circuit breaker to protect external servers. After 3 consecutive failures due to origin unavailability or blocking, the circuit breaker will skip that source for 10 minutes.

    Common Log Patterns:

    • FlixHQ temporariamente indisponivel: Cloudflare 521/origem fora (Unavailability)
    • SFlix bloqueou a requisicao: captcha/challenge (Blocking)
    • Goyabu respondeu, mas o parser nao encontrou os dados esperados (Parser failure)
    • Download link de download expirou ou foi negado: HTTP 404 (Expired CDN link)
  3. How to add or remove a streaming source

    main

    Streaming sources in GoAnime use a self-registering source registry. Sources describe themselves via Describe() source.Descriptor and register themselves in an init() function. There is no central switch statement in the dispatch path; instead, resolution, search fan-out, circuit breakers, and kill-switches all read the descriptor data.

    Adding a Source

    Adding a source involves updating approximately 12 files and 20 edit sites. The implementation follows a layered approach:

    1. internal/scraper/providers/<name>/: The leaf HTTP/scraping client.
    2. internal/scraper/manager.go: The UnifiedScraper adapter.
    3. internal/api/providers/source_providers.go: The source.Source registration (via init).
    4. internal/api/source/: The registry (handles Register, Resolve, and ActiveSources).

    Important: Capabilities are discovered via type assertion rather than flags. A source is included in search fan-out only if it implements source.Searchable. Other capabilities include source.Seasoned (via HasSeasons() bool) and source.BrowserGated (via WarmUp(ctx) error).

    Warning: Omitting updates to naming.go or source_health.go will fail silently without a compile-time error. Always use ADDING_A_SOURCE.md as a checklist.

    Removing a Source

    Depending on the urgency, choose one of three levels:

    1. Runtime disable (Immediate): Set the environment variable GOANIME_DISABLED_SOURCES="<source_name>" to disable a broken source without rebuilding.
    2. Ship disabled (Soft delete): Set DefaultDisabled: true in the source descriptor. Users can opt-in using GOANIME_ENABLED_SOURCES.
    3. Permanent delete (Hard delete): Follow the 13-step checklist in ADDING_A_SOURCE.md. When modifying the ScraperType iota, always append or delete at the end; never insert or remove from the middle.
  4. How source capabilities are discovered

    main

    GoAnime discovers source capabilities via type assertion rather than explicit flags. To enable specific behaviors, implement the corresponding interface:

    • Searchable: Implement Search(ctx, query). If missing, the source is excluded from search fan-out (though it can still play via URL).
    • Seasoned: Implement HasSeasons() bool.
    • BrowserGated: Implement WarmUp(ctx) error. This is called before every stream fetch (useful for sites requiring browser automation/cookies).

    Critical Requirement: FetchStreamURL must always start by calling util.ClearGlobalSubtitles() and util.SetGlobalAnimeSource(anime.Source) to prevent subtitle leakage between episodes.

  5. Diagnose source unavailability vs. GoAnime bugs

    main

    When a source fails, use the following classification to determine if the issue is with the external provider or a bug in GoAnime:

    Source Unavailable (Skip Health Check)

    If the source returns these errors, the health check should be skipped as the provider is unreachable:

    • HTTP Status: 521, 522, 523, 524, 530
    • DNS errors
    • Connection timeouts
    • Origin offline

    Blocked or Challenged (Skip Health Check)

    If the source is actively blocking requests, the health check should be skipped:

    • HTTP Status: 403, 429, 1020
    • Captcha or Cloudflare challenges

    Parser or Decrypt Broken (Fail Health Check)

    If the connection is successful but the data is unusable, the health check must fail:

    • ParserBroken: Received 200 OK but selectors, JSON, or expected results are missing.
    • DecryptBroken: Decrypt/API returned an invalid format.

    Other Failures

    • DownloadExpired: Extracted CDN links return 403 or 404.
    • InternalBug: Panics, nil pointers, infinite loops, or local errors.
  6. How the GoAnime auto-update process works

    main

    The auto-update functionality follows a multi-step lifecycle designed for safety and cross-platform compatibility:

    1. Detection: Compares your current semantic version against the latest GitHub release and detects your OS/architecture.
    2. Download: Selects the correct binary and downloads it to a temporary location via HTTPS.
    3. Installation:
      • Creates a backup of the current executable.
      • Replaces the executable using atomic renames (preferred), copy-and-replace (fallback), or gradual replacement for files in use.
      • Sets correct file permissions.
      • Cleans up temporary files and old backups.
    4. Platform Handling:
      • Linux/macOS: Manages "text file busy" errors and uses atomic operations.
      • Windows: Handles file locking by renaming the current executable before replacement.

    If an update fails, the system attempts an automatic rollback to the previous version.

  7. Install GoAnime on Linux

    main

    Installation steps vary by distribution:

    Debian / Ubuntu: Install mpv via apt, then download and extract the amd64.tar.gz release.

    Arch Linux / Manjaro: Use the AUR helper yay.

    Fedora: Install mpv via dnf, then download and extract the amd64.tar.gz release.

    # Debian / Ubuntu
    sudo apt update
    sudo apt install mpv -y
    
    curl -LO https://github.com/alvarorichard/Goanime/releases/latest/download/goanime-linux-amd64.tar.gz
    tar -xzf goanime-linux-amd64.tar.gz
    chmod +x goanime-linux-amd64
    sudo mv goanime-linux-amd64 /usr/local/bin/goanime
    
    # Arch Linux / Manjaro
    yay -S goanime
    
    # Fedora
    sudo dnf update
    sudo dnf install mpv
    
    curl -LO https://github.com/alvarorichard/Goanime/releases/latest/download/goanime-linux-amd64.tar.gz
    tar -xzf goanime-linux-amd64.tar.gz
    chmod +x goanime-linux-amd64
    sudo mv goanime-linux-amd64 /usr/local/bin/goanime
  8. Perform live source health checks

    main

    The TestSourceHealthLive test performs searches using known queries to verify provider status. This test uses specific tags and targets the internal/scraper package.

    Known Queries:

    • Anime/General: naruto
    • Movies/Series: dexter

    Expected Test Behavior:

    • t.Skip: Triggered if the source is offline (Cloudflare 521/522/523/524/530, DNS, timeout) or blocked (Captcha, challenge, 403/429/1020).
    • t.Fatal: Triggered if the response is 200 OK but the parser finds zero results for the known query, or if decryption fails.
    go test -tags sourcehealth -run TestSourceHealthLive -count=1 -v ./internal/scraper
  9. Quick Start with GoAnime

    main

    To get started, create a new client using goanime.NewClient() and use the SearchAnime method to find content. This example demonstrates the basic workflow of initializing the client and iterating through search results.

    package main
    
    import (
        "fmt"
        "log"
    
        "github.com/alvarorichard/Goanime/pkg/goanime"
    )
    
    func main() {
        // Create a new client
        client := goanime.NewClient()
    
        // Search for anime
        results, err := client.SearchAnime("One Piece", nil)
        if err != nil {
            log.Fatal(err)
        }
    
        // Display results
        for _, anime := range results {
            fmt.Printf("%s [%s]\n", anime.Name, anime.Source)
        }
    }
  10. Use GoAnime Enhanced Web Scraping

    main

    GoAnime includes an enhanced web scraping integration inspired by ani-cli. It supports multiple anime streaming sources with automatic fallback logic. If a primary source fails, the system automatically attempts to use alternative sources to ensure content availability.

    # Search all sources
    goanime "naruto"
    
    # Download an episode (requires -d flag)
    goanime -d "one piece" 1
  11. Install SQLite development libraries for GoAnime

    main

    To build GoAnime with SQLite support, you must have a GCC-compatible C compiler and the SQLite development libraries installed on your host system. Use the command corresponding to your distribution:

    # Ubuntu/Debian
    sudo apt-get install libsqlite3-dev
    
    # Fedora
    dnf install sqlite-devel
    
    # Arch Linux
    sudo pacman -S sqlite
    
    # macOS
    brew install sqlite3