code wiki / _hdl_build / nx_url_index.nx

nx_url_index.nx source

↩ module page · 231 lines · 14190 B

1// nx_url_index.nx -- Fetches and indexes a single live URL into the web scope using a neutral, sovereign stack. 2import "nx_gate_gn.nx" 3import "nx_gate_base.nx" 4// nx_url_index.nx -- DIRECT neutral-access indexer: fetch ONE live url over our sovereign stack (best-effort: 5// minimal hello then Chrome-JA3) and index it INTO the web scope (dp-web-pub-, INDEX-ONLY + serve-LIVE). 6// This is the path for content Common Crawl MISSES because the site blocks CC's crawler (adult-media sources 7// major engines de-rank: supjav/nhentai/etc.). We are NEUTRAL: only US-illegal content (CSAM floor) is out of 8// scope -- lawful adult media is indexed like any other page. Query '?' urls allowed (unlike the BFS crawler). 9// usage: nx_url_index <url> [display-url] 10// license_tier: ORIGINAL 11import "nx_corpus_ingest.nx" // ci_hash / ci_mkurlkey / dss_prefix / dss_mkkey / seg_store / nx_html_to_text 12import "nx_struct_extract.nx" // nx_struct_extract -- mine og/twitter/JSON-LD title+desc for enrichment 13import "nx_feed_extract.nx" // nx_feed_discover + nx_feed_extract -- non-JS content path for SPA shells 14import "nx_crawl_pace.nx" // per-host polite pacing (pace_before/after) -- don't get IP-banned 15import "nx_x509_trust_store.nx" 16import "nx_trust_store_load_from_certdata.nx" 17import "nx_https_fetch_follow.nx" 18const K_MAGIC_4194304: i64 = 4194304 19const K_MAGIC_1048576: i64 = 1048576 20const K_MAGIC_1024: i64 = 1024 21const K_MAGIC_2048: i64 = 2048 22const K_MAGIC_4096: i64 = 4096 23const K_MAGIC_8192: i64 = 8192 24const K_MAGIC_8191: i64 = 8191 25const K_MAGIC_65536: i64 = 65536 26const K_MAGIC_70000: i64 = 70000 27const K_MAGIC_69998: i64 = 69998 28 29func grow(name: *u8, ok: i64) -> i64 { if ok==1 { gw(" PASS " as *u8) } else { gw(" FAIL " as *u8) } gw(name); gw(" 30" as *u8); return ok } 31func slen(s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} return n } 32func has(hay: *u8, hn: i64, ndl: *u8) -> i64 { var nl: i64=0; while ndl[nl]!=(0 as u8){nl=nl+1} var i: i64=0; while i+nl<=hn { var m: i64=1; var j: i64=0; while j<nl { if hay[i+j]!=ndl[j] { m=0; j=nl } else { j=j+1 } } if m==1 { return 1 } i=i+1 } return 0 } 33 34// extract the host (between "://" and the next '/' or ':') from a url -> out. returns host length. 35// (flag-based loops -- do NOT jump the index past the string, that re-reads OOB in the while condition.) 36func ui_host(url: *u8, out: *u8) -> i64 { 37 var sp: i64 = 0 - 1; var i: i64 = 0; var d: i64 = 0 38 while d == 0 { 39 if url[i]==(0 as u8) { d = 1 } else { 40 if url[i]==(58 as u8) { if url[i+1]==(47 as u8) { if url[i+2]==(47 as u8) { sp = i; d = 1 } } } 41 if d == 0 { i = i + 1 } 42 } 43 } 44 var s: i64 = 0; if sp >= 0 { s = sp + 3 } 45 var o: i64 = 0; var d2: i64 = 0 46 while d2 == 0 { 47 let c: i64 = url[s] as i64 48 if c==0 { d2 = 1 } else { if c==47 { d2 = 1 } else { if c==58 { d2 = 1 } else { out[o]=url[s]; o=o+1; s=s+1 } } } 49 } 50 out[o] = 0 as u8 51 return o 52} 53 54// resolve a feed href against the page url: absolute (http...) kept; "/path" -> scheme://host/path. 55func ui_resolve(base: *u8, href: *u8, out: *u8) -> i64 { 56 if href[0]==(104 as u8) { if href[1]==(116 as u8) { if href[2]==(116 as u8) { if href[3]==(112 as u8) { 57 var i: i64=0; while href[i]!=(0 as u8) { out[i]=href[i]; i=i+1 } out[i]=0 as u8; return 0 58 } } } } 59 // find "://" in base (flag-based; never jump the index past the string) 60 var sp: i64 = 0 - 1; var i: i64 = 0; var df: i64 = 0 61 while df == 0 { 62 if base[i]==(0 as u8) { df = 1 } else { 63 if base[i]==(58 as u8) { if base[i+1]==(47 as u8) { if base[i+2]==(47 as u8) { sp = i; df = 1 } } } 64 if df == 0 { i = i + 1 } 65 } 66 } 67 if sp < 0 { var k: i64=0; while href[k]!=(0 as u8) { out[k]=href[k]; k=k+1 } out[k]=0 as u8; return 0 } 68 // he = first '/' at/after sp+3, else end of string 69 var he: i64 = sp + 3 70 var done: i64 = 0 71 while done==0 { if base[he]==(0 as u8) { done=1 } else { if base[he]==(47 as u8) { done=1 } else { he=he+1 } } } 72 var o: i64 = 0 73 while o < he { out[o]=base[o]; o=o+1 } 74 if href[0]==(47 as u8) { var j: i64=0; while href[j]!=(0 as u8) { out[o]=href[j]; o=o+1; j=j+1 } } 75 else { out[o]=47 as u8; o=o+1; var j: i64=0; while href[j]!=(0 as u8) { out[o]=href[j]; o=o+1; j=j+1 } } 76 out[o]=0 as u8 77 return 0 78} 79 80func main(argc: i64, argv: *i64) -> i64 { 81 if argc < 2 { gw("usage: nx_url_index <url> [display-url]\n" as *u8); return 1 } 82 let url: *u8 = argv[1] as *u8 83 var disp: *u8 = url 84 if argc >= 3 { disp = argv[2] as *u8 } 85 let r: i64 = nx_trust_store_load_from_certdata("data/mozilla_certdata.txt" as *u8, 512, K_MAGIC_4194304) 86 if r <= 0 { gw("trust store load failed\n" as *u8); return 2 } 87 let store: *TrustStore = r as *TrustStore 88 gw("=== nx_url_index: " as *u8); gw(url); gw(" -> dp-web-pub- (INDEX-ONLY, serve-LIVE) ===\n" as *u8) 89 90 let cap: i64 = K_MAGIC_4194304 91 let out: *u8 = sys_mmap(cap) 92 let st: *i64 = sys_mmap(8) as *i64 93 let hbuf: *u8 = sys_mmap(512); let hl: i64 = ui_host(url, hbuf) 94 let waited: i64 = pace_before(hbuf, hl) // polite per-host interval (0 on first-ever hit) 95 if waited > 0 { gw(" [pace] waited " as *u8); gn(waited); gw("ms for " as *u8); gw(hbuf); gw("\n" as *u8) } 96 let n: i64 = nx_https_fetch_follow_best(url, store, out, cap, 8, st) 97 pace_after(hbuf, hl, st[0], 0) // status-based backoff (429/503 -> exponential; 200 -> reset) 98 gw(" fetch status=" as *u8); gn(st[0]); gw(" bytes=" as *u8); gn(n); gw("\n" as *u8) 99 if st[0] != 200 { 100 var cf: i64 = 0 101 if n > 0 { if has(out, n, "Just a moment" as *u8) == 1 { cf = 1 } if has(out, n, "Cloudflare" as *u8) == 1 { cf = 1 } } 102 if cf == 1 { gw(" BLOCKED by Cloudflare bot-challenge (needs the browser JS-solver) -- NOT a neutrality issue\n" as *u8) } 103 return 3 104 } 105 // QUALITY GUARD: a 200 can still be a bot-interstitial (reddit "Please wait for verification", Cloudflare 106 // "Just a moment" / "Attention Required"). Don't index the wall as if it were content. 107 if has(out, n, "Please wait for verification" as *u8) == 1 { gw(" SKIP: bot-verification interstitial (not real content)\n" as *u8); return 6 } 108 if has(out, n, "Just a moment" as *u8) == 1 { gw(" SKIP: Cloudflare JS-challenge interstitial\n" as *u8); return 6 } 109 if has(out, n, "Attention Required! | Cloudflare" as *u8) == 1 { gw(" SKIP: Cloudflare block interstitial\n" as *u8); return 6 } 110 let body: *u8 = sys_mmap(K_MAGIC_1048576) 111 let blen: i64 = nx_html_to_text(out, n, body, K_MAGIC_1048576) 112 // STRUCTURED ENRICHMENT (grow-capabilities 2026-07-05): mine og/twitter/JSON-LD title+desc and PREPEND 113 // them -- they become searchable + the snippet, and a structured-rich SPA shell with a thin body is now 114 // indexable (title+desc present) instead of dropped as "too small". nx_struct_extract fabricates nothing. 115 let stitle: *u8 = sys_mmap(K_MAGIC_1024); let sdesc: *u8 = sys_mmap(K_MAGIC_2048) 116 let sty: *u8 = sys_mmap(256); let ssi: *u8 = sys_mmap(256) 117 let sgot: i64 = nx_struct_extract(out, n, stitle, K_MAGIC_1024, sdesc, K_MAGIC_2048, sty, 256, ssi, 256) 118 // FEED FALLBACK (MEASURED: reddit's SPA shell is empty but its /.rss is a real Atom feed): discover the 119 // page's RSS/Atom <link>, fetch it, extract clean item text -> turns a JS-only shell into real indexable 120 // content WITHOUT a JS engine. Also enriches rich pages with fresh feed items. 121 let feedtext: *u8 = sys_mmap(K_MAGIC_1048576) 122 let feedxml: *u8 = sys_mmap(cap) // kept at fn scope so per-item docs can be emitted at commit time 123 var feedxml_len: i64 = 0 124 var feed_items: i64 = 0 125 var feedlen: i64 = 0 126 let feedurl: *u8 = sys_mmap(K_MAGIC_4096) 127 if nx_feed_discover(out, n, feedurl, K_MAGIC_4096) == 1 { 128 let feedabs: *u8 = sys_mmap(K_MAGIC_4096) 129 ui_resolve(url, feedurl, feedabs) 130 gw(" feed discovered: " as *u8); gw(feedabs); gw("\n" as *u8) 131 let fst: *i64 = sys_mmap(8) as *i64 132 let fhbuf: *u8 = sys_mmap(512); let fhl: i64 = ui_host(feedabs, fhbuf) 133 pace_before(fhbuf, fhl) // pace the feed host too (may differ, e.g. rss.nytimes.com) 134 let fn: i64 = nx_https_fetch_follow_best(feedabs, store, feedxml, cap, 8, fst) 135 pace_after(fhbuf, fhl, fst[0], 0) 136 if fst[0] != 200 { gw(" feed fetch status=" as *u8); gn(fst[0]); gw(" (throttled? paced for next time)\n" as *u8) } 137 if fst[0] == 200 { if fn > 0 { feedxml_len = fn; feed_items = nx_feed_extract(feedxml, fn, feedtext, K_MAGIC_1048576); feedlen = slen(feedtext); gw(" feed items: " as *u8); gn(feed_items); gw("\n" as *u8) } } 138 } 139 if blen < CI_MINDOC { if sgot < 2 { if feed_items == 0 { gw(" extract too small (thin body + no structured data + no feed)\n" as *u8); return 4 } } } 140 if stitle[0] != (0 as u8) { gw(" struct-title: " as *u8); gw(stitle); gw("\n" as *u8) } 141 let text: *u8 = sys_mmap(2*K_MAGIC_1048576 + K_MAGIC_8192) 142 var el: i64 = 0 143 var ci2: i64 = 0 144 while stitle[ci2] != (0 as u8) { text[el] = stitle[ci2]; el = el + 1; ci2 = ci2 + 1 } 145 text[el] = 10 as u8; el = el + 1 146 ci2 = 0 147 while sdesc[ci2] != (0 as u8) { text[el] = sdesc[ci2]; el = el + 1; ci2 = ci2 + 1 } 148 text[el] = 10 as u8; el = el + 1 149 var bi: i64 = 0 150 while bi < blen { if el < 2*K_MAGIC_1048576 + K_MAGIC_8191 { text[el] = body[bi]; el = el + 1 } bi = bi + 1 } 151 if feedlen > 0 { 152 if el < 2*K_MAGIC_1048576 + K_MAGIC_8191 { text[el] = 10 as u8; el = el + 1 } 153 var fbi: i64 = 0 154 while fbi < feedlen { if el < 2*K_MAGIC_1048576 + K_MAGIC_8191 { text[el] = feedtext[fbi]; el = el + 1 } fbi = fbi + 1 } 155 } 156 let tlen: i64 = el 157 var tn: i64 = tlen; if tn > CI_DOCCAP { tn = CI_DOCCAP } 158 let cid: i64 = ci_hash(text, tn) 159 160 let prefix: *u8 = sys_mmap(512); dss_prefix("web" as *u8, prefix) 161 let segs: *i64 = sys_mmap(K_MAGIC_4096*8) as *i64 162 let nseg: i64 = ss_manifest_cap(prefix, segs, K_MAGIC_4096) 163 var segid: i64 = 1; var si: i64 = 0 164 // ROOT FIX seq1730 (id 1785450987): segs[] holds POINTERS to seg-<id> name strings 165 // (nx_seg_store.nx:1234 stores segs[cnt] = name as i64), NOT ids -- so segs[si] + 1 produced 166 // MMAP_ADDRESS+1 (~1.4e14), the pointer-shaped poison that PINS a plane forever: every later 167 // epoch id sorts BELOW it in supersede order and its rows are silently shadowed while rc=0. 168 // Parse the DIGITS, as nx_web_shard_compact.nx:55-58 already does on this SAME array. 169 while si < nseg { 170 let sg_nm: *u8 = segs[si] as *u8 171 var sg_v: i64 = 0 172 var sg_ci: i64 = 0 173 while sg_nm[sg_ci] != (0 as u8) { let sg_c: i64 = sg_nm[sg_ci] as i64; if sg_c >= 48 { if sg_c <= 57 { sg_v = sg_v * 10 + (sg_c - 48) } } sg_ci = sg_ci + 1 } 174 if sg_v >= segid { segid = sg_v + 1 } 175 si = si + 1 176 } 177 let h: *i64 = ss_open(prefix) 178 let key: *u8 = sys_mmap(64); let ukey: *u8 = sys_mmap(64) 179 let pbox: *i64 = sys_mmap(16) as *i64; let lbox: *i64 = sys_mmap(16) as *i64 180 dss_mkkey(cid, key) 181 var already: i64 = 0 182 if (h as i64) != 0 { if ss_hget(h, key, pbox, lbox) == 1 { already = 1 } } 183 let w: *i64 = ss_begin() 184 if already == 0 { 185 ss_add(w, 1, key, text, tn) 186 ci_mkurlkey(cid, ukey) 187 ss_add(w, 1, ukey, disp, slen(disp)) 188 } 189 // PER-ITEM DOCS: index each feed item as its OWN document with its OWN article URL. This makes a specific 190 // article retrievable (not just the homepage) AND seeds the frontier with fresh URLs. Idempotent: skip an 191 // item whose content-cid already exists. 192 var item_docs: i64 = 0 193 if feed_items > 0 { if feedxml_len > 0 { 194 let ititle: *u8 = sys_mmap(K_MAGIC_4096); let ilink: *u8 = sys_mmap(K_MAGIC_4096); let isum: *u8 = sys_mmap(K_MAGIC_65536) 195 let itext: *u8 = sys_mmap(K_MAGIC_70000) 196 let ikey: *u8 = sys_mmap(64); let iukey: *u8 = sys_mmap(64) 197 let ipb: *i64 = sys_mmap(16) as *i64; let ilb: *i64 = sys_mmap(16) as *i64 198 var idx: i64 = 0 199 while idx < feed_items { if idx < 1000 { 200 if nx_feed_item_at(feedxml, feedxml_len, idx, ititle, K_MAGIC_4096, ilink, K_MAGIC_4096, isum, K_MAGIC_65536) == 1 { 201 if slen(ilink) >= 8 { // require a real per-article URL 202 var il: i64 = 0; var c: i64 = 0 203 while ititle[c] != (0 as u8) { if il < K_MAGIC_69998 { itext[il] = ititle[c]; il = il + 1 } c = c + 1 } 204 if il < K_MAGIC_69998 { itext[il] = 46 as u8; il = il + 1 } if il < K_MAGIC_69998 { itext[il] = 32 as u8; il = il + 1 } 205 c = 0 206 while isum[c] != (0 as u8) { if il < K_MAGIC_69998 { itext[il] = isum[c]; il = il + 1 } c = c + 1 } 207 if il >= CI_MINDOC { 208 let icid: i64 = ci_hash(itext, il) 209 dss_mkkey(icid, ikey) 210 var iex: i64 = 0 211 if (h as i64) != 0 { if ss_hget(h, ikey, ipb, ilb) == 1 { iex = 1 } } 212 if iex == 0 { 213 ss_add(w, 1, ikey, itext, il) 214 ci_mkurlkey(icid, iukey) 215 ss_add(w, 1, iukey, ilink, slen(ilink)) 216 item_docs = item_docs + 1 217 } 218 } 219 } 220 } 221 idx = idx + 1 222 } } 223 } } 224 if already == 1 { if item_docs == 0 { gw(" already present, no new feed items (idempotent)\n" as *u8); gw("URL-INDEX GREEN\n" as *u8); return 0 } } 225 if ss_commit(prefix, w, segid) != 0 { gw(" commit failed\n" as *u8); return 5 } 226 if already == 0 { gw(" INDEXED cid=" as *u8); gn(cid); gw(" (" as *u8); gn(tn); gw(" chars) url=" as *u8); gw(disp); gw("\n" as *u8) } 227 else { gw(" page already present; added only new feed items\n" as *u8) } 228 if item_docs > 0 { gw(" + " as *u8); gn(item_docs); gw(" feed-item docs (each its own article URL -> specific-article retrieval + frontier)\n" as *u8) } 229 gw("URL-INDEX GREEN\n" as *u8) 230 return 0 231}