From a5b0aeca98dd474103d93234ac0c50cce55d0b19 Mon Sep 17 00:00:00 2001 From: mkelvers Date: Wed, 13 May 2026 17:53:12 +0200 Subject: [PATCH] fix: fetch both sub and dub streams on watch page load Previously the backend only fetched streams for the single requested mode (defaulting to sub), so modeSources never had a dub entry. The frontend's switchMode showed visual feedback but streamUrlForMode returned an empty string since no dub token existed. Now both modes are fetched and availableModes is derived from what actually resolved. --- internal/playback/service/service.go | 100 +++++++++++++++------------ 1 file changed, 57 insertions(+), 43 deletions(-) diff --git a/internal/playback/service/service.go b/internal/playback/service/service.go index 2836e5f..38685c6 100644 --- a/internal/playback/service/service.go +++ b/internal/playback/service/service.go @@ -126,19 +126,63 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title } } + type SubtitleItem struct { + Lang string `json:"lang"` + URL string `json:"url,omitempty"` + Referer string `json:"referer,omitempty"` + Token string `json:"token"` + } + + type ModeSource struct { + URL string `json:"url,omitempty"` + Referer string `json:"referer,omitempty"` + Token string `json:"token"` + Subtitles []SubtitleItem `json:"subtitles"` + Qualities []string `json:"qualities,omitempty"` + } + + modeSources := map[string]ModeSource{} var result *domain.StreamResult - for _, p := range s.providers { - res, err := p.GetStreams(ctx, animeID, searchTitles, episode, mode) - if err == nil && res != nil { - result = res + + for _, m := range []string{"sub", "dub"} { + for _, p := range s.providers { + res, err := p.GetStreams(ctx, animeID, searchTitles, episode, m) + if err != nil || res == nil { + continue + } + + var subItems []SubtitleItem + for _, sub := range res.Subtitles { + subToken, _ := s.SignProxyToken(sub.URL, res.Referer, "subtitle") + subItems = append(subItems, SubtitleItem{ + Lang: sub.Label, + Token: subToken, + }) + } + + streamToken, _ := s.SignProxyToken(res.URL, res.Referer, "stream") + modeSources[m] = ModeSource{ + URL: res.URL, + Referer: res.Referer, + Token: streamToken, + Subtitles: subItems, + } + + if m == mode { + result = res + } break } } - if result == nil { + if len(modeSources) == 0 { return nil, fmt.Errorf("no streams found") } + if result == nil { + return nil, fmt.Errorf("no streams found for mode %s", mode) + } + // 3. Get start time from progress startTime := 0.0 var watchlistStatus string @@ -193,8 +237,6 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title } // 5. Build provider data - // AllAnime currently returns one stream in result.URL - // We wrap it for the template streams := []domain.ProviderStream{ { Name: "Primary", @@ -205,41 +247,6 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title }, } - type SubtitleItem struct { - Lang string `json:"lang"` - URL string `json:"url,omitempty"` - Referer string `json:"referer,omitempty"` - Token string `json:"token"` - } - - type ModeSource struct { - URL string `json:"url,omitempty"` - Referer string `json:"referer,omitempty"` - Token string `json:"token"` - Subtitles []SubtitleItem `json:"subtitles"` - Qualities []string `json:"qualities,omitempty"` - } - - var subtitleItems []SubtitleItem - for _, sub := range result.Subtitles { - subToken, _ := s.SignProxyToken(sub.URL, result.Referer, "subtitle") - subtitleItems = append(subtitleItems, SubtitleItem{ - Lang: sub.Label, - Token: subToken, - }) - } - - token, _ := s.SignProxyToken(result.URL, result.Referer, "stream") - - modeSources := map[string]ModeSource{ - mode: { - URL: result.URL, - Referer: result.Referer, - Token: token, - Subtitles: subtitleItems, - }, - } - go s.warmStreamURL(result.URL, result.Referer) // 6. Resolve relations/seasons @@ -281,7 +288,14 @@ func (s *playbackService) BuildWatchData(ctx context.Context, animeID int, title }, "ModeSources": modeSources, "InitialMode": mode, - "AvailableModes": []string{"sub", "dub"}, + "AvailableModes": func() []string { + var modes []string + for m := range modeSources { + modes = append(modes, m) + } + sort.Strings(modes) + return modes + }(), "Segments": segments, }