code wiki / (root) / nx_cam_chaturbate.nx

nx_cam_chaturbate.nx

buildroot/runtime/nx_cam_chaturbate.nx

21340 B485 linesdepth 4pulls 4 transitivereach 2 importersview sourcekind librarytopic cam
docsdependenciesstructsconstsfunctions

about

nx_cam_chaturbate.nx -- /compare/mediaingest R9 (lr_watch) SITE ADAPTER: Chaturbate. WHY THIS EXISTS, MEASURED 2026-09-01 -- not recalled, and it corrects the record. The retired Python detector whose output sits in ~/.ctbrec/logs tried 8 regex patterns, 4 JS-object patterns and one API endpoint against the ROOM PAGE, then reported: "Room Status: PRIVATE (found 'private show') / Streams Found: 0 / DETECTION FAILED" "3. JavaScript rendering required ... Consider using Selenium/WebDriver" Re-reading the HTML that same run SAVED (page_dj_woman_20251029_110425.html, 184,898 B) refutes every part of that conclusion: - the body carries next="/?next=/dj_woman/" plus roomlist / endless_page markers, i.e. the request was BOUNCED TO THE LANDING PAGE and the room page was never retrieved at all; - the page <title> is the generic Chaturbate homepage title, not a room title; - the literal "private show" it reports matching is homepage boilerplate (3 hits, none a room status field), so the PRIVATE verdict was read off the wrong document. ALL THIRTEEN "pattern misses" therefore have ONE cause, and it is not JavaScript. A check that ran on the wrong subject produced a confident, complete-looking false negative, and its remedy ("render JavaScript") would have bought a browser engine to fix a fetch that never landed. INDEPENDENT SECOND WITNESS, found in our own tree: nx_http_client.nx's build_request_cookie comment already says "chaturbate's /?next= age-gate hands back csrftoken/sbr/AG_Key that must be replayed to reach the room -- without a jar we land on the gate page forever." THE REAL MECHANISM needs no room page and no browser. Two endpoints: 1. STATUS IN BULK -- GET /affiliates/api/onlinerooms/?format=json returns EVERY online room in ONE request. This is the rate-limit answer: N watched performers cost 1 call, not N. Paying one ajax per performer across a large fleet is precisely what flags an exit IP into a site-wide 403, so bulk is not an optimisation here, it is the correctness path. 2. URL RESOLVE -- POST /get_edge_hls_url_ajax/ (application/x-www-form-urlencoded, room_slug=<name>&bandwidth=high, X-Requested-With: XMLHttpRequest) -> JSON carrying room_status, url and cmaf_edge. *** THE EDGE TOKEN IN THAT url IS SINGLE-USE / CONNECTION-BOUND. *** ANY fetch of the tokenised playlist -- even a HEAD, even a "quick validity check" -- CONSUMES it, and the next consumer gets HTTP 403. So this organ RESOLVES AND RETURNS; it never probes, never validates and never pre-fetches the URL it hands back. That is not style: our own nx_hls_get fetches the MASTER playlist and THEN fetches the variant media playlist, which spends the token on the first fetch and 403s on the second. cb_capture_contract() states the handoff rule in the return value rather than in a comment, because a rule that lives only in a comment is invisible to every caller -- the same lesson nx_https_client.nx's NOT_IMPLEMENTED verdict records. EGRESS ETHICS (standing estate bound, /compare/mediaingest R12): sovereign-owned egress only.

dependencies 2 imports · 2 importers

nx_syscalls.nx nx_paced_fetch.nx nx_cam_chaturbate.nx nx_cam_chaturbate_gate.nx nx_cam_chaturbate_probe.nx

imports: nx_syscalls.nxnx_paced_fetch.nx

imported by: nx_cam_chaturbate_gate.nxnx_cam_chaturbate_probe.nx

structs

none

consts

