* 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>
64 lines
1.3 KiB
Go
64 lines
1.3 KiB
Go
package jellycompat
|
|
|
|
import "testing"
|
|
|
|
func TestMediaSourceIDsEqual(t *testing.T) {
|
|
cases := []struct {
|
|
name string
|
|
a string
|
|
b string
|
|
want bool
|
|
}{
|
|
{
|
|
name: "identical dashed",
|
|
a: "03000000-0000-0000-0000-00000019e8c2",
|
|
b: "03000000-0000-0000-0000-00000019e8c2",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "dashed vs compact (Wholphin)",
|
|
a: "03000000-0000-0000-0000-00000019e8c2",
|
|
b: "0300000000000000000000000019e8c2",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "compact vs dashed",
|
|
a: "0300000000000000000000000019e8c2",
|
|
b: "03000000-0000-0000-0000-00000019e8c2",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "case insensitive hex",
|
|
a: "03000000-0000-0000-0000-00000019E8C2",
|
|
b: "0300000000000000000000000019e8c2",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "different uuids",
|
|
a: "03000000-0000-0000-0000-00000019e8c2",
|
|
b: "0300000000000000000000000019e8c3",
|
|
want: false,
|
|
},
|
|
{
|
|
name: "non-uuid falls back to exact match",
|
|
a: "abc",
|
|
b: "abc",
|
|
want: true,
|
|
},
|
|
{
|
|
name: "non-uuid mismatch",
|
|
a: "abc",
|
|
b: "def",
|
|
want: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range cases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
if got := mediaSourceIDsEqual(tc.a, tc.b); got != tc.want {
|
|
t.Fatalf("mediaSourceIDsEqual(%q, %q) = %v, want %v", tc.a, tc.b, got, tc.want)
|
|
}
|
|
})
|
|
}
|
|
}
|