Pokemon_server / dist /server /chat-plugins /helptickets-auto.js.map
Jofthomas's picture
Jofthomas HF staff
Upload 4781 files
5c2ed06 verified
{
"version": 3,
"sources": ["../../../server/chat-plugins/helptickets-auto.ts"],
"sourcesContent": ["import { FS, Utils } from '../../lib';\nimport type { ModlogSearch, ModlogEntry } from '../modlog';\nimport {\n\ttype TicketState, getBattleLog, getBattleLinks,\n\twriteTickets, notifyStaff, writeStats, HelpTicket,\n\ttickets,\n} from './helptickets';\nimport * as Artemis from '../artemis';\n\nconst ORDERED_PUNISHMENTS = ['WARN', 'FORCERENAME', 'LOCK', 'NAMELOCK', 'WEEKLOCK', 'WEEKNAMELOCK'];\nconst PMLOG_IGNORE_TIME = 24 * 60 * 60 * 1000;\nconst WHITELIST = ['mia'];\n\nexport interface AutoPunishment {\n\tmodlogCount?: number;\n\tseverity?: { type: string[], certainty: number };\n\t/**\n\t * Should it be run on just one message?\n\t * or is it safe to run on averages (for the types that use averages)\n\t */\n\tisSingleMessage?: boolean;\n\tpunishment: string;\n\tticketType: string;\n}\n\nexport interface AutoSettings {\n\tpunishments: AutoPunishment[];\n\tapplyPunishments: boolean;\n}\n\nconst defaults: AutoSettings = {\n\tpunishments: [{\n\t\tticketType: 'inapname',\n\t\tpunishment: 'forcerename',\n\t\tseverity: { type: ['sexual_explicit', 'severe_toxicity', 'identity_attack'], certainty: 0.4 },\n\t}, {\n\t\tticketType: 'pmharassment',\n\t\tpunishment: 'warn',\n\t\tseverity: { type: ['sexual_explicit', 'severe_toxicity', 'identity_attack'], certainty: 0.15 },\n\t}],\n\tapplyPunishments: false,\n};\n\nexport const settings: AutoSettings = (() => {\n\ttry {\n\t\t// spreading w/ default means that\n\t\t// adding new things won't crash by not existing\n\t\treturn { ...defaults, ...JSON.parse(FS('config/chat-plugins/ht-auto.json').readSync()) };\n\t} catch {\n\t\treturn defaults;\n\t}\n})();\n\nfunction saveSettings() {\n\treturn FS('config/chat-plugins/ht-auto.json').writeUpdate(() => JSON.stringify(settings));\n}\n\nfunction visualizePunishment(punishment: AutoPunishment) {\n\tconst buf = [`punishment: ${punishment.punishment?.toUpperCase()}`];\n\tbuf.push(`ticket type: ${punishment.ticketType}`);\n\tif (punishment.severity) {\n\t\tbuf.push(`severity: ${punishment.severity.certainty} (for ${punishment.severity.type.join(', ')})`);\n\t}\n\tif (punishment.modlogCount) {\n\t\tbuf.push(`required modlog: ${punishment.modlogCount}`);\n\t}\n\tif (punishment.isSingleMessage) {\n\t\tbuf.push(`for single messages only`);\n\t}\n\treturn buf.join(', ');\n}\n\nfunction checkAccess(context: Chat.CommandContext | Chat.PageContext) {\n\tif (!WHITELIST.includes(context.user.id)) context.checkCan('bypassall');\n}\n\nexport function punishmentsFor(type: string) {\n\treturn settings.punishments.filter(t => t.ticketType === type);\n}\n\n/** Is punishment1 higher than punishment2 on the list? */\nfunction supersedes(p1: string, p2: string) {\n\treturn ORDERED_PUNISHMENTS.indexOf(p1) > ORDERED_PUNISHMENTS.indexOf(p2);\n}\n\nexport function determinePunishment(\n\tticketType: string, results: Record<string, number>, modlog: ModlogEntry[], isSingleMessage = false\n) {\n\tconst punishments = punishmentsFor(ticketType);\n\tlet action: string | null = null;\n\tconst types = [];\n\tUtils.sortBy(punishments, p => -ORDERED_PUNISHMENTS.indexOf(p.punishment));\n\tfor (const punishment of punishments) {\n\t\tif (isSingleMessage && !punishment.isSingleMessage) continue;\n\t\tif (punishment.modlogCount && modlog.length < punishment.modlogCount) continue;\n\t\tif (punishment.severity) {\n\t\t\tlet hit = false;\n\t\t\tfor (const type of punishment.severity.type) {\n\t\t\t\tif (results[type] < punishment.severity.certainty) continue;\n\t\t\t\thit = true;\n\t\t\t\ttypes.push(type);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (!hit) continue;\n\t\t}\n\t\tif (!action || supersedes(punishment.punishment, action)) {\n\t\t\taction = punishment.punishment;\n\t\t}\n\t}\n\treturn { action, types };\n}\n\nexport function globalModlog(action: string, user: User | ID | null, note: string, roomid?: string) {\n\tuser = Users.get(user) || user;\n\tvoid Rooms.Modlog.write(roomid || 'global', {\n\t\taction,\n\t\tip: user && typeof user === 'object' ? user.latestIp : undefined,\n\t\tuserid: toID(user) || undefined,\n\t\tloggedBy: 'artemis' as ID,\n\t\tnote,\n\t});\n}\n\nexport function addModAction(message: string) {\n\tRooms.get('staff')?.add(`|c|~|/log ${message}`).update();\n}\n\nexport async function getModlog(params: { user?: ID, ip?: string, actions?: string[] }) {\n\tconst search: ModlogSearch = {\n\t\tnote: [],\n\t\tuser: [],\n\t\tip: [],\n\t\taction: [],\n\t\tactionTaker: [],\n\t};\n\tif (params.user) search.user = [{ search: params.user, isExact: true }];\n\tif (params.ip) search.ip = [{ search: params.ip }];\n\tif (params.actions) search.action = params.actions.map(s => ({ search: s }));\n\tconst res = await Rooms.Modlog.search('global', search);\n\treturn res?.results || [];\n}\n\nfunction closeTicket(ticket: TicketState, msg?: string) {\n\tif (!ticket.open) return;\n\tticket.open = false;\n\tticket.active = false;\n\tticket.resolved = {\n\t\ttime: Date.now(),\n\t\tby: 'the Artemis AI', // we want it to be clear to end users that it was not a human\n\t\tseen: false,\n\t\tstaffReason: '',\n\t\tresult: msg || '',\n\t\tnote: (\n\t\t\t`Want to learn more about the AI? ` +\n\t\t\t`<a href=\"https://www.smogon.com/forums/threads/3570628/#post-9056769\">Visit the information thread</a>.`\n\t\t),\n\t};\n\twriteTickets();\n\tnotifyStaff();\n\tconst tarUser = Users.get(ticket.userid);\n\tif (tarUser) {\n\t\tHelpTicket.notifyResolved(tarUser, ticket, ticket.userid);\n\t}\n\t// TODO: Support closing as invalid\n\twriteStats(`${ticket.type}\\t${Date.now() - ticket.created}\\t0\\t0\\tresolved\\tvalid\\tartemis`);\n}\n\nasync function lock(\n\tuser: User | ID,\n\tresult: CheckerResult,\n\tticket: TicketState,\n\tisWeek?: boolean,\n\tisName?: boolean\n) {\n\tconst id = toID(user);\n\tlet desc, type;\n\tconst expireTime = isWeek ? Date.now() + 7 * 24 * 60 * 60 * 1000 : null;\n\tif (isName) {\n\t\tif (typeof user === 'object') user.resetName();\n\t\tdesc = 'locked your username and prevented you from changing names';\n\t\ttype = `locked from talking${isWeek ? ` for a week` : \"\"}`;\n\t\tawait Punishments.namelock(id, expireTime, null, false, result.reason || \"Automatically locked due to a user report\");\n\t} else {\n\t\ttype = isWeek ? 'weeknamelocked' : 'namelocked';\n\t\tdesc = 'locked you from talking in chats, battles, and PMing regular users';\n\t\tawait Punishments.lock(id, expireTime, null, false, result.reason || \"Automatically locked due to a user report\");\n\t}\n\tif (typeof user !== 'string') {\n\t\tlet message = `|popup||html|${user.name} has ${desc} for ${isWeek ? '7' : '2'} days.`;\n\t\tif (result.reason) message += `\\n\\nReason: ${result.reason}`;\n\t\tlet appeal = '';\n\t\tif (Chat.pages.help) {\n\t\t\tappeal += `<a href=\"view-help-request--appeal\"><button class=\"button\"><strong>Appeal your punishment</strong></button></a>`;\n\t\t} else if (Config.appealurl) {\n\t\t\tappeal += `appeal: <a href=\"${Config.appealurl}\">${Config.appealurl}</a>`;\n\t\t}\n\t\tif (appeal) message += `\\n\\nIf you feel that your lock was unjustified, you can ${appeal}.`;\n\t\tmessage += `\\n\\nYour lock will expire in a few days.`;\n\t\tuser.send(message);\n\t}\n\taddModAction(`${id} was ${type} by Artemis. (${result.reason || `report from ${ticket.creator}`})`);\n\tglobalModlog(\n\t\t`${isWeek ? 'WEEK' : \"\"}${isName ? \"NAME\" : \"\"}LOCK`, id,\n\t\t(result.reason || `report from ${ticket.creator}`) + (result.proof ? ` PROOF: ${result.proof}` : \"\")\n\t);\n}\n\nexport const actionHandlers: {\n\t[k: string]: (user: User | ID, result: CheckerResult, ticket: TicketState) => string | void | Promise<string | void>,\n} = {\n\tforcerename(user, result, ticket) {\n\t\tif (typeof user === 'string') return; // they can only submit users with existing userobjects anyway\n\t\tconst id = toID(user);\n\t\tuser.resetName();\n\t\tuser.trackRename = id;\n\t\tMonitor.forceRenames.set(id, true);\n\t\tuser.send(\n\t\t\t'|nametaken|Your name was detected to be breaking our name rules. ' +\n\t\t\t`${result.reason ? `Reason: ${result.reason}. ` : \"\"}` +\n\t\t\t'Please change it, or submit a help ticket by typing /ht in chat to appeal this action.'\n\t\t);\n\t\tRooms.get('staff')?.add(\n\t\t\t`|html|<span class=\"username\">${id}</span> ` +\n\t\t\t`was automatically forced to choose a new name by Artemis (report from ${ticket.userid}).`\n\t\t).update();\n\t\tglobalModlog(\n\t\t\t'FORCERENAME', id, `username determined to be inappropriate due to a report by ${ticket.creator}`, result.roomid\n\t\t);\n\t\treturn `${id} was automatically forcerenamed. Thank you for reporting.`;\n\t},\n\tasync namelock(user, result, ticket) {\n\t\tawait lock(user, result, ticket, false, true);\n\t\treturn `${toID(user)} was automatically namelocked. Thank you for reporting.`;\n\t},\n\tasync weeknamelock(user, result, ticket) {\n\t\tawait lock(user, result, ticket, true, true);\n\t\treturn `${toID(user)} was automatically weeknamelocked. Thank you for reporting.`;\n\t},\n\tasync lock(user, result, ticket) {\n\t\tawait lock(user, result, ticket);\n\t\treturn `${toID(user)} was automatically locked. Thank you for reporting.`;\n\t},\n\tasync weeklock(user, result, ticket) {\n\t\tawait lock(user, result, ticket, true);\n\t\treturn `${toID(user)} was automatically weeklocked. Thank you for reporting.`;\n\t},\n\twarn(user, result, ticket) {\n\t\tuser = toID(user);\n\t\tuser = Users.get(user) || user;\n\t\tif (typeof user === 'object') {\n\t\t\tuser.send(`|c|~|/warn ${result.reason || \"\"}`);\n\t\t} else {\n\t\t\tPunishments.offlineWarns.set(user, result.reason);\n\t\t}\n\t\taddModAction(\n\t\t\t`${user} was warned by Artemis. ${typeof user === 'string' ? 'while offline ' : \"\"}` +\n\t\t\t`(${result.reason || `report from ${ticket.creator}`})`\n\t\t);\n\t\tglobalModlog(\n\t\t\t'WARN', user, result.reason || `report from ${ticket.creator}`\n\t\t);\n\t\treturn `${user} was automatically warned. Thank you for reporting.`;\n\t},\n};\n\nfunction shouldNotProcess(message: string) {\n\treturn (\n\t\t// special 'command', blocks things like /log, /raw, /html\n\t\t// (but not a // message)\n\t\t(message.startsWith('/') && !message.startsWith('//')) ||\n\t\t// broadcasted chat command\n\t\tmessage.startsWith('!')\n\t);\n}\n\nexport async function getMessageAverages(messages: string[]) {\n\tconst counts: Record<string, { count: number, raw: number }> = {};\n\tconst classified = [];\n\tfor (const message of messages) {\n\t\tif (shouldNotProcess(message)) continue;\n\t\tconst res = await classifier.classify(message);\n\t\tif (!res) continue;\n\t\tclassified.push(res);\n\t\tfor (const k in res) {\n\t\t\tif (!counts[k]) counts[k] = { count: 0, raw: 0 };\n\t\t\tcounts[k].count++;\n\t\t\tcounts[k].raw += res[k];\n\t\t}\n\t}\n\tconst averages: Record<string, number> = {};\n\tfor (const k in counts) {\n\t\taverages[k] = counts[k].raw / counts[k].count;\n\t}\n\treturn { averages, classified };\n}\n\ninterface CheckerResult {\n\taction: string;\n\tuser: User | ID;\n\tresult: Record<string, number>;\n\treason: string;\n\troomid?: string;\n\tdisplayReason?: string;\n\tproof?: string;\n}\n\ntype CheckerOutput = void | Map<string, CheckerResult>;\n\nexport const checkers: {\n\t[k: string]: (ticket: TicketState & { text: [string, string] }) => CheckerOutput | Promise<CheckerOutput>,\n} = {\n\tasync inapname(ticket) {\n\t\tconst id = toID(ticket.text[0]);\n\t\tconst user = Users.getExact(id);\n\t\tif (user && !user.trusted) {\n\t\t\tconst result = await classifier.classify(user.name);\n\t\t\tif (!result) return;\n\t\t\tconst keys = ['identity_attack', 'sexual_explicit', 'severe_toxicity'];\n\t\t\tconst matched = keys.some(k => result[k] >= 0.4);\n\t\t\tif (matched) {\n\t\t\t\tconst modlog = await getModlog({\n\t\t\t\t\tip: user.latestIp,\n\t\t\t\t\tactions: ['FORCERENAME', 'NAMELOCK', 'WEEKNAMELOCK'],\n\t\t\t\t});\n\t\t\t\tlet { action } = determinePunishment('inapname', result, modlog);\n\t\t\t\tif (!action) action = 'forcerename';\n\t\t\t\treturn new Map([[user.id, {\n\t\t\t\t\taction,\n\t\t\t\t\tuser,\n\t\t\t\t\tresult,\n\t\t\t\t\treason: \"Username detected to be breaking username rules\",\n\t\t\t\t}]]);\n\t\t\t}\n\t\t}\n\t},\n\tasync inappokemon(ticket) {\n\t\tconst actions = new Map();\n\t\tconst links = [...getBattleLinks(ticket.text[0]), ...getBattleLinks(ticket.text[1])];\n\t\tfor (const link of links) {\n\t\t\tconst log = await getBattleLog(link);\n\t\t\tif (!log) continue;\n\t\t\tfor (const [user, pokemon] of Object.entries(log.pokemon)) {\n\t\t\t\tconst userid = toID(user);\n\t\t\t\tlet result: {\n\t\t\t\t\taction: string, name: string, result: Record<string, number>, replay: string,\n\t\t\t\t} | null = null;\n\t\t\t\tfor (const set of pokemon) {\n\t\t\t\t\tif (!set.name) continue;\n\t\t\t\t\tconst results = await classifier.classify(set.name);\n\t\t\t\t\tif (!results) continue;\n\t\t\t\t\t// atm don't factor in modlog\n\t\t\t\t\tconst curAction = determinePunishment('inappokemon', results, []).action;\n\t\t\t\t\tif (curAction && (!result || supersedes(curAction, result.action))) {\n\t\t\t\t\t\tresult = { action: curAction, name: set.name, result: results, replay: link };\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (result) {\n\t\t\t\t\tactions.set(user, {\n\t\t\t\t\t\taction: result.action,\n\t\t\t\t\t\tuser: userid,\n\t\t\t\t\t\tresult: result.result,\n\t\t\t\t\t\treason: `Pokemon name detected to be breaking rules - '${result.name}'`,\n\t\t\t\t\t\troomid: link,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (actions.size) return actions;\n\t},\n\tasync battleharassment(ticket) {\n\t\tconst urls = getBattleLinks(ticket.text[0]);\n\t\tconst actions = new Map<string, CheckerResult>();\n\t\tfor (const url of urls) {\n\t\t\tconst log = await getBattleLog(url);\n\t\t\tif (!log) continue;\n\t\t\tconst messages: Record<string, string[]> = {};\n\t\t\tfor (const message of log.log) {\n\t\t\t\tconst [username, text] = Utils.splitFirst(message.slice(3), '|').map(f => f.trim());\n\t\t\t\tconst id = toID(username);\n\t\t\t\tif (!id) continue;\n\t\t\t\tif (!messages[id]) messages[id] = [];\n\t\t\t\tmessages[id].push(text);\n\t\t\t}\n\t\t\tfor (const [id, messageList] of Object.entries(messages)) {\n\t\t\t\tconst { averages, classified } = await getMessageAverages(messageList);\n\t\t\t\tconst { action } = determinePunishment('battleharassment', averages, []);\n\t\t\t\tif (action) {\n\t\t\t\t\tconst existingPunishment = actions.get(id);\n\t\t\t\t\tif (!existingPunishment || supersedes(action, existingPunishment.action)) {\n\t\t\t\t\t\tactions.set(id, {\n\t\t\t\t\t\t\taction,\n\t\t\t\t\t\t\tuser: toID(id),\n\t\t\t\t\t\t\tresult: averages,\n\t\t\t\t\t\t\treason: `Not following rules in battles (https://${Config.routes.client}/${url})`,\n\t\t\t\t\t\t\tproof: urls.join(', '),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfor (const result of classified) {\n\t\t\t\t\tconst curPunishment = determinePunishment('battleharassment', result, [], true).action;\n\t\t\t\t\tif (!curPunishment) continue;\n\t\t\t\t\tconst exists = actions.get(id);\n\t\t\t\t\tif (!exists || supersedes(curPunishment, exists.action)) {\n\t\t\t\t\t\tactions.set(id, {\n\t\t\t\t\t\t\taction: curPunishment,\n\t\t\t\t\t\t\tuser: toID(id),\n\t\t\t\t\t\t\tresult: averages,\n\t\t\t\t\t\t\treason: `Not following rules in battles (https://${Config.routes.client}/${url})`,\n\t\t\t\t\t\t\tproof: urls.join(', '),\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// ensure reasons are clear\n\t\tconst creatorWasPunished = actions.get(ticket.userid);\n\t\tif (creatorWasPunished) {\n\t\t\tlet displayReason = 'You were punished for your behavior.';\n\t\t\tif (actions.size !== 1) { // more than 1 was punished\n\t\t\t\tdisplayReason += ` ${actions.size - 1} other(s) were also punished.`;\n\t\t\t}\n\t\t\tcreatorWasPunished.displayReason = displayReason;\n\t\t}\n\n\t\tif (actions.size) return actions;\n\t},\n\tasync pmharassment(ticket) {\n\t\tconst actions = new Map<string, CheckerResult>();\n\t\tconst targetId = toID(ticket.text[0]);\n\t\tconst creator = ticket.userid;\n\t\tif (!Config.getpmlog) return;\n\t\tconst pmLog = await Config.getpmlog(targetId, creator) as {\n\t\t\tmessage: string, from: string, to: string, timestamp: string,\n\t\t}[];\n\t\tconst messages: Record<string, string[]> = {};\n\t\tconst ids = new Set<ID>();\n\t\t// sort messages by user who sent them, also filter out old ones\n\t\tfor (const { from, message, timestamp } of pmLog) {\n\t\t\t// ignore pmlogs more than 24h old\n\t\t\tif ((Date.now() - new Date(timestamp).getTime()) > PMLOG_IGNORE_TIME) continue;\n\t\t\tconst id = toID(from);\n\t\t\tids.add(id);\n\t\t\tif (!messages[id]) messages[id] = [];\n\t\t\tmessages[id].push(message);\n\t\t}\n\t\tfor (const id of ids) {\n\t\t\tlet punishment;\n\t\t\tconst { averages, classified } = await getMessageAverages(messages[id]);\n\t\t\tconst curPunishment = determinePunishment('pmharassment', averages, []).action;\n\t\t\tif (curPunishment) {\n\t\t\t\tif (!punishment || supersedes(curPunishment, punishment)) {\n\t\t\t\t\tpunishment = curPunishment;\n\t\t\t\t}\n\t\t\t\tif (punishment) {\n\t\t\t\t\tactions.set(id, {\n\t\t\t\t\t\taction: punishment,\n\t\t\t\t\t\tuser: id,\n\t\t\t\t\t\tresult: {},\n\t\t\t\t\t\treason: `PM harassment (against ${ticket.userid === id ? targetId : ticket.userid})`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const result of classified) {\n\t\t\t\tconst { action } = determinePunishment('pmharassment', result, [], true);\n\t\t\t\tif (!action) continue;\n\t\t\t\tconst exists = actions.get(id);\n\t\t\t\tif (!exists || supersedes(action, exists.action)) {\n\t\t\t\t\tactions.set(id, {\n\t\t\t\t\t\taction,\n\t\t\t\t\t\tuser: id,\n\t\t\t\t\t\tresult: {},\n\t\t\t\t\t\treason: `PM harassment (against ${ticket.userid === id ? targetId : ticket.userid})`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst creatorWasPunished = actions.get(ticket.userid);\n\t\tif (creatorWasPunished) {\n\t\t\tlet displayReason = `You were punished for your behavior. `;\n\t\t\tif (actions.has(targetId) && targetId !== ticket.userid) {\n\t\t\t\tdisplayReason += ` The person you reported was also punished.`;\n\t\t\t}\n\t\t\tcreatorWasPunished.displayReason = displayReason;\n\t\t}\n\n\t\tif (actions.size) return actions;\n\t},\n};\n\nexport const classifier = new Artemis.LocalClassifier();\n\nexport async function runPunishments(ticket: TicketState & { text: [string, string] }, typeId: string) {\n\tlet result: Map<string, CheckerResult> | null = null;\n\tif (checkers[typeId]) {\n\t\tresult = await checkers[typeId](ticket) || null;\n\t}\n\tif (result) {\n\t\tif (settings.applyPunishments) {\n\t\t\tconst responses: [string, string][] = [];\n\t\t\tfor (const res of result.values()) {\n\t\t\t\tconst curResult = await actionHandlers[res.action.toLowerCase()](res.user, res, ticket);\n\t\t\t\tif (curResult) responses.push([res.action, res.displayReason || curResult]);\n\t\t\t\tif (toID(res.user) === ticket.creator) {\n\t\t\t\t\t// just close the ticket here.\n\t\t\t\t\tcloseTicket(ticket, res.displayReason);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (responses.length) {\n\t\t\t\t// if we don't have one for the user, find one.\n\t\t\t\tUtils.sortBy(responses, r => -ORDERED_PUNISHMENTS.indexOf(r[0]));\n\t\t\t\tcloseTicket(ticket, responses[0][1]);\n\t\t\t} else {\n\t\t\t\tcloseTicket(ticket); // no good response. just close it, because we __have__ dispatched an action.\n\t\t\t}\n\t\t} else {\n\t\t\t// eslint-disable-next-line require-atomic-updates\n\t\t\tticket.recommended = [];\n\t\t\tfor (const res of result.values()) {\n\t\t\t\tRooms.get('abuselog')?.add(\n\t\t\t\t\t`|c|~|/log [${ticket.type} Monitor] Recommended: ${res.action}: for ${res.user} (${res.reason})`\n\t\t\t\t).update();\n\t\t\t\tticket.recommended.push(`${res.action}: for ${res.user} (${res.reason})`);\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport const commands: Chat.ChatCommands = {\n\taht: 'autohelpticket',\n\tautohelpticket: {\n\t\t''() {\n\t\t\treturn this.parse(`/help autohelpticket`);\n\t\t},\n\t\tasync test(target) {\n\t\t\tcheckAccess(this);\n\t\t\ttarget = target.trim();\n\t\t\tconst response = await classifier.classify(target) || {};\n\t\t\tlet buf = Utils.html`<strong>Results for \"${target}\":</strong><br />`;\n\t\t\tbuf += `<strong>Score breakdown:</strong><br />`;\n\t\t\tfor (const k in response) {\n\t\t\t\tbuf += `&bull; ${k}: ${response[k]}<br />`;\n\t\t\t}\n\t\t\tthis.runBroadcast();\n\t\t\tthis.sendReplyBox(buf);\n\t\t},\n\t\tap: 'addpunishment',\n\t\tadd: 'addpunishment',\n\t\taddpunishment(target, room, user) {\n\t\t\tcheckAccess(this);\n\t\t\tif (!toID(target)) return this.parse(`/help autohelpticket`);\n\t\t\tconst args = Chat.parseArguments(target);\n\t\t\tconst punishment: Partial<AutoPunishment> = {};\n\t\t\tfor (const [k, list] of Object.entries(args)) {\n\t\t\t\tif (k !== 'type' && list.length > 1) throw new Chat.ErrorMessage(`More than one ${k} param provided.`);\n\t\t\t\tconst val = list[0]; // if key exists, val must exist too\n\t\t\t\tswitch (k) {\n\t\t\t\tcase 'type': case 't':\n\t\t\t\t\tconst types = list.map(f => f.toLowerCase().replace(/\\s/g, '_'));\n\t\t\t\t\tfor (const type of types) {\n\t\t\t\t\t\tif (!Artemis.LocalClassifier.ATTRIBUTES[type]) {\n\t\t\t\t\t\t\treturn this.errorReply(\n\t\t\t\t\t\t\t\t`Invalid classifier type '${type}'. Valid types are ` +\n\t\t\t\t\t\t\t\tObject.keys(Artemis.LocalClassifier.ATTRIBUTES).join(', ')\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif (!punishment.severity) {\n\t\t\t\t\t\tpunishment.severity = { certainty: 0, type: [] };\n\t\t\t\t\t}\n\t\t\t\t\tpunishment.severity.type.push(...types);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'certainty': case 'c':\n\t\t\t\t\tconst num = parseFloat(val);\n\t\t\t\t\tif (isNaN(num) || num < 0 || num > 1) {\n\t\t\t\t\t\treturn this.errorReply(`Certainty must be a number below 1 and above 0.`);\n\t\t\t\t\t}\n\t\t\t\t\tif (!punishment.severity) {\n\t\t\t\t\t\tpunishment.severity = { certainty: 0, type: [] };\n\t\t\t\t\t}\n\t\t\t\t\tpunishment.severity.certainty = num;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'modlog': case 'm':\n\t\t\t\t\tconst count = parseInt(val);\n\t\t\t\t\tif (isNaN(count) || count < 0) {\n\t\t\t\t\t\treturn this.errorReply(`Modlog count must be a number above 0.`);\n\t\t\t\t\t}\n\t\t\t\t\tpunishment.modlogCount = count;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'ticket': case 'tt': case 'tickettype':\n\t\t\t\t\tconst type = toID(val);\n\t\t\t\t\tif (!(type in checkers)) {\n\t\t\t\t\t\treturn this.errorReply(\n\t\t\t\t\t\t\t`The ticket type '${type}' does not exist or is not supported. ` +\n\t\t\t\t\t\t\t`Supported types are ${Object.keys(checkers).join(', ')}.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tpunishment.ticketType = type;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'p': case 'punishment':\n\t\t\t\t\tconst name = toID(val).toUpperCase();\n\t\t\t\t\tif (!ORDERED_PUNISHMENTS.includes(name)) {\n\t\t\t\t\t\treturn this.errorReply(\n\t\t\t\t\t\t\t`Punishment '${name}' not supported. ` +\n\t\t\t\t\t\t\t`Supported punishments: ${ORDERED_PUNISHMENTS.join(', ')}`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tpunishment.punishment = name;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'single': case 's':\n\t\t\t\t\tif (!this.meansYes(toID(val))) {\n\t\t\t\t\t\treturn this.errorReply(\n\t\t\t\t\t\t\t`The 'single' value must always be 'on'. ` +\n\t\t\t\t\t\t\t`If you don't want it enabled, just do not use this argument type.`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tpunishment.isSingleMessage = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!punishment.ticketType) {\n\t\t\t\treturn this.errorReply(`Must specify a ticket type to handle.`);\n\t\t\t}\n\t\t\tif (!punishment.punishment) {\n\t\t\t\treturn this.errorReply(`Must specify a punishment to apply.`);\n\t\t\t}\n\t\t\tif (!(punishment.severity?.certainty && punishment.severity?.type.length)) {\n\t\t\t\treturn this.errorReply(`A severity to monitor for must be specified (certainty).`);\n\t\t\t}\n\t\t\tfor (const curP of settings.punishments) {\n\t\t\t\tlet matches = 0;\n\t\t\t\tfor (const k in curP) {\n\t\t\t\t\tif (punishment[k as keyof AutoPunishment] === curP[k as keyof AutoPunishment]) {\n\t\t\t\t\t\tmatches++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (matches === Object.keys(punishment).length) {\n\t\t\t\t\treturn this.errorReply(`That punishment is already added.`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tsettings.punishments.push(punishment as AutoPunishment);\n\t\t\tsaveSettings();\n\t\t\tthis.privateGlobalModAction(\n\t\t\t\t`${user.name} added a ${punishment.punishment} punishment to the Artemis helpticket handler.`\n\t\t\t);\n\t\t\tthis.globalModlog(`AUTOHELPTICKET ADDPUNISHMENT`, null, visualizePunishment(punishment as AutoPunishment));\n\t\t},\n\t\tdp: 'deletepunishment',\n\t\tdelete: 'deletepunishment',\n\t\tdeletepunishment(target, room, user) {\n\t\t\tcheckAccess(this);\n\t\t\tconst num = parseInt(target) - 1;\n\t\t\tif (isNaN(num)) return this.parse(`/h autohelpticket`);\n\t\t\tconst punishment = settings.punishments[num];\n\t\t\tif (!punishment) return this.errorReply(`There is no punishment at index ${num + 1}.`);\n\t\t\tsettings.punishments.splice(num, 1);\n\t\t\tthis.privateGlobalModAction(\n\t\t\t\t`${user.name} removed the Artemis helpticket ${punishment.punishment} punishment indexed at ${num + 1}`\n\t\t\t);\n\t\t\tthis.globalModlog(`AUTOHELPTICKET REMOVE`, null, visualizePunishment(punishment));\n\t\t},\n\t\tvp: 'viewpunishments',\n\t\tview: 'viewpunishments',\n\t\tviewpunishments() {\n\t\t\tcheckAccess(this);\n\t\t\tlet buf = `<strong>Artemis helpticket punishments</strong><hr />`;\n\t\t\tif (!settings.punishments.length) {\n\t\t\t\tbuf += `None.`;\n\t\t\t\treturn this.sendReplyBox(buf);\n\t\t\t}\n\t\t\tbuf += settings.punishments.map(\n\t\t\t\t(curP, i) => `<strong>${i + 1}:</strong> ${visualizePunishment(curP)}`\n\t\t\t).join('<br />');\n\t\t\treturn this.sendReplyBox(buf);\n\t\t},\n\t\ttogglepunishments(target, room, user) {\n\t\t\tcheckAccess(this);\n\t\t\tlet message;\n\t\t\tif (this.meansYes(target)) {\n\t\t\t\tif (settings.applyPunishments) {\n\t\t\t\t\treturn this.errorReply(`Automatic punishments are already enabled.`);\n\t\t\t\t}\n\t\t\t\tsettings.applyPunishments = true;\n\t\t\t\tmessage = `${user.name} enabled automatic punishments for the Artemis ticket handler`;\n\t\t\t} else if (this.meansNo(target)) {\n\t\t\t\tif (!settings.applyPunishments) {\n\t\t\t\t\treturn this.errorReply(`Automatic punishments are already disabled.`);\n\t\t\t\t}\n\t\t\t\tsettings.applyPunishments = false;\n\t\t\t\tmessage = `${user.name} disabled automatic punishments for the Artemis ticket handler`;\n\t\t\t} else {\n\t\t\t\treturn this.errorReply(`Invalid setting. Must be 'on' or 'off'.`);\n\t\t\t}\n\t\t\tthis.privateGlobalModAction(message);\n\t\t\tthis.globalModlog(`AUTOHELPTICKET TOGGLE`, null, settings.applyPunishments ? 'on' : 'off');\n\t\t\tsaveSettings();\n\t\t},\n\t\tstats(target) {\n\t\t\tif (!target) target = Chat.toTimestamp(new Date()).split(' ')[0];\n\t\t\treturn this.parse(`/j view-autohelpticket-stats-${target}`);\n\t\t},\n\t\tlogs(target) {\n\t\t\tif (!target) target = Chat.toTimestamp(new Date()).split(' ')[0];\n\t\t\treturn this.parse(`/j view-autohelpticket-logs-${target}`);\n\t\t},\n\t\tresolve(target, room, user) {\n\t\t\tthis.checkCan('lock');\n\t\t\tconst [ticketId, result] = Utils.splitFirst(target, ',').map(toID);\n\t\t\tconst ticket = tickets[ticketId];\n\t\t\tif (!ticket?.open) {\n\t\t\t\treturn this.popupReply(`The user '${ticketId}' does not have a ticket open at present.`);\n\t\t\t}\n\t\t\tif (!['success', 'failure'].includes(result)) {\n\t\t\t\treturn this.popupReply(`The result must be 'success' or 'failure'.`);\n\t\t\t}\n\t\t\t(ticket.state ||= {}).recommendResult = result;\n\t\t\twriteTickets();\n\t\t\tChat.refreshPageFor(`help-text-${ticketId}`, 'staff');\n\t\t},\n\t},\n\tautohelptickethelp: [\n\t\t`/aht addpunishment [args] - Adds a punishment with the given [args]. Requires: whitelist ~`,\n\t\t`/aht deletepunishment [index] - Deletes the automatic helpticket punishment at [index]. Requires: whitelist ~`,\n\t\t`/aht viewpunishments - View automatic helpticket punishments. Requires: whitelist ~`,\n\t\t`/aht togglepunishments [on | off] - Turn [on | off] automatic helpticket punishments. Requires: whitelist ~`,\n\t\t`/aht stats - View success rates of the Artemis ticket handler. Requires: whitelist ~`,\n\t],\n};\n\nexport const pages: Chat.PageTable = {\n\tautohelpticket: {\n\t\tasync stats(query, user) {\n\t\t\tcheckAccess(this);\n\t\t\tlet month;\n\t\t\tif (query.length) {\n\t\t\t\tmonth = /[0-9]{4}-[0-9]{2}/.exec(query.join('-'))?.[0];\n\t\t\t} else {\n\t\t\t\tmonth = Chat.toTimestamp(new Date()).split(' ')[0].slice(0, -3);\n\t\t\t}\n\t\t\tif (!month) {\n\t\t\t\treturn this.errorReply(`Invalid month. Must be in YYYY-MM format.`);\n\t\t\t}\n\n\t\t\tthis.title = `[Artemis Ticket Stats] ${month}`;\n\t\t\tthis.setHTML(`<div class=\"pad\"><h3>Artemis ticket stats</h3><hr />Searching...`);\n\n\t\t\tconst found = await HelpTicket.getTextLogs(['recommendResult'], month);\n\t\t\tconst percent = (numerator: number, denom: number) => Math.floor((numerator / denom) * 100);\n\n\t\t\tlet buf = `<div class=\"pad\">`;\n\t\t\tbuf += `<button style=\"float:right;\" class=\"button\" name=\"send\" value=\"/join ${this.pageid}\">`;\n\t\t\tbuf += `<i class=\"fa fa-refresh\"></i> Refresh</button>`;\n\t\t\tbuf += `<h3>Artemis ticket stats</h3><hr />`;\n\t\t\tconst dayStats: Record<string, { successes: number, failures: number, total: number }> = {};\n\t\t\tconst total = { successes: 0, failures: 0, total: 0 };\n\t\t\tconst failed = [];\n\t\t\tfor (const ticket of found) {\n\t\t\t\tconst day = Chat.toTimestamp(new Date(ticket.created)).split(' ')[0];\n\t\t\t\tif (!dayStats[day]) dayStats[day] = { successes: 0, failures: 0, total: 0 };\n\t\t\t\tdayStats[day].total++;\n\t\t\t\ttotal.total++;\n\t\t\t\tswitch (ticket.state.recommendResult) {\n\t\t\t\tcase 'success':\n\t\t\t\t\tdayStats[day].successes++;\n\t\t\t\t\ttotal.successes++;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 'failure':\n\t\t\t\t\tdayStats[day].failures++;\n\t\t\t\t\ttotal.failures++;\n\t\t\t\t\tfailed.push([ticket.userid, ticket.type]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuf += `<strong>Total:</strong> ${total.total}<br />`;\n\t\t\tbuf += `<strong>Success rate:</strong> ${percent(total.successes, total.total)}% (${total.successes})<br />`;\n\t\t\tbuf += `<strong>Failure rate:</strong> ${percent(total.failures, total.total)}% (${total.failures})<br />`;\n\t\t\tbuf += `<strong>Day stats:</strong><br />`;\n\t\t\tbuf += `<div class=\"ladder pad\"><table>`;\n\t\t\tlet header = '';\n\t\t\tlet data = '';\n\t\t\tconst sortedDays = Utils.sortBy(Object.keys(dayStats), d => new Date(d).getTime());\n\t\t\tfor (const [i, day] of sortedDays.entries()) {\n\t\t\t\tconst cur = dayStats[day];\n\t\t\t\tif (!cur.total) continue;\n\t\t\t\theader += `<th>${day.split('-')[2]} (${cur.total})</th>`;\n\t\t\t\tdata += `<td><small>${cur.successes} (${percent(cur.successes, cur.total)}%)`;\n\t\t\t\tif (cur.failures) {\n\t\t\t\t\tdata += ` | ${cur.failures} (${percent(cur.failures, cur.total)}%)`;\n\t\t\t\t} else { // so one cannot confuse dead tickets ~ false hit tickets\n\t\t\t\t\tdata += ' | 0 (0%)';\n\t\t\t\t}\n\t\t\t\tdata += '</small></td>';\n\t\t\t\t// i + 1 ensures it's above 0 always (0 % 5 === 0)\n\t\t\t\tif ((i + 1) % 5 === 0 && sortedDays[i + 1]) {\n\t\t\t\t\tbuf += `<tr>${header}</tr><tr>${data}</tr>`;\n\t\t\t\t\tbuf += `</div></table>`;\n\t\t\t\t\tbuf += `<div class=\"ladder pad\"><table>`;\n\t\t\t\t\theader = '';\n\t\t\t\t\tdata = '';\n\t\t\t\t}\n\t\t\t}\n\t\t\tbuf += `<tr>${header}</tr><tr>${data}</tr>`;\n\t\t\tbuf += `</div></table>`;\n\t\t\tbuf += `<br />`;\n\t\t\tif (failed.length) {\n\t\t\t\tbuf += `<details class=\"readmore\"><summary>Marked as inaccurate</summary>`;\n\t\t\t\tbuf += failed.map(([userid, type]) => (\n\t\t\t\t\t`<a href=\"/view-help-text-${userid}\">${userid}</a> (${type})`\n\t\t\t\t)).join('<br />');\n\t\t\t\tbuf += `</details>`;\n\t\t\t}\n\t\t\treturn buf;\n\t\t},\n\t\tasync logs(query, user) {\n\t\t\tcheckAccess(this);\n\t\t\tlet month;\n\t\t\tif (query.length) {\n\t\t\t\tmonth = /[0-9]{4}-[0-9]{2}/.exec(query.join('-'))?.[0];\n\t\t\t} else {\n\t\t\t\tmonth = Chat.toTimestamp(new Date()).split(' ')[0].slice(0, -3);\n\t\t\t}\n\t\t\tif (!month) {\n\t\t\t\treturn this.errorReply(`Invalid month. Must be in YYYY-MM format.`);\n\t\t\t}\n\t\t\tthis.title = `[Artemis Ticket Logs]`;\n\t\t\tlet buf = `<div class=\"pad\"><h3>Artemis ticket logs</h3><hr />`;\n\t\t\tconst allHits = await HelpTicket.getTextLogs(['recommended'], month);\n\t\t\tUtils.sortBy(allHits, h => -h.created);\n\t\t\tif (allHits.length) {\n\t\t\t\tbuf += `<strong>All hits:</strong><hr />`;\n\t\t\t\tfor (const hit of allHits) {\n\t\t\t\t\tif (!hit.recommended) continue; // ???\n\t\t\t\t\tbuf += `<a href=\"/view-help-text-${hit.userid}\">${hit.userid}</a> (${hit.type}) `;\n\t\t\t\t\tbuf += `[${Chat.toTimestamp(new Date(hit.created))}]<br />`;\n\t\t\t\t\tbuf += Utils.html`&bull; <code><small>${hit.recommended.join(', ')}</small></code><hr />`;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tbuf += `<div class=\"message-error\">No hits found.</div>`;\n\t\t\t}\n\t\t\treturn buf;\n\t\t},\n\t},\n};\n"],
"mappings": "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",
"names": ["type"]
}