perf: decode Zoko configuration in place
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -26,7 +26,9 @@ Terebi resolves bounded static `window.__P` data over ordinary verified HTTPS, t
|
||||
|
||||
Use stable `anilist:<ID>:<episode>` 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user