7.9 KiB
GitHub Copilot Instructions for the FastAnime Repository
Hello, Copilot! This document provides instructions and context to help you understand the fastanime codebase. Following these guidelines will help you generate code that is consistent, maintainable, and aligned with the project's architecture.
1. High-Level Project Goal
fastanime is a command-line tool that brings the anime browsing, streaming, and management experience to the terminal. It integrates with metadata providers like AniList and scrapes streaming links from various anime provider websites. The core goals are efficiency, extensibility, and providing a powerful, scriptable user experience.
2. Core Architectural Concepts
The project follows a clean, layered architecture. When generating code, please adhere to this structure.
Layer 1: CLI (fastanime/cli)
- Purpose: Handles user interaction, command parsing, and displaying output.
- Key Libraries:
clickfor command structure,richfor styled output. - Interactive Mode: The interactive TUI is managed by the
Sessionobject infastanime/cli/interactive/session.py. It's a state machine where each menu is a function that returns the nextStateor anInternalDirective(likeBACKorEXIT). - Guideline: CLI files should not contain complex business logic. They should parse arguments and delegate tasks to the Service Layer.
Layer 2: Service (fastanime/cli/service)
- Purpose: Contains the core application logic. Services act as orchestrators, connecting the CLI layer with the various library components.
- Examples:
DownloadService,PlayerService,MediaRegistryService,WatchHistoryService. - Guideline: When adding new functionality (e.g., a new way to manage downloads), it should likely be implemented in a service or an existing service should be extended. Services are the "brains" of the application.
Layer 3: Libraries (fastanime/libs)
- Purpose: A collection of independent, reusable modules with well-defined contracts (Abstract Base Classes).
media_api: Interfaces with metadata services like AniList. All new metadata clients must inherit fromBaseApiClient.provider: Interfaces with anime streaming websites. All new providers must inherit fromBaseAnimeProvider.player: Wrappers around external media players like MPV. All new players must inherit fromBasePlayer.selectors: Wrappers for interactive UI tools like FZF or Rofi. All new selectors must inherit fromBaseSelector.- Guideline: Libraries should be self-contained and not depend on the CLI or Service layers. They receive configuration and perform their specific task.
Layer 4: Core (fastanime/core)
- Purpose: Foundational code shared across the entire application.
config: Pydantic models defining the application's configuration structure. This is the single source of truth for all settings.downloader: The underlying logic for downloading files (usingyt-dlporhttpx).exceptions: Custom exception classes used throughout the project.utils: Common, low-level utility functions.- Guideline: Code in
coreshould be generic and have no dependencies on other layers except for othercoremodules.
3. Key Technologies
- Dependency Management:
uvis used for all package management and task running. Refer topyproject.tomlfor dependencies. - Configuration: Pydantic is used exclusively. The entire configuration is defined in
fastanime/core/config/model.py. - CLI Framework:
click. We use a customLazyGroupto load commands on demand for faster startup. - HTTP Client:
httpxis the standard for all network requests.
4. How to Add New Features
Follow these patterns to ensure your contributions fit the existing architecture.
How to Add a New Provider
- Create Directory: Add a new folder in
fastanime/libs/provider/anime/newprovider/. - Implement
BaseAnimeProvider: Inprovider.py, create a classNewProviderthat inherits fromBaseAnimeProviderand implement thesearch,get, andepisode_streamsmethods. - Create Mappers: In
mappers.py, write functions to convert the provider's API/HTML data into the generic Pydantic models fromfastanime/libs/provider/anime/types.py(e.g.,SearchResult,Anime,Server). - Register Provider:
- Add the provider's name to the
ProviderNameenum infastanime/libs/provider/anime/types.py. - Add it to the
PROVIDERS_AVAILABLEdictionary infastanime/libs/provider/anime/provider.py.
- Add the provider's name to the
How to Add a New Player
- Create Directory: Add a new folder in
fastanime/libs/player/newplayer/. - Implement
BasePlayer: Inplayer.py, create a classNewPlayerthat inherits fromBasePlayerand implement theplaymethod. It should call the player's executable viasubprocess. - Add Configuration: If the player has settings, add a
NewPlayerConfigPydantic model infastanime/core/config/model.py, and add it to the mainAppConfig. Also add defaults and descriptions. - Register Player: Add the player's name to the
PLAYERSlist and the factory logic infastanime/libs/player/player.py.
How to Add a New Selector
- Create Directory: Add a new folder in
fastanime/libs/selectors/newselector/. - Implement
BaseSelector: Inselector.py, create a classNewSelectorthat inherits fromBaseSelectorand implementchoose,confirm, andask. - Add Configuration: If needed, add a
NewSelectorConfigtofastanime/core/config/model.py. - Register Selector: Add the selector's name to the
SELECTORSlist and the factory logic infastanime/libs/selectors/selector.py. Update theLiteraltype hint forselectorinGeneralConfig.
How to Add a New CLI Command
- Top-Level Command (
fastanime my-command):- Create
fastanime/cli/commands/my_command.pywith yourclick.command(). - Register it in the
commandsdictionary infastanime/cli/cli.py.
- Create
- Subcommand (
fastanime anilist my-subcommand):- Create
fastanime/cli/commands/anilist/commands/my_subcommand.py. - Register it in the
lazy_subcommandsdictionary of the parentclick.group()(e.g., infastanime/cli/commands/anilist/cmd.py).
- Create
How to Add a New Configuration Option
- Add to Model: Add the field to the appropriate Pydantic model in
fastanime/core/config/model.py. - Add Default: Add a default value in
fastanime/core/config/defaults.py. - Add Description: Add a user-friendly description in
fastanime/core/config/descriptions.py. - The config loader and CLI option generation will handle the rest automatically.
5. Code Style and Conventions
- Style:
rufffor formatting,rufffor linting. Thepre-commithooks handle this. - Types: Full type hinting is mandatory. All code must pass
pyright. - Commits: Adhere to the Conventional Commits standard.
- Logging: Use Python's
loggingmodule. Do not useprint()for debugging or informational messages in library or service code.
6. Do's and Don'ts
-
✅ DO use the abstract base classes (
BaseProvider,BasePlayer, etc.) as contracts. -
✅ DO place business logic in the
servicelayer. -
✅ DO use the Pydantic models in
fastanime/core/config/model.pyas the single source of truth for configuration. -
✅ DO use the
Contextobject in interactive menus to access services and configuration. -
❌ DON'T hardcode configuration values. Access them via the
configobject. -
❌ DON'T put complex logic directly into
clickcommand functions. Delegate to a service. -
❌ DON'T make direct
httpxcalls outside of aproviderormedia_apilibrary. -
❌ DON'T introduce new dependencies without updating
pyproject.tomland discussing it first.