* fix(jellycompat): match MediaSourceId across UUID formats (compact vs dashed)
* fix(jellycompat): honor ImageTypes=Backdrop as a filter on /Items
Wholphin genre cards request /Items?imageTypes=Backdrop&limit=1&sortBy=Random
and assume every returned item has a backdrop. Silo ignored ImageTypes, so a
random pick could lack a backdrop (BackdropImageTags: null), crashing Wholphin.
Push the filter down to the catalog browse SQL
(NULLIF(BTRIM(backdrop_path),'') IS NOT NULL) so random/limited selections only
ever consider backdrop-having items; empty genres correctly return [].
* fix(jellycompat): case-insensitive PlaySessionId + api_key in stream auth
Wholphin's jellyfin-sdk-kotlin builds its own direct-play URL
(/Videos/{id}/stream?static=true&playSessionId=...&mediaSourceId=...) with a
lowercase 'playSessionId', no api_key, and no auth header (ExoPlayer's data
source drops it). PlaybackSessionAuth read 'PlaySessionId'/'PlaySessionID'
case-sensitively, so the fallback never matched -> 401 on every direct-play
stream -> forced (often failing) transcode fallback. Resolve PlaySessionId via
newCaseInsensitiveQuery, and likewise accept case-variant api_key in
ExtractToken.
* fix(jellycompat): support Wholphin season item queries
---------
Co-authored-by: Quick <31828688+Quick104@users.noreply.github.com>
32 lines
1.1 KiB
Go
32 lines
1.1 KiB
Go
package catalog
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// TestBuildBrowsePlan_RequireBackdrop asserts the ImageTypes=Backdrop filter
|
|
// (BrowseFilters.RequireBackdrop) renders the backdrop-presence predicate into
|
|
// the WHERE clause, and is absent otherwise. Guards against a future refactor
|
|
// of buildBrowsePlan silently dropping the condition.
|
|
func TestBuildBrowsePlan_RequireBackdrop(t *testing.T) {
|
|
const predicate = "NULLIF(BTRIM(mi.backdrop_path), '') IS NOT NULL"
|
|
repo := &BrowseRepository{}
|
|
|
|
plan, earlyEmpty, err := repo.buildBrowsePlan(BrowseFilters{Type: "movie", RequireBackdrop: true})
|
|
if err != nil || earlyEmpty {
|
|
t.Fatalf("buildBrowsePlan(RequireBackdrop) err=%v earlyEmpty=%v", err, earlyEmpty)
|
|
}
|
|
if !strings.Contains(plan.whereClause, predicate) {
|
|
t.Fatalf("RequireBackdrop=true: whereClause missing predicate.\ngot: %s", plan.whereClause)
|
|
}
|
|
|
|
plan, _, err = repo.buildBrowsePlan(BrowseFilters{Type: "movie"})
|
|
if err != nil {
|
|
t.Fatalf("buildBrowsePlan err=%v", err)
|
|
}
|
|
if strings.Contains(plan.whereClause, predicate) {
|
|
t.Fatalf("RequireBackdrop unset: predicate should be absent.\ngot: %s", plan.whereClause)
|
|
}
|
|
}
|