import { join } from "node:path"; import levenshtein from "fast-levenshtein"; import { respond } from "../audio/AudioService.js"; const isStringInt = (s: string): boolean => /^-?\d+$/.test(s); import type { BotStateRow, WBWStoryRow } from "../db/schema.js"; import type { Module } from "./types.js"; export const wordbyword: Module = ({ audio, commands, db, t, rootDir }) => { const sysmsg = join(rootDir, "sysmsg.wav"); let currentWBW = ""; commands.register("wbw", async (args, message) => { if (args.length === 1) { return respond( audio, sysmsg, message, currentWBW ? t("CURRENT_STORY", currentWBW) : t("NO_STORY"), ); } if (args.length > 2) { return respond(audio, sysmsg, message, t("TOO_MANY_ARGUMENTS")); } const arg1 = args[1]; if (arg1 === undefined) return; if (isStringInt(arg1)) { const story = await db.get( "select * from WBWStories where story_id=?", parseInt(arg1, 10), ); if (!story) return respond(audio, sysmsg, message, t("WBW_INVALID_ID")); return respond(audio, sysmsg, message, story.story_text); } const lastUser = await db.get( "select value from BotState where key='last_wbw'", ); if (lastUser && message.author.id === lastUser.value && currentWBW !== "") { const lastWord = currentWBW.indexOf(" ") === currentWBW.lastIndexOf(" ") ? currentWBW.trim() : currentWBW.slice(currentWBW.slice(0, -1).lastIndexOf(" ") + 1).trim(); if (levenshtein.get(arg1, lastWord) <= 3) { currentWBW = currentWBW.replace( new RegExp(`${escapeRegExp(lastWord)}([^${escapeRegExp(lastWord)}]*)$`), `${arg1}$1 `, ); respond(audio, sysmsg, message, t("WBW_REPLACED", lastWord, arg1)); } else { return respond(audio, sysmsg, message, t("WBW_TOO_DIFFERENT")); } } else { currentWBW += `${arg1} `; respond(audio, sysmsg, message, t("WBW_NEW_WORD")); const toSay = currentWBW.indexOf(".") === -1 ? currentWBW : currentWBW.slice(currentWBW.lastIndexOf(".") + 2); const voiceChannel = message.member?.voice.channel; if (voiceChannel) await audio.speak(voiceChannel, toSay); await db.run("insert or replace into BotState (key, value) values (?, ?)", [ "last_wbw", message.author.id, ]); } }); commands.register("newwbw", async (_args, message) => { await db.run("insert into WBWStories (story_text) values(?)", [currentWBW]); currentWBW = ""; respond(audio, sysmsg, message, t("WBW_RESET")); }); }; function escapeRegExp(s: string): string { return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }