Files
Kimi Agent 520be53901
CI / Test (Python 3.11) (push) Has been cancelled
CI / Test (Python 3.12) (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Type Check (push) Has been cancelled
CI / Summary (push) Has been cancelled
fix: migrations, auth, providers health check, E2E tests, remove neko-sama
- Add proper Alembic initial migration (0001_initial_schema.py)
- Migrate refresh tokens from JSON file to SQLite (RefreshTokenTable)
- Remove Neko-Sama provider entirely (redirects to Gupy, not a host)
- Fix provider health check always showing UNKNOWN
  - Run check_all_health() on startup
  - Fix POST /providers/health/check background task bug
  - Add HTMX refresh after manual health check trigger
- Fix anime search relevance scoring with MIN_RELEVANCE_THRESHOLD=0.5
- Replace bare 'except:' with 'except Exception:' across codebase
- Add Playwright E2E test suite (12 tests, auth setup, helpers)
- Fix toast container blocking clicks via pointer-events: none
- Remove obsolete Jest/Vite test files and config
- Clean up obsolete test_watchlist scripts
- Update sonarr model comment for active providers
2026-05-12 11:45:56 +00:00

204 lines
5.4 KiB
Python

"""Anime, series and file hosting providers configuration"""
ANIME_PROVIDERS = {
"anime-sama": {
"name": "Anime-Sama",
"domains": [
"anime-sama.to",
"www.anime-sama.to",
"anime-sama.tv",
"www.anime-sama.tv",
"anime-sama.si",
"www.anime-sama.si",
"anime-sama.org",
"anime-sama.store",
"anime-sama.eu",
],
"url_pattern": "https://anime-sama.to/catalogue/{anime}/saison{season}/{lang}/",
"icon": "🎬",
"color": "#00d9ff",
},
"anime-ultime": {
"name": "Anime-Ultime",
"domains": ["anime-ultime.net", "anime-ultime.com", "www.anime-ultime.net"],
"url_pattern": "https://www.anime-ultime.net/info-{id}-{slug}",
"icon": "▶️",
"color": "#00ff88",
},
"vostfree": {
"name": "Vostfree",
"domains": ["vostfree.tv", "www.vostfree.tv"],
"url_pattern": "https://vostfree.tv/anime/{slug}",
"icon": "📺",
"color": "#ffd93d",
},
"french-manga": {
"name": "French-Manga",
"domains": [
"french-manga.net",
"w16.french-manga.net",
"w15.french-manga.net",
"www.french-manga.net",
],
"url_pattern": "https://w16.french-manga.net/{slug}.html",
"icon": "🇫🇷",
"color": "#ff7675",
},
}
SERIES_PROVIDERS = {
"fs7": {
"name": "French Stream",
"domains": [
"fs7.lol",
"www.fs7.lol",
"french-stream.tv",
"www.french-stream.tv",
"fs7.com",
"fs7.net",
"fs7.org",
"fs7.cc",
"fs7.co",
"french-stream.com",
"french-stream.net",
],
"url_pattern": "https://fs7.lol/s-tv/{slug}.html",
"icon": "🎬",
"color": "#ff6b9d",
},
"zonetelechargement": {
"name": "Zone-Telechargement",
"domains": [
"zone-telechargement.golf",
"zone-telechargement.cam",
"zone-telechargement.net",
"zone-telechargement.org",
"zone-telechargement.blue",
"zone-telechargement.lol",
"zone-telechargement.work",
"zone-telechargement.ws",
"www.zone-telechargement.golf",
"www.zone-telechargement.cam",
],
"url_pattern": "https://zone-telechargement.golf/index.php?do=search",
"icon": "⬇️",
"color": "#00d9ff",
},
}
FILE_HOSTS = {
"1fichier": {
"name": "1fichier",
"domains": ["1fichier.com", "1fichier.fr"],
"icon": "📁",
"color": "#4ecdc4",
},
"uptobox": {
"name": "Uptobox",
"domains": ["uptobox.com", "uptobox.fr"],
"icon": "📦",
"color": "#45b7d1",
},
"doodstream": {
"name": "Doodstream",
"domains": [
"doodstream.com",
"dood.stream",
"dood.to",
"dood.lol",
"dood.cx",
"dood.so",
"dood.watch",
"dood.sh",
],
"icon": "🎥",
"color": "#f7b731",
},
"rapidfile": {
"name": "Rapidfile",
"domains": ["rapidfile.net", "rapidfile.com"],
"icon": "",
"color": "#ff6b6b",
},
"vidmoly": {
"name": "VidMoly",
"domains": ["vidmoly.to", "vidmoly.org", "vidmoly.biz"],
"icon": "🎬",
"color": "#a29bfe",
},
"sendvid": {
"name": "SendVid",
"domains": ["sendvid.com", "sendvid.io"],
"icon": "📤",
"color": "#fd79a8",
},
"sibnet": {
"name": "Sibnet",
"domains": ["sibnet.ru", "video.sibnet.ru"],
"icon": "🎞️",
"color": "#00cec9",
},
"lpayer": {
"name": "Lplayer",
"domains": ["lpayer.embed4me.com", "lpayer.com", "lplayer.fr"],
"icon": "▶️",
"color": "#e17055",
},
"vidzy": {
"name": "Vidzy",
"domains": ["vidzy.com", "vidzy.net", "www.vidzy.com"],
"icon": "🎞️",
"color": "#74b9ff",
},
"luluv": {
"name": "LuLuvid",
"domains": ["luluv.com", "luluvid.com", "www.luluv.com", "www.luluvid.com"],
"icon": "🎬",
"color": "#a29bfe",
},
"uqload": {
"name": "Uqload",
"domains": ["uqload.bz", "uqload.com", "www.uqload.bz", "www.uqload.com"],
"icon": "📺",
"color": "#fd79a8",
},
"smoothpre": {
"name": "Smoothpre",
"domains": ["smoothpre.com", "www.smoothpre.com"],
"icon": "🎬",
"color": "#a29bfe",
},
}
def get_all_providers():
"""Get all supported providers (anime + series + file hosts)"""
return {**ANIME_PROVIDERS, **SERIES_PROVIDERS, **FILE_HOSTS}
def get_anime_providers():
"""Get all anime streaming providers"""
return ANIME_PROVIDERS
def get_series_providers():
"""Get all series streaming providers"""
return SERIES_PROVIDERS
def get_file_hosts():
"""Get all file hosting providers"""
return FILE_HOSTS
def detect_provider_from_url(url: str) -> str | None:
"""Detect which provider can handle the given URL"""
url_lower = url.lower()
for provider_id, provider in get_all_providers().items():
for domain in provider["domains"]:
if domain in url_lower:
return provider_id
return None