迁移 TheIntroDB 接口到 v4

v1 已删除、v2/v3 已弃用,仅保留只读的 GET /media。本次把 base URL 切到 v4,并适配响应以 tvdb_id 为身份(tmdb_id 字段已移除)。请求仍用 tmdb_id 寻址,v4 仍接受并由服务端解析季集映射。
This commit is contained in:
truewhile
2026-10-19 22:23:06 +08:00
parent f1974a179e
commit 90bfac3b09
2 changed files with 15 additions and 11 deletions
+6 -3
View File
@@ -22,8 +22,9 @@ import (
const (
// IntroDBBaseURL is the public read endpoint. Overridable on the service
// for tests and for pointing at a mirror.
IntroDBBaseURL = "https://api.theintrodb.org/v3"
// for tests and for pointing at a mirror. v1 已删除,v2/v3 冻结在只读的
// GET /media 上并被官方标记为弃用,所以这里直接跟 v4。
IntroDBBaseURL = "https://api.theintrodb.org/v4"
// IntroDBSource tags rows that came from this provider.
IntroDBSource = "theintrodb"
@@ -92,8 +93,10 @@ type introDBRange struct {
EndMs *int64 `json:"end_ms"`
}
// introDBResponse 对应 v4 的 MediaResponse。v4 以 TVDB 为身份,响应只带
// tvdb_id —— tmdb_id 字段已被官方移除,需要 tmdb_id 只能从请求侧自己记。
type introDBResponse struct {
TMDbID int `json:"tmdb_id"`
TVDBID int `json:"tvdb_id"`
Type string `json:"type"`
Intro []introDBRange `json:"intro"`
Recap []introDBRange `json:"recap"`
+9 -8
View File
@@ -11,11 +11,12 @@ import (
"go.uber.org/zap"
)
// 这两段响应是从 api.theintrodb.org/v3/media 实测抓下来的原文,
// 用来锁住 null 语义:start_ms: null = 从片头开始,end_ms: null = 一直到片尾。
// 这两段响应是从 api.theintrodb.org/v4/media 实测抓下来的原文(v4 以 TVDB 为身份,
// 响应里只有 tvdb_id),用来锁住 null 语义:start_ms: null = 从片头开始,
// end_ms: null = 一直到片尾。
const (
introDBTVPayload = `{"tmdb_id":1396,"type":"tv","season":1,"episode":1,"intro":[{"start_ms":228664,"end_ms":246143}],"credits":[{"start_ms":3431000,"end_ms":null}]}`
introDBMoviePayload = `{"tmdb_id":27205,"type":"movie","intro":[{"start_ms":null,"end_ms":38000}]}`
introDBTVPayload = `{"tvdb_id":81189,"type":"tv","season":1,"episode":1,"intro":[{"start_ms":228664,"end_ms":246143}],"credits":[{"start_ms":3431000,"end_ms":null}]}`
introDBMoviePayload = `{"tvdb_id":113,"type":"movie","intro":[{"start_ms":null,"end_ms":38000}]}`
)
func TestParseIntroDBResponseResolvesNullBounds(t *testing.T) {
@@ -48,7 +49,7 @@ func TestParseIntroDBResponseResolvesNullBounds(t *testing.T) {
}
func TestParseIntroDBResponseDropsEmptyRanges(t *testing.T) {
body := `{"tmdb_id":1,"type":"movie",
body := `{"tvdb_id":1,"type":"movie",
"intro":[{"start_ms":5000,"end_ms":5000},{"start_ms":9000,"end_ms":8000},{"start_ms":1000,"end_ms":2000}],
"recap":[],"credits":[],"preview":[]}`
spans, err := parseIntroDBResponse([]byte(body))
@@ -62,7 +63,7 @@ func TestParseIntroDBResponseDropsEmptyRanges(t *testing.T) {
}
func TestParseIntroDBResponseOrdersByType(t *testing.T) {
body := `{"tmdb_id":1,"type":"tv","credits":[{"start_ms":900,"end_ms":1000}],
body := `{"tvdb_id":1,"type":"tv","credits":[{"start_ms":900,"end_ms":1000}],
"intro":[{"start_ms":100,"end_ms":200}],"recap":[{"start_ms":50,"end_ms":60}]}`
spans, err := parseIntroDBResponse([]byte(body))
if err != nil {
@@ -82,12 +83,12 @@ func TestParseIntroDBResponseOrdersByType(t *testing.T) {
func TestIntroDBMediaURLOnlyAddsSeasonEpisodeForTV(t *testing.T) {
svc := NewIntroDBService(zap.NewNop())
if got, want := svc.mediaURL(1396, 1, 1),
"https://api.theintrodb.org/v3/media?tmdb_id=1396&season=1&episode=1"; got != want {
"https://api.theintrodb.org/v4/media?tmdb_id=1396&season=1&episode=1"; got != want {
t.Fatalf("tv url = %q, want %q", got, want)
}
// 电影(season/episode 为 0)不能带季集参数,否则会被当成剧集查不到。
if got, want := svc.mediaURL(27205, 0, 0),
"https://api.theintrodb.org/v3/media?tmdb_id=27205"; got != want {
"https://api.theintrodb.org/v4/media?tmdb_id=27205"; got != want {
t.Fatalf("movie url = %q, want %q", got, want)
}
}