Jofthomas's picture
Jofthomas HF staff
Upload 4781 files
5c2ed06 verified
{
"version": 3,
"sources": ["../../../server/chat-plugins/repeats.ts"],
"sourcesContent": ["/**\n * Chat plugin for repeating messages in chat\n * Based on bot functionality from Kid A and Expecto Botronum\n * @author Annika, Zarel\n */\n\nimport { roomFaqs, getAlias, visualizeFaq } from './room-faqs';\nimport type { MessageHandler } from '../rooms';\n\nexport interface RepeatedPhrase {\n\t/** Identifier for deleting */\n\tid: ID;\n\tphrase: string;\n\t/** interval in milliseconds */\n\tinterval: number;\n\tfaq?: boolean;\n\tisByMessages?: boolean;\n\tisHTML?: boolean;\n}\n\nexport const Repeats = new class {\n\t// keying to Room rather than RoomID will help us correctly handle room renames\n\t/** room:identifier:phrase:timeout map */\n\trepeats = new Map<BasicRoom, Map<ID, Map<string, NodeJS.Timeout | MessageHandler>>>();\n\n\tconstructor() {\n\t\tfor (const room of Rooms.rooms.values()) {\n\t\t\tif (!room.settings?.repeats?.length) continue;\n\t\t\tfor (const repeat of room.settings.repeats) {\n\t\t\t\tthis.runRepeat(room, repeat);\n\t\t\t}\n\t\t}\n\t}\n\n\tremoveRepeatHandler(room: BasicRoom, handler?: NodeJS.Timeout | MessageHandler) {\n\t\tif (typeof handler === 'function') {\n\t\t\troom.nthMessageHandlers.delete(handler);\n\t\t} else if (typeof handler === 'object') {\n\t\t\tclearInterval(handler);\n\t\t}\n\t}\n\n\thasRepeat(room: BasicRoom, id: ID) {\n\t\treturn !!this.repeats.get(room)?.get(id);\n\t}\n\n\taddRepeat(room: BasicRoom, repeat: RepeatedPhrase) {\n\t\tthis.runRepeat(room, repeat);\n\t\tif (!room.settings.repeats) room.settings.repeats = [];\n\t\troom.settings.repeats.push(repeat);\n\t\troom.saveSettings();\n\t}\n\n\tremoveRepeat(room: BasicRoom, id: ID) {\n\t\tif (!room.settings.repeats) return;\n\t\tconst phrase = room.settings.repeats.find(x => x.id === id)?.phrase;\n\t\troom.settings.repeats = room.settings.repeats.filter(repeat => repeat.id !== id);\n\t\tif (!room.settings.repeats.length) delete room.settings.repeats;\n\t\troom.saveSettings();\n\n\t\tconst roomRepeats = this.repeats.get(room);\n\t\tif (!roomRepeats) return;\n\t\tconst oldInterval = roomRepeats.get(id)?.get(phrase!);\n\t\tthis.removeRepeatHandler(room, oldInterval);\n\t\troomRepeats.delete(id);\n\t}\n\n\tclearRepeats(room: BasicRoom) {\n\t\tconst roomRepeats = this.repeats.get(room);\n\t\tif (!roomRepeats) return;\n\t\tfor (const ids of roomRepeats.values()) {\n\t\t\tfor (const interval of ids.values()) {\n\t\t\t\tthis.removeRepeatHandler(room, interval);\n\t\t\t}\n\t\t}\n\t\tthis.repeats.delete(room);\n\t}\n\n\trunRepeat(room: BasicRoom, repeat: RepeatedPhrase) {\n\t\tlet roomRepeats = this.repeats.get(room);\n\t\tif (!roomRepeats) {\n\t\t\troomRepeats = new Map();\n\t\t\tthis.repeats.set(room, roomRepeats);\n\t\t}\n\t\tconst { id, phrase, interval } = repeat;\n\n\t\tif (roomRepeats.has(id)) {\n\t\t\tthrow new Error(`Repeat already exists`);\n\t\t}\n\t\tconst repeater = (targetRoom: BasicRoom) => {\n\t\t\tif (targetRoom !== Rooms.get(targetRoom.roomid)) {\n\t\t\t\t// room was deleted\n\t\t\t\tthis.clearRepeats(targetRoom);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst repeatedPhrase = repeat.faq ?\n\t\t\t\tvisualizeFaq(roomFaqs[targetRoom.roomid][repeat.id]) : Chat.formatText(phrase, true);\n\t\t\tconst formattedText = repeat.isHTML ? phrase : repeatedPhrase;\n\t\t\ttargetRoom.add(`|uhtml|repeat-${repeat.id}|<div class=\"infobox\">${formattedText}</div>`);\n\t\t\ttargetRoom.update();\n\t\t};\n\n\t\tif (repeat.isByMessages) {\n\t\t\troom.nthMessageHandlers.set(repeater, interval);\n\t\t\troomRepeats.set(id, new Map().set(phrase, repeater));\n\t\t} else {\n\t\t\troomRepeats.set(id, new Map().set(phrase, setInterval(repeater, interval, room)));\n\t\t}\n\t}\n\n\tdestroy() {\n\t\tfor (const [room, roomRepeats] of this.repeats) {\n\t\t\tfor (const ids of roomRepeats.values()) {\n\t\t\t\tfor (const interval of ids.values()) {\n\t\t\t\t\tthis.removeRepeatHandler(room, interval);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\nexport function destroy() {\n\tRepeats.destroy();\n}\n\nexport const pages: Chat.PageTable = {\n\trepeats(args, user) {\n\t\tconst room = this.requireRoom();\n\t\tthis.title = `[Repeats]`;\n\t\tthis.checkCan(\"mute\", null, room);\n\t\tlet html = `<div class=\"ladder pad\">`;\n\t\thtml += `<button class=\"button\" name=\"send\" value=\"/join view-repeats-${room.roomid}\" style=\"float: right\"><i class=\"fa fa-refresh\"></i> ${this.tr`Refresh`}</button>`;\n\t\tif (!room.settings.repeats?.length) {\n\t\t\treturn `${html}<h1>${this.tr`There are no repeated phrases in ${room.title}.`}</h1></div>`;\n\t\t}\n\t\thtml += `<h2>${this.tr`Repeated phrases in ${room.title}`}</h2>`;\n\t\thtml += `<table><tr><th>${this.tr`Identifier`}</th><th>${this.tr`Phrase`}</th><th>${this.tr`Raw text`}</th><th>${this.tr`Interval`}</th><th>${this.tr`Action`}</th>`;\n\t\tfor (const repeat of room.settings.repeats) {\n\t\t\tconst minutes = repeat.interval / (repeat.isByMessages ? 1 : 60 * 1000);\n\t\t\tconst repeatText = repeat.faq ? roomFaqs[room.roomid][repeat.id].source : repeat.phrase;\n\t\t\tconst phrase = repeat.faq ? visualizeFaq(roomFaqs[room.roomid][repeat.id]) :\n\t\t\t\trepeat.isHTML ? repeat.phrase : Chat.formatText(repeatText, true);\n\t\t\thtml += `<tr><td>${repeat.id}</td><td>${phrase}</td><td>${Chat.getReadmoreCodeBlock(repeatText)}</td><td>${repeat.isByMessages ? this.tr`every ${minutes} chat message(s)` : this.tr`every ${minutes} minute(s)`}</td>`;\n\t\t\thtml += `<td><button class=\"button\" name=\"send\" value=\"/msgroom ${room.roomid},/removerepeat ${repeat.id}\">${this.tr`Remove`}</button></td>`;\n\t\t}\n\t\thtml += `</table>`;\n\t\tif (user.can(\"editroom\", null, room)) {\n\t\t\thtml += `<br /><button class=\"button\" name=\"send\" value=\"/msgroom ${room.roomid},/removeallrepeats\">${this.tr`Remove all repeats`}</button>`;\n\t\t}\n\t\thtml += `</div>`;\n\t\treturn html;\n\t},\n};\n\nexport const commands: Chat.ChatCommands = {\n\trepeatbymessages: 'repeat',\n\trepeathtmlbymessages: 'repeat',\n\trepeathtml: 'repeat',\n\trepeat(target, room, user, connection, cmd) {\n\t\tconst isHTML = cmd.includes('html');\n\t\tconst isByMessages = cmd.includes('bymessages');\n\t\troom = this.requireRoom();\n\t\tif (room.settings.isPersonal) return this.errorReply(`Personal rooms do not support repeated messages.`);\n\t\tthis.checkCan(isHTML ? 'addhtml' : 'mute', null, room);\n\t\tconst [intervalString, name, ...messageArray] = target.split(',');\n\t\tconst id = toID(name);\n\t\tif (!id) throw new Chat.ErrorMessage(this.tr`Repeat names must include at least one alphanumeric character.`);\n\n\t\tconst phrase = messageArray.join(',').trim();\n\t\tconst interval = parseInt(intervalString);\n\t\tif (isNaN(interval) || !/[0-9]{1,}/.test(intervalString) || interval < 1 || interval > 24 * 60) {\n\t\t\tthrow new Chat.ErrorMessage(this.tr`You must specify an interval as a number of minutes or chat messages between 1 and 1440.`);\n\t\t}\n\n\t\tif (Repeats.hasRepeat(room, id)) {\n\t\t\tthrow new Chat.ErrorMessage(this.tr`The phrase labeled with \"${id}\" is already being repeated in this room.`);\n\t\t}\n\n\t\tif (isHTML) this.checkHTML(phrase);\n\n\t\tRepeats.addRepeat(room, {\n\t\t\tid,\n\t\t\tphrase,\n\t\t\t// convert to milliseconds for time-based repeats\n\t\t\tinterval: interval * (isByMessages ? 1 : 60 * 1000),\n\t\t\tisHTML,\n\t\t\tisByMessages,\n\t\t});\n\n\t\tthis.modlog('REPEATPHRASE', null, `every ${interval} ${isByMessages ? `chat messages` : `minute`}${Chat.plural(interval)}: \"${phrase.replace(/\\n/g, ' ')}\"`);\n\t\tthis.privateModAction(\n\t\t\tisByMessages ?\n\t\t\t\troom.tr`${user.name} set the phrase labeled with \"${id}\" to be repeated every ${interval} chat message(s).` :\n\t\t\t\troom.tr`${user.name} set the phrase labeled with \"${id}\" to be repeated every ${interval} minute(s).`\n\t\t);\n\t},\n\trepeathelp() {\n\t\tthis.runBroadcast();\n\t\tthis.sendReplyBox(\n\t\t\t`<code>/repeat [minutes], [id], [phrase]</code>: repeats a given phrase every [minutes] minutes. Requires: % @ # ~<br />` +\n\t\t\t`<code>/repeathtml [minutes], [id], [phrase]</code>: repeats a given phrase containing HTML every [minutes] minutes. Requires: # ~<br />` +\n\t\t\t`<code>/repeatfaq [minutes], [FAQ name/alias]</code>: repeats a given Room FAQ every [minutes] minutes. Requires: % @ # ~<br />` +\n\t\t\t`<code>/removerepeat [id]</code>: removes a repeated phrase. Requires: % @ # ~<br />` +\n\t\t\t`<code>/viewrepeats [optional room]</code>: Displays all repeated phrases in a room. Requires: % @ # ~<br />` +\n\t\t\t`You can append <code>bymessages</code> to a <code>/repeat</code> command to repeat a phrase based on how many messages have been sent in chat. For example, <code>/repeatfaqbymessages ...</code><br />` +\n\t\t\t`Phrases for <code>/repeat</code> can include normal chat formatting, but not commands.`\n\t\t);\n\t},\n\n\trepeatfaqbymessages: 'repeatfaq',\n\trepeatfaq(target, room, user, connection, cmd) {\n\t\troom = this.requireRoom();\n\t\tthis.checkCan('mute', null, room);\n\t\tif (room.settings.isPersonal) return this.errorReply(`Personal rooms do not support repeated messages.`);\n\t\tconst isByMessages = cmd.includes('bymessages');\n\n\t\tlet [intervalString, topic] = target.split(',');\n\t\tconst interval = parseInt(intervalString);\n\t\tif (isNaN(interval) || !/[0-9]{1,}/.test(intervalString) || interval < 1 || interval > 24 * 60) {\n\t\t\tthrow new Chat.ErrorMessage(this.tr`You must specify an interval as a number of minutes or chat messages between 1 and 1440.`);\n\t\t}\n\t\tif (!roomFaqs[room.roomid]) {\n\t\t\tthrow new Chat.ErrorMessage(`This room has no FAQs.`);\n\t\t}\n\t\ttopic = toID(getAlias(room.roomid, topic) || topic);\n\t\tconst faq = roomFaqs[room.roomid][topic];\n\t\tif (!faq) {\n\t\t\tthrow new Chat.ErrorMessage(`Invalid topic.`);\n\t\t}\n\n\t\tif (Repeats.hasRepeat(room, topic as ID)) {\n\t\t\tthrow new Chat.ErrorMessage(this.tr`The text for the Room FAQ \"${topic}\" is already being repeated.`);\n\t\t}\n\n\t\tRepeats.addRepeat(room, {\n\t\t\tid: topic as ID,\n\t\t\tphrase: faq.source,\n\t\t\tinterval: interval * (isByMessages ? 1 : 60 * 1000),\n\t\t\tfaq: true,\n\t\t\tisByMessages,\n\t\t});\n\n\t\tthis.modlog('REPEATPHRASE', null, `every ${interval} ${isByMessages ? 'chat message' : 'minute'}${Chat.plural(interval)}: the Room FAQ for \"${topic}\"`);\n\t\tthis.privateModAction(\n\t\t\tisByMessages ?\n\t\t\t\troom.tr`${user.name} set the Room FAQ \"${topic}\" to be repeated every ${interval} chat message(s).` :\n\t\t\t\troom.tr`${user.name} set the Room FAQ \"${topic}\" to be repeated every ${interval} minute(s).`\n\t\t);\n\t},\n\n\tdeleterepeat: 'removerepeat',\n\tremoverepeat(target, room, user) {\n\t\troom = this.requireRoom();\n\t\tconst id = toID(target);\n\t\tif (!id) {\n\t\t\treturn this.parse(`/help repeat`);\n\t\t}\n\t\tthis.checkCan('mute', null, room);\n\t\tif (!room.settings.repeats?.length) {\n\t\t\treturn this.errorReply(this.tr`There are no repeated phrases in this room.`);\n\t\t}\n\n\t\tif (!Repeats.hasRepeat(room, id)) {\n\t\t\treturn this.errorReply(this.tr`The phrase labeled with \"${id}\" is not being repeated in this room.`);\n\t\t}\n\n\t\tRepeats.removeRepeat(room, id);\n\n\t\tthis.modlog('REMOVE REPEATPHRASE', null, `\"${id}\"`);\n\t\tthis.privateModAction(room.tr`${user.name} removed the repeated phrase labeled with \"${id}\".`);\n\t\tthis.refreshPage(`repeats-${room.roomid}`);\n\t},\n\n\tremoveallrepeats(target, room, user) {\n\t\troom = this.requireRoom();\n\t\tthis.checkCan('declare', null, room);\n\t\tif (!room.settings.repeats?.length) {\n\t\t\treturn this.errorReply(this.tr`There are no repeated phrases in this room.`);\n\t\t}\n\n\t\tfor (const { id } of room.settings.repeats) {\n\t\t\tRepeats.removeRepeat(room, id);\n\t\t}\n\n\t\tthis.modlog('REMOVE REPEATPHRASE', null, 'all repeated phrases');\n\t\tthis.privateModAction(room.tr`${user.name} removed all repeated phrases.`);\n\t},\n\n\trepeats: 'viewrepeats',\n\tviewrepeats(target, room, user) {\n\t\tconst roomid = toID(target) || room?.roomid;\n\t\tif (!roomid) return this.errorReply(this.tr`You must specify a room when using this command in PMs.`);\n\t\tthis.parse(`/j view-repeats-${roomid}`);\n\t},\n};\n\nprocess.nextTick(() => {\n\tChat.multiLinePattern.register('/repeat(html|faq)?(bymessages)? ');\n});\n"],
"mappings": "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",
"names": []
}