Files
tubular/docs/wco-feasibility.md
T

13 KiB
Raw Blame History

WCO feasibility investigation

Observed 2026-10-20 UTC. Scope: adding Western-cartoon browsing and native playback to Tubular, using ordinary HTTPS without browser automation, challenge/login/premium bypass, fabricated ad-verification results, or weakened TLS. No production implementation was added.

Decision

Browsing is feasible for the sampled catalog. Native video extraction and playback are not established. The current declared free-player route reaches a JavaScript ad-verification step; investigation stopped before submitting that verification or requesting the post-gate player. Separately, the current Tubular/Terebi source and progress contracts reject an honest WCO identity.

Do not build another full browser UI or weaken Terebi's network policy on this evidence alone. The missing prerequisite is a legitimately obtained final media URL, its required headers, and a successful native decode/seek probe. Nothing below demonstrates that WCO cannot ever support a native client.

Evidence labels:

  • Observed: live requests or an executed check in this investigation.
  • Source: current site markup, JavaScript, or implementation inspection.
  • [INFERENCE]: architectural implication, not verified WCO playback.

Live native HTTP evidence

A temporary Rust example used the project's existing ureq 3.4.2 dependency with its rustls feature: default agent, TLS verification enabled, 25-second global timeout, http_status_as_error(false), and zero automatic redirects. Responses were bounded to 512 KiB, or 4 KiB for the artwork signature check. No cookies, browser impersonation, proxy, script execution, or challenge solution was supplied. Player/initialization requests carried their referring page explicitly.

Resource Transport HTTP Content-Type Body bytes read
Cartoon directory ureq/rustls 200 text/html 311285
OTGW series ureq/rustls 200 text/html 42840
Adventure Time series ureq/rustls 200 text/html 148050
OTGW episode 1 ureq/rustls 200 text/html 39154
Episode's declared iframe, embed.wcostream.com/inc/embed/index.php ureq/rustls 200 text/html 9177
Declared player initialization ureq/rustls 200 application/javascript 3871
OTGW cover ureq/rustls 200 image/jpeg 4096
Same OTGW episode-1 URL Python urllib 403 text/html 5601
Same OTGW episode-1 URL curl 403 text/html 5580

Observed: the cover prefix has a JPEG signature. Full image decoding was not tested. Native successful page responses contained neither the Cloudflare challenge markers checked nor the explicit premium-only marker. Python's episode response contained Cloudflare's “Just a moment”; curl independently returned 403 HTML. Accessibility is transport-dependent; successful web-reader access alone would not have established local native access.

Smallest catalog integration

Observed/Source: the directory and series metadata are server-rendered. No JavaScript execution is needed to read the sampled listings.

  1. GET /cartoon-list; parse #ddmcc_container title/series links.
  2. Filter that Western-cartoon directory locally. The site's own directory search performs case-insensitive substring filtering, not another API request.
  3. Fetch the selected series page for description, genres, cover reference, season labels, and #episodeList a.dark-episode-item entries.
  4. Preserve the provider's actual playable-item labels and opaque page paths.

The global search form declares POST /search, with catara=<query> and konuara=series or episodes; the input declares a 40-character maximum. This is a markup contract, not a successful live POST probe. Local directory filtering avoids depending on that unverified endpoint for Western-cartoon title search. Site form; reference search implementation.

Series identity should use the observed canonical provider path, not a slug generated from the display title or the numeric artwork filename. The directory contains historical paths such as /anime/american-dad-season-1 for “American Dad!”. Long-term URL stability has not been established. Directory.

Artwork is available through og:image and #sidebar_cat img.img5; normalize scheme-relative references. Sidebar prose and genre links are available, but quality varies: Adventure Time's synopsis describes its pilot rather than the whole series. No episode runtime, publication date, or chapter timestamps were established.

Identity and ordering traps

  • OTGW has eight page entries covering ten numbered segments: 1–6 separately, 7–8 together, 9–10 together. These eight links were also extracted from the native response.
  • Adventure Time season 1 labels one video “Episode 1 Slumber Party Panic / Trouble in Lumpy Space”; season 10 has a combined “Episode 13–16 Come Along with Me”. Pilot, specials, Distant Lands and Side Quests coexist on the series page.
  • Map data-season through #seasonFilter option[value]; preserve the token and label. Adventure Time includes s-1-0, labeled “Special: Distant Lands”.
  • Read the direct title span, not all anchor text: quality/finale badges are separate metadata.
  • Preserve source order initially. It is mostly descending, but not consistently numerically sorted.
  • Use an opaque episode-page identity, not series ID plus an assumed single positive episode number. Do not synthesize chapters, segment boundaries, or separate watched states from slash-separated titles.

Sources: OTGW, Adventure Time. The current Miruro identity cannot be reused unchanged: src/miruro.rs:28-77.

Actual page-to-player boundary

Observed: ordinary native requests reached this sequence:

  1. The episode HTML contains a statically encoded iframe string. Its visible script applies Base64 decoding, retains decimal digits, subtracts a page-supplied constant, then constructs characters. This transform was decoded as data; no downloaded JavaScript was executed.
  2. The decoded iframe targets embed.wcostream.com/inc/embed/index.php with episode query parameters.
  3. That iframe returns an “Announcement” document, not an MP4/HLS URL. Its close button is initially disabled, with a 10-second countdown and a 12-second fallback timer.
  4. The document loads /inc/embed/pre-init.js?v2. That script generates a browser nonce, performs DOM ad-bait and script-loading checks, and sends an /ad-verify beacon containing the nonce, video ID and clear/blocked result.
  5. Closing the announcement normally navigates to video-js.php, using AdGate.buildUrl() to append the nonce. The page also has a fallback navigation if AdGate is unavailable; that fallback was not requested to skip verification.

