{
"version": 3,
"sources": ["../../../server/chat-plugins/responder.ts"],
"sourcesContent": ["/**\n * PS Help room auto-response plugin.\n * Uses Regex to match room frequently asked question (RFAQ) entries,\n * and replies if a match is found.\n * Supports configuration, and works in all rooms, though intended mainly for Help.\n * Written by Mia.\n * @author mia-pi-git\n */\n\nimport { FS, Utils } from '../../lib';\nimport { LogViewer } from './chatlog';\nimport { roomFaqs, visualizeFaq } from './room-faqs';\n\nconst DATA_PATH = 'config/chat-plugins/responder.json';\nconst LOG_PATH = Monitor.logPath('responder.jsonl').path;\n\nexport let answererData: { [roomid: string]: PluginData } = {};\n\ntry {\n\tanswererData = JSON.parse(FS(DATA_PATH).readSync());\n} catch {}\n\n/**\n * A message caught by the filter.\n */\ninterface LoggedMessage {\n\t/** Message that's matched by the filter. */\n\tmessage: string;\n\t/** The FAQ that it's matched to. */\n\tfaqName: string;\n\t/** The regex that it's matched to. */\n\tregex: string;\n\tdate: string;\n}\ninterface PluginData {\n\t/** Word pairs that have been marked as a match for a specific FAQ. */\n\tpairs: { [k: string]: string[] };\n\t/** Common terms to be ignored in question parsing. */\n\tignore?: string[];\n}\n\nexport class AutoResponder {\n\tdata: PluginData;\n\troom: Room;\n\tconstructor(room: Room, data?: PluginData) {\n\t\tthis.room = room;\n\t\tthis.data = data || { pairs: {}, ignore: [] };\n\t\tAutoResponder.migrateStats(this.data, this);\n\t}\n\tstatic migrateStats(data: any, responder: AutoResponder) {\n\t\tif (!data.stats) return data;\n\t\tfor (const date in data.stats) {\n\t\t\tfor (const entry of data.stats[date].matches) {\n\t\t\t\tvoid this.logMessage(responder.room.roomid, { ...entry, date });\n\t\t\t}\n\t\t}\n\t\tdelete data.stats;\n\t\tresponder.data = data;\n\t\tresponder.writeState();\n\t\treturn data;\n\t}\n\tstatic logStream = FS(LOG_PATH).createAppendStream();\n\tstatic logMessage(roomid: RoomID, entry: LoggedMessage) {\n\t\treturn this.logStream.writeLine(JSON.stringify({\n\t\t\t...entry,\n\t\t\troom: roomid,\n\t\t\tregex: entry.regex.toString(),\n\t\t}));\n\t}\n\tfind(question: string, user?: User) {\n\t\t// sanity slice, APPARENTLY people are dumb.\n\t\tquestion = question.slice(0, 300);\n\t\tconst room = this.room;\n\t\tconst helpFaqs = roomFaqs[room.roomid];\n\t\tif (!helpFaqs) return null;\n\t\tconst normalized = Chat.normalize(question);\n\t\tif (this.data.ignore) {\n\t\t\tif (this.data.ignore.some(t => new RegExp(t, \"i\").test(normalized))) {\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tconst faqs = Object.keys(helpFaqs).filter(item => !helpFaqs[item].alias);\n\t\tfor (const faq of faqs) {\n\t\t\tconst match = this.test(normalized, faq);\n\t\t\tif (match) {\n\t\t\t\tif (user) {\n\t\t\t\t\tconst timestamp = Chat.toTimestamp(new Date()).split(' ')[1];\n\t\t\t\t\tconst log = `${timestamp} |c| ${user.name}|${question}`;\n\t\t\t\t\tthis.log(log, faq, match.regex);\n\t\t\t\t}\n\t\t\t\treturn helpFaqs[match.faq];\n\t\t\t}\n\t\t}\n\t\treturn null;\n\t}\n\tvisualize(question: string, hideButton?: boolean, user?: User) {\n\t\tconst response = this.find(question, user);\n\t\tif (response) {\n\t\t\tlet buf = '';\n\t\t\tbuf += Utils.html`You said: ${question}
`;\n\t\t\tbuf += `Our automated reply: ${Chat.collapseLineBreaksHTML(visualizeFaq(response))}`;\n\t\t\tif (!hideButton) {\n\t\t\t\tbuf += Utils.html`
/autoresponder view [page]
- Views the Autoresponder page [page]. (options: keys, stats)`,\n\t\t\t`/autoresponder toggle [on | off]
- Enables or disables the Autoresponder for the current room. Requires: @ # ~`,\n\t\t\t`/autoresponder add [input] => [faq]
- Adds regex made from the input string to the current room's Autoresponder, to respond with [faq] to matches.`,\n\t\t\t`/autoresponder remove [faq], [regex index]
- removes the regex matching the [index] from the current room's responses for [faq].`,\n\t\t\t`Indexes can be found in /autoresponder keys.`,\n\t\t\t`Requires: @ # ~`,\n\t\t];\n\t\treturn this.sendReplyBox(help.join('${entry.regex}
Index | Regex | `;\n\t\t\t\tif (canChange) buffer += `Options | `;\n\t\t\t\tbuffer += `
---|---|---|
${index} | ${regex} | `;\n\t\t\t\t\tif (canChange) buffer += `${button} |