Live-TV: die Lineup-Kennung ist eine Adresse, keine Kennung

Der zweite Abzug zeigt den Pfad, der 404 ergab:

    /tv.plex.providers.epg.cloud:2/lineups/
      lineup://tv.plex.providers.epg.cloud/6228f7f2364e02fa5ec8e51c
      #Swisscom%20Blue%20TV%20%28Deutschschweiz%29%20%28521%20channels%29
      /channels

`Lineup.id` heißt zwar Kennung, ist aber eine vollständige Adresse: mit
Schema, Doppelschrägstrich, Prozentzeichen und einem Anhang hinter der
Raute. Die habe ich roh in den Pfad gespleißt.

Gebraucht wird der nackte Teil in der Mitte —
`6228f7f2364e02fa5ec8e51c`. `PlexLineup.pathIdentifier` packt ihn aus,
vier Tests halten die Fälle fest.

Da die Pfadform zwischen Serverfassungen schwankt und dieser Teil der
API keine Beschreibung hat, werden drei Adressen der Reihe nach
probiert. Welche gegriffen hat, steht in der Diagnose — damit aus dem
Durchprobieren beim nächsten Mal Wissen wird. Der Strukturabzug deckt
jetzt alle drei ab.

173 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Guido
2026-09-12 10:55:14 +02:00
co-authored by Claude Opus 5
parent 90d5d96485
commit 9f9eec1b7f
3 changed files with 154 additions and 35 deletions
@@ -82,9 +82,28 @@ public struct PlexDVR: Sendable, Equatable, Decodable, Identifiable {
/// Eine Senderliste des Anbieters — bei Kabel oder IPTV oft mehrere hundert.
public struct PlexLineup: Sendable, Equatable, Decodable, Identifiable {
/// Die Kennung, wie Plex sie liefert.
///
/// Trotz des Namens keine Kennung, sondern eine vollständige Adresse:
///
/// lineup://tv.plex.providers.epg.cloud/6228f7f2364e02fa5ec8e51c#Swisscom%20Blue%20TV
///
/// Mit Schema, Doppelschrägstrich, Prozentzeichen und einem Anhang hinter
/// der Raute. Roh in einen Pfad gesetzt ergibt das zwangsläufig 404 —
/// genau daran scheiterte die Senderabfrage.
public let id: String
public let title: String?
/// Der nackte Teil in der Mitte, als Pfadabschnitt verwendbar.
///
/// Aus der Adresse oben wird `6228f7f2364e02fa5ec8e51c`.
public var pathIdentifier: String {
// Der Anhang hinter der Raute ist der Anzeigename und gehört nicht in
// die Adresse.
let withoutFragment = id.split(separator: "#", maxSplits: 1).first.map(String.init) ?? id
return withoutFragment.split(separator: "/").last.map(String.init) ?? withoutFragment
}
public init(id: String, title: String? = nil) {
self.id = id
self.title = title