import Foundation @main struct ZokoCheck { struct Failure: LocalizedError { let message: String var errorDescription: String? { message } } static func require(_ condition: @autoclosure () -> Bool, _ message: String) throws { if !condition() { throw Failure(message: message) } } static func expect(_ category: ZokoError, _ operation: () throws -> Void) throws { do { try operation() } catch let error as ZokoError where error == category { return } throw Failure(message: "Incorrect provider error category") } static func page(_ config: [String: Any]) throws -> String { try page(data: JSONSerialization.data(withJSONObject: config)) } static func page(data: Data) -> String { var data = Array(data) let key = Array("otaku-embed-v1".utf8) for i in data.indices { data[i] ^= key[i % key.count] } return "" } static func checks() async throws { let watch = "https://zokoanime.video/stream/ani/1/1/sub" guard case .anilist(let id, let episode) = try StreamURL.parse(watch) else { throw Failure(message: "AniList URL classification") } try require(id == "1" && episode == 1, "AniList stable ID admission") for bad in ["http://zokoanime.video/stream/ani/1/1/sub", "https://zokoanime.video/stream/anilist/1/1/sub", watch + "?token=bad", watch + "#bad", watch + "/", watch.replacingOccurrences(of: "/1/1/", with: "/01/1/"), watch.replacingOccurrences(of: "/1/sub", with: "/01/sub"), watch.replacingOccurrences(of: "/1/sub", with: "/2147483648/sub"), watch.replacingOccurrences(of: "/sub", with: "/dub"), "https://a@zokoanime.video/stream/ani/1/1/sub", "https://zokoanime.video/stream/ani/%31/1/sub"] { do { _ = try StreamURL.parse(bad) } catch { continue } throw Failure(message: "Noncanonical provider URL accepted") } var config: [String: Any] = ["src": "https://hls.dramahot.top/master.m3u8?token=fixture", "subtitles": [["src": "https://hls.dramahot.top/en.vtt", "lang": "en", "label": "English", "default": true]]] let intro = ProviderInterval(kind: .intro, start: 49.25, end: 144.75) let outro = ProviderInterval(kind: .outro, start: 1357.125, end: 1451.5) config["skip"] = ["intro": ["start": intro.start, "end": intro.end], "outro": ["start": outro.start, "end": outro.end]] let source = try ZokoResolver.parse(page: page(config), mediaID: "1", episode: 1) try require(source.intervals == [intro, outro], "fractional provider boundaries retain seconds and kinds") let replaced = source.replacingSubtitles([]) try require(replaced.intervals == source.intervals && replaced.subtitles.isEmpty && replaced.identity == source.identity && replaced.requirements.zoko, "subtitle replacement preserves provider intervals and playback requirements") let malformedMetadata: [Any] = [NSNull(), true, "bad", [], [:], ["intro": NSNull(), "outro": "bad"]] for metadata in malformedMetadata { var malformed = config malformed["skip"] = metadata let parsed = try ZokoResolver.parse(page: page(malformed), mediaID: "1", episode: 1) try require(parsed.intervals.isEmpty && parsed.url == source.url && parsed.subtitles.count == 1, "missing or malformed skip metadata does not block valid playback") } var absent = config absent.removeValue(forKey: "skip") let withoutTimings = try ZokoResolver.parse(page: page(absent), mediaID: "1", episode: 1) try require(withoutTimings.intervals.isEmpty && withoutTimings.url == source.url, "provider timings are optional") let invalidTimings: [Any] = [ NSNull(), true, "bad", [], [:], ["start": 1], ["end": 2], ["start": true, "end": 144], ["start": 49, "end": false], ["start": "49", "end": 144], ["start": 49, "end": "144"], ["start": -1, "end": 144], ["start": 49, "end": -1], ["start": 49, "end": 49], ["start": 144, "end": 49] ] for invalid in invalidTimings { for badKind in ["intro", "outro"] { var malformed = config var skip = config["skip"] as! [String: Any] skip[badKind] = invalid malformed["skip"] = skip let parsed = try ZokoResolver.parse(page: page(malformed), mediaID: "1", episode: 1) try require(parsed.intervals == (badKind == "intro" ? [outro] : [intro]) && parsed.url == source.url, "each malformed interval is discarded independently without blocking playback") } } for timing in [#"{"start":1e999,"end":144}"#, #"{"start":49,"end":1e999}"#] { let data = Data(""" {"src":"https://hls.dramahot.top/master.m3u8","subtitles":[], "skip":{"intro":\(timing),"outro":{"start":1357.125,"end":1451.5}}} """.utf8) let parsed = try ZokoResolver.parse(page: page(data: data), mediaID: "1", episode: 1) try require(parsed.intervals == [outro], "nonfinite numeric interval never blocks a valid sibling or playback") } var zeroStart = config zeroStart["skip"] = ["intro": ["start": 0, "end": 1.5]] let zeroSource = try ZokoResolver.parse(page: page(zeroStart), mediaID: "1", episode: 1) try require(zeroSource.intervals == [ProviderInterval(kind: .intro, start: 0, end: 1.5)], "zero-based intervals remain valid") let mapped = try await ZokoResolver.resolve(mediaID: "97940", episode: 1, fetchResponse: { request in let data: Data let mime: String if request.url?.absoluteString == "https://graphql.anilist.co/" { let body = try JSONSerialization.jsonObject(with: request.httpBody!) as! [String: Any] try require((body["variables"] as? [String: Int])?["id"] == 97940, "mapping uses the original AniList ID") data = Data(#"{"data":{"Media":{"id":97940,"idMal":34572,"title":{"english":"Black Clover"}}}}"#.utf8) mime = "application/json" } else { try require(request.url?.absoluteString == "https://zokoanime.video/stream/mal/34572/1/sub", "provider lookup uses the exact mapped MAL ID, not AniList ID") data = Data(try page(["src": "https://hls.dramahot.top/master.m3u8", "subtitles": [], "skip": ["intro": ["start": 49.25, "end": 144.75]]]).utf8) mime = "text/html" } return (data, HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: ["Content-Type": mime])!) }) try require(mapped.identity == "anilist:97940:1" && mapped.title == "Black Clover · Episode 1 (sub)", "mapped playback preserves AniList identity and catalog title") try require(mapped.intervals == [intro] && mapped.requirements.zoko, "catalog title enrichment preserves provider intervals and transport requirements") for bad in [ #"{"data":{"Media":{"id":34572,"idMal":97940}}}"#, #"{"data":{"Media":{"id":97940,"idMal":0}}}"#, #"{"data":{"Media":{"id":97940,"idMal":-1}}}"#, #"{"data":{"Media":{"id":97940,"idMal":2147483648}}}"#, #"{"data":{"Media":{"id":97940,"idMal":true}}}"#, #"{"data":{"Media":{"id":97940,"idMal":34572}},"errors":[{"message":"partial failure"}]}"# ] { try expect(.malformed) { _ = try ZokoResolver.decodeCatalog(Data(bad.utf8), mediaID: "97940") } } do { _ = try await ZokoResolver.resolve(mediaID: "97940", episode: 1, enrichTitle: false, fetchResponse: { request in try require(request.url?.host == "graphql.anilist.co", "missing mapping must not guess a provider ID") return (Data(#"{"data":{"Media":{"id":97940,"idMal":null}}}"#.utf8), HTTPURLResponse(url: request.url!, statusCode: 200, httpVersion: nil, headerFields: ["Content-Type": "application/json"])!) }) throw Failure(message: "missing mapping accepted") } catch ZokoError.mapping {} try require(source.identity == "anilist:1:1" && source.requirements.zoko, "native scoped transport selected") try require(source.title == "AniList 1 · Episode 1 (sub)" && source.subtitles.count == 1 && source.subtitles[0].isDefault, "honest fallback title and VTT metadata") try require(source.headers == ZokoResolver.referer && source.subtitles[0].headers == ZokoResolver.referer, "only fixed public Referer scoped to declared CDN") let semicolonless = try page(config).replacingOccurrences(of: "';", with: "'") let deployedSource = try ZokoResolver.parse(page: semicolonless, mediaID: "1", episode: 1) try require(deployedSource.identity == source.identity, "deployed semicolonless static assignment is accepted") let missing = "// Error404

Not found.

We couldn't find anything to play here.

" try expect(.unavailable) { _ = try ZokoResolver.parse(page: missing, mediaID: "1", episode: 27) } for protected in ["Just a moment", "", "

Sorry, you have been blocked

", missing + "
captcha
"] { try expect(.protection) { _ = try ZokoResolver.parse(page: protected, mediaID: "1", episode: 1) } } for malformed in ["", "window.__P='broken';", try page(config) + page(config), String(repeating: "x", count: ZokoResolver.bodyLimit + 1)] { try expect(.malformed) { _ = try ZokoResolver.parse(page: malformed, mediaID: "1", episode: 1) } } for bad in ["https://evil.example/master.m3u8", "https://hls1.drama1.cfd/master.m3u8", "http://hls.dramahot.top/master.m3u8", "https://hls.dramahot.top:8443/master.m3u8", "https://hls.dramahot.top.evil.example/master.m3u8", "https://user@hls.dramahot.top/master.m3u8", "https://127.0.0.1/master.m3u8"] { config["src"] = bad try expect(.malformed) { _ = try ZokoResolver.parse(page: page(config), mediaID: "1", episode: 1) } } config["src"] = "https://hls.dramahot.top/master.m3u8" let invalidSubtitles: [[[String: Any]]] = [ [["src": "https://evil.example/en.vtt", "lang": "en", "label": "English"]], [["src": "https://hls.dramahot.top/en.vtt", "lang": "en", "label": "bad\nlabel"]], Array(repeating: ["src": "https://hls.dramahot.top/en.vtt", "lang": "en", "label": "English", "default": true], count: 2), Array(repeating: ["src": "https://hls.dramahot.top/en.vtt", "lang": "en", "label": "English"], count: 33)] for subtitles in invalidSubtitles { config["subtitles"] = subtitles try expect(.malformed) { _ = try ZokoResolver.parse(page: page(config), mediaID: "1", episode: 1) } } try require(ZokoResolver.validResource(URL(string: "https://hls1.drama1.cfd/segment.jpg")!), "exact demonstrated segment origin admitted") for bad in ["https://evil.example/segment.ts", "http://hls1.drama1.cfd/segment.ts", "https://hls1.drama1.cfd:8443/segment.ts", "https://hls1.drama1.cfd.evil.example/segment.ts", "https://127.0.0.1/segment.ts"] { try require(!ZokoResolver.validResource(URL(string: bad)!), "hostile manifest resource rejected before request") } let suite = "terebi.zoko-check." + UUID().uuidString let defaults = UserDefaults(suiteName: suite)! defer { defaults.removePersistentDomain(forName: suite) } var progress = PlaybackProgress(defaults: defaults) let identity = URL(string: source.identity)! progress.save(123, for: identity) progress.save(456, for: URL(string: "miruro:1:1")!) progress = PlaybackProgress(defaults: defaults) try require(progress.position(for: identity) == 123 && progress.position(for: URL(string: "miruro:1:1")!) == 456, "AniList resume persists separately from Miruro") print("PASS: AniList URL/identity, static codec, optional independent fractional skip metadata, source transformations, unavailable/protection/malformed categories, bounded resources/subtitles, narrow CDN policy and isolated resume") } // No NSApplication, window or audio playback. The production player opens and // decodes while paused; acknowledged frame stepping proves real video decode. static func until(_ player: OpaquePointer, _ predicate: (PlayerState) -> Bool) async throws -> PlayerState { let deadline = ContinuousClock.now.advanced(by: .seconds(60)) while ContinuousClock.now < deadline { let state = player_get_state(player) if state.status == PLAYER_ERROR { throw Failure(message: "Native player failed (source details redacted)") } if predicate(state) { return state } try await Task.sleep(for: .milliseconds(10)) } throw Failure(message: "Native player acknowledgement timed out") } static func live(mediaID: String = "1", episode: Int = 1) async throws { let source = try await MiruroTransport.prepare(ZokoResolver.resolve(mediaID: mediaID, episode: episode)) defer { _fixLifetime(source) } try require(source.identity == "anilist:\(mediaID):\(episode)" && source.headers.isEmpty, "native relay preserves identity without upstream headers") guard let track = source.subtitles.first(where: \.isDefault) else { throw Failure(message: "Live source has no default subtitle") } let document = try await WebVTTDocument.load(url: track.url, headers: track.headers) guard let cue = document.cues.first(where: { !$0.text.isEmpty && $0.end > $0.start }) else { throw Failure(message: "Live VTT contains no active cues") } let directory = FileManager.default.temporaryDirectory.appendingPathComponent("terebi-zoko-" + UUID().uuidString) try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true, attributes: [.posixPermissions: 0o700]) defer { try? FileManager.default.removeItem(at: directory) } let report = directory.appendingPathComponent("progress.jsonl") guard let player = player_create() else { throw Failure(message: "Native player creation") } var destroyed = false defer { if !destroyed { player_destroy(player) } } var error = [CChar](repeating: 0, count: 512) try require(report.path.withCString { player_set_progress_file(player, $0, &error) }, "Native progress file admission") func open(_ position: Double) -> Bool { source.url.withCString { url in source.identity.withCString { identity in var input = PlayerNetworkSource(video_url: url, audio_url: nil, video_headers: nil, audio_headers: nil, duration: 0, is_live: false, media_url: identity, initial_position: position) return player_open_network(player, &input) } } } try require(open(0), "Native AniList source admission") var state = try await until(player) { $0.status == PLAYER_PAUSED && $0.has_video && $0.has_audio && !$0.seek_pending } try require(state.can_seek && state.duration > 600, "Native tracks/duration/seekability") let revision = state.revision try require(player_step_frame(player, 1), "Native first-frame step") state = try await until(player) { $0.status == PLAYER_PAUSED && !$0.seek_pending && $0.revision != revision && $0.position > 0 } try require(player_seek(player, (cue.start + cue.end) / 2), "Native subtitle-position seek") state = try await until(player) { !$0.seek_pending && $0.position >= cue.start && $0.position < cue.end } try require(!document.text(at: state.position).isEmpty, "Subtitles render at acknowledged native position") let beforeSeek = state.revision try require(player_seek(player, 600), "Native ten-minute seek admission") state = try await until(player) { !$0.seek_pending && $0.revision != beforeSeek && abs($0.position - 600) < 0.1 } let beforeStep = state.position let seekRevision = state.revision try require(player_step_frame(player, 1), "Native post-seek decode step") state = try await until(player) { !$0.seek_pending && $0.revision != seekRevision && $0.position > beforeStep } let saved = state.position try require(player_close(player), "Native close before resume") _ = try await until(player) { $0.status == PLAYER_EMPTY } try require(open(saved), "Native restored AniList source admission") state = try await until(player) { $0.status == PLAYER_PAUSED && !$0.seek_pending && abs($0.position - saved) < 0.1 } try require(state.has_audio && state.has_video, "Native restored tracks") player_destroy(player) destroyed = true let rows = try String(contentsOf: report, encoding: .utf8).split(separator: "\n").map { try JSONSerialization.jsonObject(with: Data($0.utf8)) as! [String: Any] } try require(!rows.isEmpty, "Native progress records emitted") for row in rows { let identity = row["media_identity"] as? [String: Any] try require(row["version"] as? Int == 2 && row["media_url"] == nil && identity?["provider"] as? String == "anilist" && identity?["media_id"] as? String == mediaID && identity?["episode"] as? Int == episode, "Native progress uses AniList v2 identity with no media URL") } try require(rows.contains { ($0["position_seconds"] as? Double ?? 0) >= 600 }, "Acknowledged seek/resume position reported") print("PASS: fresh AniList \(mediaID) episode \(episode) mapped via MAL; actual native decode/frame step, 600s seek/decode, VTT text, restored position and AniList v2 progress (no GUI/audio playback)") } static func main() async { do { try await checks() if CommandLine.arguments.contains("--live") { try await live() } if CommandLine.arguments.contains("--live-black-clover") { try await live(mediaID: "97940") } } catch { FileHandle.standardError.write(Data("FAIL: Zoko check: \(error.localizedDescription)\n".utf8)) exit(1) } } }