Boundary: no /ad-verify request was submitted; no DOM results were fabricated, scripts executed, announcement flow skipped, alternative player endpoint substituted, premium workaround invoked, or post-gate player/media requested. Server-side enforcement of the nonce was not tested. A script containing a gate is not proof that every WCO stream is inaccessible to a native client.

The Kodi resolver is reference code, not a proven current contract. It rewrites index.php to video-js-new.php, parses internal source JSON, resolves media redirects, and contains separate premium-workaround paths. Those behaviors were not transplanted or exercised. Its recent maintenance does not establish that this sample is playable through Tubular's permitted flow.

Unverified: current source-JSON schema after the gate; final media type/codecs; required headers/cookies; redirect chain; URL expiration/IP binding; byte-range/seek support; nested HLS origins; subtitles; actual Terebi playback. No episode media was downloaded.

Actual Tubular/Terebi compatibility

Executed source-contract smoke

A temporary Foundation-only Swift executable compiled the actual ../terebi/Sources/App/ResolvedSource.swift unchanged. It validated a synthetic, otherwise valid source document with provider miruro, then changed only the provider to wco and required rejection. The synthetic example URL was not fetched.

Observed output, exit 0:

Actual Terebi validator: Miruro control accepted; identical document with provider=wco rejected

This proves source-contract rejection, not anything about live media decoding. No player UI was launched.

Required integration changes if usable media is established

  • Provider selection: Tubular's chooser is Boolean/two-way, not a third-provider interface: src/main.rs:3674-3698,3762-3774.
  • Honest stable identity: Tubular's Identity validation/key parsing and Terebi's source validator hardcode Miruro. WCO needs a provider-correct opaque playback-item identity that accommodates paired episodes and specials. Do not disguise WCO media as Miruro. src/miruro.rs:28-77; ../terebi/Sources/App/ResolvedSource.swift:84-102.
  • Native admission and safety: native progress identity validation accepts only canonical YouTube URLs or miruro:. Resolved-source security classification also uses starts_with("miruro:"). Updating Swift admission alone is insufficient and would not apply the protected resolved-source path. ../terebi/Sources/Core/progress_reporter.cpp:62-90; ../terebi/Sources/Core/player.cpp:565-567,1460-1466.
  • Progress/state: native version-2 reporting emits a literal Miruro provider. Tubular sessions, snapshot validation, report admission and provider-specific collection filtering also need coordinated changes. Broadening the Miruro identity parser without updating its UI callers would mix WCO records into Miruro collections. ../terebi/Sources/Core/progress_reporter.cpp:163-186; src/video_state.rs:379-396,651-669; src/miruro_ui.rs:265-268,989-990,1938-1941.
  • Reuse, not another player: the existing source launcher already passes private source/progress files to Terebi. Resume storage is identity-keyed. No new playback framework is indicated. src/youtube.rs:937-981; ../terebi/Sources/App/TerebiApp.swift:516-524,1525-1530; ../terebi/Sources/App/PlaybackProgress.swift:24-35,54-57.

[INFERENCE] Direct MP4 should fit the general native media architecture. Source-file validation is not HLS-only; native FFmpeg opens input without forcing a demuxer and discovers audio/video streams. The HLS-only rule belongs to Miruro's Sun projection, not the general source document. WCO must not be routed through that projection. src/miruro.rs:101-178; ../terebi/Sources/Core/player.cpp:543-547,565-580.

The existing protected network path rejects all media redirects, even same-origin redirects, and requires HLS variants/segments/keys/init resources to share the initial media origin. Preserve that policy. A resolver would need to obtain an already-final acceptable URL through a separately reviewed extraction flow; no need for redirect/cross-origin support has yet been established. ../terebi/Sources/Core/player.cpp:111-126,532-537.

The existing resolved-playback-check is not an unchanged subtitle-free WCO smoke: it requires a default subtitle and two cues. The full player suite also requires graphical/audio resources. Neither was run. See ../terebi/Checks/resolved-playback.swift:24-80 and ../terebi/README.md:178-190.

Recommendation and limits

  • Go: a native WCO catalog is evidenced for the sampled directory, two shows, episode page and cover host.
  • Not yet go: do not implement end-to-end WCO playback on the strength of catalog access or old extractor code.
  • Next prerequisite: observe/document an authorized normal free-player route through the verification boundary, or obtain a supported native playback interface. Browser observation would need explicit permission and would not itself prove native extraction. Do not emulate successful ad-verification results or weaken security to create a passing demo.
  • Then: resolve one real item, inspect only bounded media/manifest data with explicit headers, and verify native decode, duration and seek behavior before implementing browsing/state changes. Test a combined entry as well as a single episode before claiming identity correctness.

Investigation changes are this report only; temporary HTTP/Swift probes and response files were removed. No application behavior, player source, dependency, remote state, or persistent stream token was changed. Findings are a point-in-time sample, not a service reliability or distribution-rights guarantee.