code wiki / (root) / nx_magnet_discover.nx

nx_magnet_discover.nx source

↩ module page · 166 lines · 7622 B

1// nx_magnet_discover.nx -- paste a URL, get EVERY magnet on the page + info on each. 2// Fetches the URL over a VALIDATED TLS 1.3 session (nx_https_get + real CA store), 3// scans the response for every "magnet:?" link (decoding HTML &amp; -> &), parses each 4// (info_hash, display name, tracker count) via mg_parse, dedupes by info_hash, and 5// writes a TSV the torrent daemon serves to the UI. The "find all magnets" rung. 6// 7// argv[1] = page URL (https://...) argv[2] = output TSV path 8// out rows: <hash_hex>\t<name>\t<ntrackers>\t<magnet_uri>\n ; plus <out>.status state line. 9// license_tier: ORIGINAL kind: discovery layer: L6 (over validated-HTTPS + magnet-parse) 10// 11// module: nishi-core.torrent.magnet_discover 12import "nx_magnet.nx" 13import "nx_https_get.nx" 14import "nx_x509_trust_store.nx" 15import "nx_pem_loader.nx" 16import "nx_csprng.nx" 17import "nx_syscalls.nx" 18const K_MAGIC_1024: i64 = 1024 19const K_MAGIC_1048576: i64 = 1048576 20const K_MAGIC_4096: i64 = 4096 21const K_MAGIC_4095: i64 = 4095 22 23func md_w(fd: i64, s: *u8) -> i64 { var n: i64=0; while s[n]!=(0 as u8){n=n+1} sys_write(fd,s,n); return 0 } 24func md_wn(fd: i64, v: i64) -> i64 { 25 let t: *u8=sys_mmap(28); var m: i64=v; if m<0 {m=0-m} 26 var k: i64=0; if m==0 {t[0]=48 as u8;k=1}; while m>0 {t[k]=(48+(m%10)) as u8; m=m/10; k=k+1} 27 let b: *u8=sys_mmap(28); var i: i64=0; while i<k {b[i]=t[k-1-i]; i=i+1}; sys_write(fd,b,k); return 0 28} 29func md_open_w(path: *u8) -> i64 { return sys_openat_wr(path, 0x1a4) } 30 31// hex-encode the 20-byte info_hash into out[0..40]+NUL 32func md_hex(ihash: *u8, out: *u8) -> i64 { 33 let hd: *u8 = "0123456789abcdef" as *u8 34 var i: i64 = 0 35 while i < 20 { let b: i64 = ihash[i] as i64; out[i*2]=hd[(b>>4)&0xf]; out[i*2+1]=hd[b&0xf]; i=i+1 } 36 out[40]=0 as u8 37 return 40 38} 39 40func md_is_term(c: i64) -> i64 { 41 if c==34 { return 1 } // " 42 if c==39 { return 1 } // ' 43 if c==60 { return 1 } // < 44 if c==62 { return 1 } // > 45 if c==32 { return 1 } // space 46 if c==9 { return 1 } // tab 47 if c==10 { return 1 } // \n 48 if c==13 { return 1 } // \r 49 if c==92 { return 1 } // backslash 50 return 0 51} 52 53// write the status sidecar: <outpath>.status holding one state line 54func md_status(outpath: *u8, state: *u8, count: i64, bytes: i64) -> i64 { 55 let sp: *u8 = sys_mmap(K_MAGIC_1024) 56 var i: i64 = 0; while outpath[i]!=(0 as u8) { sp[i]=outpath[i]; i=i+1 } 57 let suf: *u8 = ".status" as *u8; var j: i64 = 0; while suf[j]!=(0 as u8) { sp[i]=suf[j]; i=i+1; j=j+1 } sp[i]=0 as u8 58 let fd: i64 = md_open_w(sp); if fd<0 { return 0 } 59 md_w(fd, "state=" as *u8); md_w(fd, state) 60 md_w(fd, "\ncount=" as *u8); md_wn(fd, count) 61 md_w(fd, "\nbytes=" as *u8); md_wn(fd, bytes); md_w(fd, "\n" as *u8) 62 sys_close(fd) 63 return 0 64} 65 66func main(argc: i64, argv: *i64) -> i64 { 67 var url: *u8 = "https://example.com/" as *u8 68 if argc >= 2 { url = argv[1] as *u8 } 69 var outpath: *u8 = "/mnt/c/Users/elder/Downloads/nishi-torrents/discover.tsv" as *u8 70 if argc >= 3 { outpath = argv[2] as *u8 } 71 72 md_status(outpath, "fetching" as *u8, 0, 0) 73 74 // ---- validated TLS 1.3 boot ---- 75 let store: *TrustStore = trust_store_alloc(400) 76 let nroots: i64 = nx_pem_trust_load_file("/etc/ssl/certs/ca-certificates.crt\x00", store) 77 if nroots <= 0 { md_status(outpath, "error-no-ca" as *u8, 0, 0); sys_exit(1); return 1 } 78 let cr: *u8 = sys_mmap(32); let pk: *u8 = sys_mmap(32) 79 nx_csprng_fill(cr, 32); nx_csprng_fill(pk, 32) 80 81 let cap: i64 = K_MAGIC_1048576 82 let resp: *u8 = sys_mmap(cap) 83 let n: i64 = nx_https_get(url, cr, pk, store, sys_now_realtime_sec(), resp, cap) 84 if n <= 0 { 85 // negative = sealed verdict; surface it 86 let vp: *u8 = sys_mmap(64); var z: i64 = 0 87 let pre: *u8 = "error-fetch-" as *u8; while pre[z]!=(0 as u8){vp[z]=pre[z]; z=z+1} 88 var vv: i64 = 0 - n; if vv==0 { vv=1 } 89 let t: *u8=sys_mmap(28); var m: i64=vv; var k: i64=0; while m>0 {t[k]=(48+(m%10)) as u8; m=m/10; k=k+1} 90 var q: i64=0; while q<k { vp[z]=t[k-1-q]; z=z+1; q=q+1 } vp[z]=0 as u8 91 md_status(outpath, vp, 0, 0) 92 let efd: i64 = md_open_w(outpath); if efd>=0 { sys_close(efd) } // empty result 93 sys_exit(1); return 1 94 } 95 96 // ---- scan for every magnet:?... ---- 97 let outfd: i64 = md_open_w(outpath) 98 if outfd < 0 { md_status(outpath, "error-no-out" as *u8, 0, n); sys_exit(1); return 1 } 99 100 let ihash: *u8 = sys_mmap(32) 101 let trk: *i64 = sys_mmap(MG_NTRK_MAX*8) as *i64 102 let ntrk: *i64 = sys_mmap(16) as *i64 103 let name: *u8 = sys_mmap(K_MAGIC_1024) 104 let hexb: *u8 = sys_mmap(64) 105 let SEENMAX: i64 = 512 106 let seen: *u8 = sys_mmap(SEENMAX*42) // 41 hex+NUL per slot 107 var nseen: i64 = 0 108 var count: i64 = 0 109 110 var i: i64 = 0 111 while i + 8 <= n { 112 var hit: i64 = 0 113 if resp[i]==(109 as u8) { if resp[i+1]==(97 as u8) { if resp[i+2]==(103 as u8) { if resp[i+3]==(110 as u8) { if resp[i+4]==(101 as u8) { if resp[i+5]==(116 as u8) { if resp[i+6]==(58 as u8) { if resp[i+7]==(63 as u8) { 114 hit = 1 115 }}}}}}}} 116 if hit == 1 { 117 // copy the magnet, decoding &amp; -> & 118 let mbuf: *u8 = sys_mmap(K_MAGIC_4096) 119 var j: i64 = i; var k: i64 = 0; var go: i64 = 1 120 while go == 1 { 121 if j >= n { go = 0 } else { 122 let c: i64 = resp[j] as i64 123 if md_is_term(c) == 1 { go = 0 } else { 124 if c == 38 { 125 if k < K_MAGIC_4095 { mbuf[k]=38 as u8; k=k+1 } 126 if j+4 < n { if resp[j+1]==(97 as u8) { if resp[j+2]==(109 as u8) { if resp[j+3]==(112 as u8) { if resp[j+4]==(59 as u8) { j=j+4 } } } } } 127 j = j+1 128 } else { 129 if k < K_MAGIC_4095 { mbuf[k]=c as u8; k=k+1 } 130 j = j+1 131 } 132 } 133 } 134 } 135 mbuf[k] = 0 as u8 136 i = j 137 // parse 138 if mg_parse(mbuf, ihash, trk, MG_NTRK_MAX, ntrk, name) == 1 { 139 md_hex(ihash, hexb) 140 // dedupe by hash 141 var dup: i64 = 0; var s: i64 = 0 142 while s < nseen { 143 var eq: i64 = 1; var x: i64 = 0 144 while x < 40 { if seen[s*42+x] != hexb[x] { eq = 0; x = 40 } else { x = x + 1 } } 145 if eq == 1 { dup = 1; s = nseen } else { s = s + 1 } 146 } 147 if dup == 0 { 148 if nseen < SEENMAX { var x: i64 = 0; while x < 41 { seen[nseen*42+x]=hexb[x]; x=x+1 } nseen = nseen + 1 } 149 // sanitize name: strip tab/newline 150 var y: i64 = 0; while name[y]!=(0 as u8) { let nc: i64 = name[y] as i64; if nc==9 { name[y]=32 as u8 } if nc==10 { name[y]=32 as u8 } if nc==13 { name[y]=32 as u8 } y=y+1 } 151 md_w(outfd, hexb); md_w(outfd, "\t" as *u8) 152 if name[0]==(0 as u8) { md_w(outfd, "(no name)" as *u8) } else { md_w(outfd, name) } 153 md_w(outfd, "\t" as *u8); md_wn(outfd, ntrk[0]) 154 md_w(outfd, "\t" as *u8); md_w(outfd, mbuf); md_w(outfd, "\n" as *u8) 155 count = count + 1 156 } 157 } 158 } else { i = i + 1 } 159 } 160 sys_close(outfd) 161 md_status(outpath, "done" as *u8, count, n) 162 163 md_w(1, "DISCOVER url-bytes=" as *u8); md_wn(1, n); md_w(1, " magnets=" as *u8); md_wn(1, count); md_w(1, "\n" as *u8) 164 sys_exit(0) 165 return 0 166}