// A bot which responds to `jarvis` with a box // BUG: The Scheduler, Search, Claims, ident, AND Write Listener can ALL be // used as extensions for Socket. This would make the code so much easier to // understand const Space = require('../space'); const Socket = require('../socket'); const ms = require('../utils/measurespace'); const vec = require('../utils/vec'); const comb = require('../utils/comb'); const Search = require('../tools/search'); const sched = require('../tools/schedule'); const ri = require('../utils/rectintersect'); const id = require('../utils/ident'); const maketiles = require('../utils/maketiles'); const wwrap = require('../utils/writewrap'); const Claims = require('../tools/claim'); //// The queue of all writes to be sent to the server @ 200chars/1000ms class MetaSocket extends Socket{ constructor(world='', delayms=1000){ super(world); let self = this; sched.Queue.call(self, 1000, 200, (elems) => self.write(elems)); Claims.call(self); id.call(self); wwrap.call(self); self.sender; self.on('init',(send)=>{ self.sender = send; }); Search.call(this); } } var main = new MetaSocket(); // See ident.js for further documentation, but this basically sets up init functions main.on('init', (send)=>{ setTimeout(()=>{main.enable()},1000); main.enqueue(genNotif().towrite()); }); main.on('close', ()=>main.disable()); main.on('initOnce', ()=>{ timect(); main.on('tileUpdate', tileHandler); // Should only be active after the "control space" of the notification has been established }); //// Management utilities // When a tile changes, processes data into usable form and runs every function in `funcs` w/ that data. // Note that functions can edit inputs function tileHandler(send, source, tiles){ if (send == main.sender) return; let tiledata = maketiles(tiles); main.handle(send, tiledata.tilespaces, tiledata.locs); } //// "userspace" functions for responses, like to tileUpdates const command = 'jarvis' const sig = 'feynmansfedora' const notifsrc = '\ \n\ For a node.js YWOT api: \n\ & git.hrhr.dev/ywot-clean \n\ & Try `COMMAND` today. Uptime: UPTIME. \n\ & Called: JARVISx ~SIGNATURE \n\ & If you have any good bullet art (<100 chars),\n\ & please send it to me at hr@hrhr.dev. \n\ '.replace('COMMAND', command).replace('SIGNATURE', sig); const notifloc = [0, 20]; var minsUp = 0; var callct = 0; var notifClaim; function genNotif(){ let newnotif = new Space(); newnotif.loc = notifloc; text = notifsrc; text = text.replace('UPTIME', Math.floor(minsUp/60) + 'h' + minsUp%60 + 'm'); text = text.replace('JARVIS', callct); newnotif.adhoc(text); return newnotif } var notif = new Space(); notif.loc = notifloc; function notifRefresh(){ let newnotif = genNotif(); let diff = newnotif.copy(); diff.comb(notif, comb.sub); notif = newnotif; if (notifClaim) main.unclaim(notifClaim); notifClaim = main.claim(newnotif, protectArea); return (diff.towrite()); } function timect(){ minsUp++; main.enqueue(notifRefresh()); setTimeout(timect, 60*1000); } function protectArea(send, tiles, locs, id, space, ctrl){ let writelist = []; for (let loc of locs){ let tile = tiles[loc]; // Write diffs from the tile let diff = space.copy(); // Acts as a window for tile (only see relevant data) diff.comb(tile, comb.flip(comb.unmask)); diff.comb(tile, comb.sub); writelist.push(...diff.towrite()) } main.enqueue(writelist); } var search = new Space(); search.adhoc('jarvis'); // The search space is the word jarvis, so whenever that's caught, a relevant function can be called. var read = new Search(); read.match(search, respond); var expire = {}; main.on('fallback', (send, tiles, locs) => { // tries to detect the prompt ('jarvis') and calls respond if found. for (let loc of locs){ if (read.has(loc)){ clearTimeout(expire[loc]); read.del(loc); } read.add(loc, tiles[loc]); expire[loc] = setTimeout(() => {read.del(loc); delete expire[loc];}, 30000); } }); let response = new Space(); response.adhoc('yes, my liege'); var limits = []; // an array of senders within the last 5 seconds to act as a 'rate limiter' function respond(coord, send){ if (limits.indexOf(send) >= 0) return; console.log('called at', coord); callct += 1; response.loc = coord; main.enqueue(response.towrite().concat(notifRefresh())); read.update(response); setTimeout(() => {limits.splice(limits.indexOf(send))}, 5*1000); limits.push(send); }