56const CB_UNKNOWN: i64 = 0
57const CB_PUBLIC: i64 = 1
58const CB_PRIVATE: i64 = 2
59const CB_HIDDEN: i64 = 3
60const CB_OFFLINE: i64 = 4
61const CB_RESTRICTED: i64 = 5 // room says PUBLIC but the ajax returned an EMPTY url -> geo/age-gated for this exit
62const CB_RATELIMIT: i64 = 6 // 429 / 5xx / 403-challenge -> BACK OFF, never fast-retry
63const CB_NOTEXIST: i64 = 7 // 404
64const CB_WALL: i64 = 8 // challenge body, classified by nx_antibot in the capture path (R13)
65const CB_STATE_N: i64 = 9
67const CB_HTTP_OK: i64 = 200
68const CB_HTTP_FORBIDDEN: i64 = 403
69const CB_HTTP_NOTFOUND: i64 = 404
70const CB_HTTP_TOOMANY: i64 = 429
71const CB_HTTP_SERVER_MIN: i64 = 500
74const CB_HANDOFF_SINGLE_CONSUMER: i64 = 1
76const CB_CH_QUOTE: i64 = 34
77const CB_CH_COLON: i64 = 58
78const CB_CH_SPACE: i64 = 32
79const CB_CH_TAB: i64 = 9
80const CB_CH_DIGIT0: i64 = 48
81const CB_CH_UPPER_A: i64 = 65
82const CB_CH_UPPER_Z: i64 = 90
83const CB_CH_CASE_DELTA: i64 = 32
85const CB_NUMBUF_BYTES: i64 = 32

functions

87func cb_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n }
88func cb_w(s: *u8) -> i64 { sys_write(1, s, cb_slen(s)); return 0 }
89func cb_wb(b: *u8, n: i64) -> i64 { sys_write(1, b, n); return 0 }
calls 1: sys_write
90func cb_wn(v: i64) -> i64
called by 1: p_wn calls 2: sys_mmapsys_write
102func cb_state_name(st: i64) -> *u8
called by 1: main
114func cb_state_is_valid(st: i64) -> i64
123func cb_is_recordable(st: i64) -> i64 { if st == CB_PUBLIC { return 1 } return 0 }
called by 1: main
128func cb_should_backoff(st: i64) -> i64
called by 1: main
137func cb_capture_contract() -> i64 { return CB_HANDOFF_SINGLE_CONSUMER }
139func cb_lc(c: i64) -> i64
called by 1: cb_ieq
145func cb_ieq(buf: *u8, off: i64, n: i64, lit: *u8) -> i64
161func cb_decide(http_status: i64, rs: *u8, rs_off: i64, rs_len: i64, url_len: i64) -> i64
called by 1: main calls 1: cb_state_of_show
183func cb_field_from(buf: *u8, n: i64, key: *u8, from: i64, off_out: *i64) -> i64
246func cb_flag(buf: *u8, n: i64, key: *u8) -> i64
called by 1: main calls 1: cb_slen
288func cb_find(buf: *u8, n: i64, lit: *u8, from: i64) -> i64
called by 1: cb_cmaf_rewrite calls 1: cb_slen
305func cb_rfind(buf: *u8, n: i64, lit: *u8) -> i64
called by 1: cb_cmaf_rewrite calls 1: cb_slen
323func cb_apps(dst: *u8, k0: i64, src: *u8) -> i64
331func cb_appn(dst: *u8, k0: i64, src: *u8, n: i64) -> i64
called by 1: cb_cmaf_rewrite
345func cb_cmaf_rewrite(src: *u8, srclen: i64, out: *u8, outcap: i64) -> i64
374func cb_field(buf: *u8, n: i64, key: *u8, off_out: *i64) -> i64
called by 2: cb_bulk_lookupmain calls 1: cb_field_from
383func cb_state_of_show(rs: *u8, off: i64, len: i64) -> i64
called by 2: cb_decidecb_bulk_lookup calls 1: cb_ieq
404func cb_record_start(buf: *u8, n: i64, at: i64) -> i64
called by 1: cb_bulk_lookup
414func cb_record_end(buf: *u8, n: i64, at: i64) -> i64
called by 1: cb_bulk_lookup
424func cb_bulk_count(buf: *u8, n: i64) -> i64
called by 1: main calls 2: sys_mmapcb_field_from
445func cb_bulk_lookup(buf: *u8, n: i64, user: *u8, off_out: *i64) -> i64
478func cb_build_body(user: *u8, out: *u8, outcap: i64) -> i64
called by 1: p_post_ajax calls 2: cb_slencb_apps