import { readdirSync } from "node:fs"; import { join } from "node:path"; import { respond } from "../audio/AudioService.js"; import type { TTSPreferencesRow } from "../db/schema.js"; import { formatCandidates } from "../tts/BaseEngine.js"; import type { Module } from "./types.js"; export const canttalk: Module = ({ client, audio, commands, tts, db, t, config, rootDir }) => { const sysmsg = join(rootDir, "sysmsg.wav"); client.on("messageCreate", async (message) => { if (message.author.bot) return; if (message.content.startsWith(config.PREFIX)) return; if (!config.TTS_CHANNEL || message.channel.id !== config.TTS_CHANNEL) return; const voiceChannel = message.member?.voice.channel; if (!voiceChannel) return; let userRow = await db.get( "select * from TTSPreferences where user_id=?", message.author.id, ); if (!userRow) { await db.run("insert into TTSPreferences (user_id,engine,voice) values (?,?,?)", [ message.author.id, tts.announcement.shortName, tts.announcementVoice, ]); userRow = await db.get( "select * from TTSPreferences where user_id=?", message.author.id, ); } if (!userRow) return; const engine = tts.get(userRow.engine); if (engine) { await audio.speak(voiceChannel, message.content, engine, userRow.voice); } }); commands.register("myvoice", async (args, message) => { const engineName = args[1]; if (!engineName || args.length < 3) { return respond(audio, sysmsg, message, t("TOO_MANY_ARGUMENTS")); } const engine = tts.get(engineName); if (!engine) { return respond(audio, sysmsg, message, t("INVALID_ENGINE", engineName)); } const voiceInput = args.slice(2).join(" "); const res = engine.resolveVoice(voiceInput); let chosenVoice: string; if (res.kind === "exact" || res.kind === "fuzzy") { chosenVoice = res.voice; respond(audio, sysmsg, message, t("USER_VOICE_CHANGED", chosenVoice, engine.longName)); } else if (res.kind === "ambiguous") { return respond( audio, sysmsg, message, t("AMBIGUOUS_VOICE", voiceInput, formatCandidates(res.candidates)), ); } else { chosenVoice = engine.getDefaultVoice(); respond(audio, sysmsg, message, t("INVALID_VOICE", chosenVoice, engine.longName)); } await db.run("update TTSPreferences set engine=?, voice=? where user_id=?", [ engineName, chosenVoice, message.author.id, ]); }); commands.register("random", async (_args, _message) => { const tmpPath = config.VOICE_TMP_PATH; const files = readdirSync(tmpPath); if (files.length === 0) return; const rnd = files[Math.floor(Math.random() * files.length)]; if (!rnd) return; audio.queue.add(sysmsg); audio.queue.add(join(tmpPath, rnd)); }); };