feat: use canonical episodes in watch data and wire episode service
This commit is contained in:
@@ -22,10 +22,10 @@ var Module = fx.Options(
|
||||
fx.Provide(
|
||||
repository.NewPlaybackRepository,
|
||||
fx.Annotate(
|
||||
func(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, proxyTokenKey string) domain.PlaybackService {
|
||||
return service.NewPlaybackService(repo, providers, jikan, proxyTokenKey)
|
||||
func(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, episodeSvc domain.EpisodeService, proxyTokenKey string) domain.PlaybackService {
|
||||
return service.NewPlaybackService(repo, providers, jikan, episodeSvc, proxyTokenKey)
|
||||
},
|
||||
fx.ParamTags(``, ``, ``, ``),
|
||||
fx.ParamTags(``, ``, ``, ``, ``),
|
||||
),
|
||||
func(svc domain.PlaybackService, animeSvc domain.AnimeService) *handler.PlaybackHandler {
|
||||
return handler.NewPlaybackHandler(svc, animeSvc)
|
||||
|
||||
@@ -26,6 +26,7 @@ type playbackService struct {
|
||||
repo domain.PlaybackRepository
|
||||
providers []domain.Provider
|
||||
jikan *jikan.Client
|
||||
episodes domain.EpisodeService
|
||||
httpClient *http.Client
|
||||
proxyTokenKey string
|
||||
}
|
||||
@@ -43,8 +44,8 @@ type proxyTokenPayload struct {
|
||||
ExpiresAt int64 `json:"exp"`
|
||||
}
|
||||
|
||||
func NewPlaybackService(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, proxyTokenKey string) domain.PlaybackService {
|
||||
return &playbackService{repo: repo, providers: providers, jikan: jikan, httpClient: &http.Client{Timeout: 10 * time.Second}, proxyTokenKey: proxyTokenKey}
|
||||
func NewPlaybackService(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, episodes domain.EpisodeService, proxyTokenKey string) domain.PlaybackService {
|
||||
return &playbackService{repo: repo, providers: providers, jikan: jikan, episodes: episodes, httpClient: &http.Client{Timeout: 10 * time.Second}, proxyTokenKey: proxyTokenKey}
|
||||
}
|
||||
|
||||
func (s *playbackService) SignProxyToken(targetURL, referer, scope string) (string, error) {
|
||||
@@ -127,6 +128,23 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
|
||||
}
|
||||
}
|
||||
|
||||
canonicalEpisodes, err := s.episodes.GetCanonicalEpisodes(ctx, anime, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch episodes: %w", err)
|
||||
}
|
||||
|
||||
requestedMode := mode
|
||||
modeSwitchedFrom := ""
|
||||
if epNum, parseErr := strconv.Atoi(episode); parseErr == nil && requestedMode == "dub" {
|
||||
for _, ep := range canonicalEpisodes.Episodes {
|
||||
if ep.Number == epNum && !ep.HasDub && ep.HasSub {
|
||||
mode = "sub"
|
||||
modeSwitchedFrom = requestedMode
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type SubtitleItem struct {
|
||||
Lang string `json:"lang"`
|
||||
URL string `json:"url,omitempty"`
|
||||
@@ -213,42 +231,6 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Get Episodes list
|
||||
jikanEpisodes, err := s.jikan.GetAllEpisodes(ctx, animeID)
|
||||
if err != nil {
|
||||
}
|
||||
|
||||
// Fallback/Fill episodes if needed
|
||||
totalCount := anime.Episodes
|
||||
if len(jikanEpisodes) < totalCount {
|
||||
epMap := make(map[int]jikan.Episode)
|
||||
for _, ep := range jikanEpisodes {
|
||||
epMap[ep.MalID] = ep
|
||||
}
|
||||
for i := 1; i <= totalCount; i++ {
|
||||
if _, ok := epMap[i]; !ok {
|
||||
jikanEpisodes = append(jikanEpisodes, jikan.Episode{
|
||||
MalID: i,
|
||||
Episode: fmt.Sprintf("Episode %d", i),
|
||||
Title: fmt.Sprintf("Episode %d", i),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Slice(jikanEpisodes, func(i, j int) bool {
|
||||
return jikanEpisodes[i].MalID < jikanEpisodes[j].MalID
|
||||
})
|
||||
|
||||
domainEpisodes := make([]domain.EpisodeData, len(jikanEpisodes))
|
||||
for i, ep := range jikanEpisodes {
|
||||
domainEpisodes[i] = domain.EpisodeData{
|
||||
MalID: ep.MalID,
|
||||
Title: ep.Title,
|
||||
IsFiller: ep.Filler,
|
||||
IsRecap: ep.Recap,
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Build provider data
|
||||
streams := []domain.ProviderStream{
|
||||
{
|
||||
@@ -295,12 +277,13 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
|
||||
"Title": anime.DisplayTitle(),
|
||||
"CurrentEpisode": episode,
|
||||
"StartTimeSeconds": startTime,
|
||||
"Episodes": domainEpisodes,
|
||||
"Episodes": canonicalEpisodes.Episodes,
|
||||
"Providers": []domain.ProviderData{
|
||||
{Streams: streams},
|
||||
},
|
||||
"ModeSources": modeSources,
|
||||
"InitialMode": mode,
|
||||
"ModeSources": modeSources,
|
||||
"InitialMode": mode,
|
||||
"ModeSwitchedFrom": modeSwitchedFrom,
|
||||
"AvailableModes": func() []string {
|
||||
var modes []string
|
||||
for m := range modeSources {
|
||||
@@ -315,7 +298,7 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
|
||||
return map[string]any{
|
||||
"WatchData": watchData,
|
||||
"Anime": anime,
|
||||
"Episodes": domainEpisodes,
|
||||
"Episodes": canonicalEpisodes.Episodes,
|
||||
"CurrentEpID": episode,
|
||||
"WatchlistStatus": watchlistStatus,
|
||||
"WatchlistIDs": watchlistIDs,
|
||||
|
||||
Reference in New Issue
Block a user