7.8 KiB
GitHub Copilot Instructions for the viu Repository
Hello, Copilot! This document provides instructions and context to help you understand the viu 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
viu 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 (viu/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 inviu/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 (viu/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 (viu/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 (viu/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
viu/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
viu/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 fromviu/libs/provider/anime/types.py(e.g.,SearchResult,Anime,Server). - Register Provider:
- Add the provider's name to the
ProviderNameenum inviu/libs/provider/anime/types.py. - Add it to the
PROVIDERS_AVAILABLEdictionary inviu/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
viu/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 inviu/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 inviu/libs/player/player.py.
How to Add a New Selector
- Create Directory: Add a new folder in
viu/libs/selectors/newselector/. - Implement
BaseSelector: Inselector.py, create a classNewSelectorthat inherits fromBaseSelectorand implementchoose,confirm, andask. - Add Configuration: If needed, add a
NewSelectorConfigtoviu/core/config/model.py. - Register Selector: Add the selector's name to the
SELECTORSlist and the factory logic inviu/libs/selectors/selector.py. Update theLiteraltype hint forselectorinGeneralConfig.
How to Add a New CLI Command
- Top-Level Command (
viu my-command):- Create
viu/cli/commands/my_command.pywith yourclick.command(). - Register it in the
commandsdictionary inviu/cli/cli.py.
- Create
- Subcommand (
viu anilist my-subcommand):- Create
viu/cli/commands/anilist/commands/my_subcommand.py. - Register it in the
lazy_subcommandsdictionary of the parentclick.group()(e.g., inviu/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
viu/core/config/model.py. - Add Default: Add a default value in
viu/core/config/defaults.py. - Add Description: Add a user-friendly description in
viu/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
viu/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.