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(
|
fx.Provide(
|
||||||
repository.NewPlaybackRepository,
|
repository.NewPlaybackRepository,
|
||||||
fx.Annotate(
|
fx.Annotate(
|
||||||
func(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, proxyTokenKey string) domain.PlaybackService {
|
func(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, episodeSvc domain.EpisodeService, proxyTokenKey string) domain.PlaybackService {
|
||||||
return service.NewPlaybackService(repo, providers, jikan, proxyTokenKey)
|
return service.NewPlaybackService(repo, providers, jikan, episodeSvc, proxyTokenKey)
|
||||||
},
|
},
|
||||||
fx.ParamTags(``, ``, ``, ``),
|
fx.ParamTags(``, ``, ``, ``, ``),
|
||||||
),
|
),
|
||||||
func(svc domain.PlaybackService, animeSvc domain.AnimeService) *handler.PlaybackHandler {
|
func(svc domain.PlaybackService, animeSvc domain.AnimeService) *handler.PlaybackHandler {
|
||||||
return handler.NewPlaybackHandler(svc, animeSvc)
|
return handler.NewPlaybackHandler(svc, animeSvc)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ type playbackService struct {
|
|||||||
repo domain.PlaybackRepository
|
repo domain.PlaybackRepository
|
||||||
providers []domain.Provider
|
providers []domain.Provider
|
||||||
jikan *jikan.Client
|
jikan *jikan.Client
|
||||||
|
episodes domain.EpisodeService
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
proxyTokenKey string
|
proxyTokenKey string
|
||||||
}
|
}
|
||||||
@@ -43,8 +44,8 @@ type proxyTokenPayload struct {
|
|||||||
ExpiresAt int64 `json:"exp"`
|
ExpiresAt int64 `json:"exp"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlaybackService(repo domain.PlaybackRepository, providers []domain.Provider, jikan *jikan.Client, proxyTokenKey string) domain.PlaybackService {
|
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, httpClient: &http.Client{Timeout: 10 * time.Second}, proxyTokenKey: proxyTokenKey}
|
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) {
|
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 {
|
type SubtitleItem struct {
|
||||||
Lang string `json:"lang"`
|
Lang string `json:"lang"`
|
||||||
URL string `json:"url,omitempty"`
|
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
|
// 5. Build provider data
|
||||||
streams := []domain.ProviderStream{
|
streams := []domain.ProviderStream{
|
||||||
{
|
{
|
||||||
@@ -295,12 +277,13 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
|
|||||||
"Title": anime.DisplayTitle(),
|
"Title": anime.DisplayTitle(),
|
||||||
"CurrentEpisode": episode,
|
"CurrentEpisode": episode,
|
||||||
"StartTimeSeconds": startTime,
|
"StartTimeSeconds": startTime,
|
||||||
"Episodes": domainEpisodes,
|
"Episodes": canonicalEpisodes.Episodes,
|
||||||
"Providers": []domain.ProviderData{
|
"Providers": []domain.ProviderData{
|
||||||
{Streams: streams},
|
{Streams: streams},
|
||||||
},
|
},
|
||||||
"ModeSources": modeSources,
|
"ModeSources": modeSources,
|
||||||
"InitialMode": mode,
|
"InitialMode": mode,
|
||||||
|
"ModeSwitchedFrom": modeSwitchedFrom,
|
||||||
"AvailableModes": func() []string {
|
"AvailableModes": func() []string {
|
||||||
var modes []string
|
var modes []string
|
||||||
for m := range modeSources {
|
for m := range modeSources {
|
||||||
@@ -315,7 +298,7 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title
|
|||||||
return map[string]any{
|
return map[string]any{
|
||||||
"WatchData": watchData,
|
"WatchData": watchData,
|
||||||
"Anime": anime,
|
"Anime": anime,
|
||||||
"Episodes": domainEpisodes,
|
"Episodes": canonicalEpisodes.Episodes,
|
||||||
"CurrentEpID": episode,
|
"CurrentEpID": episode,
|
||||||
"WatchlistStatus": watchlistStatus,
|
"WatchlistStatus": watchlistStatus,
|
||||||
"WatchlistIDs": watchlistIDs,
|
"WatchlistIDs": watchlistIDs,
|
||||||
|
|||||||
Reference in New Issue
Block a user