diff --git a/integrations/playback/allanime/client.go b/integrations/playback/allanime/client.go index c4d3f4e..1e366b8 100644 --- a/integrations/playback/allanime/client.go +++ b/integrations/playback/allanime/client.go @@ -46,7 +46,7 @@ func (c *AllAnimeProvider) Name() string { } func (c *AllAnimeProvider) GetStreams(ctx context.Context, animeID int, titleCandidates []string, episode string, mode string) (*domain.StreamResult, error) { - showID := c.resolveShowIDWithFallback(ctx, animeID, titleCandidates, mode) + showID := c.showID(ctx, animeID, titleCandidates, mode) if showID == "" { return nil, fmt.Errorf("allanime: show not found for malID %d", animeID) } diff --git a/integrations/playback/allanime/client_test.go b/integrations/playback/allanime/client_test.go index faff683..6881ca8 100644 --- a/integrations/playback/allanime/client_test.go +++ b/integrations/playback/allanime/client_test.go @@ -251,7 +251,7 @@ func TestBuildStreamSource(t *testing.T) { func TestResolveDirectSourceSkipsEmbeds(t *testing.T) { t.Parallel() - if _, ok := resolveDirectSource(sourceReference{ + if _, ok := directSource(sourceReference{ URL: "https://ok.ru/videoembed/123", Name: "ok", }); ok { diff --git a/integrations/playback/allanime/crypto.go b/integrations/playback/allanime/crypto.go index dc9bfca..35e225c 100644 --- a/integrations/playback/allanime/crypto.go +++ b/integrations/playback/allanime/crypto.go @@ -120,7 +120,7 @@ func decodeSourceURL(encoded string) string { } func responseFromTobeparsed(data map[string]any) (map[string]any, error) { - toBeParsed := firstNonEmptyString( + toBeParsed := firstString( nestedString(data, "tobeparsed"), nestedString(data, "episode", "tobeparsed"), ) @@ -138,7 +138,7 @@ func responseFromTobeparsed(data map[string]any) (map[string]any, error) { return nil, err } - sourceURLs := firstNonEmptySlice( + sourceURLs := firstSlice( nestedSlice(parsed, "sourceUrls"), nestedSlice(parsed, "episode", "sourceUrls"), ) @@ -166,7 +166,8 @@ func parseGraphQLResponse(respBody []byte, decodeErrPrefix string) (map[string]a return parsed, nil } -func firstNonEmptyString(values ...string) string { +// first non-empty +func firstString(values ...string) string { for _, value := range values { if value != "" { return value @@ -176,7 +177,8 @@ func firstNonEmptyString(values ...string) string { return "" } -func firstNonEmptySlice(values ...[]any) []any { +// first non-empty +func firstSlice(values ...[]any) []any { for _, value := range values { if len(value) > 0 { return value diff --git a/integrations/playback/allanime/extractor.go b/integrations/playback/allanime/extractor.go index 4826b0e..efd71bb 100644 --- a/integrations/playback/allanime/extractor.go +++ b/integrations/playback/allanime/extractor.go @@ -81,7 +81,7 @@ func (e *providerExtractor) ExtractVideoLinks(ctx context.Context, providerPath return nil, fmt.Errorf("read provider response: %w", err) } - return e.parseProviderResponse(ctx, string(body)), nil + return e.parseResponse(ctx, string(body)), nil } func (e *providerExtractor) ExtractEmbedVideoLinks(ctx context.Context, rawURL string) ([]StreamSource, error) { @@ -98,11 +98,11 @@ func (e *providerExtractor) ExtractEmbedVideoLinks(ctx context.Context, rawURL s return nil, fmt.Errorf("read embed response: %w", err) } - return parseExternalEmbedResponse(rawURL, string(body), e.referer), nil + return parseEmbed(rawURL, string(body), e.referer), nil } -// parseProviderResponse extracts stream sources from provider JSON response. -func (e *providerExtractor) parseProviderResponse(ctx context.Context, response string) []StreamSource { +// provider response +func (e *providerExtractor) parseResponse(ctx context.Context, response string) []StreamSource { var root any if err := json.Unmarshal([]byte(response), &root); err != nil { return []StreamSource{} @@ -367,12 +367,13 @@ func quality(bandwidth int) string { } } -func parseExternalEmbedResponse(rawURL string, body string, fallbackReferer string) []StreamSource { +// embed page +func parseEmbed(rawURL string, body string, fallbackReferer string) []StreamSource { switch { case strings.Contains(strings.ToLower(rawURL), "ok.ru/"): return parseOKRUSources(body, fallbackReferer) case strings.Contains(strings.ToLower(rawURL), "mp4upload.com/"): - return parseMP4UploadSources(body, fallbackReferer) + return parseMP4Upload(body, fallbackReferer) default: return nil } @@ -386,7 +387,7 @@ func parseOKRUSources(body string, referer string) []StreamSource { return nil } - playlistURL := decodeEscapedMediaURL(firstNonEmptyString(match[1], match[2])) + playlistURL := mediaURL(firstString(match[1], match[2])) if playlistURL == "" { return nil } @@ -400,27 +401,27 @@ func parseOKRUSources(body string, referer string) []StreamSource { }} } -func parseMP4UploadSources(body string, referer string) []StreamSource { +func parseMP4Upload(body string, referer string) []StreamSource { srcPattern := regexp.MustCompile(`(?m)src:\s*"([^"]+)"`) match := srcPattern.FindStringSubmatch(body) if len(match) < 2 { return nil } - mediaURL := decodeEscapedMediaURL(match[1]) - if mediaURL == "" { + url := mediaURL(match[1]) + if url == "" { return nil } return []StreamSource{{ - URL: mediaURL, + URL: url, Provider: "mp4upload", - Type: sourceType(mediaURL), + Type: sourceType(url), Referer: referer, }} } -func decodeEscapedMediaURL(raw string) string { +func mediaURL(raw string) string { if unquoted, err := strconv.Unquote(`"` + raw + `"`); err == nil { raw = unquoted } diff --git a/integrations/playback/allanime/http_test.go b/integrations/playback/allanime/http_test.go index 7df20c3..8a87732 100644 --- a/integrations/playback/allanime/http_test.go +++ b/integrations/playback/allanime/http_test.go @@ -539,7 +539,7 @@ func TestParseProviderResponse(t *testing.T) { referer: allAnimeReferer, } - sources := extractor.parseProviderResponse(context.Background(), body) + sources := extractor.parseResponse(context.Background(), body) if len(sources) == 0 { t.Fatal("expected at least one source") } @@ -566,7 +566,7 @@ func TestParseProviderResponse(t *testing.T) { referer: allAnimeReferer, } - sources := extractor.parseProviderResponse(context.Background(), "not json") + sources := extractor.parseResponse(context.Background(), "not json") if len(sources) != 0 { t.Errorf("expected empty, got %d sources", len(sources)) } @@ -580,7 +580,7 @@ func TestParseProviderResponse(t *testing.T) { referer: allAnimeReferer, } - sources := extractor.parseProviderResponse(context.Background(), "{}") + sources := extractor.parseResponse(context.Background(), "{}") if len(sources) != 0 { t.Errorf("expected empty, got %d sources", len(sources)) } @@ -594,7 +594,7 @@ func TestParseExternalEmbedResponse(t *testing.T) { t.Parallel() body := `{"flashvars":{"metadata":"{\"hlsManifestUrl\":\"https://ok.example.test/playlist.m3u8\"}"}}` - sources := parseExternalEmbedResponse("https://ok.ru/video/123", body, allAnimeReferer) + sources := parseEmbed("https://ok.ru/video/123", body, allAnimeReferer) if len(sources) != 1 { t.Fatalf("got %d sources, want 1", len(sources)) } @@ -610,7 +610,7 @@ func TestParseExternalEmbedResponse(t *testing.T) { t.Parallel() body := `src: "https://mp4upload.example.test/video.mp4"` - sources := parseExternalEmbedResponse("https://mp4upload.com/e/abc", body, allAnimeReferer) + sources := parseEmbed("https://mp4upload.com/e/abc", body, allAnimeReferer) if len(sources) != 1 { t.Fatalf("got %d sources, want 1", len(sources)) } @@ -625,7 +625,7 @@ func TestParseExternalEmbedResponse(t *testing.T) { t.Run("unknown embed returns empty", func(t *testing.T) { t.Parallel() - sources := parseExternalEmbedResponse("https://unknown.example.com/video", "", allAnimeReferer) + sources := parseEmbed("https://unknown.example.com/video", "", allAnimeReferer) if len(sources) != 0 { t.Errorf("expected empty, got %d sources", len(sources)) } diff --git a/integrations/playback/allanime/search.go b/integrations/playback/allanime/search.go index f6ded3b..3b5dec2 100644 --- a/integrations/playback/allanime/search.go +++ b/integrations/playback/allanime/search.go @@ -99,7 +99,7 @@ func (c *AllAnimeProvider) Search(ctx context.Context, query string, mode string return out, nil } -func (c *AllAnimeProvider) resolveShowIDWithFallback(ctx context.Context, animeID int, titleCandidates []string, mode string) string { +func (c *AllAnimeProvider) showID(ctx context.Context, animeID int, titleCandidates []string, mode string) string { targetMalIDStr := strconv.Itoa(animeID) fallbackID := "" @@ -131,7 +131,7 @@ func exactMatchShowID(searchResults []searchResult, targetMalID string) string { func (c *AllAnimeProvider) ResolveEpisodeProviderID(ctx context.Context, animeID int, titleCandidates []string) (string, error) { for _, mode := range []string{"sub", "dub"} { - showID, err := c.resolveShowIDStrict(ctx, animeID, titleCandidates, mode) + showID, err := c.strictShowID(ctx, animeID, titleCandidates, mode) if err == nil { return showID, nil } @@ -139,7 +139,7 @@ func (c *AllAnimeProvider) ResolveEpisodeProviderID(ctx context.Context, animeID return "", fmt.Errorf("allanime: no exact mal id match for %d", animeID) } -func (c *AllAnimeProvider) resolveShowIDStrict(ctx context.Context, animeID int, titleCandidates []string, mode string) (string, error) { +func (c *AllAnimeProvider) strictShowID(ctx context.Context, animeID int, titleCandidates []string, mode string) (string, error) { targetMalIDStr := strconv.Itoa(animeID) for _, title := range titleCandidates { searchResults, err := c.Search(ctx, title, mode) diff --git a/integrations/playback/allanime/sources.go b/integrations/playback/allanime/sources.go index 0e7cbbe..46b79cd 100644 --- a/integrations/playback/allanime/sources.go +++ b/integrations/playback/allanime/sources.go @@ -25,7 +25,7 @@ func (c *AllAnimeProvider) GetEpisodeSources(ctx context.Context, showID string, result, err := c.graphqlRequestWithHash(ctx, showID, episode, mode) if err == nil { - sources := c.extractSourceURLsFromData(ctx, result) + sources := c.sourcesFrom(ctx, result) if len(sources) > 0 { return sources, nil } @@ -69,7 +69,7 @@ func (c *AllAnimeProvider) GetEpisodeSources(ctx context.Context, showID string, return out, nil } -func (c *AllAnimeProvider) extractSourceURLsFromData(ctx context.Context, data map[string]any) []StreamSource { +func (c *AllAnimeProvider) sourcesFrom(ctx context.Context, data map[string]any) []StreamSource { episodeData, ok := data["episode"].(map[string]any) if !ok { return nil @@ -91,7 +91,7 @@ func (c *AllAnimeProvider) extractSourceURLsFromData(ctx context.Context, data m func (c *AllAnimeProvider) resolveRefs(ctx context.Context, references []sourceReference) []StreamSource { out := make([]StreamSource, 0, len(references)) for _, ref := range references { - if source, ok := resolveDirectSource(ref); ok { + if source, ok := directSource(ref); ok { out = append(out, source) return out } @@ -106,7 +106,7 @@ func (c *AllAnimeProvider) resolveRefs(ctx context.Context, references []sourceR return out } -func resolveDirectSource(ref sourceReference) (StreamSource, bool) { +func directSource(ref sourceReference) (StreamSource, bool) { target := strings.TrimSpace(ref.URL) if target == "" { return StreamSource{}, false @@ -240,7 +240,7 @@ func stringMapValue(item map[string]any, key string) (string, bool) { } func (c *AllAnimeProvider) graphqlRequestWithHash(ctx context.Context, showID, episode, mode string) (map[string]any, error) { - req, err := newEpisodeHashRequest(ctx, showID, episode, mode) + req, err := newHashRequest(ctx, showID, episode, mode) if err != nil { return nil, fmt.Errorf("create GET request: %w", err) } @@ -289,7 +289,7 @@ func (c *AllAnimeProvider) graphqlRequestWithHash(ctx context.Context, showID, e return nil, errors.New("no usable data in response") } -func newEpisodeHashRequest(ctx context.Context, showID, episode, mode string) (*http.Request, error) { +func newHashRequest(ctx context.Context, showID, episode, mode string) (*http.Request, error) { varsJSON := fmt.Sprintf(`{"showId":"%s","translationType":"%s","episodeString":"%s"}`, showID, strings.ToLower(mode), episode) extJSON := fmt.Sprintf(`{"persistedQuery":{"version":1,"sha256Hash":"%s"}}`, episodeQueryHash)