From e6a275949766616f79a7955057ca0018b6e0af7c Mon Sep 17 00:00:00 2001 From: hl-valdemar Date: Sun, 25 Oct 2026 15:59:24 +0100 Subject: [PATCH] perf: decode Zoko configuration in place --- Sources/App/ZokoResolver.swift | 13 ++++++++----- docs/miruro-playback-handoff.md | 4 +++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Sources/App/ZokoResolver.swift b/Sources/App/ZokoResolver.swift index 127e8ba..c5d2b7f 100644 --- a/Sources/App/ZokoResolver.swift +++ b/Sources/App/ZokoResolver.swift @@ -16,6 +16,7 @@ enum ZokoError: String, LocalizedError { enum ZokoResolver { static let bodyLimit = 2 * 1024 * 1024 static let referer = "Referer: https://zokoanime.video/\r\n" + private static let codecKey = Array("otaku-embed-v1".utf8) static func validResource(_ url: URL, playlist: Bool = false) -> Bool { guard ResolvedSource.validURL(url.absoluteString), url.scheme == "https", @@ -47,6 +48,7 @@ enum ZokoResolver { if response.statusCode == 403 || response.statusCode == 429 || response.statusCode == 503 { throw ZokoError.protection } guard response.statusCode == 200 else { throw ZokoError.transport } var data = Data() + if response.expectedContentLength > 0 { data.reserveCapacity(Int(response.expectedContentLength)) } for try await byte in bytes { try Task.checkCancellation() guard data.count < bodyLimit else { throw ZokoError.malformed } @@ -88,17 +90,18 @@ enum ZokoResolver { lower.contains("captcha") || lower.contains("sorry, you have been blocked") { throw ZokoError.protection } throw ZokoError.malformed } - guard let encoded = Data(base64Encoded: String(page[range])), !encoded.isEmpty else { throw ZokoError.malformed } - let key = Array("otaku-embed-v1".utf8) - var decoded = Array(encoded) - for i in decoded.indices { decoded[i] ^= key[i % key.count] } + guard var decoded = Data(base64Encoded: String(page[range])), !decoded.isEmpty else { throw ZokoError.malformed } + decoded.withUnsafeMutableBytes { (buffer: UnsafeMutableRawBufferPointer) in + let bytes = buffer.bindMemory(to: UInt8.self) + for i in bytes.indices { bytes[i] ^= codecKey[i % codecKey.count] } + } struct Config: Decodable { struct Subtitle: Decodable { let src: String; let lang: String; let label: String; let `default`: Bool? } let src: String let subtitles: [Subtitle] } let config: Config - do { config = try JSONDecoder().decode(Config.self, from: Data(decoded)) } + do { config = try JSONDecoder().decode(Config.self, from: decoded) } catch { throw ZokoError.malformed } guard let url = URL(string: config.src), validResource(url, playlist: true), url.path.hasSuffix(".m3u8"), config.subtitles.count <= 32 else { throw ZokoError.malformed } let subtitles = try config.subtitles.map { row -> ResolvedSubtitle in diff --git a/docs/miruro-playback-handoff.md b/docs/miruro-playback-handoff.md index e2e638c..c41e2c7 100644 --- a/docs/miruro-playback-handoff.md +++ b/docs/miruro-playback-handoff.md @@ -26,7 +26,9 @@ Terebi resolves bounded static `window.__P` data over ordinary verified HTTPS, t Use stable `anilist::` for resume and report registration. Queue/enqueue documents keep their existing version-1 shape and use the watch URL. Version-2 reports keep exactly the existing event/position/duration/eligibility fields, substituting `media_identity: {"provider":"anilist","media_id":"1","episode":1}`. Validate against the exact expected provider/ID/episode; never reinterpret an old `miruro` identity as AniList. Explicit external source documents also accept the `anilist` identity namespace with decimal IDs, retaining the existing strict native same-origin resource policy. -`make check-zoko check-reporting check-cli check-stream check-progress` is the focused non-GUI regression command. Optional `make check-zoko-live` uses the real native decoder (paused frame stepping, ten-minute seek/decode, restored position), VTT text at acknowledged positions and actual version-2 progress. It does not start GUI/audio playback or verify visible rendering/full episodes; Core Audio initializes a device. These commands are provided for integrated verification, not a claim they have been exercised. +`make check-zoko check-reporting check-cli check-stream check-progress` is the focused non-GUI regression command. Optional `make check-zoko-live` uses the real native decoder (paused frame stepping, ten-minute seek/decode, restored position), VTT text at acknowledged positions and actual version-2 progress. It does not start GUI/audio playback or verify visible rendering/full episodes; Core Audio initializes a device. + +Integrated verification on 2026-10-25 passed all six targets above, including live fresh AniList 1 episode 1 resolution and actual native frame/seek/VTT/resume/version-2 reporting. The live run emitted redacted FFmpeg warnings/errors despite completing its assertions; it was not warning-free. The deployed static assignment omits its semicolon, which the parser explicitly supports without evaluating JavaScript. No GUI/browser test, audio-output test or full-episode verification was performed. ## Launch contract