diff --git a/Packages/FlixyKit/Sources/FlixyProbe/main.swift b/Packages/FlixyKit/Sources/FlixyProbe/main.swift index 7154d91..c60b760 100644 --- a/Packages/FlixyKit/Sources/FlixyProbe/main.swift +++ b/Packages/FlixyKit/Sources/FlixyProbe/main.swift @@ -66,7 +66,11 @@ print("Server: \(resource.name) über \(connection.local ? "lokal" : "entfernt") // `swift run FlixyProbe /pfad /noch-ein-pfad …` fragt genau diese Adressen ab // und zeigt die Antwort. Dafür ist das Werkzeug da: eine Schnittstelle ohne // Beschreibung erkundet man, indem man sie fragt, nicht indem man rät. -let requested = CommandLine.arguments.dropFirst().filter { !$0.hasPrefix("--") } +var requested = CommandLine.arguments.dropFirst().filter { !$0.hasPrefix("--") } +// Was hinter `--channel` steht, ist keine Adresse. +if let wanted = CommandLine.arguments.drop(while: { $0 != "--channel" }).dropFirst().first { + requested.removeAll { $0 == wanted } +} if !requested.isEmpty { for path in requested { print("=== \(path) ===") @@ -115,7 +119,21 @@ print("Empfänger: \(dvr.key), Programmführer: \(dvr.epgIdentifier ?? "–")") let guide = await server.liveTVGuide(dvr: dvr, hours: 2) print("Sender: \(guide.channels.count) — \(guide.source)\n") -guard let channel = guide.channels.first else { exit(0) } +// `--channel 002` wählt einen bestimmten Sender. Sonst der erste, auf dem +// überhaupt etwas läuft — ein Sender ohne Sendung sagt über das +// Einschalten wenig aus. +let wanted = CommandLine.arguments.drop(while: { $0 != "--channel" }).dropFirst().first + +let channel = guide.channels.first { candidate in + guard let wanted else { return false } + return candidate.channelIdentifier == wanted + || candidate.channelIdentifier == wanted.trimmingCharacters(in: CharacterSet(charactersIn: "0")) + || candidate.title.localizedCaseInsensitiveContains(wanted) +} + ?? guide.channels.first { guide.programs[$0.id]?.contains { $0.isRunning() } == true } + ?? guide.channels.first + +guard let channel else { exit(0) } let program = guide.programs[channel.id]?.first { $0.isRunning() } print("Einschalten: \(channel.title) (\(channel.channelIdentifier ?? "–"))") diff --git a/Packages/FlixyKit/Sources/PlexKit/Endpoints/PlexServer+LiveTV.swift b/Packages/FlixyKit/Sources/PlexKit/Endpoints/PlexServer+LiveTV.swift index 4af9072..3adbd43 100644 --- a/Packages/FlixyKit/Sources/PlexKit/Endpoints/PlexServer+LiveTV.swift +++ b/Packages/FlixyKit/Sources/PlexKit/Endpoints/PlexServer+LiveTV.swift @@ -1556,9 +1556,21 @@ extension PlexServer { for (name, items) in variants { lines.append(" \(name): \(await probe(items: items, endpoint: "start.m3u8"))") } - // Und derselbe Satz an den Entscheider: er antwortet in Plex' Format - // statt mit HTML, wenn er überhaupt antwortet. lines.append(" Entscheider: \(await probe(items: variants.last!.1, endpoint: "decision"))") + + // Lebt der Transcoder überhaupt? `ping` und `stop` gehören zu + // derselben Familie und brauchen nur eine Sitzungskennung. Wenn auch + // sie mit 400 antworten, ist nicht die Anfrage falsch, sondern der + // ganze Zweig nicht da. + let session2 = [URLQueryItem(name: "session", value: session), + URLQueryItem(name: "X-Plex-Token", value: token)] + lines.append(" ping: \(await probe(items: session2, endpoint: "ping"))") + lines.append(" stop: \(await probe(items: session2, endpoint: "stop"))") + + // Und zur Gegenkontrolle etwas, von dem wir wissen, dass es geht: + // die Bilder kommen über denselben `/:/`-Aufbau. + lines.append(" Bild-Transcoder: \(await rawResponse(forPath: "/photo/:/transcode", limit: 120))") + lines.append(" Mediathek: \(await rawResponse(forPath: "/library/sections", limit: 120))") return lines }