const irc = require("irc-upd") const childProcess = require("child_process") const syllables = require("syllable") const R = require("ramda") const pluralize = require("pluralize") const { DB, SQL } = require("./db") var client = new irc.Client(process.argv[2] || "207:1473:146:ae77:a3be:d39f:8e59:d256", "testbot", { channels: ["#a", "#botrobots", "#b"], userName: "testbot", encoding: "utf8", port: 6667 }); let links = null let linksResolve = null const logEv = (ty, thing) => SQL`INSERT INTO thing_log (timestamp, type, thing) VALUES (${Date.now()}, ${ty}, ${thing})`.run() const scanlinks = () => { return new Promise(resolve => { if (!linksResolve) { client.send("LINKS") linksResolve = [resolve] links = [] } else { linksResolve.push(resolve) } }) } let sylhist = [] let mhist = [] // pluralize seems to drop unicode sometimes // hackily cope with this const safelyOperate = (s, fn) => { let res = fn(s) if (res.trim() === "") { return s } return res } const handleOf = (thing, fn) => { const ofsplt = /^(.*)\W+of\W+(.*)$/.exec(thing) if (ofsplt) { return `${fn(ofsplt[1])} of ${ofsplt[2]}` } else { return fn(thing) } } const renderItem = x => x.quantity === 1 ? x.thing : `${x.quantity} ${handleOf(x.thing, pluralize.plural)}` client.addListener("message", (nick, channel, message, ev) => { const e = /^<([^>]+)> (.*)$/.exec(message) if (e) { nick = e[1] message = e[2] } const res = /^([A-Za-z0-9_-]+)[:, ]*([A-Za-z0-9_-]+) *(.*)$/.exec(message) if (res) { let [_, tnick, cmd, args] = res tnick = tnick.toLowerCase() args = args.trim().replace(/[.!?]$/, "") cmd = cmd.toLowerCase() if (tnick === client.nick) { console.log(nick, cmd, channel) if (cmd === "starch") { client.say(channel, `starch exists (${Math.random() * 20 + 80}% confidence).`) } else if (cmd === "stats") { client.say(channel, "haha no") } else if (cmd === "help") { client.say(channel, "nobody can help you now") } else if (cmd === "fortune") { childProcess.exec("fortune", (err, out) => { if (err) { return console.warn(err) } client.say(channel, out) }) } else if (cmd === "cat") { client.say(channel, "meow") } else if (cmd === "servers") { scanlinks().then(links => client.say(channel, links.map(x => `${x[1]}: ${/^[0-9]+ (.*)$/.exec(x[3])[1]}`).join("\n"))) } else if (cmd === "take" || cmd === "have") { const things = args.split(/(,| and )/).map(x => x.trim().replace(",", "").replace(/^(an?|the) /, "")).filter(x => x !== "" && x !== "and") for (let thing of things) { let qty = 1 const res = /^([-0-9.]+|some|many)\b\s*(.*)$/iu.exec(thing) if (res) { const [_, rrqty, rthing] = res thing = rthing const rqty = rrqty.toLowerCase() if (rqty === "some") { qty = Math.floor(Math.random() * 17) } else if (rqty === "many") { qty = Math.floor(Math.random() * 2300) } else { qty = parseFloat(rqty) } } thing = handleOf(thing, pluralize.singular) const currQty = SQL`SELECT * FROM inventory WHERE thing = ${thing}`.get()?.quantity if (currQty) { qty += currQty } qty = qty || 0 SQL`INSERT OR REPLACE INTO inventory VALUES (${thing}, ${Date.now()}, ${qty})`.run() console.log("attained", qty, thing) client.say(channel, `I have ${renderItem({ thing, quantity: qty })}.`) } } else if (cmd.startsWith("inv")) { const inv = SQL`SELECT * FROM inventory ORDER BY obtained_at DESC LIMIT 10`.all() client.say(channel, inv.map(renderItem).join("\n")) } else if (cmd === "deploy") { client.say(channel, `Deploying ${args}`) } } } sylhist = R.takeLast(3, R.append(syllables(message), sylhist)) mhist = R.takeLast(50, R.append(message, mhist)) if (R.equals(sylhist, [5, 7, 5])) { client.say(channel, "haiku detected!") logEv("haiku", R.takeLast(3, mhist).join("\n")) } console.log(sylhist) }) client.addListener("raw", ev => { if (ev.command === "rpl_links") { links.push(ev.args) } else if (ev.command === "rpl_endoflinks" && linksResolve) { linksResolve.forEach(r => r(links)) linksResolve = null links = [] } })