-
Notifications
You must be signed in to change notification settings - Fork 0
Closed
Labels
documentationImprovements or additions to documentationImprovements or additions to documentationenhancementNew feature or requestNew feature or request
Description
Summary
- Extend AniBridge so it can broker both anime (aniworld.to) and general-series (s.to) catalogues at the same time.
- Teach the HTTP, Torznab, and qBittorrent layers to fan out queries to both sites, merge results, and hand Sonarr/Prowlarr back whichever entries match the requested slug/keywords.
- Reuse the upstream
aniworldlibrary's multi-site features, but expose the required site hints, language maps, and metadata so the bridge can choose the correct catalogue per request.
Context & Findings
- Different content domains: In the upstream CLI,
aniworld.totargets anime whiles.tofronts series. AniBridge currently assumes every inbound request is anime, so all slug resolution, availability caching, and naming is hard-coded to/anime/stream/...anchors (app/utils/title_resolver.py:18-124). We need dual indices:/anime/stream/<slug>for AniWorld and/serie/stream/<slug>for s.to. - Downloader site defaults:
build_episodenever passes asiteargument when constructinganiworld.models.Episode, so the library falls back toaniworld.to(app/core/downloader.py:83). The literalLanguageunion also omits"English Dub", which is a valid s.to language (aniworld.config.LANGUAGE_CODES_STO,.venv/lib/python3.13/site-packages/aniworld/config.py:37-43). - Absolute episode helper:
resolve_absolute_episodecallsget_season_episode_count(slug)with no base URL. The helper distinguishes sites by inspecting the link it is called with (aniworld.common.common:get_season_episode_count). Without a site-aware wrapper AniBridge will always hit the AniWorld endpoint even when the slug is an s.to show. - Library readiness:
aniworld.models.Anime/Episodeacceptsite="s.to"(and adjust base URL + stream path accordingly) and share provider extraction logic across both (.venv/lib/python3.13/site-packages/aniworld/models.py:68-520). We simply never surface that knob. - Naming & metadata: The release naming helper hard-codes
RELEASE_GROUP=aniworldand magnet payload prefixes (aw_*). If we aggregate both catalogues the metadata should either encode the originating site, or at minimum stop labelling non-anime releases as AniWorld-only (app/utils/naming.py:133-180,app/utils/magnet.py:14-75). - Search orchestration gap: Torznab and qBittorrent flows currently assume a single slug → provider pipeline. There is no abstraction for "search both catalogues and merge"; we need to design the fan-out/fan-in layer (sequential vs parallel, conflict resolution when both return hits, caching strategy, etc.).
Proposed Changes
- Configuration surface
- Add a
CATALOG_SITES(defaultaniworld.to,s.to) env variable plus optional mirrors (base URL overrides for each). Provide per-site defaults for alphabet/search endpoints, release groups, and language maps.
- Add a
- Dual title indices
- Refactor
title_resolverso it can fetch and cache per-site indices (e.g.,aniworld_titles,sto_titles). Store(site, slug)pairs and extend_slug_from_queryto consider both sets so Sonarr lookups can locate shows from either catalogue.
- Refactor
- Site-aware request pipeline
- Update torznab search handlers to fan out to each enabled site. Decide on strategy: run lookups concurrently (async tasks) or sequentially with early exit when the first positive match appears. Preserve the site in the returned payload so the download scheduler knows which
Episode(site=...)to instantiate. - When both sites return hits for the same query, dedupe by canonical title/season/episode and decide ordering (e.g., prefer explicit matches over fuzzy ones, allow configuration to prioritise anime vs series).
- Update torznab search handlers to fan out to each enabled site. Decide on strategy: run lookups concurrently (async tasks) or sequentially with early exit when the first positive match appears. Preserve the site in the returned payload so the download scheduler knows which
- Downloader & helpers
- Thread the selected site through
build_episode,get_direct_url_with_fallback,probe_episode_quality, and absolute-number helpers. Expand theLanguageliteral and rename variables (e.g.,ANIWORLD_*) that are now site-agnostic. - Persist availability/job metadata with a
source_sitecolumn so qBittorrent sync responses report the right origin.
- Thread the selected site through
- Metadata & naming
- Extend
build_release_name/build_magnetto encode site-aware tags (source=aniworld|stoor site-specific release groups). Update docs so users can configure distinct group suffixes per site.
- Extend
- API/CLI surface
- Expose an optional query parameter or environment flag so operators can toggle one catalogue off if required (rate limits/legal reasons) without redeploying a different image.
- Docs & onboarding
- Update README, docs (
docs/src/guide/configuration.md,docs/src/api/environment.md) and onboarding checklists to explain the dual catalogue behaviour, configuration knobs, and new terminology (anime vs series).
- Update README, docs (
Testing Ideas
- Unit tests for the new
title_resolverthat feed sample AniWorld and s.to HTML and ensure queries resolve to the correct(site, slug)pair. - Downloader tests that instantiate
Episode(site="s.to"), verify language probing includes"English Dub", and confirm provider fallbacks still operate. - Torznab integration tests that simulate:
- Query resolving only on AniWorld
- Query resolving only on s.to
- Query resolving on both; validate dedupe/ordering logic and that magnets carry site metadata.
- Regression tests for absolute-number mapping when the site is s.to (ensure the helper calls the correct base URL).
- Tests ensuring qBittorrent sync endpoint returns site-qualified jobs and that CLI jobs persist the new
source_sitefield.
Open Questions
- Search orchestration: Should we query both catalogues in parallel for every request, or first check the site most likely to contain the content (e.g., anime → AniWorld, live action → s.to) based on heuristics/config? Provide a knob for sequential vs parallel to balance latency vs rate limits.
- Result collisions: When both sites return plausible matches (e.g., a live-action adaptation on s.to and its anime counterpart on AniWorld), how should Sonarr see them? Present both entries, prefer one, or allow per-series configuration?
- Base URLs / mirrors: s.to currently ships as
http://186.2.175.5in the library. Do we want to expose mirror configuration (including HTTPS) by default to avoid hardcoding an IP that may change? - Language defaults: How should we expose per-site language defaults to users (e.g., prefer
English Dubon s.to vsGerman Dubon AniWorld) without forcing global overrides? - Magnet payload naming: Do downstream consumers rely on the
aw_*magnet params? If so, do we add parallelsto_*fields or transition to a neutral namespace while preserving backwards compatibility?
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
documentationImprovements or additions to documentationImprovements or additions to documentationenhancementNew feature or requestNew feature or request