stats
This commit is contained in:
parent
06285689d7
commit
3a6c14961a
@ -1,6 +1,6 @@
|
||||
const Database = require("better-sqlite3")
|
||||
import Database from "better-sqlite3"
|
||||
|
||||
const DB = Database(process.env.DB || "./db.sqlite3")
|
||||
export const DB = Database(process.env.DB || "./db.sqlite3")
|
||||
|
||||
const migrations = [
|
||||
`
|
||||
@ -17,6 +17,12 @@ CREATE TABLE inventory (
|
||||
obtained_at INTEGER NOT NULL,
|
||||
quantity REAL NOT NULL
|
||||
);
|
||||
`,
|
||||
`
|
||||
CREATE TABLE stats (
|
||||
stat TEXT PRIMARY KEY,
|
||||
value BLOB NOT NULL
|
||||
);
|
||||
`
|
||||
]
|
||||
|
||||
@ -39,7 +45,7 @@ DB.pragma("foreign_keys = 1")
|
||||
|
||||
const preparedStatements = new Map()
|
||||
|
||||
const SQL = (strings, ...params) => {
|
||||
export const SQL = (strings, ...params) => {
|
||||
const sql = strings.join("?")
|
||||
let stmt
|
||||
const cachedValue = preparedStatements.get(sql)
|
||||
@ -55,6 +61,4 @@ const SQL = (strings, ...params) => {
|
||||
all: () => stmt.all.apply(stmt, params),
|
||||
statement: stmt
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { DB, SQL }
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
const irc = require("irc-upd")
|
||||
const childProcess = require("child_process")
|
||||
const syllables = require("syllable")
|
||||
const R = require("ramda")
|
||||
const pluralize = require("pluralize")
|
||||
import irc from "irc-upd"
|
||||
import * as childProcess from "child_process"
|
||||
import syllables from "syllable"
|
||||
import * as R from "ramda"
|
||||
import pluralize from "pluralize"
|
||||
const { HyperLogLog } = await import("hyperlolo")
|
||||
|
||||
const { DB, SQL } = require("./db")
|
||||
const { DB, SQL } = await import("./db.mjs")
|
||||
|
||||
var client = new irc.Client(process.argv[2] || "irc.osmarks.net", "testbot", {
|
||||
channels: ["#a", "#botrobots", "#b"],
|
||||
@ -62,12 +63,12 @@ const PLURALS = [
|
||||
["Category:English irregular plurals", "Categories:English irregular plurals"],
|
||||
["enigma", "enigmas"],
|
||||
["radix", "radixes"],
|
||||
["water", "water"],
|
||||
["funny", "funnies"],
|
||||
["octopus", "octopoda"],
|
||||
["the place in the world which is northernmost", "the places in the world which are northernmost"],
|
||||
["datum", "data"],
|
||||
["testbot", "testbots"],
|
||||
["notion of LLM use", "notions of LLM use"],
|
||||
["oil of vitriol", "oil of vitriol"],
|
||||
["noun phrase", "noun phrases"],
|
||||
["information", "information"],
|
||||
@ -76,6 +77,8 @@ const PLURALS = [
|
||||
["potions of cryoapiocity", "potions of cryoapiocity"],
|
||||
["sulfuric acid", "sulfuric acid"],
|
||||
["dollar", "dollars"],
|
||||
["acid", "acid"],
|
||||
["water", "water"],
|
||||
]
|
||||
const PLURALS_KEEP_SAME = [
|
||||
"mice",
|
||||
@ -84,7 +87,8 @@ const PLURALS_KEEP_SAME = [
|
||||
"dodecahedra",
|
||||
"those things which must not be seen",
|
||||
"announcements",
|
||||
"rotations"
|
||||
"rotations",
|
||||
"spider-based countermeasures"
|
||||
]
|
||||
const SINGULARS_KEEP_SAME = [
|
||||
"mouse",
|
||||
@ -93,12 +97,13 @@ const SINGULARS_KEEP_SAME = [
|
||||
"dodecahedron",
|
||||
"that thing which must not be seen",
|
||||
"announcement",
|
||||
"rotation"
|
||||
"rotation",
|
||||
"spider-based countermeasure"
|
||||
]
|
||||
|
||||
const spliceIn = (xs, ys) => {
|
||||
const locations = new Map(ys.map((y, i) => [Math.floor(xs.length * (i / ys.length)), y]))
|
||||
const out = xs.map((x, i) => (locations.get(i) ? [x, locations.get(i)] : [x]))
|
||||
const out = xs.map((x, i) => (locations.get(i) ? [locations.get(i), x] : [x]))
|
||||
const realOut = []
|
||||
for (const x of out) {
|
||||
for (const y of x) {
|
||||
@ -144,7 +149,17 @@ client.addListener("message", async (nick, channel, message, ev) => {
|
||||
nick = e[1]
|
||||
message = e[2]
|
||||
}
|
||||
const allStatsRaw = SQL`SELECT * FROM stats`.all().map(x => [x.stat, x.value])
|
||||
const origStats = new Map(allStatsRaw)
|
||||
const allStats = new Map(allStatsRaw)
|
||||
allStats.set("messages", (allStats.get("messages") ?? 0) + 1)
|
||||
const res = /^([A-Za-z0-9_-]+)[:, ]*([A-Za-z0-9_-]+) *(.*)$/.exec(message)
|
||||
const uniqueUsersCounter = allStats.get("users") ? HyperLogLog.deserialize(allStats.get("users")) : new HyperLogLog({ hasherId: "jenkins32", precision: 5 })
|
||||
uniqueUsersCounter.add(nick)
|
||||
allStats.set("users", uniqueUsersCounter.serialize())
|
||||
const uniqueMessagesCounter = allStats.get("uniqueMessages") ? HyperLogLog.deserialize(allStats.get("uniqueMessages")) : new HyperLogLog({ hasherId: "jenkins32", precision: 5 })
|
||||
uniqueMessagesCounter.add(message)
|
||||
allStats.set("uniqueMessages", uniqueMessagesCounter.serialize())
|
||||
if (res) {
|
||||
let [_, tnick, cmd, args] = res
|
||||
tnick = tnick.toLowerCase()
|
||||
@ -152,21 +167,23 @@ client.addListener("message", async (nick, channel, message, ev) => {
|
||||
cmd = cmd.toLowerCase()
|
||||
if (tnick === client.nick) {
|
||||
console.log(nick, cmd, channel)
|
||||
allStats.set("commands", (allStats.get("commands") ?? 0) + 1)
|
||||
if (cmd === "starch") {
|
||||
client.say(channel, `starch exists (${Math.random() * 20 + 80}% confidence).`)
|
||||
client.say(channel, `Starch exists (${Math.random() * 20 + 80}% confidence).`)
|
||||
} else if (cmd === "stats") {
|
||||
client.say(channel, "haha no")
|
||||
client.say(channel, `${allStats.get("commands")} run, ${allStats.get("messages")} messages seen, about ${Math.floor(uniqueUsersCounter.count())} nicks seen, about ${Math.floor(uniqueMessagesCounter.count())} unique messages seen.`)
|
||||
} else if (cmd === "help") {
|
||||
client.say(channel, "nobody can help you now")
|
||||
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")
|
||||
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")))
|
||||
const links = await scanlinks()
|
||||
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) {
|
||||
@ -199,7 +216,7 @@ client.addListener("message", async (nick, channel, message, ev) => {
|
||||
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}`)
|
||||
client.say(channel, `Deploying ${args}.`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -208,10 +225,18 @@ client.addListener("message", async (nick, channel, message, ev) => {
|
||||
sylhist = R.takeLast(3, R.append(syllables(messageContent), sylhist))
|
||||
mhist = R.takeLast(50, R.append(messageContent, mhist))
|
||||
if (R.equals(sylhist, [5, 7, 5])) {
|
||||
client.say(channel, "haiku detected!")
|
||||
client.say(channel, "Haiku detected!")
|
||||
logEv("haiku", R.takeLast(3, mhist).join("\n"))
|
||||
}
|
||||
console.log(sylhist)
|
||||
|
||||
DB.transaction(() => {
|
||||
for (const [k, v] of allStats) {
|
||||
if (origStats.get(k) !== v) {
|
||||
SQL`INSERT OR REPLACE INTO stats VALUES (${k}, ${v})`.run()
|
||||
}
|
||||
}
|
||||
})()
|
||||
})
|
||||
|
||||
client.addListener("raw", ev => {
|
Loading…
Reference in New Issue
Block a user