App v0.2.26 and gateway 0.1.20
Client: seek controls, Bazarr subtitle download and cast panel in the player; MDBList ratings strip; episode and schedule detail pages; series pace estimate; what's new panel; install-permission onboarding step; synced per-profile preferences; Emby outage banner. Gateway: rebuilt admin console (one fragment per page), preference history and restore, merged Continue Watching, Emby health probe, subtitle selection and Bazarr download, structured request logging with per-request identity, and embedded build version. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
2675e6d82b
commit
4a4df7a73c
@@ -61,19 +61,25 @@ func New(baseURL string, timeout time.Duration) *Client {
|
||||
}
|
||||
}
|
||||
|
||||
// Movie resolves a movie through one of the identifier providers accepted by MDBList.
|
||||
// The single-title endpoint returns every rating source available for that title in one
|
||||
// request, which lets source selection happen locally without spending more API quota.
|
||||
func (c *Client) Movie(
|
||||
ctx context.Context, apiKey, provider, providerID string,
|
||||
// Media resolves a movie or series through one of the identifier providers accepted by
|
||||
// MDBList. The single-title endpoint returns every rating source in one request, which
|
||||
// lets source selection happen locally without spending more API quota.
|
||||
func (c *Client) Media(
|
||||
ctx context.Context, apiKey, provider, providerID, mediaType string,
|
||||
) ([]Rating, error) {
|
||||
apiKey = strings.TrimSpace(apiKey)
|
||||
provider = strings.ToLower(strings.TrimSpace(provider))
|
||||
providerID = strings.TrimSpace(providerID)
|
||||
if apiKey == "" || providerID == "" || (provider != "tmdb" && provider != "imdb") {
|
||||
return nil, fmt.Errorf("mdblist: invalid movie lookup")
|
||||
mediaType = strings.ToLower(strings.TrimSpace(mediaType))
|
||||
if mediaType == "series" || mediaType == "tv" {
|
||||
mediaType = "show"
|
||||
}
|
||||
endpoint, err := url.Parse(c.baseURL + "/" + provider + "/movie/" + url.PathEscape(providerID) + "/")
|
||||
if apiKey == "" || providerID == "" ||
|
||||
(provider != "tmdb" && provider != "imdb") ||
|
||||
(mediaType != "movie" && mediaType != "show") {
|
||||
return nil, fmt.Errorf("mdblist: invalid media lookup")
|
||||
}
|
||||
endpoint, err := url.Parse(c.baseURL + "/" + provider + "/" + mediaType + "/" + url.PathEscape(providerID) + "/")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("mdblist: build request: %w", err)
|
||||
}
|
||||
@@ -111,6 +117,10 @@ func (c *Client) Movie(
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Client) Movie(ctx context.Context, apiKey, provider, providerID string) ([]Rating, error) {
|
||||
return c.Media(ctx, apiKey, provider, providerID, "movie")
|
||||
}
|
||||
|
||||
func numericValue(raw json.RawMessage) (float64, bool) {
|
||||
text := strings.TrimSpace(string(raw))
|
||||
if text == "" || text == "null" {
|
||||
|
||||
@@ -40,3 +40,17 @@ func TestMovieRejectsUnsupportedProviderBeforeCallingUpstream(t *testing.T) {
|
||||
t.Fatal("expected unsupported provider to fail")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMediaUsesShowEndpointForSeries(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/imdb/show/tt0944947/" {
|
||||
t.Fatalf("unexpected path %s", r.URL.Path)
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"ratings":[{"source":"trakt","value":89}]}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
got, err := New(server.URL, time.Second).Media(context.Background(), "secret", "imdb", "tt0944947", "series")
|
||||
if err != nil || len(got) != 1 || got[0].Value != 89 {
|
||||
t.Fatalf("ratings=%+v err=%v", got, err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user