Intro skip: MAL timings via keyless Jikan + player button
- upstream: _intros(mal_id) -> per-episode {start,length} (seconds),
30d TTL cache; Jikan is down or show uncovered -> [] (no button)
- app: GET /api/intros/{mal_id}, never errors into the player
- player: 'skip intro' pill appears while currentTime is inside the
intro window (+8s grace); click seeks past; reappears if rewound.
Ep-1 intros are often missing in MAL data, so falls back to the
show's first known timing (usually identical across eps)
- test: _parse_intros unit test (Jikan itself is 504ing right now,
live path verified by hand: endpoint returns [] cleanly)
This commit is contained in:
1 parent
c2461f8fba
commit
0613cf7e27
5 files changed
+77
-1
No files matched your search
+19
-1
@@ -1,4 +1,5 @@
|
||||
"""upstream.py — the only module that talks to anidb.app.
|
||||
"""upstream.py — the only module that talks to anidb.app (and keyless Jikan
|
||||
for intro timings).
|
||||
|
||||
anidb.app sits behind Cloudflare: plain curl gets 403. All requests use
|
||||
curl_cffi Chrome TLS impersonation (verified to pass the challenge).
|
||||
@@ -120,6 +121,22 @@ def _languages(ep_id):
|
||||
return _get(f"{BASE}/api/frontend/episode/{ep_id}/languages").json()["languages"]
|
||||
|
||||
|
||||
def _parse_intros(eps):
|
||||
"""Jikan episode list -> [{start, length}, ...], None where MAL has no timing"""
|
||||
out = []
|
||||
for e in eps:
|
||||
i = e.get("intro") or {}
|
||||
out.append({"start": int(i["start"]), "length": int(i["length"])}
|
||||
if i.get("start") is not None else None)
|
||||
return out
|
||||
|
||||
|
||||
def _intros(mal_id):
|
||||
"""Jikan (keyless MAL mirror): per-episode intro start/length, seconds"""
|
||||
r = _get("https://api.jikan.moe/v4/anime/{}".format(mal_id) + "/episodes")
|
||||
return _parse_intros(r.json().get("data", {}).get("episodes", []))
|
||||
|
||||
|
||||
def _master_m3u8(ep_id, lang="eng"):
|
||||
"""Steps 5+6: embed page -> 'file: <master m3u8>' URL (None if unavailable)"""
|
||||
for l in languages(ep_id):
|
||||
@@ -136,6 +153,7 @@ details = lambda s: _cached(f"details:{s}", 3600, _details, s)
|
||||
episodes = lambda i: _cached(f"episodes:{i}", 300, _episodes, i) # 5m: airing shows gain eps
|
||||
languages = lambda e: _cached(f"languages:{e}", 3600, _languages, e)
|
||||
master_m3u8 = lambda e, l="eng": _cached(f"master:{e}:{l}", 3600, _master_m3u8, e, l)
|
||||
intros = lambda m: _cached(f"intros:{m}", 30 * 86400, _intros, m) # static data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in new issue
Block a user