{ "version": 3, "sources": ["../../../server/chat-plugins/modlog-viewer.ts"], "sourcesContent": ["/**\n * Modlog viewer\n * Pokemon Showdown - http://pokemonshowdown.com/\n *\n * Actually reading, writing, and searching modlog is handled in server/modlog/.\n *\n * @license MIT\n */\n\nimport { Dashycode, Utils } from '../../lib';\nimport type { ModlogID, ModlogSearch, ModlogEntry } from '../modlog';\n\nconst MAX_QUERY_LENGTH = 2500;\nconst DEFAULT_RESULTS_LENGTH = 100;\nconst MORE_BUTTON_INCREMENTS = [200, 400, 800, 1600, 3200];\nconst LINES_SEPARATOR = 'lines=';\nconst MAX_RESULTS_LENGTH = MORE_BUTTON_INCREMENTS[MORE_BUTTON_INCREMENTS.length - 1];\nconst IPS_REGEX = /[([]?([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})[)\\]]?/g;\n\nconst ALIASES: { [k: string]: string } = {\n\t'helpticket': 'help-rooms',\n\t'groupchat': 'groupchat-rooms',\n\t'battle': 'battle-rooms',\n};\n\n/*********************************************************\n * Modlog Functions\n *********************************************************/\n\nfunction getMoreButton(\n\troomid: ModlogID, searchCmd: string,\n\tlines: number, maxLines: number, onlyPunishments: boolean, onlyNotes: boolean,\n) {\n\tlet newLines = 0;\n\tfor (const increase of MORE_BUTTON_INCREMENTS) {\n\t\tif (increase > lines) {\n\t\t\tnewLines = increase;\n\t\t\tbreak;\n\t\t}\n\t}\n\tif (!newLines || lines < maxLines) {\n\t\treturn ''; // don't show a button if no more pre-set increments are valid or if the amount of results is already below the max\n\t} else {\n\t\tlet cmd = `/modlog`;\n\t\tif (onlyNotes) cmd = `/modnotes`;\n\t\tif (onlyPunishments) cmd = `/punishlog`;\n\n\t\treturn Utils.html`
`;\n\t}\n}\n\nfunction getRoomID(id: string) {\n\tif (id in ALIASES) return ALIASES[id] as ModlogID;\n\treturn id as ModlogID;\n}\n\nfunction prettifyResults(\n\tresultArray: ModlogEntry[], roomid: ModlogID, search: ModlogSearch, searchCmd: string,\n\taddModlogLinks: boolean, hideIps: boolean, maxLines: number, onlyPunishments: boolean, onlyNotes: boolean\n) {\n\tif (resultArray === null) {\n\t\treturn \"|popup|The modlog query crashed.\";\n\t}\n\tlet roomName;\n\tswitch (roomid) {\n\tcase 'all':\n\t\troomName = \"all rooms\";\n\t\tbreak;\n\tcase 'public':\n\t\troomName = \"all public rooms\";\n\t\tbreak;\n\tdefault:\n\t\troomName = `room ${roomid}`;\n\t}\n\tconst scope = onlyPunishments ? 'punishment-related ' : '';\n\tlet searchString = ``;\n\tconst excludes = search.note.filter(s => s.isExclusion).map(s => s.search) || [];\n\tconst includes = search.note.filter(s => !s.isExclusion).map(s => s.search) || [];\n\tif (includes.length) searchString += `with a note including any of: ${includes.join(', ')} `;\n\tif (excludes.length) searchString += `with a note that does not include any of: ${excludes.join(', ')} `;\n\tfor (const u of search.user) searchString += `${u.isExclusion ? 'not ' : ''}taken against ${u.search} `;\n\tfor (const ip of search.ip) {\n\t\tsearchString += `${ip.isExclusion ? 'not ' : ''}taken against a user on the IP ${ip.search} `;\n\t}\n\tfor (const action of search.action) searchString += `${action.isExclusion ? 'not ' : ''}of the type ${action.search} `;\n\tfor (const actionTaker of search.actionTaker) {\n\t\tsearchString += `${actionTaker.isExclusion ? 'not ' : ''}taken by ${actionTaker.search} `;\n\t}\n\tif (!resultArray.length) {\n\t\treturn `|popup|No ${scope}moderator actions ${searchString}found on ${roomName}.`;\n\t}\n\tconst title = `[${roomid}] ${searchCmd}`;\n\tconst lines = resultArray.length;\n\tlet curDate = '';\n\tconst resultString = resultArray.map(result => {\n\t\tconst date = new Date(result.time || Date.now());\n\t\tconst entryRoom = result.visualRoomID || result.roomID || 'global';\n\t\tlet [dateString, timestamp] = Chat.toTimestamp(date, { human: true }).split(' ');\n\t\tlet line = `[${timestamp}] (${entryRoom}) ${result.action}`;\n\t\tif (result.userid) {\n\t\t\tline += `: [${result.userid}]`;\n\t\t\tif (result.autoconfirmedID) line += ` ac: [${result.autoconfirmedID}]`;\n\t\t\tif (result.alts.length) line += ` alts: [${result.alts.join('], [')}]`;\n\t\t\tif (!hideIps && result.ip) line += ` [${result.ip}]`;\n\t\t}\n\n\t\tif (result.loggedBy) line += `: by ${result.loggedBy}`;\n\t\tif (result.note) line += `: ${result.note}`;\n\n\t\tif (dateString !== curDate) {\n\t\t\tcurDate = dateString;\n\t\t\tdateString = `

[${dateString}]
`;\n\t\t} else {\n\t\t\tdateString = ``;\n\t\t}\n\t\tconst thisRoomID = entryRoom?.split(' ')[0];\n\t\tif (addModlogLinks) {\n\t\t\tif (thisRoomID.startsWith('battle-')) {\n\t\t\t\ttimestamp = `${timestamp}`;\n\t\t\t} else {\n\t\t\t\tconst [day, time] = Chat.toTimestamp(date).split(' ');\n\t\t\t\ttimestamp = `${timestamp}`;\n\t\t\t}\n\t\t}\n\t\tline = Utils.escapeHTML(line.slice(line.indexOf(')') + ` `.length));\n\t\tline = line.replace(\n\t\t\tIPS_REGEX,\n\t\t\thideIps ? '' : `[$1]`\n\t\t);\n\t\treturn `${dateString}[${timestamp}] (${thisRoomID})${line}`;\n\t}).join(`
`);\n\tconst [dateString, timestamp] = Chat.toTimestamp(new Date(), { human: true }).split(' ');\n\tlet preamble;\n\tconst modlogid = roomid + (searchString ? '-' + Dashycode.encode(searchString) : '');\n\tif (searchString) {\n\t\tpreamble = `>view-modlog-${modlogid}\\n|init|html\\n|title|[Modlog]${title}\\n` +\n\t\t\t`|pagehtml|

The last ${scope}${Chat.count(lines, \"logged actions\")} ${Utils.escapeHTML(searchString)} on ${roomName}.`;\n\t} else {\n\t\tpreamble = `>view-modlog-${modlogid}\\n|init|html\\n|title|[Modlog]${title}\\n` +\n\t\t\t`|pagehtml|

The last ${Chat.count(lines, `${scope}lines`)} of the Moderator Log of ${roomName}.`;\n\t}\n\tpreamble += `

[${dateString}]
[${timestamp}] \\u2190 current server time`;\n\tconst moreButton = getMoreButton(roomid, searchCmd, lines, maxLines, onlyPunishments, onlyNotes);\n\treturn `${preamble}${resultString}${moreButton}

`;\n}\n\nasync function getModlog(\n\tconnection: Connection, roomid: ModlogID = 'global', search: ModlogSearch,\n\tsearchCmd: string, maxLines = 20, onlyPunishments = false, timed = false, onlyNotes = false,\n) {\n\tconst targetRoom = Rooms.search(roomid);\n\tconst user = connection.user;\n\troomid = getRoomID(roomid);\n\n\t// permission checking\n\tif (roomid === 'all' || roomid === 'public') {\n\t\tif (!user.can('modlog')) {\n\t\t\treturn connection.popup(\"Access denied\");\n\t\t}\n\t} else {\n\t\tif (!user.can('modlog', null, targetRoom) && !user.can('modlog')) {\n\t\t\treturn connection.popup(\"Access denied\");\n\t\t}\n\t}\n\n\tconst hideIps = !user.can('lock');\n\tconst addModlogLinks = !!(\n\t\t(user.tempGroup !== ' ' || (targetRoom && targetRoom.settings.isPrivate !== true))\n\t);\n\tif (hideIps && search.ip.length) {\n\t\tconnection.popup(`You cannot search for IPs.`);\n\t\treturn;\n\t}\n\tif (Object.values(search).join('').length > MAX_QUERY_LENGTH) {\n\t\tconnection.popup(`Your search query is too long.`);\n\t\treturn;\n\t}\n\n\tif (search.note?.length) {\n\t\tfor (const [i, noteSearch] of search.note.entries()) {\n\t\t\tif (/^[\"'].+[\"']$/.test(noteSearch.search)) {\n\t\t\t\tsearch.note[i] = { ...noteSearch, search: noteSearch.search.substring(1, noteSearch.search.length - 1) };\n\t\t\t\tsearch.note[i].isExact = true;\n\t\t\t}\n\t\t}\n\t}\n\n\tfor (const [i, userSearch] of search.user.entries()) {\n\t\tif (/^[\"'].+[\"']$/.test(userSearch.search)) {\n\t\t\tuserSearch.search = userSearch.search.substring(1, userSearch.search.length - 1);\n\t\t\tuserSearch.isExact = true;\n\t\t}\n\t\tuserSearch.search = toID(userSearch.search);\n\n\t\tsearch.user[i] = userSearch;\n\t}\n\tif (onlyNotes) search.action.push({ search: 'NOTE' });\n\n\tconst response = await Rooms.Modlog.search(roomid, search, maxLines, onlyPunishments);\n\tif (!response) return connection.popup(`The moderator log is currently disabled.`);\n\n\tconnection.send(\n\t\tprettifyResults(\n\t\t\tresponse.results,\n\t\t\troomid,\n\t\t\tsearch,\n\t\t\tsearchCmd,\n\t\t\taddModlogLinks,\n\t\t\thideIps,\n\t\t\tmaxLines,\n\t\t\tonlyPunishments,\n\t\t\tonlyNotes,\n\t\t)\n\t);\n\tif (timed) connection.popup(`The modlog query took ${response.duration} ms to complete.`);\n}\n\nconst shouldSearchGlobal = ['staff', 'adminlog'];\n\nexport const commands: Chat.ChatCommands = {\n\tml: 'modlog',\n\tpunishlog: 'modlog',\n\tpl: 'modlog',\n\ttimedmodlog: 'modlog',\n\tmlid: 'modlog',\n\tmlip: 'modlog',\n\tplid: 'modlog',\n\tplip: 'modlog',\n\tmodnotes: 'modlog',\n\tmodlog(target, room, user, connection, cmd) {\n\t\tlet roomid: ModlogID = (!room || shouldSearchGlobal.includes(room.roomid) ? 'global' : room.roomid);\n\t\tconst onlyPunishments = cmd.startsWith('pl') || cmd.startsWith('punishlog');\n\t\tlet lines;\n\t\tconst possibleParam = cmd.slice(2);\n\t\tconst targets = target.split(',').map(f => f.trim()).filter(Boolean);\n\t\tconst search: ModlogSearch = { note: [], user: [], ip: [], action: [], actionTaker: [] };\n\n\t\tswitch (possibleParam) {\n\t\tcase 'id':\n\t\t\ttargets.unshift(`user='${targets.shift()}'`);\n\t\t\tbreak;\n\t\tcase 'ip':\n\t\t\ttargets.unshift(`ip=${targets.shift()}`);\n\t\t\tbreak;\n\t\t}\n\n\t\tfor (const [i, option] of targets.entries()) {\n\t\t\tlet [param, value] = option.split('=').map(part => part.trim());\n\t\t\tif (!value) {\n\t\t\t\t// If no specific parameter is specified, we should search all fields\n\t\t\t\tvalue = param.trim();\n\t\t\t\tif (i === 0 && value) {\n\t\t\t\t\t// they might mean a roomid, as per the old format of /modlog\n\t\t\t\t\tparam = 'room';\n\t\t\t\t\t// if the room exists, they probably mean a roomid. otherwise, assume they're misusing it.\n\t\t\t\t\t// we except gdrivers+ from this because drivers can access deleted room modlogs\n\t\t\t\t\tif (!Rooms.search(toID(value)) && !user.can('lock')) {\n\t\t\t\t\t\treturn this.parse(`/help modlog`);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.errorReply(`You must specify a search type and search value.`);\n\t\t\t\t\treturn this.parse(`/help modlog`);\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst isExclusion = param.endsWith('!');\n\t\t\tparam = toID(param);\n\t\t\tswitch (param) {\n\t\t\tcase 'note': case 'text':\n\t\t\t\tif (!search.note) search.note = [];\n\t\t\t\tsearch.note.push({ search: value, isExclusion });\n\t\t\t\tbreak;\n\t\t\tcase 'user': case 'name': case 'username': case 'userid':\n\t\t\t\tsearch.user.push({ search: value });\n\t\t\t\tbreak;\n\t\t\tcase 'ip': case 'ipaddress': case 'ipaddr':\n\t\t\t\tsearch.ip.push({ search: value, isExclusion });\n\t\t\t\tbreak;\n\t\t\tcase 'action': case 'punishment':\n\t\t\t\tsearch.action.push({ search: value.toUpperCase(), isExclusion });\n\t\t\t\tbreak;\n\t\t\tcase 'actiontaker': case 'moderator': case 'staff': case 'mod':\n\t\t\t\tsearch.actionTaker.push({ search: toID(value), isExclusion });\n\t\t\t\tbreak;\n\t\t\tcase 'room': case 'roomid':\n\t\t\t\troomid = value.toLowerCase().replace(/[^a-z0-9-]+/g, '') as ModlogID;\n\t\t\t\tbreak;\n\t\t\tcase 'lines': case 'maxlines':\n\t\t\t\tlines = parseInt(value);\n\t\t\t\tif (isNaN(lines) || lines < 1) return this.errorReply(`Invalid linecount: '${value}'.`);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.errorReply(`Invalid modlog parameter: '${param}'.`);\n\t\t\t\treturn this.errorReply(`Please specify 'room', 'note', 'user', 'ip', 'action', 'staff', or 'lines'.`);\n\t\t\t}\n\t\t}\n\n\t\tconst targetRoom = Rooms.search(roomid);\n\t\t// if a room alias was used, replace alias with actual id\n\t\tif (targetRoom) roomid = targetRoom.roomid;\n\n\t\tif (roomid.includes('-')) {\n\t\t\tif (user.can('modlog')) {\n\t\t\t\t// default to global modlog for staff convenience\n\t\t\t\troomid = 'global';\n\t\t\t} else {\n\t\t\t\treturn this.errorReply(`Only global staff may view battle and groupchat modlogs.`);\n\t\t\t}\n\t\t}\n\n\t\tif (!target && !lines) {\n\t\t\tlines = 20;\n\t\t}\n\t\tif (!lines) lines = DEFAULT_RESULTS_LENGTH;\n\t\tif (lines > MAX_RESULTS_LENGTH) lines = MAX_RESULTS_LENGTH;\n\n\t\tvoid getModlog(\n\t\t\tconnection,\n\t\t\troomid,\n\t\t\tsearch,\n\t\t\ttarget.replace(/^\\s?([^,=]*),\\s?/, '').replace(/,?\\s*(room|lines)\\s*=[^,]*,?/g, ''),\n\t\t\tlines,\n\t\t\tonlyPunishments,\n\t\t\tcmd === 'timedmodlog',\n\t\t\tcmd === 'modnotes',\n\t\t);\n\t},\n\tmodloghelp() {\n\t\tthis.sendReplyBox(\n\t\t\t`/modlog [comma-separated list of parameters]: searches the moderator log, defaulting to the current room unless specified otherwise.
` +\n\t\t\t`You can replace the = in a parameter with a != to exclude entries that match that parameter.
` +\n\t\t\t`
Parameters` +\n\t\t\t`` +\n\t\t\t`
` +\n\t\t\t`
Additional commands` +\n\t\t\t`` +\n\t\t\t`
`\n\t\t);\n\t},\n\tmls: 'modlogstats',\n\tmodlogstats(target, room, user) {\n\t\tthis.checkCan('lock');\n\t\ttarget = toID(target);\n\t\tif (!target) return this.parse(`/help modlogstats`);\n\t\treturn this.parse(`/join view-modlogstats-${target}`);\n\t},\n\tmodlogstatshelp: [`/modlogstats [userid] - Fetch all information on that [userid] from the modlog (IPs, alts, etc). Requires: @ ~`],\n};\n\nexport const pages: Chat.PageTable = {\n\tasync modlogstats(query, user) {\n\t\tthis.checkCan('lock');\n\t\tconst target = toID(query.shift());\n\t\tif (!target || target.length > 18) {\n\t\t\treturn this.errorReply(`Invalid userid - must be between 1 and 18 characters long.`);\n\t\t}\n\t\tthis.title = `[Modlog Stats] ${target}`;\n\t\tthis.setHTML(`
Running modlog search...
`);\n\t\tconst entries = await Rooms.Modlog.search('global', {\n\t\t\tuser: [{\n\t\t\t\tsearch: target,\n\t\t\t\tisExact: true,\n\t\t\t}], note: [], ip: [], action: [], actionTaker: [],\n\t\t}, 1000);\n\t\tif (!entries?.results.length) {\n\t\t\treturn this.errorReply(`No data found.`);\n\t\t}\n\t\tconst punishmentTable = new Utils.Multiset();\n\t\tconst punishmentsByIp = new Map>();\n\t\tconst actionsWithIp = new Set();\n\t\tconst alts = new Set();\n\t\tconst autoconfirmed = new Set();\n\t\tconst ips = new Set();\n\t\tfor (const entry of entries.results) {\n\t\t\tif (entry.action !== 'NOTE') {\n\t\t\t\tpunishmentTable.add(entry.action);\n\t\t\t\tif (entry.ip) {\n\t\t\t\t\tlet ipTable = punishmentsByIp.get(entry.ip);\n\t\t\t\t\tif (!ipTable) {\n\t\t\t\t\t\tipTable = new Utils.Multiset();\n\t\t\t\t\t\tpunishmentsByIp.set(entry.ip, ipTable);\n\t\t\t\t\t}\n\t\t\t\t\tipTable.add(entry.action);\n\t\t\t\t\tactionsWithIp.add(entry.action);\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (entry.alts) {\n\t\t\t\tfor (const alt of entry.alts) alts.add(alt);\n\t\t\t}\n\t\t\tif (entry.autoconfirmedID) autoconfirmed.add(entry.autoconfirmedID);\n\t\t\tif (entry.ip) ips.add(entry.ip);\n\t\t}\n\t\tlet buf = `

Modlog information for ${target}


`;\n\t\tif (alts.size) {\n\t\t\tbuf += `Listed alts: `;\n\t\t\tbuf += `(These are userids sharing the same IP at the time of the punishment, they may not be direct alts)
`;\n\t\t\tbuf += [...alts]\n\t\t\t\t.map(id => `${toID(id)}`)\n\t\t\t\t.join(', ');\n\t\t\tbuf += `

`;\n\t\t}\n\n\t\tif (autoconfirmed.size) {\n\t\t\tbuf += `Autoconfirmed alts:`;\n\t\t\tbuf += ` (these are autoconfirmed accounts linked to their name, and are very likely them)
`;\n\t\t\tbuf += [...autoconfirmed]\n\t\t\t\t.map(id => `${toID(id)}`)\n\t\t\t\t.join(', ');\n\t\t\tbuf += `

`;\n\t\t}\n\n\t\tif (ips.size) {\n\t\t\tbuf += `Known IPs:
`;\n\t\t\tconst mapped = await Promise.all([...ips].map(async ip => {\n\t\t\t\tconst info = await IPTools.lookup(ip);\n\t\t\t\treturn `${ip} [${info.hostType}]`;\n\t\t\t}));\n\t\t\tbuf += mapped.join(', ');\n\t\t\tbuf += `

`;\n\t\t}\n\n\t\tif (punishmentTable.size) {\n\t\t\tbuf += `Punishments:
`;\n\t\t\tbuf += `
`;\n\t\t\tbuf += ``;\n\t\t\tfor (const [punishment, number] of punishmentTable) {\n\t\t\t\tbuf += ``;\n\t\t\t}\n\t\t\tbuf += `
Punishment typeCount
${punishment}${number}

`;\n\t\t}\n\t\tif (punishmentsByIp.size) {\n\t\t\tbuf += `Punishments by IP:
`;\n\t\t\tconst keys = [...actionsWithIp];\n\t\t\tbuf += `
`;\n\t\t\tbuf += `${keys.map(k => ``).join(\"\")}`;\n\t\t\tfor (const [ip, table] of punishmentsByIp) {\n\t\t\t\tbuf += ``;\n\t\t\t\tfor (const key of keys) {\n\t\t\t\t\tbuf += ``;\n\t\t\t\t}\n\t\t\t\tbuf += ``;\n\t\t\t}\n\t\t\tbuf += `
${k}
${ip}${table.get(key)}
`;\n\t\t}\n\n\t\tbuf += `

`;\n\t\treturn buf;\n\t},\n};\n"], "mappings": "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", "names": ["dateString", "timestamp"] }