code wiki / _hdl_build / nx_vizsla_notify.nx

nx_vizsla_notify.nx source

↩ module page · 685 lines · 25191 B

1// nx_vizsla_notify.nx -- NISHI VIZSLA OUTWARD DELIVERY (census PA18): the reminder actually REACHES you. 2// Operator 2026-07-08: "birthday and important event reminder ... engagement partner ... state of the art". 3// The reminder ENGINE (nx_vizsla_remind) computes WHAT is due; this organ DELIVERS it. Two honest channels: 4// * ON-SITE (default, fully sovereign, no consent needed -- it surfaces on YOUR first-party page): 5// `deliver` composes remind-due, and for each DUE notice NOT already delivered, appends a notification 6// record. The notification store IS the once-only delivery ledger (additive, CID plane) -- re-running 7// the same day delivers nothing new. This is "never make users do what the system can": the assistant 8// pushes the reminder to your surface without you asking. 9// * EMAIL (compose-ready): `email` composes ONE digest message of all due notices as a valid RFC5322 10// message (From/To/Subject/Date headers + body) written to a .eml -- ready for the DKIM-sign + submit 11// step (nx_email_send/nx_email_submit). The final external SMTP hop is the operator-consent boundary; 12// everything up to a submittable message is sovereign here. 13// 14// Commands: 15// deliver <notifprefix> <calprefix|-> <contacts|-> <today> <leads> [channel] compose remind-due -> on-site records 16// feed <notifprefix> [kind|-] list delivered notifications 17// email <calprefix|-> <contacts|-> <today> <leads> <from> <to> <out.eml> compose the digest email 18// Composes the BLESSED _offc/nx_vizsla_remind.elf (run from the nxc2 dir). Loud-fail: remind errors, bad dates. 19// spec: knowledge/research/2026-06-22-vizsla-sclass-roadmap.md license_tier: ORIGINAL 20import "nx_syscalls.nx" 21import "nx_canon_cid.nx" 22import "nx_seg_store.nx" 23const K_MAGIC_1970: i64 = 1970 24const K_MAGIC_146097: i64 = 146097 25const K_MAGIC_719468: i64 = 719468 26const K_MAGIC_2048: i64 = 2048 27const K_MAGIC_65536: i64 = 65536 28const K_MAGIC_1024: i64 = 1024 29const K_MAGIC_131072: i64 = 131072 30const K_MAGIC_146096: i64 = 146096 31const K_MAGIC_1460: i64 = 1460 32const K_MAGIC_36524: i64 = 36524 33 34func nt_slen(s: *u8) -> i64 { var n: i64 = 0; while s[n] != (0 as u8) { n = n + 1 } return n } 35func nt_p(s: *u8) -> i64 { sys_write(1, s, nt_slen(s)); return 0 } 36 37func nt_eq(a: *u8, b: *u8) -> i64 { 38 var i: i64 = 0 39 var go: i64 = 1 40 while go == 1 { 41 if a[i] != b[i] { return 0 } 42 if a[i] == (0 as u8) { return 1 } 43 i = i + 1 44 } 45 return 0 46} 47 48func nt_dup(s: *u8) -> *u8 { 49 let n: i64 = nt_slen(s) 50 let d: *u8 = sys_mmap(n + 2) 51 var i: i64 = 0 52 while i <= n { d[i] = s[i]; i = i + 1 } 53 return d 54} 55 56func nt_atoi(s: *u8) -> i64 { 57 var v: i64 = 0 58 var i: i64 = 0 59 while s[i] != (0 as u8) { 60 let d: i64 = (s[i] as i64) - 48 61 if d >= 0 { if d <= 9 { v = v * 10 + d } } 62 i = i + 1 63 } 64 return v 65} 66 67func nt_cat(dst: *u8, off: i64, s: *u8) -> i64 { 68 var i: i64 = 0 69 while s[i] != (0 as u8) { dst[off + i] = s[i]; i = i + 1 } 70 return off + i 71} 72 73func nt_catn(dst: *u8, off: i64, v: i64) -> i64 { 74 var o: i64 = off 75 var m: i64 = v 76 if m < 0 { dst[o] = 45 as u8; o = o + 1; m = 0 - m } 77 let t: *u8 = sys_mmap(28) 78 var k: i64 = 0 79 if m == 0 { t[0] = 48 as u8; k = 1 } 80 while m > 0 { t[k] = (48 + (m % 10)) as u8; m = m / 10; k = k + 1 } 81 var i: i64 = 0 82 while i < k { dst[o + i] = t[k - 1 - i]; i = i + 1 } 83 return o + k 84} 85 86func nt_kmemeq(b: *u8, off: i64, n: i64, s: *u8) -> i64 { 87 if nt_slen(s) != n { return 0 } 88 var i: i64 = 0 89 while i < n { 90 if b[off + i] != s[i] { return 0 } 91 i = i + 1 92 } 93 return 1 94} 95 96func nt_field(rec: *u8, rl: i64, want: *u8, out: *u8, cap: i64) -> i64 { 97 if rl < 8 { return 0 } 98 let nf: i64 = ss_r32(rec, 4) 99 var off: i64 = 8 100 var fi: i64 = 0 101 while fi < nf { 102 if off + 8 > rl { return 0 } 103 let kl: i64 = ss_r32(rec, off) 104 let koff: i64 = off + 4 105 let vl: i64 = ss_r32(rec, koff + kl) 106 let voff: i64 = koff + kl + 4 107 if nt_kmemeq(rec, koff, kl, want) == 1 { 108 var t: i64 = 0 109 while t < vl { 110 if t < cap - 1 { out[t] = rec[voff + t] } 111 t = t + 1 112 } 113 if t > cap - 1 { t = cap - 1 } 114 out[t] = 0 as u8 115 return 1 116 } 117 off = voff + vl 118 fi = fi + 1 119 } 120 return 0 121} 122 123func nt_iskind(b: *u8, koff: i64, kl: i64, pfx: *u8) -> i64 { 124 if kl <= 4 { return 0 } 125 return nt_kmemeq(b, koff, 4, pfx) 126} 127 128func nt_datedays(s: *u8) -> i64 { 129 let nums: *i64 = sys_mmap(8 * 4) as *i64 130 var nn: i64 = 0 131 var cur: i64 = 0 132 var indig: i64 = 0 133 var i: i64 = 0 134 var go: i64 = 1 135 while go == 1 { 136 let c: i64 = s[i] as i64 137 var isd: i64 = 0 138 if c >= 48 { if c <= 57 { isd = 1 } } 139 if isd == 1 { cur = cur * 10 + (c - 48); indig = 1 } 140 if isd == 0 { 141 if indig == 1 { 142 if nn < 4 { nums[nn] = cur; nn = nn + 1 } 143 cur = 0 144 indig = 0 145 } 146 } 147 if c == 0 { go = 0 } 148 i = i + 1 149 } 150 if nn != 3 { return 0 - 1 } 151 var y: i64 = nums[0] 152 let m: i64 = nums[1] 153 let d: i64 = nums[2] 154 if y < K_MAGIC_1970 { return 0 - 1 } 155 if m < 1 { return 0 - 1 } 156 if m > 12 { return 0 - 1 } 157 if d < 1 { return 0 - 1 } 158 if d > 31 { return 0 - 1 } 159 if m <= 2 { y = y - 1 } 160 let era: i64 = y / 400 161 let yoe: i64 = y - era * 400 162 var mp: i64 = m - 3 163 if m <= 2 { mp = m + 9 } 164 let doy: i64 = (153 * mp + 2) / 5 + d - 1 165 let doe: i64 = yoe * 365 + yoe / 4 - yoe / 100 + doy 166 return era * K_MAGIC_146097 + doe - K_MAGIC_719468 167} 168 169func nt_find(list: *i64, n: i64, s: *u8) -> i64 { 170 var i: i64 = 0 171 while i < n { 172 if nt_eq(list[i] as *u8, s) == 1 { return i } 173 i = i + 1 174 } 175 return 0 - 1 176} 177 178func nt_put(keys: *i64, vals: *i64, nf: i64, kp: *u8, st: *i64) -> i64 { 179 let enc: *u8 = sys_mmap(K_MAGIC_2048) 180 let el: i64 = canon_encode(keys, vals, nf, enc) 181 let cid: *u8 = sys_mmap(96) 182 cid_of(enc, el, cid) 183 let kbuf: *u8 = sys_mmap(128) 184 var ko: i64 = 0 185 ko = nt_cat(kbuf, ko, kp) 186 ko = nt_cat(kbuf, ko, cid) 187 kbuf[ko] = 0 as u8 188 let seen: *i64 = st[1] as *i64 189 var fresh: i64 = 1 190 if nt_find(seen, st[2], kbuf) >= 0 { fresh = 0; st[4] = st[4] + 1 } 191 if fresh == 1 { 192 if st[2] < K_MAGIC_2048 { 193 let dk: *u8 = nt_dup(kbuf) 194 seen[st[2]] = dk as i64 195 st[2] = st[2] + 1 196 } 197 } 198 if fresh == 1 { 199 let pp: *i64 = sys_mmap(16) as *i64 200 let ll: *i64 = sys_mmap(16) as *i64 201 if ss_get_idx(st[6] as *u8, kbuf, pp, ll) == 1 { fresh = 0; st[5] = st[5] + 1 } 202 } 203 if fresh == 1 { 204 if ss_add(st[0] as *i64, 1, kbuf, enc, el) != 0 { return 0 - 1 } 205 st[3] = st[3] + 1 206 } 207 return 0 208} 209 210// fork the blessed remind engine `due <cal> <contacts> <today> <leads>`, stdout -> outpath 211func nt_run_due(cal: *u8, contacts: *u8, today: *u8, leads: *u8, outpath: *u8) -> i64 { 212 let pid: i64 = sys_fork() 213 if pid == 0 { 214 let ofd: i64 = sys_openat_wr(outpath, 0x1a4) 215 if ofd >= 0 { sys_dup3(ofd, 1, 0); sys_dup3(ofd, 2, 0) } 216 let argv: *i64 = sys_mmap(64) as *i64 217 argv[0] = "_offc/nx_vizsla_remind.elf" as *u8 as i64 218 argv[1] = "due" as *u8 as i64 219 argv[2] = cal as i64 220 argv[3] = contacts as i64 221 argv[4] = today as i64 222 argv[5] = leads as i64 223 argv[6] = 0 224 let envp: *i64 = sys_mmap(16) as *i64 225 envp[0] = 0 226 sys_execve("_offc/nx_vizsla_remind.elf" as *u8, argv, envp) 227 sys_exit(127) 228 } 229 let st: *i64 = sys_mmap(16) as *i64 230 sys_wait4(pid, st, 0) 231 let sig: i64 = st[0] & 0x7f 232 if sig != 0 { return 128 + sig } 233 return (st[0] >> 8) & 0xff 234} 235 236func nt_readall(path: *u8, szout: *i64) -> *u8 { 237 let fd: i64 = sys_openat_rd(path) 238 if fd < 0 { szout[0] = 0 - 1; return 0 as *u8 } 239 let sz: i64 = sys_lseek(fd, 0, 2) 240 sys_lseek(fd, 0, 0) 241 let buf: *u8 = sys_mmap(sz + 64) 242 var got: i64 = 0 243 var n: i64 = 1 244 while n > 0 { 245 n = sys_read(fd, (buf as i64 + got) as *u8, K_MAGIC_65536) 246 if n > 0 { got = got + n } 247 } 248 sys_close(fd) 249 szout[0] = got 250 return buf 251} 252 253// line[off..] starts with kw? 254func nt_starts(line: *u8, llen: i64, off: i64, kw: *u8) -> i64 { 255 let kl: i64 = nt_slen(kw) 256 if off + kl > llen { return 0 } 257 var j: i64 = 0 258 while j < kl { if line[off + j] != kw[j] { return 0 } j = j + 1 } 259 return 1 260} 261 262// extract " key=" value from line[0,llen) into out; tillend=1 -> rest of line, else until next space 263func nt_lfield(line: *u8, llen: i64, key: *u8, out: *u8, cap: i64, tillend: i64) -> i64 { 264 let kl: i64 = nt_slen(key) 265 var i: i64 = 0 266 while i + kl <= llen { 267 var ok: i64 = 1 268 var j: i64 = 0 269 while j < kl { if line[i + j] != key[j] { ok = 0; j = kl } else { j = j + 1 } } 270 if ok == 1 { 271 var p: i64 = i + kl 272 var t: i64 = 0 273 var go: i64 = 1 274 while go == 1 { 275 if p >= llen { go = 0 } else { 276 if tillend == 0 { if line[p] == (32 as u8) { go = 0 } } 277 if go == 1 { if t < cap - 1 { out[t] = line[p]; t = t + 1 } p = p + 1 } 278 } 279 } 280 out[t] = 0 as u8 281 return 1 282 } 283 i = i + 1 284 } 285 out[0] = 0 as u8 286 return 0 287} 288 289// ---------------- DELIVER (on-site) ---------------- 290func nt_cmd_deliver(argc: i64, argv: *i64) -> i64 { 291 if argc < 7 { nt_p("VIZSLA-NOTIFY deliver needs <notifprefix> <cal|-> <contacts|-> <today> <leads> [channel] -- fail loud\n" as *u8); return 1 } 292 let prefix: *u8 = argv[2] as *u8 293 let cal: *u8 = argv[3] as *u8 294 let contacts: *u8 = argv[4] as *u8 295 let today: *u8 = argv[5] as *u8 296 let leads: *u8 = argv[6] as *u8 297 if nt_datedays(today) < 0 { nt_p("VIZSLA-NOTIFY deliver bad today date -- fail loud\n" as *u8); return 1 } 298 var channel: *u8 = "onsite" as *u8 299 if argc > 7 { channel = argv[7] as *u8 } 300 301 // compose the reminder engine (no sent-prefix -> ALL due surfaced; THIS store is the delivery ledger) 302 let due: *u8 = sys_mmap(256) 303 var do2: i64 = 0 304 do2 = nt_cat(due, do2, "/tmp/nt_due_" as *u8) 305 do2 = nt_catn(due, do2, sys_now_us()) 306 do2 = nt_cat(due, do2, ".txt" as *u8) 307 due[do2] = 0 as u8 308 let rc: i64 = nt_run_due(cal, contacts, today, leads, due) 309 if rc != 0 { nt_p("VIZSLA-NOTIFY remind-due FAILED -- fail loud\n" as *u8); return 1 } 310 311 let szp: *i64 = sys_mmap(16) as *i64 312 let bb: *u8 = nt_readall(due, szp) 313 let bn: i64 = szp[0] 314 315 // existing delivered keys (ntkind|id|date) = the once-only ledger 316 let delk: *i64 = sys_mmap(8 * 512) as *i64 317 var ndk: i64 = 0 318 let segs: *i64 = sys_mmap(8 * 260) as *i64 319 let ns: i64 = ss_manifest(prefix, segs) 320 let f1: *u8 = sys_mmap(256) 321 let f2: *u8 = sys_mmap(256) 322 let f3: *u8 = sys_mmap(128) 323 var s: i64 = 0 324 while s < ns { 325 let path: *u8 = sys_mmap(512) 326 var po: i64 = 0 327 po = nt_cat(path, po, prefix) 328 po = nt_cat(path, po, segs[s] as *u8) 329 po = nt_cat(path, po, ".docs" as *u8) 330 path[po] = 0 as u8 331 let szp2: *i64 = sys_mmap(16) as *i64 332 let b: *u8 = ss_readall(path, szp2) 333 let sz: i64 = szp2[0] 334 var j: i64 = 0 335 while j + 9 <= sz { 336 let kind: i64 = b[j] 337 let kl: i64 = ss_r32(b, j + 1) 338 let koff: i64 = j + 5 339 let vl: i64 = ss_r32(b, koff + kl) 340 let voff: i64 = koff + kl + 4 341 var take: i64 = 0 342 if kind == 1 { take = nt_iskind(b, koff, kl, "ntf:" as *u8) } 343 if take == 1 { 344 let rec: *u8 = (b as i64 + voff) as *u8 345 nt_field(rec, vl, "ntkind" as *u8, f1, 256) 346 nt_field(rec, vl, "id" as *u8, f2, 256) 347 nt_field(rec, vl, "date" as *u8, f3, 128) 348 let key: *u8 = sys_mmap(512) 349 var ko: i64 = 0 350 ko = nt_cat(key, ko, f1) 351 key[ko] = 124 as u8; ko = ko + 1 352 ko = nt_cat(key, ko, f2) 353 key[ko] = 124 as u8; ko = ko + 1 354 ko = nt_cat(key, ko, f3) 355 key[ko] = 0 as u8 356 if ndk < 512 { delk[ndk] = key as i64; ndk = ndk + 1 } 357 } 358 j = voff + vl 359 } 360 s = s + 1 361 } 362 363 let keys: *i64 = sys_mmap(8 * 8) as *i64 364 let vals: *i64 = sys_mmap(8 * 8) as *i64 365 keys[0] = "kind" as *u8 as i64 366 keys[1] = "channel" as *u8 as i64 367 keys[2] = "ntkind" as *u8 as i64 368 keys[3] = "id" as *u8 as i64 369 keys[4] = "date" as *u8 as i64 370 keys[5] = "title" as *u8 as i64 371 keys[6] = "on" as *u8 as i64 372 vals[0] = "ntf" as *u8 as i64 373 vals[1] = channel as i64 374 vals[6] = today as i64 375 376 let st: *i64 = sys_mmap(8 * 8) as *i64 377 st[0] = ss_begin() as i64 378 st[1] = sys_mmap(8 * K_MAGIC_2048) 379 st[2] = 0 380 st[3] = 0 381 st[4] = 0 382 st[5] = 0 383 st[6] = prefix as i64 384 385 let segid: i64 = sys_now_us() 386 var delivered: i64 = 0 387 var skipped: i64 = 0 388 let lk: *u8 = sys_mmap(256) 389 let lid: *u8 = sys_mmap(256) 390 let ldt: *u8 = sys_mmap(128) 391 let ltl: *u8 = sys_mmap(256) 392 393 var i: i64 = 0 394 while i < bn { 395 var e: i64 = i 396 var go: i64 = 1 397 while go == 1 { if e >= bn { go = 0 } else { if bb[e] == (10 as u8) { go = 0 } else { e = e + 1 } } } 398 let line: *u8 = (bb as i64 + i) as *u8 399 let llen: i64 = e - i 400 if nt_starts(line, llen, 0, "VIZSLA-REM-DUE" as *u8) == 1 { 401 nt_lfield(line, llen, "kind=" as *u8, lk, 256, 0) 402 nt_lfield(line, llen, "id=" as *u8, lid, 256, 0) 403 nt_lfield(line, llen, "date=" as *u8, ldt, 128, 0) 404 nt_lfield(line, llen, "title=" as *u8, ltl, 256, 1) 405 let key: *u8 = sys_mmap(512) 406 var ko: i64 = 0 407 ko = nt_cat(key, ko, lk) 408 key[ko] = 124 as u8; ko = ko + 1 409 ko = nt_cat(key, ko, lid) 410 key[ko] = 124 as u8; ko = ko + 1 411 ko = nt_cat(key, ko, ldt) 412 key[ko] = 0 as u8 413 if nt_find(delk, ndk, key) >= 0 { 414 skipped = skipped + 1 415 } else { 416 delk[ndk] = key as i64; ndk = ndk + 1 417 vals[2] = nt_dup(lk) as i64 418 vals[3] = nt_dup(lid) as i64 419 vals[4] = nt_dup(ldt) as i64 420 vals[5] = nt_dup(ltl) as i64 421 if nt_put(keys, vals, 7, "ntf:" as *u8, st) != 0 { nt_p("VIZSLA-NOTIFY writer full -- fail loud\n" as *u8); return 1 } 422 delivered = delivered + 1 423 } 424 } 425 i = e + 1 426 } 427 428 var committed: i64 = 0 429 if st[3] > 0 { 430 if ss_commit(prefix, st[0] as *i64, segid) != 0 { nt_p("VIZSLA-NOTIFY commit FAILED -- fail loud\n" as *u8); return 1 } 431 committed = 1 432 } 433 434 let rep: *u8 = sys_mmap(K_MAGIC_1024) 435 var o: i64 = 0 436 o = nt_cat(rep, o, "VIZSLA-NOTIFY-DELIVER channel=" as *u8) 437 o = nt_cat(rep, o, channel) 438 o = nt_cat(rep, o, " today=" as *u8) 439 o = nt_cat(rep, o, today) 440 o = nt_cat(rep, o, " delivered=" as *u8) 441 o = nt_catn(rep, o, delivered) 442 o = nt_cat(rep, o, " skipped=" as *u8) 443 o = nt_catn(rep, o, skipped) 444 o = nt_cat(rep, o, " segment=" as *u8) 445 if committed == 1 { 446 o = nt_cat(rep, o, "seg-" as *u8) 447 o = nt_catn(rep, o, segid) 448 } else { 449 o = nt_cat(rep, o, "none" as *u8) 450 } 451 o = nt_cat(rep, o, "\n" as *u8) 452 sys_write(1, rep, o) 453 return 0 454} 455 456// ---------------- FEED ---------------- 457func nt_cmd_feed(argc: i64, argv: *i64) -> i64 { 458 if argc < 4 { nt_p("VIZSLA-NOTIFY feed needs <notifprefix> <kind|-> -- fail loud\n" as *u8); return 1 } 459 let prefix: *u8 = argv[2] as *u8 460 let kindf: *u8 = argv[3] as *u8 461 let segs: *i64 = sys_mmap(8 * 260) as *i64 462 let ns: i64 = ss_manifest(prefix, segs) 463 let fch: *u8 = sys_mmap(128) 464 let fnk: *u8 = sys_mmap(128) 465 let fid: *u8 = sys_mmap(256) 466 let fdt: *u8 = sys_mmap(128) 467 let fon: *u8 = sys_mmap(128) 468 let ftl: *u8 = sys_mmap(256) 469 let rep: *u8 = sys_mmap(K_MAGIC_131072) 470 var o: i64 = 0 471 var cnt: i64 = 0 472 var s: i64 = 0 473 while s < ns { 474 let path: *u8 = sys_mmap(512) 475 var po: i64 = 0 476 po = nt_cat(path, po, prefix) 477 po = nt_cat(path, po, segs[s] as *u8) 478 po = nt_cat(path, po, ".docs" as *u8) 479 path[po] = 0 as u8 480 let szp: *i64 = sys_mmap(16) as *i64 481 let b: *u8 = ss_readall(path, szp) 482 let sz: i64 = szp[0] 483 var j: i64 = 0 484 while j + 9 <= sz { 485 let kind: i64 = b[j] 486 let kl: i64 = ss_r32(b, j + 1) 487 let koff: i64 = j + 5 488 let vl: i64 = ss_r32(b, koff + kl) 489 let voff: i64 = koff + kl + 4 490 var take: i64 = 0 491 if kind == 1 { take = nt_iskind(b, koff, kl, "ntf:" as *u8) } 492 if take == 1 { 493 let rec: *u8 = (b as i64 + voff) as *u8 494 nt_field(rec, vl, "ntkind" as *u8, fnk, 128) 495 var show: i64 = 1 496 if nt_eq(kindf, "-" as *u8) == 0 { if nt_eq(fnk, kindf) == 0 { show = 0 } } 497 if show == 1 { 498 nt_field(rec, vl, "channel" as *u8, fch, 128) 499 nt_field(rec, vl, "id" as *u8, fid, 256) 500 nt_field(rec, vl, "date" as *u8, fdt, 128) 501 nt_field(rec, vl, "on" as *u8, fon, 128) 502 nt_field(rec, vl, "title" as *u8, ftl, 256) 503 o = nt_cat(rep, o, "VIZSLA-NOTIFY channel=" as *u8) 504 o = nt_cat(rep, o, fch) 505 o = nt_cat(rep, o, " kind=" as *u8) 506 o = nt_cat(rep, o, fnk) 507 o = nt_cat(rep, o, " id=" as *u8) 508 o = nt_cat(rep, o, fid) 509 o = nt_cat(rep, o, " date=" as *u8) 510 o = nt_cat(rep, o, fdt) 511 o = nt_cat(rep, o, " on=" as *u8) 512 o = nt_cat(rep, o, fon) 513 o = nt_cat(rep, o, " title=" as *u8) 514 o = nt_cat(rep, o, ftl) 515 o = nt_cat(rep, o, "\n" as *u8) 516 cnt = cnt + 1 517 } 518 } 519 j = voff + vl 520 } 521 s = s + 1 522 } 523 o = nt_cat(rep, o, "VIZSLA-NOTIFY-FEED kind=" as *u8) 524 o = nt_cat(rep, o, kindf) 525 o = nt_cat(rep, o, " notifications=" as *u8) 526 o = nt_catn(rep, o, cnt) 527 o = nt_cat(rep, o, "\n" as *u8) 528 sys_write(1, rep, o) 529 return 0 530} 531 532// ---------------- EMAIL (compose a valid RFC5322 digest, ready to submit) ---------------- 533func nt_dow(dst: *u8, off: i64, days: i64) -> i64 { 534 let idx: i64 = ((days % 7) + 7 + 4) % 7 // 0=Sun (K_MAGIC_1970-01-01 = Thu -> +4) 535 var o: i64 = off 536 if idx == 0 { o = nt_cat(dst, o, "Sun" as *u8) } 537 if idx == 1 { o = nt_cat(dst, o, "Mon" as *u8) } 538 if idx == 2 { o = nt_cat(dst, o, "Tue" as *u8) } 539 if idx == 3 { o = nt_cat(dst, o, "Wed" as *u8) } 540 if idx == 4 { o = nt_cat(dst, o, "Thu" as *u8) } 541 if idx == 5 { o = nt_cat(dst, o, "Fri" as *u8) } 542 if idx == 6 { o = nt_cat(dst, o, "Sat" as *u8) } 543 return o 544} 545 546func nt_mon(dst: *u8, off: i64, m: i64) -> i64 { 547 var o: i64 = off 548 if m == 1 { o = nt_cat(dst, o, "Jan" as *u8) } 549 if m == 2 { o = nt_cat(dst, o, "Feb" as *u8) } 550 if m == 3 { o = nt_cat(dst, o, "Mar" as *u8) } 551 if m == 4 { o = nt_cat(dst, o, "Apr" as *u8) } 552 if m == 5 { o = nt_cat(dst, o, "May" as *u8) } 553 if m == 6 { o = nt_cat(dst, o, "Jun" as *u8) } 554 if m == 7 { o = nt_cat(dst, o, "Jul" as *u8) } 555 if m == 8 { o = nt_cat(dst, o, "Aug" as *u8) } 556 if m == 9 { o = nt_cat(dst, o, "Sep" as *u8) } 557 if m == 10 { o = nt_cat(dst, o, "Oct" as *u8) } 558 if m == 11 { o = nt_cat(dst, o, "Nov" as *u8) } 559 if m == 12 { o = nt_cat(dst, o, "Dec" as *u8) } 560 return o 561} 562 563func nt_cmd_email(argc: i64, argv: *i64) -> i64 { 564 if argc < 9 { nt_p("VIZSLA-NOTIFY email needs <cal|-> <contacts|-> <today> <leads> <from> <to> <out.eml> -- fail loud\n" as *u8); return 1 } 565 let cal: *u8 = argv[2] as *u8 566 let contacts: *u8 = argv[3] as *u8 567 let today: *u8 = argv[4] as *u8 568 let leads: *u8 = argv[5] as *u8 569 let from: *u8 = argv[6] as *u8 570 let to: *u8 = argv[7] as *u8 571 let outp: *u8 = argv[8] as *u8 572 let tdays: i64 = nt_datedays(today) 573 if tdays < 0 { nt_p("VIZSLA-NOTIFY email bad today date -- fail loud\n" as *u8); return 1 } 574 575 let due: *u8 = sys_mmap(256) 576 var do2: i64 = 0 577 do2 = nt_cat(due, do2, "/tmp/nt_edue_" as *u8) 578 do2 = nt_catn(due, do2, sys_now_us()) 579 do2 = nt_cat(due, do2, ".txt" as *u8) 580 due[do2] = 0 as u8 581 let rc: i64 = nt_run_due(cal, contacts, today, leads, due) 582 if rc != 0 { nt_p("VIZSLA-NOTIFY remind-due FAILED -- fail loud\n" as *u8); return 1 } 583 let szp: *i64 = sys_mmap(16) as *i64 584 let bb: *u8 = nt_readall(due, szp) 585 let bn: i64 = szp[0] 586 587 let ymd: *i64 = sys_mmap(8 * 4) as *i64 588 // civil from tdays (inline Hinnant inverse) 589 var z: i64 = tdays + K_MAGIC_719468 590 var era: i64 = z / K_MAGIC_146097 591 if z < 0 { era = (z - K_MAGIC_146096) / K_MAGIC_146097 } 592 let doe: i64 = z - era * K_MAGIC_146097 593 let yoe: i64 = (doe - doe / K_MAGIC_1460 + doe / K_MAGIC_36524 - doe / K_MAGIC_146096) / 365 594 let y0: i64 = yoe + era * 400 595 let doy: i64 = doe - (365 * yoe + yoe / 4 - yoe / 100) 596 let mp: i64 = (5 * doy + 2) / 153 597 let dd: i64 = doy - (153 * mp + 2) / 5 + 1 598 var mm: i64 = mp + 3 599 if mp >= 10 { mm = mp - 9 } 600 var yy: i64 = y0 601 if mm <= 2 { yy = y0 + 1 } 602 603 let msg: *u8 = sys_mmap(K_MAGIC_131072) 604 var o: i64 = 0 605 o = nt_cat(msg, o, "From: " as *u8) 606 o = nt_cat(msg, o, from) 607 o = nt_cat(msg, o, "\r\nTo: " as *u8) 608 o = nt_cat(msg, o, to) 609 o = nt_cat(msg, o, "\r\nSubject: Your reminders for " as *u8) 610 o = nt_cat(msg, o, today) 611 o = nt_cat(msg, o, "\r\nDate: " as *u8) 612 o = nt_dow(msg, o, tdays) 613 o = nt_cat(msg, o, ", " as *u8) 614 if dd < 10 { msg[o] = 48 as u8; o = o + 1 } 615 o = nt_catn(msg, o, dd) 616 msg[o] = 32 as u8; o = o + 1 617 o = nt_mon(msg, o, mm) 618 msg[o] = 32 as u8; o = o + 1 619 o = nt_catn(msg, o, yy) 620 o = nt_cat(msg, o, " 09:00:00 +0000\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=utf-8\r\n\r\n" as *u8) 621 o = nt_cat(msg, o, "Nishi Vizsla reminders:\r\n\r\n" as *u8) 622 623 var due_cnt: i64 = 0 624 let lnk: *u8 = sys_mmap(128) 625 let lid: *u8 = sys_mmap(256) 626 let ldt: *u8 = sys_mmap(128) 627 let ltl: *u8 = sys_mmap(256) 628 let lin: *u8 = sys_mmap(64) 629 var i: i64 = 0 630 while i < bn { 631 var e: i64 = i 632 var go: i64 = 1 633 while go == 1 { if e >= bn { go = 0 } else { if bb[e] == (10 as u8) { go = 0 } else { e = e + 1 } } } 634 let line: *u8 = (bb as i64 + i) as *u8 635 let llen: i64 = e - i 636 if nt_starts(line, llen, 0, "VIZSLA-REM-DUE" as *u8) == 1 { 637 nt_lfield(line, llen, "kind=" as *u8, lnk, 128, 0) 638 nt_lfield(line, llen, "id=" as *u8, lid, 256, 0) 639 nt_lfield(line, llen, "date=" as *u8, ldt, 128, 0) 640 nt_lfield(line, llen, "in=" as *u8, lin, 64, 0) 641 nt_lfield(line, llen, "title=" as *u8, ltl, 256, 1) 642 o = nt_cat(msg, o, " * " as *u8) 643 o = nt_cat(msg, o, ltl) 644 o = nt_cat(msg, o, " (" as *u8) 645 o = nt_cat(msg, o, lnk) 646 o = nt_cat(msg, o, ") on " as *u8) 647 o = nt_cat(msg, o, ldt) 648 o = nt_cat(msg, o, " -- in " as *u8) 649 o = nt_cat(msg, o, lin) 650 o = nt_cat(msg, o, " days\r\n" as *u8) 651 due_cnt = due_cnt + 1 652 } 653 i = e + 1 654 } 655 o = nt_cat(msg, o, "\r\n-- Nishi Vizsla, on your hardware.\r\n" as *u8) 656 657 let fd: i64 = sys_openat_wr(outp, 0x1a4) 658 if fd < 0 { nt_p("VIZSLA-NOTIFY cannot write out.eml -- fail loud\n" as *u8); return 1 } 659 sys_write(fd, msg, o) 660 sys_close(fd) 661 662 let rep: *u8 = sys_mmap(512) 663 var ro: i64 = 0 664 ro = nt_cat(rep, ro, "VIZSLA-NOTIFY-EMAIL today=" as *u8) 665 ro = nt_cat(rep, ro, today) 666 ro = nt_cat(rep, ro, " reminders=" as *u8) 667 ro = nt_catn(rep, ro, due_cnt) 668 ro = nt_cat(rep, ro, " bytes=" as *u8) 669 ro = nt_catn(rep, ro, o) 670 ro = nt_cat(rep, ro, " -> " as *u8) 671 ro = nt_cat(rep, ro, outp) 672 ro = nt_cat(rep, ro, " (RFC5322, DKIM-signable via nx_email_send; external submit operator-gated)\n" as *u8) 673 sys_write(1, rep, ro) 674 return 0 675} 676 677func main(argc: i64, argv: *i64) -> i64 { 678 if argc < 2 { nt_p("VIZSLA-NOTIFY usage: deliver|feed|email -- fail loud\n" as *u8); return 1 } 679 let cmd: *u8 = argv[1] as *u8 680 if nt_eq(cmd, "deliver" as *u8) == 1 { return nt_cmd_deliver(argc, argv) } 681 if nt_eq(cmd, "feed" as *u8) == 1 { return nt_cmd_feed(argc, argv) } 682 if nt_eq(cmd, "email" as *u8) == 1 { return nt_cmd_email(argc, argv) } 683 nt_p("VIZSLA-NOTIFY unknown command (deliver|feed|email) -- fail loud\n" as *u8) 684 return 1 685}