Live-TV: die Kennung der Sendung muss zweimal kodiert werden
Der Bericht nennt zwei Zeilen, die alles erklären:
Media.protocol = livetv
ratingKey = plex%3A%2F%2Fepisode%2F6a9a1255715fa1c9375df709
Plex führt die Kennung selbst schon kodiert — auch im JSON, wo es dafür
keinen Grund gäbe. Als Abfragewert geschickt dekodiert der Server sie
einmal, bevor er sie als Pfad liest, und bekommt `plex://episode/…`. Das
ist kein gültiger Schlüssel, und die Antwort darauf war die nackte
„400 Bad Request"-Seite.
Für eine Datei in der Mediathek ist das kein Thema: `/library/metadata/123`
enthält nichts zu kodieren. Deshalb ist beides nötig, und welche Form
gilt, hängt daran, woher die Adresse stammt.
Ich habe in diesem Punkt inzwischen jede Variante einmal für die richtige
gehalten — entpackt, einfach, doppelt. Ein Test hält jetzt alle drei
Formen fest, damit die Frage nicht ein viertes Mal aufkommt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
162247e8dc
commit
024f396641
@@ -446,7 +446,15 @@ extension PlexServer {
|
||||
// Ohne Profil als dritter Versuch: die Profilangaben stecken
|
||||
// voller `&` und `=`, die in einem Abfragewert mehrdeutig sind.
|
||||
// Trägt es ohne, liegt es daran — und das steht dann in der Spur.
|
||||
let variants: [(index: Int, profile: Bool)] = [(0, true), (-1, true), (0, false)]
|
||||
// Doppelt kodiert zuerst: der Server dekodiert den Abfragewert
|
||||
// einmal, bevor er ihn als Pfad liest. Nur so kommt bei ihm
|
||||
// wieder `plex%3A%2F%2Fepisode%2F…` an statt `plex://episode/…`.
|
||||
let variants: [(index: Int, profile: Bool, keep: Bool)] = [
|
||||
(0, true, false),
|
||||
(-1, true, false),
|
||||
(0, true, true),
|
||||
(0, false, false),
|
||||
]
|
||||
for variant in variants {
|
||||
attempts += 1
|
||||
let outcome = await attemptStream(
|
||||
@@ -454,6 +462,7 @@ extension PlexServer {
|
||||
ratingKey: channel.id,
|
||||
mediaIndex: variant.index,
|
||||
includeProfile: variant.profile,
|
||||
keepPathEncoding: variant.keep,
|
||||
maximumBitrate: maximumBitrate,
|
||||
session: session
|
||||
)
|
||||
@@ -606,6 +615,7 @@ extension PlexServer {
|
||||
ratingKey: String,
|
||||
mediaIndex: Int,
|
||||
includeProfile: Bool,
|
||||
keepPathEncoding: Bool = true,
|
||||
maximumBitrate: Int?,
|
||||
session: String
|
||||
) async -> (url: URL?, probe: ChannelProbe) {
|
||||
@@ -619,12 +629,18 @@ extension PlexServer {
|
||||
pathOverride: path
|
||||
)
|
||||
|
||||
guard let url = transcodeURL(for: request, includeProfile: includeProfile) else {
|
||||
guard let url = transcodeURL(
|
||||
for: request,
|
||||
includeProfile: includeProfile,
|
||||
keepPathEncoding: keepPathEncoding
|
||||
) else {
|
||||
return (nil, ChannelProbe(path: path, result: "Adresse nicht baubar"))
|
||||
}
|
||||
|
||||
let outcome = await probeStream(url: url)
|
||||
let label = "\(path) (mediaIndex \(mediaIndex)\(includeProfile ? "" : ", ohne Profil"))"
|
||||
let label = "\(path) (mediaIndex \(mediaIndex)"
|
||||
+ "\(includeProfile ? "" : ", ohne Profil")"
|
||||
+ "\(keepPathEncoding ? "" : ", doppelt kodiert"))"
|
||||
return (outcome.hasPrefix("HTTP 200") ? url : nil, ChannelProbe(path: label, result: outcome))
|
||||
}
|
||||
|
||||
@@ -713,6 +729,8 @@ extension PlexServer {
|
||||
}
|
||||
|
||||
paths += sessionKeys(channel: channel, program: program).map { "\(sessionPath)/\($0)" }
|
||||
// Und die Sitzung ohne Schlüssel — bisher nie probiert.
|
||||
paths.append(sessionPath)
|
||||
|
||||
var seen = Set<String>()
|
||||
return paths.filter { seen.insert($0).inserted }
|
||||
|
||||
Reference in New Issue
Block a user