{ "version": 3, "sources": ["../../../../server/chat-commands/moderation.ts"], "sourcesContent": ["/**\r\n * Moderation commands\r\n * Pokemon Showdown - http://pokemonshowdown.com/\r\n *\r\n * These are commands for staff.\r\n *\r\n * For the API, see chat-plugins/COMMANDS.md\r\n *\r\n * @license MIT\r\n */\r\nimport {Utils} from '../../lib';\r\nimport {RoomSection, RoomSections} from './room-settings';\r\n\r\n/* eslint no-else-return: \"error\" */\r\n\r\nconst MAX_REASON_LENGTH = 600;\r\nconst MUTE_LENGTH = 7 * 60 * 1000;\r\nconst HOURMUTE_LENGTH = 60 * 60 * 1000;\r\nconst DAY = 24 * 60 * 60 * 1000;\r\n\r\n/** Require reasons for punishment commands */\r\nconst REQUIRE_REASONS = true;\r\n\r\n/**\r\n * Promotes a user within a room. Returns a User object if a popup should be shown to the user,\r\n * and null otherwise. Throws a Chat.ErrorMesage on an error.\r\n *\r\n * @param promoter the User object of the user who is promoting\r\n * @param room the Room in which the promotion is happening\r\n * @param userid the ID of the user to promote\r\n * @param symbol the GroupSymbol to promote to\r\n * @param username the username of the user to promote\r\n * @param force whether or not to forcibly promote\r\n */\r\nexport function runPromote(\r\n\tpromoter: User,\r\n\troom: Room,\r\n\tuserid: ID,\r\n\tsymbol: GroupSymbol,\r\n\tusername?: string,\r\n\tforce?: boolean\r\n) {\r\n\tconst targetUser = Users.getExact(userid);\r\n\tusername = username || userid;\r\n\tif (!username) return;\r\n\r\n\tif (userid.length > 18) {\r\n\t\tthrow new Chat.ErrorMessage(`User '${username}' does not exist (the username is too long).`);\r\n\t}\r\n\tif (!targetUser && !Users.isUsernameKnown(userid) && !force) {\r\n\t\tthrow new Chat.ErrorMessage(`User '${username}' is offline and unrecognized, and so can't be promoted.`);\r\n\t}\r\n\tif (targetUser && !targetUser.registered) {\r\n\t\tthrow new Chat.ErrorMessage(`User '${username}' is unregistered, and so can't be promoted.`);\r\n\t}\r\n\r\n\tlet currentSymbol: GroupSymbol | 'whitelist' = room.auth.getDirect(userid);\r\n\tif (room.auth.has(userid) && currentSymbol === Users.Auth.defaultSymbol()) {\r\n\t\tcurrentSymbol = 'whitelist';\r\n\t}\r\n\tconst currentGroup = Users.Auth.getGroup(currentSymbol);\r\n\tconst currentGroupName = currentGroup.name || \"regular user\";\r\n\r\n\tconst nextGroup = Config.groups[symbol];\r\n\r\n\tif (currentSymbol === symbol) {\r\n\t\tthrow new Chat.ErrorMessage(`User '${username}' is already a ${nextGroup?.name || symbol || 'regular user'} in this room.`);\r\n\t}\r\n\tif (!promoter.can('makeroom')) {\r\n\t\tif (currentGroup.id && !promoter.can(`room${currentGroup.id || 'voice'}` as 'roomvoice', null, room)) {\r\n\t\t\tthrow new Chat.ErrorMessage(`Access denied for promoting/demoting ${username} from ${currentGroupName}.`);\r\n\t\t}\r\n\t\tif (symbol !== ' ' && !promoter.can(`room${nextGroup.id || 'voice'}` as 'roomvoice', null, room)) {\r\n\t\t\tthrow new Chat.ErrorMessage(`Access denied for promoting/demoting ${username} to ${nextGroup.name}.`);\r\n\t\t}\r\n\t}\r\n\tif (targetUser?.locked && room.persist && room.settings.isPrivate !== true && nextGroup.rank > 2) {\r\n\t\tthrow new Chat.ErrorMessage(`${username} is locked and can't be promoted.`);\r\n\t}\r\n\r\n\tif (symbol === Users.Auth.defaultSymbol()) {\r\n\t\troom.auth.delete(userid);\r\n\t} else {\r\n\t\troom.auth.set(userid, symbol);\r\n\t}\r\n\r\n\tif (targetUser) {\r\n\t\ttargetUser.updateIdentity(room.roomid);\r\n\t\tif (room.subRooms) {\r\n\t\t\tfor (const subRoom of room.subRooms.values()) {\r\n\t\t\t\ttargetUser.updateIdentity(subRoom.roomid);\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\t// Only show popup if: user is online and in the room, the room is public, and not a groupchat or a battle.\r\n\tif (targetUser && room.users[targetUser.id] && room.persist && room.settings.isPrivate !== true) {\r\n\t\treturn targetUser;\r\n\t}\r\n\treturn null;\r\n}\r\n\r\nexport function runCrisisDemote(userid: ID) {\r\n\tconst from = [];\r\n\tconst section = Users.globalAuth.sectionLeaders.get(userid);\r\n\tif (section) {\r\n\t\tfrom.push(`Section Leader (${RoomSections.sectionNames[section] || section})`);\r\n\t\tUsers.globalAuth.deleteSection(userid);\r\n\t}\r\n\tconst globalGroup = Users.globalAuth.get(userid);\r\n\tif (globalGroup && globalGroup !== ' ') {\r\n\t\tfrom.push(globalGroup);\r\n\t\tUsers.globalAuth.delete(userid);\r\n\t}\r\n\tfor (const room of Rooms.global.chatRooms) {\r\n\t\tif (!room.settings.isPrivate && room.auth.isStaff(userid)) {\r\n\t\t\tlet oldGroup: string = room.auth.getDirect(userid);\r\n\t\t\tif (oldGroup === ' ') {\r\n\t\t\t\toldGroup = 'whitelist in ';\r\n\t\t\t} else {\r\n\t\t\t\troom.auth.set(userid, '+');\r\n\t\t\t}\r\n\t\t\tfrom.push(`${oldGroup}${room.roomid}`);\r\n\t\t}\r\n\t}\r\n\treturn from;\r\n}\r\n\r\nPunishments.addPunishmentType({\r\n\ttype: 'YEARLOCK',\r\n\tdesc: \"Locked for a year\",\r\n\tonActivate: (user, punishment) => {\r\n\t\tuser.locked = user.id;\r\n\t\tChat.punishmentfilter(user, punishment);\r\n\t},\r\n});\r\n\r\nexport const commands: Chat.ChatCommands = {\r\n\troomowner(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!room.persist) {\r\n\t\t\treturn this.sendReply(\"/roomowner - This room isn't designed for per-room moderation to be added\");\r\n\t\t}\r\n\t\tif (!target) return this.parse('/help roomowner');\r\n\t\tconst {targetUser, targetUsername, rest} = this.splitUser(target, {exactName: true});\r\n\t\tif (rest) return this.errorReply(`This command does not support specifying a reason.`);\r\n\t\tconst userid = toID(targetUsername);\r\n\r\n\t\tif (!Users.isUsernameKnown(userid)) {\r\n\t\t\treturn this.errorReply(`User '${targetUsername}' is offline and unrecognized, and so can't be promoted.`);\r\n\t\t}\r\n\r\n\t\tthis.checkCan('makeroom');\r\n\t\tif (room.auth.getDirect(userid) === '#') return this.errorReply(`${targetUsername} is already a room owner.`);\r\n\r\n\t\troom.auth.set(userid, '#');\r\n\t\tconst message = `${targetUsername} was appointed Room Owner by ${user.name}.`;\r\n\t\tif (room.settings.isPrivate === true) {\r\n\t\t\tthis.addModAction(message);\r\n\t\t\tRooms.get(`upperstaff`)?.addByUser(user, `<<${room.roomid}>> ${message}`).update();\r\n\t\t} else {\r\n\t\t\tthis.addGlobalModAction(message);\r\n\t\t}\r\n\t\tthis.modlog('ROOMOWNER', userid);\r\n\t\tif (targetUser) {\r\n\t\t\ttargetUser.popup(`You were appointed Room Owner by ${user.name} in ${room.roomid}.`);\r\n\t\t\troom.onUpdateIdentity(targetUser);\r\n\t\t\tif (room.subRooms) {\r\n\t\t\t\tfor (const subRoom of room.subRooms.values()) {\r\n\t\t\t\t\tsubRoom.onUpdateIdentity(targetUser);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\troom.saveSettings();\r\n\t},\r\n\troomownerhelp: [`/roomowner [username] - Appoints [username] as a room owner. Requires: &`],\r\n\r\n\troomdemote: 'roompromote',\r\n\tforceroompromote: 'roompromote',\r\n\tforceroomdemote: 'roompromote',\r\n\troompromote(target, room, user, connection, cmd) {\r\n\t\tif (!room) {\r\n\t\t\t// this command isn't marked as room-only because it's usable in PMs through /invite\r\n\t\t\treturn this.errorReply(\"This command is only available in rooms\");\r\n\t\t}\r\n\t\tthis.checkChat();\r\n\t\tif (!target) return this.parse('/help roompromote');\r\n\r\n\t\tconst force = cmd.startsWith('force');\r\n\t\tconst users = target.split(',').map(part => part.trim());\r\n\t\tlet nextSymbol = users.pop() as GroupSymbol | 'deauth';\r\n\t\tif (nextSymbol === 'deauth') nextSymbol = Users.Auth.defaultSymbol();\r\n\t\tconst nextGroup = Users.Auth.getGroup(nextSymbol);\r\n\r\n\t\tif (!nextSymbol) {\r\n\t\t\treturn this.errorReply(\"Please specify a group such as /roomvoice or /roomdeauth\");\r\n\t\t}\r\n\t\tif (!Config.groups[nextSymbol]) {\r\n\t\t\tif (!force || !user.can('bypassall')) {\r\n\t\t\t\tthis.errorReply(`Group '${nextSymbol}' does not exist.`);\r\n\t\t\t\tif (user.can('bypassall')) {\r\n\t\t\t\t\tthis.errorReply(`If you want to promote to a nonexistent group, use /forceroompromote`);\r\n\t\t\t\t}\r\n\t\t\t\treturn;\r\n\t\t\t} else if (!Users.Auth.isValidSymbol(nextSymbol)) {\r\n\t\t\t\t// yes I know this excludes astral-plane characters and includes combining characters\r\n\t\t\t\treturn this.errorReply(`Admins can forcepromote to nonexistent groups only if they are one character long`);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!force && (nextGroup.globalonly || (nextGroup.battleonly && !room.battle))) {\r\n\t\t\treturn this.errorReply(`Group 'room${nextGroup.id || nextSymbol}' does not exist as a room rank.`);\r\n\t\t}\r\n\t\tconst nextGroupName = nextGroup.name || \"regular user\";\r\n\r\n\t\tfor (const toPromote of users) {\r\n\t\t\tconst userid = toID(toPromote);\r\n\t\t\tif (!userid) return this.parse('/help roompromote');\r\n\r\n\t\t\t// weird ts bug (?) - 7022\r\n\t\t\t// it implicitly is 'any' because it has no annotation and is \"is referenced directly or indirectly in its own initializer.\"\r\n\t\t\t// dunno why this happens, but for now we can just cast over it.\r\n\t\t\tconst oldSymbol: GroupSymbol = room.auth.getDirect(userid);\r\n\t\t\tlet shouldPopup;\r\n\t\t\ttry {\r\n\t\t\t\tshouldPopup = runPromote(user, room, userid, nextSymbol, toPromote, force);\r\n\t\t\t} catch (err: any) {\r\n\t\t\t\tif (err.name?.endsWith('ErrorMessage')) {\r\n\t\t\t\t\tthis.errorReply(err.message);\r\n\t\t\t\t\tcontinue;\r\n\t\t\t\t}\r\n\t\t\t\tthrow err;\r\n\t\t\t}\r\n\t\t\tconst targetUser = Users.getExact(userid);\r\n\t\t\tconst name = targetUser?.name || toPromote;\r\n\r\n\t\t\tif (this.pmTarget && targetUser) {\r\n\t\t\t\tconst text = `${targetUser.name} was invited (and promoted to Room ${nextGroupName}) by ${user.name}.`;\r\n\t\t\t\troom.add(`|c|${user.getIdentity(room)}|/log ${text}`).update();\r\n\t\t\t\tthis.modlog('INVITE', targetUser, null, {noip: 1, noalts: 1});\r\n\t\t\t} else if (\r\n\t\t\t\tnextSymbol in Config.groups && oldSymbol in Config.groups &&\r\n\t\t\t\tnextGroup.rank < Config.groups[oldSymbol].rank\r\n\t\t\t) {\r\n\t\t\t\tif (targetUser && room.users[targetUser.id] && !nextGroup.modlog) {\r\n\t\t\t\t\t// if the user can't see the demotion message (i.e. rank < %), it is shown in the chat\r\n\t\t\t\t\ttargetUser.send(`>${room.roomid}\\n(You were demoted to Room ${nextGroupName} by ${user.name}.)`);\r\n\t\t\t\t}\r\n\t\t\t\tthis.privateModAction(`${name} was demoted to Room ${nextGroupName} by ${user.name}.`);\r\n\t\t\t\tthis.modlog(`ROOM${nextGroupName.toUpperCase()}`, userid, '(demote)');\r\n\t\t\t\tshouldPopup?.popup(`You were demoted to Room ${nextGroupName} by ${user.name} in ${room.roomid}.`);\r\n\t\t\t} else if (nextSymbol === '#') {\r\n\t\t\t\tthis.addModAction(`${name} was promoted to ${nextGroupName} by ${user.name}.`);\r\n\t\t\t\tconst logRoom = Rooms.get(room.settings.isPrivate === true ? 'upperstaff' : 'staff');\r\n\t\t\t\tlogRoom?.addByUser(user, `<<${room.roomid}>> ${name} was appointed Room Owner by ${user.name}`);\r\n\t\t\t\tthis.modlog('ROOM OWNER', userid);\r\n\t\t\t\tshouldPopup?.popup(`You were promoted to ${nextGroupName} by ${user.name} in ${room.roomid}.`);\r\n\t\t\t} else {\r\n\t\t\t\tthis.addModAction(`${name} was promoted to Room ${nextGroupName} by ${user.name}.`);\r\n\t\t\t\tthis.modlog(`ROOM${nextGroupName.toUpperCase()}`, userid);\r\n\t\t\t\tshouldPopup?.popup(`You were promoted to Room ${nextGroupName} by ${user.name} in ${room.roomid}.`);\r\n\t\t\t}\r\n\r\n\t\t\tif (targetUser) {\r\n\t\t\t\ttargetUser.updateIdentity(room.roomid);\r\n\t\t\t\tif (room.subRooms) {\r\n\t\t\t\t\tfor (const subRoom of room.subRooms.values()) {\r\n\t\t\t\t\t\ttargetUser.updateIdentity(subRoom.roomid);\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t\tif (targetUser.trusted && !Users.isTrusted(targetUser.id)) {\r\n\t\t\t\t\ttargetUser.trusted = '';\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\troom.saveSettings();\r\n\t},\r\n\troompromotehelp: [\r\n\t\t`/roompromote OR /roomdemote [comma-separated usernames], [group symbol] - Promotes/demotes the user(s) to the specified room rank. Requires: @ # &`,\r\n\t\t`/room[group] [comma-separated usernames] - Promotes/demotes the user(s) to the specified room rank. Requires: @ # &`,\r\n\t\t`/roomdeauth [comma-separated usernames] - Removes all room rank from the user(s). Requires: @ # &`,\r\n\t],\r\n\r\n\tauth: 'authority',\r\n\tstafflist: 'authority',\r\n\tglobalauth: 'authority',\r\n\tauthlist: 'authority',\r\n\tauthority(target, room, user, connection) {\r\n\t\tif (target && target !== '+') {\r\n\t\t\tconst targetRoom = Rooms.search(target);\r\n\t\t\tconst availableRoom = targetRoom?.checkModjoin(user);\r\n\t\t\tif (targetRoom && availableRoom) return this.parse(`/roomauth1 ${target}`);\r\n\t\t\treturn this.parse(`/userauth ${target}`);\r\n\t\t}\r\n\t\tconst showAll = !!target;\r\n\t\tconst rankLists: {[k: string]: string[]} = {};\r\n\t\tfor (const [id, symbol] of Users.globalAuth) {\r\n\t\t\tif (symbol === ' ' || (symbol === '+' && !showAll)) continue;\r\n\t\t\tif (!rankLists[symbol]) rankLists[symbol] = [];\r\n\t\t\trankLists[symbol].push(Users.globalAuth.usernames.get(id) || id);\r\n\t\t}\r\n\r\n\t\tconst buffer = Utils.sortBy(\r\n\t\t\tObject.entries(rankLists) as [GroupSymbol, string[]][],\r\n\t\t\t([symbol]) => -Users.Auth.getGroup(symbol).rank\r\n\t\t).filter(\r\n\t\t\t([symbol]) => symbol !== Users.SECTIONLEADER_SYMBOL\r\n\t\t).map(\r\n\t\t\t([symbol, names]) => (\r\n\t\t\t\t`${(Config.groups[symbol] ? `**${Config.groups[symbol].name}s** (${symbol})` : symbol)}:\\n` +\r\n\t\t\t\tUtils.sortBy(names, name => toID(name)).join(\", \")\r\n\t\t\t)\r\n\t\t);\r\n\t\tif (!showAll) buffer.push(`(Use \\`\\`/auth +\\`\\` to show global voice users.)`);\r\n\r\n\t\tif (!buffer.length) return connection.popup(\"This server has no global authority.\");\r\n\t\tconnection.popup(buffer.join(\"\\n\\n\"));\r\n\t},\r\n\tauthhelp: [\r\n\t\t`/auth - Show global staff for the server.`,\r\n\t\t`/auth + - Show global staff for the server, including voices.`,\r\n\t\t`/auth [room] - Show what roomauth a room has.`,\r\n\t\t`/auth [user] - Show what global and roomauth a user has.`,\r\n\t],\r\n\r\n\troomstaff: 'roomauth',\r\n\troomauth1: 'roomauth',\r\n\troomauth(target, room, user, connection, cmd) {\r\n\t\tlet userLookup = '';\r\n\t\tif (cmd === 'roomauth1') userLookup = `\\n\\nTo look up auth for a user, use /userauth ${target}`;\r\n\t\tlet targetRoom = room;\r\n\t\tif (target) targetRoom = Rooms.search(target)!;\r\n\t\tif (!targetRoom?.checkModjoin(user)) {\r\n\t\t\treturn this.errorReply(`The room \"${target}\" does not exist.`);\r\n\t\t}\r\n\t\tconst showAll = user.can('mute', null, targetRoom);\r\n\r\n\t\tconst rankLists: {[groupSymbol: string]: ID[]} = {};\r\n\t\tfor (const [id, rank] of targetRoom.auth) {\r\n\t\t\tif (rank === ' ' && !showAll) continue;\r\n\t\t\tif (!rankLists[rank]) rankLists[rank] = [];\r\n\t\t\trankLists[rank].push(id);\r\n\t\t}\r\n\r\n\t\tconst buffer = Utils.sortBy(\r\n\t\t\tObject.entries(rankLists) as [GroupSymbol, ID[]][],\r\n\t\t\t([symbol]) => -Users.Auth.getGroup(symbol).rank\r\n\t\t).map(([symbol, names]) => {\r\n\t\t\tlet group = Config.groups[symbol] ? `${Config.groups[symbol].name}s (${symbol})` : symbol;\r\n\t\t\tif (symbol === ' ') group = 'Whitelisted (this list is only visible to staff)';\r\n\t\t\treturn `${group}:\\n` +\r\n\t\t\t\tUtils.sortBy(names).map(userid => {\r\n\t\t\t\t\tconst isOnline = Users.get(userid)?.statusType === 'online';\r\n\t\t\t\t\t// targetRoom guaranteed to exist above\r\n\t\t\t\t\treturn userid in targetRoom!.users && isOnline ? `**${userid}**` : userid;\r\n\t\t\t\t}).join(', ');\r\n\t\t});\r\n\r\n\t\tlet curRoom = targetRoom;\r\n\t\twhile (curRoom.parent) {\r\n\t\t\tconst modjoinSetting = curRoom.settings.modjoin === true ? curRoom.settings.modchat : curRoom.settings.modjoin;\r\n\t\t\tconst roomType = (modjoinSetting ? `modjoin ${modjoinSetting} ` : '');\r\n\t\t\tconst inheritedUserType = (modjoinSetting ? ` of rank ${modjoinSetting} and above` : '');\r\n\t\t\tif (curRoom.parent) {\r\n\t\t\t\tconst also = buffer.length === 0 ? `` : ` also`;\r\n\t\t\t\tbuffer.push(`${curRoom.title} is a ${roomType}subroom of ${curRoom.parent.title}, so ${curRoom.parent.title} users${inheritedUserType}${also} have authority in this room.`);\r\n\t\t\t}\r\n\t\t\tcurRoom = curRoom.parent;\r\n\t\t}\r\n\t\tif (!buffer.length) {\r\n\t\t\tconnection.popup(`The room '${targetRoom.title}' has no auth. ${userLookup}`);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!curRoom.settings.isPrivate) {\r\n\t\t\tbuffer.push(`${curRoom.title} is a public room, so global auth with no relevant roomauth will have authority in this room.`);\r\n\t\t} else if (curRoom.settings.isPrivate === 'hidden' || curRoom.settings.isPrivate === 'voice') {\r\n\t\t\tbuffer.push(`${curRoom.title} is a hidden room, so global auth with no relevant roomauth will have authority in this room.`);\r\n\t\t}\r\n\t\tbuffer.push(`Names in **bold** are online.`);\r\n\t\tif (targetRoom !== room) buffer.unshift(`${targetRoom.title} room auth:`);\r\n\t\tconnection.popup(`${buffer.join(\"\\n\\n\")}${userLookup}`);\r\n\t},\r\n\troomauthhelp: [\r\n\t\t`/roomauth [room] - Shows a list of the staff and authority in the given [room].`,\r\n\t\t`If no room is given, it defaults to the current room.`,\r\n\t],\r\n\r\n\tuserauth(target, room, user, connection) {\r\n\t\tconst targetId = toID(target) || user.id;\r\n\t\tconst targetUser = Users.getExact(targetId);\r\n\t\tconst targetUsername = targetUser?.name || target;\r\n\r\n\t\tconst buffer = [];\r\n\t\tlet innerBuffer = [];\r\n\t\tconst group = Users.globalAuth.get(targetId);\r\n\t\tif (group !== ' ' || Users.isTrusted(targetId)) {\r\n\t\t\tbuffer.push(`Global auth: ${group === ' ' ? 'trusted' : group}`);\r\n\t\t}\r\n\t\tconst sectionLeader = Users.globalAuth.sectionLeaders.get(targetId);\r\n\t\tif (sectionLeader) {\r\n\t\t\tbuffer.push(`Section leader: ${RoomSections.sectionNames[sectionLeader]}`);\r\n\t\t}\r\n\t\tfor (const curRoom of Rooms.rooms.values()) {\r\n\t\t\tif (curRoom.settings.isPrivate) continue;\r\n\t\t\tif (!curRoom.auth.has(targetId)) continue;\r\n\t\t\tinnerBuffer.push(curRoom.auth.getDirect(targetId).trim() + curRoom.roomid);\r\n\t\t}\r\n\t\tif (innerBuffer.length) {\r\n\t\t\tbuffer.push(`Room auth: ${innerBuffer.join(', ')}`);\r\n\t\t}\r\n\t\tif (targetId === user.id || user.can('lock')) {\r\n\t\t\tinnerBuffer = [];\r\n\t\t\tfor (const curRoom of Rooms.rooms.values()) {\r\n\t\t\t\tif (!curRoom.settings.isPrivate) continue;\r\n\t\t\t\tif (curRoom.settings.isPrivate === true) continue;\r\n\t\t\t\tif (!curRoom.auth.has(targetId)) continue;\r\n\t\t\t\tinnerBuffer.push(curRoom.auth.getDirect(targetId).trim() + curRoom.roomid);\r\n\t\t\t}\r\n\t\t\tif (innerBuffer.length) {\r\n\t\t\t\tbuffer.push(`Hidden room auth: ${innerBuffer.join(', ')}`);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (targetId === user.id || user.can('makeroom')) {\r\n\t\t\tinnerBuffer = [];\r\n\t\t\tfor (const chatRoom of Rooms.global.chatRooms) {\r\n\t\t\t\tif (!chatRoom.settings.isPrivate) continue;\r\n\t\t\t\tif (chatRoom.settings.isPrivate !== true) continue;\r\n\t\t\t\tif (!chatRoom.auth.has(targetId)) continue;\r\n\t\t\t\tinnerBuffer.push(chatRoom.auth.getDirect(targetId).trim() + chatRoom.roomid);\r\n\t\t\t}\r\n\t\t\tif (innerBuffer.length) {\r\n\t\t\t\tbuffer.push(`Private room auth: ${innerBuffer.join(', ')}`);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!buffer.length) {\r\n\t\t\tbuffer.push(\"No global or room auth.\");\r\n\t\t}\r\n\r\n\t\tbuffer.unshift(`${targetUsername} user auth:`);\r\n\t\tconnection.popup(buffer.join(\"\\n\\n\"));\r\n\t},\r\n\tuserauthhelp: [\r\n\t\t`/userauth [username] - Shows all authority visible to the user for the given [username].`,\r\n\t\t`If no username is given, it defaults to the current user.`,\r\n\t],\r\n\r\n\tsectionleaders(target, room, user, connection) {\r\n\t\tconst usernames = Users.globalAuth.usernames;\r\n\t\tconst buffer = [];\r\n\t\tconst sections: {[k in RoomSection]: Set} = Object.create(null);\r\n\t\tfor (const [id, username] of usernames) {\r\n\t\t\tconst sectionid = Users.globalAuth.sectionLeaders.get(id);\r\n\t\t\tif (!sectionid) continue;\r\n\t\t\tif (!sections[sectionid]) sections[sectionid] = new Set();\r\n\t\t\tsections[sectionid].add(username);\r\n\t\t}\r\n\t\tlet sectionid: RoomSection;\r\n\t\tfor (sectionid in sections) {\r\n\t\t\tif (!sections[sectionid].size) continue;\r\n\t\t\tbuffer.push(`**${RoomSections.sectionNames[sectionid]}**:\\n` + Utils.sortBy([...sections[sectionid]]).join(', '));\r\n\t\t}\r\n\t\tif (!buffer.length) throw new Chat.ErrorMessage(`There are no Section Leaders currently.`);\r\n\t\tconnection.popup(buffer.join(`\\n\\n`));\r\n\t},\r\n\tsectionleadershelp: [\r\n\t\t`/sectionleaders - Shows the current room sections and their section leaders.`,\r\n\t],\r\n\r\n\tasync autojoin(target, room, user, connection) {\r\n\t\tconst targets = target.split(',');\r\n\t\tif (targets.length > 16 || connection.inRooms.size > 1) {\r\n\t\t\treturn connection.popup(\"To prevent DoS attacks, you can only use /autojoin for 16 or fewer rooms, when you haven't joined any rooms yet. Please use /join for each room separately.\");\r\n\t\t}\r\n\t\tRooms.global.autojoinRooms(user, connection);\r\n\t\tconst autojoins: string[] = [];\r\n\r\n\t\tconst promises = targets.map(\r\n\t\t\troomid => user.tryJoinRoom(roomid as RoomID, connection).then(ret => {\r\n\t\t\t\tif (ret === Rooms.RETRY_AFTER_LOGIN) {\r\n\t\t\t\t\tautojoins.push(roomid);\r\n\t\t\t\t}\r\n\t\t\t})\r\n\t\t);\r\n\r\n\t\tawait Promise.all(promises);\r\n\t\tconnection.autojoins = autojoins.join(',');\r\n\t},\r\n\tautojoinhelp: [`/autojoin [rooms] - Automatically joins all the given rooms.`],\r\n\r\n\tjoim: 'join',\r\n\tj: 'join',\r\n\tasync join(target, room, user, connection) {\r\n\t\ttarget = target.trim();\r\n\t\tif (!target) return this.parse('/help join');\r\n\t\tif (target.startsWith('http://')) target = target.slice(7);\r\n\t\tif (target.startsWith('https://')) target = target.slice(8);\r\n\t\tif (target.startsWith(`${Config.routes.client}/`)) target = target.slice(Config.routes.client.length + 1);\r\n\t\tif (target.startsWith(`${Config.routes.replays}/`)) target = `battle-${target.slice(Config.routes.replays.length + 1)}`;\r\n\t\tif (target.startsWith('psim.us/')) target = target.slice(8);\r\n\t\t// isn't in tryJoinRoom so you can still join your own battles / gameRooms etc\r\n\t\tconst numRooms = [...Rooms.rooms.values()].filter(r => user.id in r.users).length;\r\n\t\tif (!user.can('altsself') && !target.startsWith('view-') && numRooms >= 50) {\r\n\t\t\treturn connection.sendTo(target as RoomID, `|noinit||You can only join 50 rooms at a time.`);\r\n\t\t}\r\n\t\tconst ret = await user.tryJoinRoom(target as RoomID, connection);\r\n\t\tif (ret === Rooms.RETRY_AFTER_LOGIN) {\r\n\t\t\tconnection.sendTo(\r\n\t\t\t\ttarget as RoomID,\r\n\t\t\t\t`|noinit|namerequired|The room '${target}' does not exist or requires a login to join.`\r\n\t\t\t);\r\n\t\t}\r\n\t},\r\n\tjoinhelp: [`/join [roomname] - Attempt to join the room [roomname].`],\r\n\r\n\tleave: 'part',\r\n\tpart(target, room, user, connection) {\r\n\t\tconst targetRoom = target ? Rooms.search(target) : room;\r\n\t\tif (!targetRoom) {\r\n\t\t\tif (target.startsWith('view-')) {\r\n\t\t\t\tconnection.openPages?.delete(target.slice(5));\r\n\t\t\t\tif (!connection.openPages?.size) connection.openPages = null;\r\n\t\t\t\tChat.handleRoomClose(target as RoomID, user, connection);\r\n\t\t\t\treturn;\r\n\t\t\t}\r\n\t\t\treturn this.errorReply(`The room '${target}' does not exist.`);\r\n\t\t}\r\n\t\tChat.handleRoomClose(targetRoom.roomid, user, connection);\r\n\t\tuser.leaveRoom(targetRoom, connection);\r\n\t},\r\n\tleavehelp: [`/leave - Leave the current room, or a given room.`],\r\n\r\n\t/*********************************************************\r\n\t * Moderating: Punishments\r\n\t *********************************************************/\r\n\r\n\tkick: 'warn',\r\n\tk: 'warn',\r\n\twarn(target, room, user) {\r\n\t\tif (!target) return this.parse('/help warn');\r\n\t\tthis.checkChat();\r\n\t\tif (room?.settings.isPersonal && !user.can('warn' as any)) {\r\n\t\t\treturn this.errorReply(\"Warning is unavailable in group chats.\");\r\n\t\t}\r\n\t\t// If used in pms, staff, help tickets or battles, log the warn to the global modlog.\r\n\t\tconst globalWarn = (\r\n\t\t\t!room || ['staff', 'adminlog'].includes(room.roomid) ||\r\n\t\t\troom.roomid.startsWith('help-') || (room.battle && !room.parent)\r\n\t\t);\r\n\r\n\t\tconst {targetUser, inputUsername, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tconst targetID = toID(targetUsername);\r\n\t\tconst {privateReason, publicReason} = this.parseSpoiler(reason);\r\n\r\n\t\tconst saveReplay = globalWarn && room?.battle;\r\n\t\tif (!targetUser?.connected) {\r\n\t\t\tif (!globalWarn) return this.errorReply(`User '${targetUsername}' not found.`);\r\n\t\t\tif (room) {\r\n\t\t\t\tthis.checkCan('warn', null, room);\r\n\t\t\t} else {\r\n\t\t\t\tthis.checkCan('lock');\r\n\t\t\t}\r\n\r\n\t\t\tthis.addGlobalModAction(\r\n\t\t\t\t`${targetID} was warned by ${user.name} while offline.${publicReason ? ` (${publicReason})` : ``}`\r\n\t\t\t);\r\n\t\t\tthis.globalModlog('WARN OFFLINE', targetUser || targetID, privateReason);\r\n\t\t\tPunishments.offlineWarns.set(targetID, reason);\r\n\t\t\tif (saveReplay) this.parse('/savereplay forpunishment');\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!globalWarn && !(targetUser.id in room.users)) {\r\n\t\t\treturn this.errorReply(`User ${targetUsername} is not in the room ${room.roomid}.`);\r\n\t\t}\r\n\t\tif (publicReason.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tif (room) {\r\n\t\t\tthis.checkCan('warn', targetUser, room);\r\n\t\t} else {\r\n\t\t\tthis.checkCan('lock', targetUser);\r\n\t\t}\r\n\t\tif (targetUser.can('makeroom')) return this.errorReply(\"You are not allowed to warn upper staff members.\");\r\n\r\n\t\tconst now = Date.now();\r\n\t\tconst timeout = now - targetUser.lastWarnedAt;\r\n\t\tif (timeout < 15 * 1000) {\r\n\t\t\tconst remainder = (15 - (timeout / 1000)).toFixed(2);\r\n\t\t\treturn this.errorReply(`You must wait ${remainder} more seconds before you can warn ${targetUser.name} again.`);\r\n\t\t}\r\n\r\n\t\tconst logMessage = `${targetUser.name} was warned by ${user.name}.${(publicReason ? ` (${publicReason})` : ``)}`;\r\n\t\tif (globalWarn) {\r\n\t\t\tthis.addGlobalModAction(logMessage);\r\n\t\t\tthis.globalModlog('WARN', targetUser, privateReason);\r\n\t\t} else {\r\n\t\t\tthis.addModAction(logMessage);\r\n\t\t\tthis.modlog('WARN', targetUser, privateReason, {noalts: 1});\r\n\t\t}\r\n\t\ttargetUser.send(`|c|~|/warn ${publicReason}`);\r\n\r\n\t\tconst userid = targetUser.getLastId();\r\n\r\n\t\tif (room) {\r\n\t\t\tthis.add(`|hidelines|unlink|${userid}`);\r\n\t\t\tif (userid !== toID(inputUsername)) this.add(`|hidelines|unlink|${toID(inputUsername)}`);\r\n\t\t}\r\n\r\n\t\ttargetUser.lastWarnedAt = now;\r\n\r\n\t\t// Automatically upload replays as evidence/reference to the punishment\r\n\t\tif (saveReplay) this.parse('/savereplay forpunishment');\r\n\t\treturn true;\r\n\t},\r\n\twarnhelp: [\r\n\t\t`/warn OR /k [username], [reason] - Warns a user showing them the site rules and [reason] in an overlay.`,\r\n\t\t`/warn OR /k [username], [reason] spoiler: [private reason] - Warns a user, marking [private reason] only in the modlog.`,\r\n\t\t`Requires: % @ # &`,\r\n\t],\r\n\r\n\tredirect: 'redir',\r\n\tredir(target, room, user, connection) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help redirect');\r\n\t\tif (room.settings.isPrivate || room.settings.isPersonal) {\r\n\t\t\treturn this.errorReply(\"Users cannot be redirected from private or personal rooms.\");\r\n\t\t}\r\n\t\tconst {targetUser, targetUsername, rest: targetRoomid} = this.splitUser(target);\r\n\t\tconst targetRoom = Rooms.search(targetRoomid);\r\n\t\tif (!targetRoom || targetRoom.settings.modjoin || targetRoom.settings.staffRoom) {\r\n\t\t\treturn this.errorReply(`The room \"${targetRoomid}\" does not exist.`);\r\n\t\t}\r\n\t\tthis.checkCan('warn', targetUser, room);\r\n\t\tthis.checkCan('warn', targetUser, targetRoom);\r\n\r\n\t\tif (!user.can('rangeban', targetUser)) {\r\n\t\t\tthis.errorReply(`Redirects have been deprecated. Instead of /redirect, use <> or /invite to guide users to the correct room, and punish if users don't cooperate.`);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!targetUser?.connected) {\r\n\t\t\treturn this.errorReply(`User ${targetUsername} not found.`);\r\n\t\t}\r\n\t\tif (targetRoom.roomid === \"global\") return this.errorReply(`Users cannot be redirected to the global room.`);\r\n\t\tif (targetRoom.settings.isPrivate || targetRoom.settings.isPersonal) {\r\n\t\t\treturn this.errorReply(`The room \"${targetRoom.title}\" is not public.`);\r\n\t\t}\r\n\t\tif (targetUser.inRooms.has(targetRoom.roomid)) {\r\n\t\t\treturn this.errorReply(`User ${targetUser.name} is already in the room ${targetRoom.title}!`);\r\n\t\t}\r\n\t\tif (!targetUser.inRooms.has(room.roomid)) {\r\n\t\t\treturn this.errorReply(`User ${targetUsername} is not in the room ${room.roomid}.`);\r\n\t\t}\r\n\t\ttargetUser.leaveRoom(room.roomid);\r\n\t\ttargetUser.popup(`You are in the wrong room; please go to <<${targetRoom.roomid}>> instead`);\r\n\t\tthis.addModAction(`${targetUser.name} was redirected to room ${targetRoom.title} by ${user.name}.`);\r\n\t\tthis.modlog('REDIRECT', targetUser, `to ${targetRoom.title}`, {noip: 1, noalts: 1});\r\n\t\ttargetUser.leaveRoom(room);\r\n\t},\r\n\tredirhelp: [\r\n\t\t`/redirect OR /redir [username], [roomname] - [DEPRECATED]`,\r\n\t\t`Attempts to redirect the [username] to the [roomname]. Requires: &`,\r\n\t],\r\n\r\n\tm: 'mute',\r\n\tmute(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help mute');\r\n\t\tthis.checkChat();\r\n\r\n\t\tconst {targetUser, inputUsername, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tif (!targetUser) return this.errorReply(`User '${targetUsername}' not found.`);\r\n\t\tif (reason.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tconst {publicReason, privateReason} = this.parseSpoiler(reason);\r\n\r\n\t\tconst muteDuration = ((cmd === 'hm' || cmd === 'hourmute') ? HOURMUTE_LENGTH : MUTE_LENGTH);\r\n\t\tthis.checkCan('mute', targetUser, room);\r\n\t\tif (targetUser.can('makeroom')) return this.errorReply(\"You are not allowed to mute upper staff members.\");\r\n\t\tconst canBeMutedFurther = ((room.getMuteTime(targetUser) || 0) <= (muteDuration * 5 / 6));\r\n\t\tif (targetUser.locked ||\r\n\t\t\t(room.isMuted(targetUser) && !canBeMutedFurther) ||\r\n\t\t\tPunishments.isRoomBanned(targetUser, room.roomid)) {\r\n\t\t\tconst alreadyPunishment = targetUser.locked ? \"locked\" : room.isMuted(targetUser) ? \"muted\" : \"room banned\";\r\n\t\t\tconst problem = ` but was already ${alreadyPunishment}`;\r\n\t\t\tif (!reason) {\r\n\t\t\t\treturn this.privateModAction(`${targetUser.name} would be muted by ${user.name} ${problem}.`);\r\n\t\t\t}\r\n\t\t\treturn this.addModAction(`${targetUser.name} would be muted by ${user.name} ${problem}. (${publicReason})`);\r\n\t\t}\r\n\r\n\t\tif (targetUser.id in room.users) {\r\n\t\t\ttargetUser.popup(`|modal|${user.name} has muted you in ${room.roomid} for ${Chat.toDurationString(muteDuration)}. ${publicReason}`);\r\n\t\t}\r\n\t\tthis.addModAction(`${targetUser.name} was muted by ${user.name} for ${Chat.toDurationString(muteDuration)}.${(publicReason ? ` (${publicReason})` : ``)}`);\r\n\t\tthis.modlog(`${cmd.includes('h') ? 'HOUR' : ''}MUTE`, targetUser, privateReason);\r\n\t\tif (targetUser.autoconfirmed && targetUser.autoconfirmed !== targetUser.id) {\r\n\t\t\tconst displayMessage = `${targetUser.name}'s ac account: ${targetUser.autoconfirmed}`;\r\n\t\t\tthis.privateModAction(displayMessage);\r\n\t\t}\r\n\t\tconst userid = targetUser.getLastId();\r\n\t\tthis.add(`|hidelines|unlink|${userid}`);\r\n\t\tif (userid !== toID(inputUsername)) this.add(`|hidelines|unlink|${toID(inputUsername)}`);\r\n\r\n\t\troom.mute(targetUser, muteDuration);\r\n\t},\r\n\tmutehelp: [`/mute OR /m [username], [reason] - Mutes a user with reason for 7 minutes. Requires: % @ # &`],\r\n\r\n\thm: 'hourmute',\r\n\thourmute(target) {\r\n\t\tif (!target) return this.parse('/help hourmute');\r\n\t\tthis.run('mute');\r\n\t},\r\n\thourmutehelp: [`/hourmute OR /hm [username], [reason] - Mutes a user with reason for an hour. Requires: % @ # &`],\r\n\r\n\tum: 'unmute',\r\n\tunmute(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help unmute');\r\n\t\tconst {targetUser, targetUsername, rest} = this.splitUser(target);\r\n\t\tif (rest) return this.errorReply(`This command does not support specifying a reason.`);\r\n\t\tthis.checkChat();\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\tconst successfullyUnmuted = room.unmute(\r\n\t\t\ttargetUser?.id || toID(targetUsername), `Your mute in '${room.title}' has been lifted.`\r\n\t\t);\r\n\r\n\t\tif (successfullyUnmuted) {\r\n\t\t\tthis.addModAction(`${(targetUser ? targetUser.name : successfullyUnmuted)} was unmuted by ${user.name}.`);\r\n\t\t\tthis.modlog('UNMUTE', (targetUser || successfullyUnmuted), null, {noip: 1, noalts: 1});\r\n\t\t} else {\r\n\t\t\tthis.errorReply(`${(targetUser ? targetUser.name : targetUsername)} is not muted.`);\r\n\t\t}\r\n\t},\r\n\tunmutehelp: [`/unmute [username] - Removes mute from user. Requires: % @ # &`],\r\n\r\n\trb: 'ban',\r\n\tweekban: 'ban',\r\n\twb: 'ban',\r\n\twrb: 'ban',\r\n\tforceroomban: 'ban',\r\n\tforceweekban: 'ban',\r\n\tweekroomban: 'ban',\r\n\tforcerb: 'ban',\r\n\troomban: 'ban',\r\n\tb: 'ban',\r\n\tban(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help ban');\r\n\t\tthis.checkChat();\r\n\t\tconst week = ['wrb', 'wb'].includes(cmd) || cmd.includes('week');\r\n\r\n\t\tconst {targetUser, inputUsername, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tconst {publicReason, privateReason} = this.parseSpoiler(reason);\r\n\t\tif (!targetUser) return this.errorReply(`User '${targetUsername}' not found.`);\r\n\t\tif (reason.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tthis.checkCan('ban', targetUser, room);\r\n\t\tif (targetUser.can('makeroom')) return this.errorReply(\"You are not allowed to ban upper staff members.\");\r\n\t\tif (Punishments.hasRoomPunishType(room, toID(targetUsername), 'BLACKLIST')) {\r\n\t\t\treturn this.errorReply(`This user is already blacklisted from ${room.roomid}.`);\r\n\t\t}\r\n\t\tconst name = targetUser.getLastName();\r\n\t\tconst userid = targetUser.getLastId();\r\n\t\tconst force = cmd.startsWith('force');\r\n\t\tif (targetUser.trusted) {\r\n\t\t\tif (!force) {\r\n\t\t\t\treturn this.sendReply(\r\n\t\t\t\t\t`${name} is a trusted user. If you are sure you would like to ban them, use /force${week ? 'week' : 'room'}ban.`\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t} else if (force) {\r\n\t\t\treturn this.errorReply(`Use /${week ? 'week' : 'room'}ban; ${name} is not a trusted user.`);\r\n\t\t}\r\n\t\tif (!reason && !week && Punishments.isRoomBanned(targetUser, room.roomid)) {\r\n\t\t\tconst problem = \" but was already banned\";\r\n\t\t\treturn this.privateModAction(`${name} would be banned by ${user.name} ${problem}.`);\r\n\t\t}\r\n\r\n\t\tif (targetUser.trusted && room.settings.isPrivate !== true && !room.settings.isPersonal) {\r\n\t\t\tMonitor.log(`[CrisisMonitor] Trusted user ${targetUser.name} ${(targetUser.trusted !== targetUser.id ? ` (${targetUser.trusted})` : ``)} was roombanned from ${room.roomid} by ${user.name}, and should probably be demoted.`);\r\n\t\t}\r\n\r\n\t\tif (targetUser.id in room.users || user.can('lock')) {\r\n\t\t\ttargetUser.popup(\r\n\t\t\t\t`|modal||html|

${Utils.escapeHTML(user.name)} has banned you from the room ${room.roomid} ` +\r\n\t\t\t\t`${(room.subRooms ? ` and its subrooms` : ``)}${week ? ' for a week' : ''}.` +\r\n\t\t\t\t`

${(publicReason ? `

Reason: ${Utils.escapeHTML(publicReason)}

` : ``)}` +\r\n\t\t\t\t`

To appeal the ban, PM the staff member that banned you${room.persist ? ` or a room owner. ` +\r\n\t\t\t\t`

` : `.

`}`\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthis.addModAction(`${name} was banned ${week ? ' for a week' : ''} from ${room.title} by ${user.name}.${publicReason ? ` (${publicReason})` : ``}`);\r\n\r\n\t\tconst time = week ? Date.now() + 7 * 24 * 60 * 60 * 1000 : null;\r\n\t\tconst affected = Punishments.roomBan(room, targetUser, time, null, privateReason);\r\n\r\n\t\tif (!room.settings.isPrivate && room.persist) {\r\n\t\t\tconst acAccount = (targetUser.autoconfirmed !== userid && targetUser.autoconfirmed);\r\n\t\t\tlet displayMessage = '';\r\n\t\t\tif (affected.length > 1) {\r\n\t\t\t\tdisplayMessage = `${name}'s ${(acAccount ? ` ac account: ${acAccount}, ` : ``)} banned alts: ${affected.slice(1).map(curUser => curUser.getLastName()).join(\", \")}`;\r\n\t\t\t\tthis.privateModAction(displayMessage);\r\n\t\t\t} else if (acAccount) {\r\n\t\t\t\tdisplayMessage = `${name}'s ac account: ${acAccount}`;\r\n\t\t\t\tthis.privateModAction(displayMessage);\r\n\t\t\t}\r\n\t\t}\r\n\t\troom.hideText([\r\n\t\t\t...affected.map(u => u.id),\r\n\t\t\ttoID(inputUsername),\r\n\t\t]);\r\n\r\n\t\tif (room.settings.isPrivate !== true && room.persist) {\r\n\t\t\tthis.globalModlog(`${week ? 'WEEK' : ''}ROOMBAN`, targetUser, privateReason);\r\n\t\t} else {\r\n\t\t\tthis.modlog(`${week ? 'WEEK' : ''}ROOMBAN`, targetUser, privateReason);\r\n\t\t}\r\n\t\treturn true;\r\n\t},\r\n\tbanhelp: [\r\n\t\t`/ban [username], [reason] - Bans the user from the room you are in. Requires: @ # &`,\r\n\t\t`/weekban [username], [reason] - Bans the user from the room you are in for a week. Requires: @ # &`,\r\n\t],\r\n\r\n\tunroomban: 'unban',\r\n\troomunban: 'unban',\r\n\tunban(target, room, user, connection) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help unban');\r\n\t\tthis.checkCan('ban', null, room);\r\n\r\n\t\tconst name = Punishments.roomUnban(room, target);\r\n\r\n\t\tif (name) {\r\n\t\t\tthis.addModAction(`${name} was unbanned from ${room.title} by ${user.name}.`);\r\n\t\t\tif (room.settings.isPrivate !== true && room.persist) {\r\n\t\t\t\tthis.globalModlog(\"UNROOMBAN\", name);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthis.errorReply(`User '${target}' is not banned from this room.`);\r\n\t\t}\r\n\t},\r\n\tunbanhelp: [`/unban [username] - Unbans the user from the room you are in. Requires: @ # &`],\r\n\r\n\tforcelock: 'lock',\r\n\tforceweeklock: 'lock',\r\n\tforcemonthlock: 'lock',\r\n\tl: 'lock',\r\n\tipmute: 'lock',\r\n\twl: 'lock',\r\n\tweeklock: 'lock',\r\n\tmonthlock: 'lock',\r\n\tasync lock(target, room, user, connection, cmd) {\r\n\t\tconst week = cmd === 'wl' || cmd.includes('week');\r\n\t\tconst month = cmd.includes('month');\r\n\t\tconst force = cmd.includes('force');\r\n\r\n\t\tif (!target) {\r\n\t\t\tif (week) return this.parse('/help weeklock');\r\n\t\t\treturn this.parse('/help lock');\r\n\t\t}\r\n\r\n\t\tconst {targetUser, inputUsername, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tlet userid: ID = toID(targetUsername);\r\n\r\n\t\tif (!targetUser && !Punishments.search(userid).length && !force) {\r\n\t\t\treturn this.errorReply(\r\n\t\t\t\t`User '${targetUsername}' not found. Use \\`\\`/force${month ? 'month' : (week ? 'week' : '')}lock\\`\\` if you need to to lock them anyway.`\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (reason.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tthis.checkCan('lock', userid);\r\n\t\tif (month) this.checkCan('rangeban');\r\n\r\n\t\tlet name;\r\n\r\n\t\tif (targetUser) {\r\n\t\t\tname = targetUser.getLastName();\r\n\t\t\tuserid = targetUser.getLastId();\r\n\r\n\t\t\tif (targetUser.locked && !targetUser.locked.startsWith('#') && !week && !month) {\r\n\t\t\t\treturn this.privateModAction(`${name} would be locked by ${user.name} but was already locked.`);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tname = targetUsername;\r\n\t\t\tuserid = toID(targetUsername);\r\n\t\t}\r\n\r\n\t\tif (Users.isTrusted(userid)) {\r\n\t\t\tif (force) {\r\n\t\t\t\tconst from = runCrisisDemote(userid);\r\n\t\t\t\tMonitor.log(`[CrisisMonitor] ${name} was locked by ${user.name} and demoted from ${from.join(\", \")}.`);\r\n\t\t\t\tthis.globalModlog(\"CRISISDEMOTE\", targetUser, ` from ${from.join(\", \")}`);\r\n\t\t\t} else {\r\n\t\t\t\treturn this.sendReply(`${name} is a trusted user. If you are sure you would like to lock them use /force${month ? 'month' : (week ? 'week' : '')}lock.`);\r\n\t\t\t}\r\n\t\t} else if (force && targetUser) {\r\n\t\t\treturn this.errorReply(`Use /lock; ${name} is not a trusted user and is online.`);\r\n\t\t}\r\n\r\n\t\tconst {privateReason, publicReason} = this.parseSpoiler(reason);\r\n\r\n\r\n\t\t// Use default time for locks.\r\n\t\tconst duration = week ? Date.now() + 7 * 24 * 60 * 60 * 1000 : (month ? Date.now() + 30 * 24 * 60 * 60 * 1000 : null);\r\n\t\tlet affected = [];\r\n\r\n\t\tif (targetUser) {\r\n\t\t\tconst ignoreAlts = Punishments.isSharedIp(targetUser.latestIp);\r\n\t\t\taffected = await Punishments.lock(targetUser, duration, null, ignoreAlts, publicReason);\r\n\t\t} else {\r\n\t\t\taffected = await Punishments.lock(userid, duration, null, false, publicReason);\r\n\t\t}\r\n\r\n\t\tthis.globalModlog(\r\n\t\t\t(force ? `FORCE` : ``) + (week ? \"WEEKLOCK\" : (month ? \"MONTHLOCK\" : \"LOCK\")), targetUser || userid, privateReason\r\n\t\t);\r\n\r\n\t\tconst durationMsg = week ? ' for a week' : (month ? ' for a month' : '');\r\n\t\tthis.addGlobalModAction(`${name} was locked from talking${durationMsg} by ${user.name}.` + (publicReason ? ` (${publicReason})` : \"\"));\r\n\r\n\t\tif (room && !room.settings.isHelp) {\r\n\t\t\troom.hideText([\r\n\t\t\t\t...affected.map(u => u.id),\r\n\t\t\t\ttoID(inputUsername),\r\n\t\t\t]);\r\n\t\t}\r\n\r\n\t\tconst acAccount = (targetUser && targetUser.autoconfirmed !== userid && targetUser.autoconfirmed);\r\n\t\tlet displayMessage = '';\r\n\t\tif (affected.length > 1) {\r\n\t\t\tdisplayMessage = `${name}'s ${(acAccount ? ` ac account: ${acAccount}, ` : \"\")} locked alts: ${affected.slice(1).map((curUser: User) => curUser.getLastName()).join(\", \")}`;\r\n\t\t\tthis.privateModAction(displayMessage);\r\n\t\t} else if (acAccount) {\r\n\t\t\tdisplayMessage = `${name}'s ac account: ${acAccount}`;\r\n\t\t\tthis.privateModAction(displayMessage);\r\n\t\t}\r\n\r\n\t\tif (targetUser) {\r\n\t\t\tlet message = `|popup||html|${user.name} has locked you from talking in chats, battles, and PMing regular users${durationMsg}`;\r\n\t\t\tif (publicReason) message += `\\n\\nReason: ${publicReason}`;\r\n\r\n\t\t\tlet appeal = '';\r\n\t\t\tif (Chat.pages.help) {\r\n\t\t\t\tappeal += ``;\r\n\t\t\t} else if (Config.appealurl) {\r\n\t\t\t\tappeal += `appeal: ${Config.appealurl}`;\r\n\t\t\t}\r\n\r\n\t\t\tif (appeal) message += `\\n\\nIf you feel that your lock was unjustified, you can ${appeal}.`;\r\n\t\t\tmessage += `\\n\\nYour lock will expire in a few days.`;\r\n\t\t\ttargetUser.send(message);\r\n\r\n\t\t\tconst roomauth = Rooms.global.destroyPersonalRooms(userid);\r\n\t\t\tif (roomauth.length) {\r\n\t\t\t\tMonitor.log(`[CrisisMonitor] Locked user ${name} has public roomauth (${roomauth.join(', ')}), and should probably be demoted.`);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\t// Automatically upload replays as evidence/reference to the punishment\r\n\t\tif (room?.battle) this.parse('/savereplay forpunishment');\r\n\t\treturn true;\r\n\t},\r\n\tlockhelp: [\r\n\t\t`/lock OR /l [username], [reason] - Locks the user from talking in all chats. Requires: % @ &`,\r\n\t\t`/weeklock OR /wl [username], [reason] - Same as /lock, but locks users for a week.`,\r\n\t\t`/lock OR /l [username], [reason] spoiler: [private reason] - Marks [private reason] in modlog only.`,\r\n\t],\r\n\r\n\tunlock(target, room, user) {\r\n\t\tif (!target) return this.parse('/help unlock');\r\n\t\tthis.checkCan('lock');\r\n\r\n\t\tconst targetUser = Users.get(target);\r\n\t\tif (targetUser?.namelocked) {\r\n\t\t\treturn this.errorReply(`User ${targetUser.name} is namelocked, not locked. Use /unnamelock to unnamelock them.`);\r\n\t\t}\r\n\t\tlet reason = '';\r\n\t\tif (targetUser?.locked && targetUser.locked.startsWith('#')) {\r\n\t\t\treason = ` (${targetUser.locked})`;\r\n\t\t}\r\n\r\n\t\tconst unlocked = Punishments.unlock(target);\r\n\r\n\t\tif (unlocked) {\r\n\t\t\tthis.addGlobalModAction(`${unlocked.join(\", \")} ${((unlocked.length > 1) ? \"were\" : \"was\")} unlocked by ${user.name}.${reason}`);\r\n\t\t\tif (!reason) this.globalModlog(\"UNLOCK\", toID(target));\r\n\t\t\tif (targetUser) targetUser.popup(`${user.name} has unlocked you.`);\r\n\t\t} else {\r\n\t\t\tthis.errorReply(`User '${target}' is not locked.`);\r\n\t\t}\r\n\t},\r\n\tunlockname(target, room, user) {\r\n\t\tif (!target) return this.parse('/help unlock');\r\n\t\tthis.checkCan('lock');\r\n\r\n\t\tconst userid = toID(target);\r\n\t\tif (userid.startsWith('guest')) {\r\n\t\t\treturn this.errorReply(`You cannot unlock the guest userid - provide their original username instead.`);\r\n\t\t}\r\n\t\tconst punishment = Punishments.userids.getByType(userid, 'LOCK') || Punishments.userids.getByType(userid, 'NAMELOCK');\r\n\t\tif (!punishment) return this.errorReply(\"This name isn't locked.\");\r\n\t\tif (punishment.id === userid || Users.get(userid)?.previousIDs.includes(punishment.id as ID)) {\r\n\t\t\treturn this.errorReply(`\"${userid}\" was specifically locked by a staff member (check the global modlog). Use /unlock if you really want to unlock this name.`);\r\n\t\t}\r\n\t\tPunishments.userids.delete(userid);\r\n\t\tPunishments.savePunishments();\r\n\r\n\t\tfor (const curUser of Users.findUsers([userid], [])) {\r\n\t\t\tconst locked = Punishments.hasPunishType(curUser.id, ['LOCK', 'NAMELOCK'], curUser.latestIp);\r\n\t\t\tif (curUser.locked && !curUser.locked.startsWith('#') && !locked) {\r\n\t\t\t\tcurUser.locked = null;\r\n\t\t\t\tcurUser.namelocked = null;\r\n\t\t\t\tcurUser.destroyPunishmentTimer();\r\n\t\t\t\tcurUser.updateIdentity();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.addGlobalModAction(`The name '${target}' was unlocked by ${user.name}.`);\r\n\t\tthis.globalModlog(\"UNLOCKNAME\", userid);\r\n\t},\r\n\tunrangelock: 'unlockip',\r\n\trangeunlock: 'unlockip',\r\n\tunlockip(target, room, user) {\r\n\t\ttarget = target.trim();\r\n\t\tif (!target) return this.parse('/help unlock');\r\n\t\tthis.checkCan('globalban');\r\n\t\tconst range = target.endsWith('*');\r\n\t\tif (range) this.checkCan('rangeban');\r\n\r\n\t\tif (!(range ? IPTools.ipRangeRegex : IPTools.ipRegex).test(target)) {\r\n\t\t\treturn this.errorReply(\"Please enter a valid IP address.\");\r\n\t\t}\r\n\r\n\t\tconst punishment = Punishments.ips.get(target);\r\n\t\tif (!punishment) return this.errorReply(`${target} is not a locked/banned IP or IP range.`);\r\n\r\n\t\tPunishments.ips.delete(target);\r\n\t\tPunishments.savePunishments();\r\n\r\n\t\tfor (const curUser of Users.findUsers([], [target])) {\r\n\t\t\tif (\r\n\t\t\t\t(range ? curUser.locked === '#rangelock' : !curUser.locked?.startsWith('#')) &&\r\n\t\t\t\t!Punishments.getPunishType(curUser.id)\r\n\t\t\t) {\r\n\t\t\t\tcurUser.locked = null;\r\n\t\t\t\tif (curUser.namelocked) {\r\n\t\t\t\t\tcurUser.namelocked = null;\r\n\t\t\t\t\tcurUser.resetName();\r\n\t\t\t\t}\r\n\t\t\t\tcurUser.destroyPunishmentTimer();\r\n\t\t\t\tcurUser.updateIdentity();\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.privateGlobalModAction(`${user.name} unlocked the ${range ? \"IP range\" : \"IP\"}: ${target}`);\r\n\t\tthis.globalModlog(`UNLOCK${range ? 'RANGE' : 'IP'}`, null, null, target);\r\n\t},\r\n\tunlockiphelp: [`/unlockip [ip] - Unlocks a punished ip while leaving the original punishment intact. Requires: @ &`],\r\n\tunlocknamehelp: [`/unlockname [name] - Unlocks a punished alt, leaving the original lock intact. Requires: % @ &`],\r\n\tunlockhelp: [\r\n\t\t`/unlock [username] - Unlocks the user. Requires: % @ &`,\r\n\t\t`/unlockname [username] - Unlocks a punished alt while leaving the original punishment intact. Requires: % @ &`,\r\n\t\t`/unlockip [ip] - Unlocks a punished ip while leaving the original punishment intact. Requires: @ &`,\r\n\t],\r\n\r\n\tforceglobalban: 'globalban',\r\n\tgban: 'globalban',\r\n\tasync globalban(target, room, user, connection, cmd) {\r\n\t\tif (!target) return this.parse('/help globalban');\r\n\t\tconst force = cmd.includes('force');\r\n\r\n\t\tconst {targetUser, inputUsername, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tlet userid: ID = toID(targetUsername);\r\n\r\n\t\tif (!targetUser && !force) {\r\n\t\t\treturn this.errorReply(`User '${targetUsername}' not found. Use /forceglobalban to ban them anyway.`);\r\n\t\t}\r\n\t\tif (reason.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tif (!reason && REQUIRE_REASONS) {\r\n\t\t\treturn this.errorReply(\"Global bans require a reason.\");\r\n\t\t}\r\n\t\tthis.checkCan('globalban', targetUser);\r\n\t\tlet name;\r\n\r\n\t\tif (targetUser) {\r\n\t\t\tname = targetUser.getLastName();\r\n\t\t\tuserid = targetUser.getLastId();\r\n\t\t} else {\r\n\t\t\tname = targetUsername;\r\n\t\t}\r\n\r\n\t\tif (Users.isTrusted(userid)) {\r\n\t\t\tif (force) {\r\n\t\t\t\tconst from = runCrisisDemote(userid);\r\n\t\t\t\tMonitor.log(`[CrisisMonitor] ${name} was globally banned by ${user.name} and demoted from ${from?.join(\", \")}.`);\r\n\t\t\t\tthis.globalModlog(\"CRISISDEMOTE\", targetUser, ` from ${from?.join(\", \")}`);\r\n\t\t\t} else {\r\n\t\t\t\treturn this.sendReply(`${name} is a trusted user. If you are sure you would like to ban them use /forceglobalban.`);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst roomauth = Rooms.global.destroyPersonalRooms(userid);\r\n\t\tif (roomauth.length) {\r\n\t\t\tMonitor.log(`[CrisisMonitor] Globally banned user ${name} has public roomauth (${roomauth.join(', ')}), and should probably be demoted.`);\r\n\t\t}\r\n\t\tconst {privateReason, publicReason} = this.parseSpoiler(reason);\r\n\t\ttargetUser?.popup(\r\n\t\t\t`|modal|${user.name} has globally banned you.${(publicReason ? `\\n\\nReason: ${publicReason}` : ``)} ` +\r\n\t\t\t`${(Config.appealurl ? `\\n\\nIf you feel that your ban was unjustified, you can appeal:\\n${Config.appealurl}` : ``)}` +\r\n\t\t\t`\\n\\nYour ban will expire in a few days.`\r\n\t\t);\r\n\r\n\t\tthis.addGlobalModAction(`${name} was globally banned by ${user.name}.${(publicReason ? ` (${publicReason})` : ``)}`);\r\n\r\n\t\tconst affected = await Punishments.ban(userid, null, null, false, publicReason);\r\n\t\tconst acAccount = (targetUser && targetUser.autoconfirmed !== userid && targetUser.autoconfirmed);\r\n\t\tlet displayMessage = '';\r\n\t\tif (affected.length > 1) {\r\n\t\t\tlet guests = affected.length - 1;\r\n\t\t\tconst affectedAlts = affected.slice(1)\r\n\t\t\t\t.map(curUser => curUser.getLastName())\r\n\t\t\t\t.filter(alt => !alt.startsWith('[Guest '));\r\n\t\t\tguests -= affectedAlts.length;\r\n\t\t\tdisplayMessage = `${name}'s ${(acAccount ? `ac account: ${acAccount}, ` : ``)} banned alts: ${affectedAlts.join(\", \")} ${(guests ? ` [${guests} guests]` : ``)}`;\r\n\t\t\tthis.privateModAction(displayMessage);\r\n\t\t\tfor (const id of affectedAlts) {\r\n\t\t\t\tthis.add(`|hidelines|unlink|${toID(id)}`);\r\n\t\t\t}\r\n\t\t} else if (acAccount) {\r\n\t\t\tdisplayMessage = `${name}'s ac account: ${acAccount}`;\r\n\t\t\tthis.privateModAction(displayMessage);\r\n\t\t}\r\n\r\n\t\troom?.hideText([\r\n\t\t\t...affected.map(u => u.id),\r\n\t\t\ttoID(inputUsername),\r\n\t\t]);\r\n\r\n\t\tthis.globalModlog(`${force ? `FORCE` : ''}BAN`, targetUser, privateReason);\r\n\t\treturn true;\r\n\t},\r\n\tglobalbanhelp: [\r\n\t\t`/globalban OR /gban [username], [reason] - Kick user from all rooms and ban user's IP address with reason. Requires: @ &`,\r\n\t\t`/globalban OR /gban [username], [reason] spoiler: [private reason] - Marks [private reason] in modlog only.`,\r\n\t],\r\n\r\n\tglobalunban: 'unglobalban',\r\n\tunglobalban(target, room, user) {\r\n\t\tif (!target) return this.parse(`/help unglobalban`);\r\n\t\tthis.checkCan('globalban');\r\n\r\n\t\tconst name = Punishments.unban(target);\r\n\r\n\t\tif (!name) {\r\n\t\t\treturn this.errorReply(`User '${target}' is not globally banned.`);\r\n\t\t}\r\n\r\n\t\tthis.addGlobalModAction(`${name} was globally unbanned by ${user.name}.`);\r\n\t\tthis.globalModlog(\"UNBAN\", target);\r\n\t},\r\n\tunglobalbanhelp: [`/unglobalban [username] - Unban a user. Requires: @ &`],\r\n\r\n\tderoomvoiceall(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('editroom', null, room);\r\n\t\tif (!room.auth.size) return this.errorReply(\"Room does not have roomauth.\");\r\n\t\tif (!target) {\r\n\t\t\tuser.lastCommand = '/deroomvoiceall';\r\n\t\t\tthis.errorReply(\"THIS WILL DEROOMVOICE ALL ROOMVOICED USERS.\");\r\n\t\t\tthis.errorReply(\"To confirm, use: /deroomvoiceall confirm\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (user.lastCommand !== '/deroomvoiceall' || target !== 'confirm') {\r\n\t\t\treturn this.parse('/help deroomvoiceall');\r\n\t\t}\r\n\t\tuser.lastCommand = '';\r\n\t\tlet count = 0;\r\n\t\tfor (const [userid, symbol] of room.auth) {\r\n\t\t\tif (symbol === '+') {\r\n\t\t\t\troom.auth.delete(userid);\r\n\t\t\t\tif (userid in room.users) room.users[userid].updateIdentity(room.roomid);\r\n\t\t\t\tcount++;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!count) {\r\n\t\t\treturn this.sendReply(\"(This room has zero roomvoices)\");\r\n\t\t}\r\n\t\troom.saveSettings();\r\n\t\tthis.addModAction(`All ${count} roomvoices have been cleared by ${user.name}.`);\r\n\t\tthis.modlog('DEROOMVOICEALL');\r\n\t},\r\n\tderoomvoiceallhelp: [`/deroomvoiceall - Devoice all roomvoiced users. Requires: # &`],\r\n\r\n\t// this is a separate command for two reasons\r\n\t// a - yearticketban is preferred over /ht yearban\r\n\t// b - it would be messy to switch\r\n\t// from both Punishments.punishRange and #punish in /ht ban\r\n\t// since this takes ips / userids\r\n\tasync yearticketban(target, room, user) {\r\n\t\tthis.checkCan('rangeban');\r\n\t\ttarget = target.trim();\r\n\t\tlet reason = '';\r\n\t\t[target, reason] = this.splitOne(target);\r\n\t\tlet isIP = false;\r\n\t\tlet descriptor = '';\r\n\t\tif (IPTools.ipRangeRegex.test(target)) {\r\n\t\t\tisIP = true;\r\n\t\t\tif (IPTools.ipRegex.test(target)) {\r\n\t\t\t\tdescriptor = 'the IP ';\r\n\t\t\t} else {\r\n\t\t\t\tdescriptor = 'the IP range ';\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\ttarget = toID(target);\r\n\t\t}\r\n\t\tif (!target) return this.parse(`/help yearticketban`);\r\n\t\tconst expireTime = Date.now() + 365 * 24 * 60 * 60 * 1000;\r\n\t\tif (isIP) {\r\n\t\t\tPunishments.punishRange(target, reason, expireTime, 'TICKETBAN');\r\n\t\t} else {\r\n\t\t\tawait Punishments.punish(target as ID, {\r\n\t\t\t\ttype: 'TICKETBAN',\r\n\t\t\t\tid: target as ID,\r\n\t\t\t\texpireTime,\r\n\t\t\t\treason,\r\n\t\t\t\trest: [],\r\n\t\t\t}, true);\r\n\t\t}\r\n\t\tthis.addGlobalModAction(\r\n\t\t\t`${user.name} banned ${descriptor}${target} from opening tickets for a year` +\r\n\t\t\t`${reason ? ` (${reason})` : \"\"}`\r\n\t\t);\r\n\t\tthis.globalModlog(\r\n\t\t\t'YEARTICKETBAN',\r\n\t\t\tisIP ? null : target,\r\n\t\t\treason,\r\n\t\t\tisIP ? target : undefined\r\n\t\t);\r\n\t},\r\n\tyearticketbanhelp: [\r\n\t\t`/yearticketban [IP/userid] - Ban an IP or a userid from opening tickets for a year. `,\r\n\t\t`Accepts wildcards to ban ranges. Requires: &`,\r\n\t],\r\n\r\n\trangeban: 'banip',\r\n\tyearbanip: 'banip',\r\n\tbanip(target, room, user, connection, cmd) {\r\n\t\tconst [ip, reason] = this.splitOne(target);\r\n\t\tif (!ip || !/^[0-9.]+(?:\\.\\*)?$/.test(ip)) return this.parse('/help banip');\r\n\t\tif (!reason) return this.errorReply(\"/banip requires a ban reason\");\r\n\r\n\t\tthis.checkCan('rangeban');\r\n\t\tconst ipDesc = `IP ${(ip.endsWith('*') ? `range ` : ``)}${ip}`;\r\n\r\n\t\tconst year = cmd.startsWith('year');\r\n\t\tconst time = year ? Date.now() + 365 * 24 * 60 * 60 * 1000 : null;\r\n\r\n\t\tconst curPunishment = Punishments.ipSearch(ip, 'BAN');\r\n\t\tif (curPunishment?.type === 'BAN' && !time) {\r\n\t\t\treturn this.errorReply(`The ${ipDesc} is already temporarily banned.`);\r\n\t\t}\r\n\t\tPunishments.punishRange(ip, reason, time, 'BAN');\r\n\r\n\t\tconst duration = year ? 'year' : 'hour';\r\n\t\tif (!this.room || this.room.roomid !== 'staff') {\r\n\t\t\tthis.sendReply(`You ${duration}-banned the ${ipDesc}.`);\r\n\t\t}\r\n\t\tthis.room = Rooms.get('staff') || null;\r\n\t\tthis.addGlobalModAction(\r\n\t\t\t`${user.name} ${duration}-banned the ${ipDesc}: ${reason}`\r\n\t\t);\r\n\t\tthis.globalModlog(\r\n\t\t\t`${year ? \"YEAR\" : \"\"}RANGEBAN`,\r\n\t\t\tnull,\r\n\t\t\t`${ip.endsWith('*') ? ip : `[${ip}]`}: ${reason}`\r\n\t\t);\r\n\t},\r\n\tbaniphelp: [\r\n\t\t`/banip [ip] OR /yearbanip [ip] - Globally bans this IP or IP range for an hour. Accepts wildcards to ban ranges.`,\r\n\t\t`Existing users on the IP will not be banned. Requires: &`,\r\n\t],\r\n\r\n\tunrangeban: 'unbanip',\r\n\tunbanip(target, room, user) {\r\n\t\ttarget = target.trim();\r\n\t\tif (!target) {\r\n\t\t\treturn this.parse('/help unbanip');\r\n\t\t}\r\n\t\tthis.checkCan('rangeban');\r\n\t\tif (!Punishments.ips.has(target)) {\r\n\t\t\treturn this.errorReply(`${target} is not a locked/banned IP or IP range.`);\r\n\t\t}\r\n\t\tPunishments.ips.delete(target);\r\n\r\n\t\tthis.addGlobalModAction(`${user.name} unbanned the ${(target.endsWith('*') ? \"IP range\" : \"IP\")}: ${target}`);\r\n\t\tthis.modlog('UNRANGEBAN', null, target);\r\n\t},\r\n\tunbaniphelp: [`/unbanip [ip] - Unbans. Accepts wildcards to ban ranges. Requires: &`],\r\n\r\n\tforceyearlockname: 'yearlockname',\r\n\tyearlockid: 'yearlockname',\r\n\tforceyearlockid: 'yearlockname',\r\n\tyearlockuserid: 'yearlockname',\r\n\tforceyearlockuserid: 'yearlockname',\r\n\tyearlockname(target, room, user) {\r\n\t\tthis.checkCan('rangeban');\r\n\t\tconst [targetUsername, rest] = Utils.splitFirst(target, ',').map(k => k.trim());\r\n\t\tconst targetUser = Users.get(targetUsername);\r\n\t\tconst targetUserid = toID(targetUsername);\r\n\t\tif (!targetUserid || targetUserid.length > 18) {\r\n\t\t\treturn this.errorReply(`Invalid userid.`);\r\n\t\t}\r\n\t\tconst force = this.cmd.includes('force');\r\n\t\tif (targetUser?.registered && !force) {\r\n\t\t\treturn this.errorReply(`That user is registered. Either permalock them normally or use /forceyearlockname.`);\r\n\t\t}\r\n\t\tconst punishment = {\r\n\t\t\ttype: 'YEARLOCK',\r\n\t\t\tid: targetUserid,\r\n\t\t\texpireTime: Date.now() + 365 * 24 * 60 * 60 * 1000,\r\n\t\t\treason: rest || \"\",\r\n\t\t};\r\n\t\tPunishments.userids.add(targetUserid, punishment);\r\n\t\tPunishments.savePunishments();\r\n\t\tthis.addGlobalModAction(`${user.name} locked the userid '${targetUserid}' for a year${rest ? ` (${rest})` : ''}.`);\r\n\t\tthis.globalModlog(`${force ? `FORCE` : ''}YEARLOCKNAME`, targetUserid, rest);\r\n\t\tif (targetUser) {\r\n\t\t\tChat.punishmentfilter(targetUser, punishment);\r\n\t\t\ttargetUser.locked = targetUserid;\r\n\t\t}\r\n\t},\r\n\trangelock: 'lockip',\r\n\tyearlockip: 'lockip',\r\n\tyearnamelockip: 'lockip',\r\n\tlockip(target, room, user, connection, cmd) {\r\n\t\tconst [ip, reason] = this.splitOne(target);\r\n\t\tif (!ip || !/^[0-9.]+(?:\\.\\*)?$/.test(ip)) return this.parse('/help lockip');\r\n\t\tif (!reason) return this.errorReply(\"/lockip requires a lock reason\");\r\n\r\n\t\tthis.checkCan('rangeban');\r\n\t\tconst ipDesc = ip.endsWith('*') ? `IP range ${ip}` : `IP ${ip}`;\r\n\r\n\t\tconst year = cmd.startsWith('year');\r\n\t\tconst curPunishment = Punishments.byWeight(Punishments.ipSearch(ip) || [])[0];\r\n\t\tif (!year && curPunishment && (curPunishment.type === 'BAN' || curPunishment.type === 'LOCK')) {\r\n\t\t\tconst punishDesc = curPunishment.type === 'BAN' ? `temporarily banned` : `temporarily locked`;\r\n\t\t\treturn this.errorReply(`The ${ipDesc} is already ${punishDesc}.`);\r\n\t\t}\r\n\r\n\t\tconst time = year ? Date.now() + 365 * 24 * 60 * 60 * 1000 : null;\r\n\t\tconst type = cmd.includes('name') ? 'NAMELOCK' : 'LOCK';\r\n\t\tPunishments.punishRange(ip, reason, time, type);\r\n\r\n\t\tif (year) {\r\n\t\t\tthis.addGlobalModAction(`${user.name} year-${type.toLowerCase()}ed the ${ipDesc}: ${reason}`);\r\n\t\t} else {\r\n\t\t\tthis.addGlobalModAction(`${user.name} hour-${type.toLowerCase()}ed the ${ipDesc}: ${reason}`);\r\n\t\t}\r\n\t\tthis.globalModlog(\r\n\t\t\t`${year ? 'YEAR' : 'RANGE'}${type}`,\r\n\t\t\tnull,\r\n\t\t\t`${ip.endsWith('*') ? ip : `[${ip}]`}: ${reason}`,\r\n\t\t\tip.endsWith('*') ? `${ip.slice(0, -2)}` : ip\r\n\t\t);\r\n\t},\r\n\tlockiphelp: [\r\n\t\t`/lockip [ip] - Globally locks this IP or IP range for an hour. Accepts wildcards to ban ranges.`,\r\n\t\t`/yearlockip [ip] - Globally locks this IP or IP range for one year. Accepts wildcards to ban ranges.`,\r\n\t\t`/yearnamelockip [ip] - Namelocks this IP or IP range for one year. Accepts wildcards to ban ranges.`,\r\n\t\t`Existing users on the IP will not be banned. Requires: &`,\r\n\t],\r\n\r\n\t/*********************************************************\r\n\t * Moderating: Other\r\n\t *********************************************************/\r\n\r\n\tmn: 'modnote',\r\n\tmodnote(target, room, user, connection) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help modnote');\r\n\t\tthis.checkChat();\r\n\r\n\t\tif (target.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The note is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tthis.checkCan('receiveauthmessages', null, room);\r\n\t\ttarget = target.replace(/\\n/g, \"; \");\r\n\t\tlet targeted = /\\[([^\\]]+)\\]/.exec(target)?.[1] || null;\r\n\t\tif (!targeted) {\r\n\t\t\t// allow `name, note` and `name - note` syntax\r\n\t\t\ttargeted = target.split(/[,-]/)[0]?.trim() || \"\";\r\n\t\t\tif (!targeted || !(\r\n\t\t\t\tUsers.get(targeted) || Punishments.search(target).length || IPTools.ipRegex.test(targeted)\r\n\t\t\t) || toID(targeted) === toID(target)) {\r\n\t\t\t\ttargeted = null;\r\n\t\t\t}\r\n\t\t}\r\n\t\tlet targetUserid, targetIP;\r\n\r\n\t\tif (targeted) {\r\n\t\t\tif (IPTools.ipRegex.test(targeted)) {\r\n\t\t\t\ttargetIP = targeted;\r\n\t\t\t} else {\r\n\t\t\t\ttargetUserid = toID(targeted);\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (\r\n\t\t\t['staff', 'upperstaff'].includes(room.roomid) ||\r\n\t\t\t(Rooms.Modlog.getSharedID(room.roomid) && user.can('modlog'))\r\n\t\t) {\r\n\t\t\tthis.globalModlog('NOTE', targetUserid || null, target, targetIP);\r\n\t\t} else {\r\n\t\t\tthis.modlog('NOTE', targetUserid || null, target);\r\n\t\t}\r\n\r\n\t\tthis.privateModAction(`${user.name} notes: ${target}`);\r\n\t},\r\n\tmodnotehelp: [`/modnote [note] - Adds a moderator note that can be read through modlog. Requires: % @ # &`],\r\n\r\n\tglobalpromote: 'promote',\r\n\tpromote(target, room, user, connection, cmd) {\r\n\t\tif (!target) return this.parse('/help promote');\r\n\r\n\t\tconst {targetUser, targetUsername, rest: nextGroupName} = this.splitUser(target, {exactName: true});\r\n\t\tconst userid = toID(targetUsername);\r\n\t\tconst name = targetUser?.name || targetUsername;\r\n\r\n\t\tif (!userid) return this.parse('/help promote');\r\n\r\n\t\tconst currentGroup = targetUser?.tempGroup || Users.globalAuth.get(userid);\r\n\t\tlet nextGroup = nextGroupName as GroupSymbol;\r\n\t\tif (nextGroupName === 'deauth') nextGroup = Users.Auth.defaultSymbol();\r\n\t\tif (!nextGroup) {\r\n\t\t\treturn this.errorReply(\"Please specify a group such as /globalvoice or /globaldeauth\");\r\n\t\t}\r\n\t\tif (!Config.groups[nextGroup]) {\r\n\t\t\treturn this.errorReply(`Group '${nextGroup}' does not exist.`);\r\n\t\t}\r\n\t\tif (!cmd.startsWith('global')) {\r\n\t\t\tlet groupid = Config.groups[nextGroup].id;\r\n\t\t\tif (!groupid && nextGroup === Users.Auth.defaultSymbol()) groupid = 'deauth' as ID;\r\n\t\t\tif (Config.groups[nextGroup].globalonly) return this.errorReply(`Did you mean \"/global${groupid}\"?`);\r\n\t\t\tif (Config.groups[nextGroup].roomonly) return this.errorReply(`Did you mean \"/room${groupid}\"?`);\r\n\t\t\treturn this.errorReply(`Did you mean \"/room${groupid}\" or \"/global${groupid}\"?`);\r\n\t\t}\r\n\t\tif (Config.groups[nextGroup].roomonly || Config.groups[nextGroup].battleonly) {\r\n\t\t\treturn this.errorReply(`Group '${nextGroup}' does not exist as a global rank.`);\r\n\t\t}\r\n\r\n\t\tconst groupName = Config.groups[nextGroup].name || \"regular user\";\r\n\t\tif (currentGroup === nextGroup) {\r\n\t\t\treturn this.errorReply(`User '${name}' is already a ${groupName}`);\r\n\t\t}\r\n\t\tif (!Users.Auth.hasPermission(user, 'promote', currentGroup)) {\r\n\t\t\tthis.errorReply(`/${cmd} - Access denied for promoting from ${currentGroup}`);\r\n\t\t\tthis.errorReply(`You can only promote to/from: ${Users.Auth.listJurisdiction(user, 'promote')}`);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (!Users.Auth.hasPermission(user, 'promote', nextGroup)) {\r\n\t\t\tthis.errorReply(`/${cmd} - Access denied for promoting to ${groupName}`);\r\n\t\t\tthis.errorReply(`You can only promote to/from: ${Users.Auth.listJurisdiction(user, 'promote')}`);\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tif (!Users.isUsernameKnown(userid)) {\r\n\t\t\treturn this.errorReply(`/globalpromote - WARNING: '${name}' is offline and unrecognized. The username might be misspelled (either by you or the person who told you) or unregistered. Use /forcepromote if you're sure you want to risk it.`);\r\n\t\t}\r\n\t\tif (targetUser && !targetUser.registered) {\r\n\t\t\treturn this.errorReply(`User '${name}' is unregistered, and so can't be promoted.`);\r\n\t\t}\r\n\t\tif (nextGroup === Users.Auth.defaultSymbol()) {\r\n\t\t\tUsers.globalAuth.delete(targetUser ? targetUser.id : userid);\r\n\t\t} else {\r\n\t\t\tUsers.globalAuth.set(targetUser ? targetUser.id : userid, nextGroup);\r\n\t\t}\r\n\t\tif (Users.Auth.getGroup(nextGroup).rank < Users.Auth.getGroup(currentGroup).rank) {\r\n\t\t\tthis.privateGlobalModAction(`${name} was demoted to Global ${groupName} by ${user.name}.`);\r\n\t\t\tthis.globalModlog(`GLOBAL ${groupName.toUpperCase()}`, userid, `(demote)`);\r\n\t\t\tif (targetUser) targetUser.popup(`You were demoted to Global ${groupName} by ${user.name}.`);\r\n\t\t} else {\r\n\t\t\tthis.addGlobalModAction(`${name} was promoted to Global ${groupName} by ${user.name}.`);\r\n\t\t\tthis.globalModlog(`GLOBAL ${groupName.toUpperCase()}`, userid);\r\n\t\t\tif (targetUser) targetUser.popup(`You were promoted to Global ${groupName} by ${user.name}.`);\r\n\t\t}\r\n\r\n\t\tif (targetUser) {\r\n\t\t\ttargetUser.updateIdentity();\r\n\t\t\tRooms.global.checkAutojoin(targetUser);\r\n\t\t\tif (targetUser.trusted && !Users.isTrusted(targetUser.id)) {\r\n\t\t\t\ttargetUser.trusted = '';\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\tpromotehelp: [`/promote [username], [group] - Promotes the user to the specified group. Requires: &`],\r\n\r\n\tuntrustuser: 'trustuser',\r\n\tunconfirmuser: 'trustuser',\r\n\tconfirmuser: 'trustuser',\r\n\tforceconfirmuser: 'trustuser',\r\n\tforcetrustuser: 'trustuser',\r\n\ttrustuser(target, room, user, connection, cmd) {\r\n\t\tif (!target) return this.parse('/help trustuser');\r\n\t\tthis.checkCan('promote');\r\n\r\n\t\tconst force = cmd.includes('force');\r\n\t\tconst untrust = cmd.includes('un');\r\n\t\tconst {targetUser, targetUsername, rest} = this.splitUser(target, {exactName: true});\r\n\t\tif (rest) return this.errorReply(`This command does not support specifying a reason.`);\r\n\t\tconst userid = toID(targetUsername);\r\n\t\tconst name = targetUser?.name || targetUsername;\r\n\r\n\t\tconst currentGroup = Users.globalAuth.get(userid);\r\n\r\n\t\tif (untrust) {\r\n\t\t\tif (currentGroup !== Users.Auth.defaultSymbol()) {\r\n\t\t\t\treturn this.errorReply(`User '${name}' is trusted indirectly through global rank ${currentGroup}. Demote them from that rank to remove trusted status.`);\r\n\t\t\t}\r\n\t\t\tconst trustedSourceRooms = Rooms.global.chatRooms\r\n\t\t\t\t.filter(authRoom => authRoom.persist && authRoom.settings.isPrivate !== true && authRoom.auth.isStaff(userid))\r\n\t\t\t\t.map(authRoom => authRoom.auth.get(userid) + authRoom.roomid).join(' ');\r\n\t\t\tif (trustedSourceRooms.length && !Users.globalAuth.has(userid)) {\r\n\t\t\t\treturn this.errorReply(`User '${name}' is trusted indirectly through room ranks ${trustedSourceRooms}. Demote them from those ranks to remove trusted status.`);\r\n\t\t\t}\r\n\t\t\tif (!Users.globalAuth.has(userid)) return this.errorReply(`User '${name}' is not trusted.`);\r\n\r\n\t\t\tif (targetUser) {\r\n\t\t\t\ttargetUser.setGroup(Users.Auth.defaultSymbol());\r\n\t\t\t} else {\r\n\t\t\t\tUsers.globalAuth.delete(userid);\r\n\t\t\t}\r\n\r\n\t\t\tthis.privateGlobalModAction(`${name} was set to no longer be a trusted user by ${user.name}.`);\r\n\t\t\tthis.globalModlog('UNTRUSTUSER', userid);\r\n\t\t} else {\r\n\t\t\tif (!targetUser && !force) return this.errorReply(`User '${name}' is offline. Use /force${cmd} if you're sure.`);\r\n\t\t\tif (currentGroup) {\r\n\t\t\t\tif (Users.globalAuth.has(userid)) {\r\n\t\t\t\t\tif (currentGroup === Users.Auth.defaultSymbol()) return this.errorReply(`User '${name}' is already trusted.`);\r\n\t\t\t\t\treturn this.errorReply(`User '${name}' has a global rank higher than trusted.`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\tif (targetUser) {\r\n\t\t\t\ttargetUser.setGroup(Users.Auth.defaultSymbol(), true);\r\n\t\t\t} else {\r\n\t\t\t\tUsers.globalAuth.set(userid, Users.Auth.defaultSymbol());\r\n\t\t\t}\r\n\r\n\t\t\tthis.privateGlobalModAction(`${name} was set as a trusted user by ${user.name}.`);\r\n\t\t\tthis.globalModlog('TRUSTUSER', userid);\r\n\t\t}\r\n\t},\r\n\ttrustuserhelp: [\r\n\t\t`/trustuser [username] - Trusts the user (makes them immune to locks). Requires: &`,\r\n\t\t`/untrustuser [username] - Removes the trusted user status from the user. Requires: &`,\r\n\t],\r\n\r\n\tdesectionleader: 'sectionleader',\r\n\tsectionleader(target, room, user, connection, cmd) {\r\n\t\tthis.checkCan('gdeclare');\r\n\t\troom = this.requireRoom();\r\n\t\tconst demoting = cmd === 'desectionleader';\r\n\t\tif (!target || (target.split(',').length < 2 && !demoting)) return this.parse(`/help sectionleader`);\r\n\r\n\t\tconst {targetUser, targetUsername, rest: sectionid} = this.splitUser(target, {exactName: true});\r\n\t\tconst userid = toID(targetUsername);\r\n\t\tconst section = demoting ? Users.globalAuth.sectionLeaders.get(userid)! : room.validateSection(sectionid);\r\n\t\tconst name = targetUser ? targetUser.name : targetUsername;\r\n\t\tif (Users.globalAuth.sectionLeaders.has(targetUser?.id || userid) && !demoting) {\r\n\t\t\tthrow new Chat.ErrorMessage(`${name} is already a Section Leader of ${RoomSections.sectionNames[section]}.`);\r\n\t\t} else if (!Users.globalAuth.sectionLeaders.has(targetUser?.id || userid) && demoting) {\r\n\t\t\tthrow new Chat.ErrorMessage(`${name} is not a Section Leader.`);\r\n\t\t}\r\n\t\tconst staffRoom = Rooms.get('staff');\r\n\t\tif (!demoting) {\r\n\t\t\tUsers.globalAuth.setSection(userid, section);\r\n\t\t\tthis.addGlobalModAction(`${name} was appointed Section Leader of ${RoomSections.sectionNames[section]} by ${user.name}.`);\r\n\t\t\tthis.globalModlog(`SECTION LEADER`, userid, section);\r\n\t\t\tif (targetUser) {\r\n\t\t\t\t// do not use global /forcepromote\r\n\t\t\t\tif (!Users.globalAuth.atLeast(targetUser, Users.SECTIONLEADER_SYMBOL)) {\r\n\t\t\t\t\tthis.parse(`/globalsectionleader ${userid}`);\r\n\t\t\t\t}\r\n\t\t\t} else {\r\n\t\t\t\tthis.sendReply(`User ${userid} is offline and unrecognized, and so can't be globally promoted.`);\r\n\t\t\t}\r\n\t\t\ttargetUser?.popup(`You were appointed Section Leader of ${RoomSections.sectionNames[section]} by ${user.name}.`);\r\n\t\t} else {\r\n\t\t\tconst group = Users.globalAuth.get(userid);\r\n\t\t\tUsers.globalAuth.deleteSection(userid);\r\n\t\t\tthis.privateGlobalModAction(`${name} was demoted from Section Leader of ${RoomSections.sectionNames[section]} by ${user.name}.`);\r\n\t\t\tif (group === ' ') this.sendReply(`They are also no longer manually trusted. If they should be, use '/trustuser'.`);\r\n\t\t\tthis.globalModlog(`DESECTION LEADER`, userid, section);\r\n\t\t\tif (staffRoom?.auth.getDirect(userid) as any === '\\u25B8') this.parse(`/msgroom staff,/roomdeauth ${userid}`);\r\n\t\t\ttargetUser?.popup(`You were demoted from Section Leader of ${RoomSections.sectionNames[section]} by ${user.name}.`);\r\n\t\t}\r\n\r\n\t\tif (targetUser) {\r\n\t\t\ttargetUser.updateIdentity();\r\n\t\t\tRooms.global.checkAutojoin(targetUser);\r\n\t\t\tif (targetUser.trusted && !Users.isTrusted(targetUser.id)) {\r\n\t\t\t\ttargetUser.trusted = '';\r\n\t\t\t}\r\n\t\t}\r\n\t},\r\n\tsectionleaderhelp: [\r\n\t\t`/sectionleader [target user], [sectionid] - Appoints [target user] Section Leader.`,\r\n\t\t`/desectionleader [target user] - Demotes [target user] from Section Leader.`,\r\n\t\t`Valid sections: ${RoomSections.sections.join(', ')}`,\r\n\t\t`If you want to change which section someone leads, demote them and then re-promote them in the desired section.`,\r\n\t\t`Requires: &`,\r\n\t],\r\n\r\n\tglobaldemote: 'demote',\r\n\tdemote(target) {\r\n\t\tif (!target) return this.parse('/help demote');\r\n\t\tthis.run('promote');\r\n\t},\r\n\tdemotehelp: [`/demote [username], [group] - Demotes the user to the specified group. Requires: &`],\r\n\r\n\tforcepromote(target, room, user, connection) {\r\n\t\t// warning: never document this command in /help\r\n\t\tthis.checkCan('forcepromote');\r\n\t\tconst {targetUsername, rest: nextGroupName} = this.splitUser(target, {exactName: true});\r\n\t\tlet name = this.filter(targetUsername);\r\n\t\tif (!name) return;\r\n\t\tname = name.slice(0, 18);\r\n\t\tconst nextGroup = nextGroupName as GroupSymbol;\r\n\t\tif (!Config.groups[nextGroup]) return this.errorReply(`Group '${nextGroup}' does not exist.`);\r\n\t\tif (Config.groups[nextGroup].roomonly || Config.groups[nextGroup].battleonly) {\r\n\t\t\treturn this.errorReply(`Group '${nextGroup}' does not exist as a global rank.`);\r\n\t\t}\r\n\r\n\t\tif (Users.isUsernameKnown(name)) {\r\n\t\t\treturn this.errorReply(\"/forcepromote - Don't forcepromote unless you have to.\");\r\n\t\t}\r\n\t\tUsers.globalAuth.set(name as ID, nextGroup);\r\n\r\n\t\tthis.addGlobalModAction(`${name} was promoted to Global ${(Config.groups[nextGroup].name || \"regular user\")} by ${user.name}.`);\r\n\t\tthis.globalModlog(`GLOBAL${(Config.groups[nextGroup].name || \"regular\").toUpperCase()}`, toID(name));\r\n\t},\r\n\r\n\tdevoice: 'deauth',\r\n\tdeauth(target, room, user) {\r\n\t\treturn this.parse(`/demote ${target}, deauth`);\r\n\t},\r\n\r\n\tdeglobalvoice: 'globaldeauth',\r\n\tdeglobalauth: 'globaldeauth',\r\n\tglobaldevoice: 'globaldeauth',\r\n\tglobaldeauth(target, room, user) {\r\n\t\treturn this.parse(`/globaldemote ${target}, deauth`);\r\n\t},\r\n\r\n\tderoomvoice: 'roomdeauth',\r\n\troomdevoice: 'roomdeauth',\r\n\tderoomauth: 'roomdeauth',\r\n\troomdeauth(target, room, user) {\r\n\t\treturn this.parse(`/roomdemote ${target}, deauth`);\r\n\t},\r\n\r\n\tdeclare(target, room, user) {\r\n\t\ttarget = target.trim();\r\n\t\tif (!target) return this.parse('/help declare');\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('declare', null, room);\r\n\t\tthis.checkChat();\r\n\t\tif (target.length > 2000) return this.errorReply(\"Declares should not exceed 2000 characters.\");\r\n\r\n\t\tfor (const id in room.users) {\r\n\t\t\troom.users[id].sendTo(room, `|notify|${room.title} announcement!|${target}`);\r\n\t\t}\r\n\t\tthis.add(Utils.html`|raw|
${target}
`);\r\n\t\tthis.modlog('DECLARE', null, target);\r\n\t},\r\n\tdeclarehelp: [`/declare [message] - Anonymously announces a message. Requires: # * &`],\r\n\r\n\thtmldeclare(target, room, user) {\r\n\t\tif (!target) return this.parse('/help htmldeclare');\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('declare', null, room);\r\n\t\tthis.checkChat();\r\n\t\tthis.checkHTML(target);\r\n\r\n\t\tfor (const u in room.users) {\r\n\t\t\tUsers.get(u)?.sendTo(\r\n\t\t\t\troom,\r\n\t\t\t\t`|notify|${room.title} announcement!|${Utils.stripHTML(target)}`\r\n\t\t\t);\r\n\t\t}\r\n\t\tthis.add(`|raw|
${target}
`);\r\n\t\tthis.modlog(`HTMLDECLARE`, null, target);\r\n\t},\r\n\thtmldeclarehelp: [`/htmldeclare [message] - Anonymously announces a message using safe HTML. Requires: # * &`],\r\n\r\n\tgdeclare: 'globaldeclare',\r\n\tglobaldeclare(target, room, user) {\r\n\t\tif (!target) return this.parse('/help globaldeclare');\r\n\t\tthis.checkCan('gdeclare');\r\n\t\tthis.checkHTML(target);\r\n\r\n\t\tfor (const u of Users.users.values()) {\r\n\t\t\tif (u.connected) u.send(`|pm|&|${u.tempGroup}${u.name}|/raw
${target}
`);\r\n\t\t}\r\n\t\tthis.globalModlog(`GLOBALDECLARE`, null, target);\r\n\t},\r\n\tglobaldeclarehelp: [`/globaldeclare [message] - Anonymously sends a private message to all the users on the site. Requires: &`],\r\n\r\n\tcdeclare: 'chatdeclare',\r\n\tchatdeclare(target, room, user) {\r\n\t\tif (!target) return this.parse('/help chatdeclare');\r\n\t\tthis.checkCan('gdeclare');\r\n\t\tthis.checkHTML(target);\r\n\r\n\t\tfor (const curRoom of Rooms.rooms.values()) {\r\n\t\t\tif (curRoom.type !== 'battle') {\r\n\t\t\t\tcurRoom.addRaw(`
${target}
`).update();\r\n\t\t\t}\r\n\t\t}\r\n\t\tthis.globalModlog(`CHATDECLARE`, null, target);\r\n\t},\r\n\tchatdeclarehelp: [`/cdeclare [message] - Anonymously announces a message to all chatrooms on the server. Requires: &`],\r\n\r\n\twall: 'announce',\r\n\tannounce(target, room, user) {\r\n\t\tif (!target) return this.parse('/help announce');\r\n\r\n\t\tif (room) this.checkCan('announce', null, room);\r\n\r\n\t\tthis.checkChat(target);\r\n\r\n\t\treturn `/announce ${target}`;\r\n\t},\r\n\tannouncehelp: [`/announce OR /wall [message] - Makes an announcement. Requires: % @ # &`],\r\n\r\n\tnotifyoffrank: 'notifyrank',\r\n\tnotifyrank(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse(`/help notifyrank`);\r\n\t\tthis.checkCan('addhtml', null, room);\r\n\t\tthis.checkChat();\r\n\t\tlet [rank, titleNotification] = this.splitOne(target);\r\n\t\tif (rank === 'all') rank = ` `;\r\n\t\tif (!(rank in Config.groups)) return this.errorReply(`Group '${rank}' does not exist.`);\r\n\t\tconst id = `${room.roomid}-rank-${(Config.groups[rank].id || `all`)}`;\r\n\t\tif (cmd === 'notifyoffrank') {\r\n\t\t\tif (rank === ' ') {\r\n\t\t\t\troom.send(`|tempnotifyoff|${id}`);\r\n\t\t\t} else {\r\n\t\t\t\troom.sendRankedUsers(`|tempnotifyoff|${id}`, rank as GroupSymbol);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tlet [title, notificationHighlight] = this.splitOne(titleNotification);\r\n\t\t\tif (!title) title = `${room.title} ${(Config.groups[rank].name ? `${Config.groups[rank].name}+ ` : ``)}message!`;\r\n\t\t\tif (!user.can('addhtml')) {\r\n\t\t\t\ttitle += ` (notification from ${user.name})`;\r\n\t\t\t}\r\n\t\t\tconst [notification, highlight] = this.splitOne(notificationHighlight);\r\n\t\t\tif (notification.length > 300) return this.errorReply(`Notifications should not exceed 300 characters.`);\r\n\t\t\tconst message = `|tempnotify|${id}|${title}|${notification}${(highlight ? `|${highlight}` : ``)}`;\r\n\t\t\tif (rank === ' ') {\r\n\t\t\t\troom.send(message);\r\n\t\t\t} else {\r\n\t\t\t\troom.sendRankedUsers(message, rank as GroupSymbol);\r\n\t\t\t}\r\n\t\t\tthis.modlog(`NOTIFYRANK`, null, target);\r\n\t\t}\r\n\t},\r\n\tnotifyrankhelp: [\r\n\t\t`/notifyrank [rank], [title], [message], [highlight] - Sends a notification to users who are [rank] or higher (and highlight on [highlight], if specified). Requires: # * &`,\r\n\t\t`/notifyoffrank [rank] - Closes the notification previously sent with /notifyrank [rank]. Requires: # * &`,\r\n\t],\r\n\r\n\tnotifyoffuser: 'notifyuser',\r\n\tnotifyuser(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse(`/help notifyuser`);\r\n\t\tthis.checkCan('addhtml', null, room);\r\n\t\tthis.checkChat();\r\n\t\tconst {targetUser, targetUsername, rest: titleNotification} = this.splitUser(target);\r\n\t\tif (!targetUser?.connected) return this.errorReply(`User '${targetUsername}' not found.`);\r\n\t\tconst id = `${room.roomid}-user-${toID(targetUsername)}`;\r\n\t\tif (cmd === 'notifyoffuser') {\r\n\t\t\troom.sendUser(targetUser, `|tempnotifyoff|${id}`);\r\n\t\t\tthis.sendReply(`Closed the notification previously sent to ${targetUser.name}.`);\r\n\t\t} else {\r\n\t\t\tlet [title, notification] = this.splitOne(titleNotification);\r\n\t\t\tif (!title) title = `${room.title} notification!`;\r\n\t\t\tif (!user.can('addhtml')) {\r\n\t\t\t\ttitle += ` (notification from ${user.name})`;\r\n\t\t\t}\r\n\t\t\tif (notification.length > 300) return this.errorReply(`Notifications should not exceed 300 characters.`);\r\n\t\t\tconst message = `|tempnotify|${id}|${title}|${notification}`;\r\n\t\t\troom.sendUser(targetUser, message);\r\n\t\t\tthis.sendReply(`Sent a notification to ${targetUser.name}.`);\r\n\t\t}\r\n\t},\r\n\tnotifyuserhelp: [\r\n\t\t`/notifyuser [username], [title], [message] - Sends a notification to [user]. Requires: # * &`,\r\n\t\t`/notifyoffuser [user] - Closes the notification previously sent with /notifyuser [user]. Requires: # * &`,\r\n\t],\r\n\r\n\tfr: 'forcerename',\r\n\tofr: 'forcerename',\r\n\tofflineforcerename: 'forcerename',\r\n\tforcerename(target, room, user) {\r\n\t\tif (!target) return this.parse('/help forcerename');\r\n\r\n\t\tconst {targetUser, targetUsername, rest: reason} = this.splitUser(target, {exactName: true});\r\n\t\tconst offline = this.cmd.startsWith('o');\r\n\t\tconst targetID = targetUser?.id || toID(targetUsername);\r\n\t\t// && !offline because maybe we're trying to disallow the name after they namechanged\r\n\t\tif (!targetUser && !offline) {\r\n\t\t\tconst {targetUser: targetUserInexact, inputUsername} = this.splitUser(target);\r\n\t\t\tif (targetUserInexact) {\r\n\t\t\t\treturn this.errorReply(`User has already changed their name to '${targetUserInexact.name}'.`);\r\n\t\t\t}\r\n\t\t\treturn this.errorReply(`User '${inputUsername}' not found. (use /offlineforcerename to rename anyway.)`);\r\n\t\t}\r\n\t\tif (Punishments.namefilterwhitelist.has(targetID)) {\r\n\t\t\tthis.errorReply(`That name is blocked from being forcerenamed.`);\r\n\t\t\tif (user.can('bypassall')) {\r\n\t\t\t\tthis.errorReply(`Use /noforcerename remove to remove it from the list if you wish to rename it.`);\r\n\t\t\t}\r\n\t\t\treturn false;\r\n\t\t}\r\n\t\tthis.checkCan('forcerename', targetID);\r\n\t\tconst {publicReason, privateReason} = this.parseSpoiler(reason);\r\n\r\n\t\tMonitor.forceRenames.set(targetID, false);\r\n\r\n\t\tlet forceRenameMessage;\r\n\t\tif (targetUser?.connected) {\r\n\t\t\tforceRenameMessage = `was forced to choose a new name by ${user.name}${(publicReason ? `: ${publicReason}` : ``)}`;\r\n\t\t\tthis.globalModlog('FORCERENAME', targetUser, reason);\r\n\t\t\tLadders.cancelSearches(targetUser);\r\n\t\t\ttargetUser.send(`|nametaken||${user.name} considers your name inappropriate${(publicReason ? `: ${publicReason}` : ``)}`);\r\n\t\t} else {\r\n\t\t\tforceRenameMessage = `was forced to choose a new name by ${user.name} while offline${(publicReason ? `: ${publicReason}` : ``)}`;\r\n\t\t\tthis.globalModlog('FORCERENAME OFFLINE', targetUser, privateReason);\r\n\t\t}\r\n\t\tMonitor.forceRenames.set(targetID, false);\r\n\r\n\t\tif (room?.roomid !== 'staff') {\r\n\t\t\tif (room?.roomid.startsWith('help-')) {\r\n\t\t\t\tthis.addModAction(`${targetUser?.name || targetID} ${forceRenameMessage}`);\r\n\t\t\t} else {\r\n\t\t\t\tthis.privateModAction(`${targetUser?.name || targetID} ${forceRenameMessage}`);\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst roomMessage = this.pmTarget ? `` :\r\n\t\t\troom && room.roomid !== 'staff' ? `\u00AB${room.roomid}\u00BB ` :\r\n\t\t\t'';\r\n\t\tconst rankMessage = targetUser?.getAccountStatusString() || \"\";\r\n\t\tRooms.global.notifyRooms(\r\n\t\t\t['staff'],\r\n\t\t\t`|html|${roomMessage}` + Utils.html`${targetUser?.name || targetID} ${rankMessage} ${forceRenameMessage}`\r\n\t\t);\r\n\r\n\t\ttargetUser?.resetName(true);\r\n\t\treturn true;\r\n\t},\r\n\tforcerenamehelp: [\r\n\t\t`/forcerename OR /fr [username], [reason] - Forcibly change a user's name and shows them the [reason]. Requires: % @ &`,\r\n\t\t`/allowname [username] - Unmarks a forcerenamed username, stopping staff from being notified when it is used. Requires % @ &`,\r\n\t],\r\n\r\n\tnfr: 'noforcerename',\r\n\tnoforcerename: {\r\n\t\tadd(target, room, user) {\r\n\t\t\tconst [targetUsername, rest] = Utils.splitFirst(target, ',').map(f => f.trim());\r\n\t\t\tconst targetId = toID(targetUsername);\r\n\t\t\tif (!targetId) return this.parse('/help noforcerename');\r\n\t\t\tthis.checkCan('bypassall');\r\n\t\t\tif (!Punishments.whitelistName(targetId, user.name)) {\r\n\t\t\t\treturn this.errorReply(`${targetUsername} is already on the noforcerename list.`);\r\n\t\t\t}\r\n\t\t\tthis.addGlobalModAction(`${user.name} added the name ${targetId} to the no forcerename list.${rest ? ` (${rest})` : ''}`);\r\n\t\t\tthis.globalModlog('NOFORCERENAME', targetId, rest);\r\n\t\t},\r\n\t\tremove(target, room, user) {\r\n\t\t\tconst {targetUsername, rest} = this.splitUser(target);\r\n\t\t\tconst targetId = toID(targetUsername);\r\n\t\t\tif (!targetId) return this.parse('/help noforcerename');\r\n\t\t\tthis.checkCan('bypassall');\r\n\t\t\tif (!Punishments.namefilterwhitelist.has(targetId)) {\r\n\t\t\t\treturn this.errorReply(`${targetUsername} is not on the noforcerename list.`);\r\n\t\t\t}\r\n\t\t\tPunishments.unwhitelistName(targetId);\r\n\t\t\tthis.addGlobalModAction(`${user.name} removed ${targetId} from the no forcerename list.${rest ? ` (${rest})` : ''}`);\r\n\t\t\tthis.globalModlog('UNNOFORCERENAME', targetId, rest);\r\n\t\t},\r\n\t},\r\n\tnoforcerenamehelp: [\r\n\t\t`/noforcerename add OR /nfr add [username] - Adds [username] to the list of users who can't be forcerenamed by staff.`,\r\n\t\t`/noforcerename remove OR /nfr remove [username] - Removes [username] from the list of users who can't be forcerenamed by staff.`,\r\n\t],\r\n\r\n\tforceclearstatus(target, room, user) {\r\n\t\tconst {targetUser, rest: reason} = this.requireUser(target, {allowOffline: true});\r\n\t\tthis.checkCan('forcerename', targetUser);\r\n\r\n\t\tif (!targetUser.userMessage) return this.errorReply(this.tr`${targetUser.name} does not have a status set.`);\r\n\r\n\t\tconst displayReason = reason ? `: ${reason}` : ``;\r\n\t\tthis.privateGlobalModAction(this.tr`${targetUser.name}'s status \"${targetUser.userMessage}\" was cleared by ${user.name}${displayReason}.`);\r\n\t\tthis.globalModlog('CLEARSTATUS', targetUser, ` from \"${targetUser.userMessage}\"${displayReason}`);\r\n\t\ttargetUser.clearStatus();\r\n\t\ttargetUser.popup(`${user.name} has cleared your status message for being inappropriate${displayReason || '.'}`);\r\n\t},\r\n\r\n\tnl: 'namelock',\r\n\tforcenamelock: 'namelock',\r\n\tweeknamelock: 'namelock',\r\n\twnl: 'namelock',\r\n\tfwnl: 'namelock',\r\n\tforceweeknamelock: 'namelock',\r\n\tasync namelock(target, room, user, connection, cmd) {\r\n\t\tif (!target) return this.parse('/help namelock');\r\n\t\tconst week = cmd.includes('w');\r\n\t\tconst force = cmd.includes('f');\r\n\r\n\t\tconst {targetUser, inputUsername, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tconst userid = toID(targetUsername);\r\n\r\n\t\tif (!targetUser && !force) {\r\n\t\t\treturn this.errorReply(\r\n\t\t\t\t`User '${targetUsername}' not found. Use \\`\\`/force${week ? 'week' : ''}namelock\\`\\` if you need to namelock them anyway.`\r\n\t\t\t);\r\n\t\t}\r\n\t\tif (targetUser && targetUser.id !== toID(inputUsername) && !force) {\r\n\t\t\treturn this.errorReply(`${inputUsername} has already changed their name to ${targetUser.name}. To namelock anyway, use /force${week ? 'week' : ''}namelock.`);\r\n\t\t}\r\n\t\tthis.checkCan('forcerename', userid);\r\n\t\tif (targetUser?.namelocked && !week) {\r\n\t\t\treturn this.errorReply(`User '${targetUser.name}' is already namelocked.`);\r\n\t\t}\r\n\t\tif (!force && !week) {\r\n\t\t\tconst existingPunishments = Punishments.search(userid);\r\n\t\t\tfor (const [,, punishment] of existingPunishments) {\r\n\t\t\t\tif (punishment.type === 'LOCK' && (punishment.expireTime - Date.now()) > (2 * DAY)) {\r\n\t\t\t\t\tthis.errorReply(`User '${userid}' is already normally locked for more than 2 days.`);\r\n\t\t\t\t\tthis.errorReply(`Use /weeknamelock to namelock them instead, so you don't decrease the existing punishment.`);\r\n\t\t\t\t\treturn this.errorReply(`If you really need to override this, use /forcenamelock.`);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst {privateReason, publicReason} = this.parseSpoiler(reason);\r\n\t\tconst reasonText = publicReason ? ` (${publicReason})` : `.`;\r\n\t\tthis.privateGlobalModAction(`${targetUser?.name || userid} was ${week ? 'week' : ''}namelocked by ${user.name}${reasonText}`);\r\n\t\tthis.globalModlog(`${force ? `FORCE` : ``}${week ? 'WEEK' : \"\"}NAMELOCK`, targetUser || userid, privateReason);\r\n\r\n\t\tconst roomauth = Rooms.global.destroyPersonalRooms(userid);\r\n\t\tif (roomauth.length) {\r\n\t\t\tMonitor.log(`[CrisisMonitor] Namelocked user ${userid} has public roomauth (${roomauth.join(', ')}), and should probably be demoted.`);\r\n\t\t}\r\n\t\tif (targetUser) {\r\n\t\t\tLadders.cancelSearches(targetUser);\r\n\t\t\ttargetUser.popup(`|modal|${user.name} has locked your name and you can't change names anymore${reasonText}`);\r\n\t\t}\r\n\t\tconst duration = week ? 7 * 24 * 60 * 60 * 1000 : 48 * 60 * 60 * 1000;\r\n\t\tawait Punishments.namelock(userid, Date.now() + duration, null, false, publicReason);\r\n\t\t// Automatically upload replays as evidence/reference to the punishment\r\n\t\tif (room?.battle) this.parse('/savereplay forpunishment');\r\n\t\tMonitor.forceRenames.set(userid, false);\r\n\t\tif (connection.openPages) {\r\n\t\t\t// this hardcode is necessary because when /namelock and /uspage are send together in one button\r\n\t\t\t// the uspage output is sent before the user's name is reset\r\n\t\t\t// so it takes two clicks, which is bad behavior\r\n\t\t\tfor (const page of connection.openPages) {\r\n\t\t\t\tif (page.includes('usersearch-')) {\r\n\t\t\t\t\tthis.refreshPage(page);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\treturn true;\r\n\t},\r\n\tnamelockhelp: [`/namelock OR /nl [user], [reason] - Name locks a [user] and shows the [reason]. Requires: % @ &`],\r\n\r\n\tunl: 'unnamelock',\r\n\tunnamelock(target, room, user) {\r\n\t\tif (!target) return this.parse('/help unnamelock');\r\n\t\tthis.checkCan('forcerename');\r\n\r\n\t\tconst targetUser = Users.get(target);\r\n\t\tlet reason = '';\r\n\t\tif (targetUser?.namelocked) {\r\n\t\t\treason = ` (${targetUser.namelocked})`;\r\n\t\t}\r\n\r\n\t\tconst unlocked = Punishments.unnamelock(target);\r\n\r\n\t\tif (!unlocked) {\r\n\t\t\treturn this.errorReply(`User '${target}' is not namelocked.`);\r\n\t\t}\r\n\r\n\t\tthis.addGlobalModAction(`${unlocked} was unnamelocked by ${user.name}.${reason}`);\r\n\t\tif (!reason) this.globalModlog(\"UNNAMELOCK\", toID(target));\r\n\t\tif (targetUser) targetUser.popup(`${user.name} has unnamelocked you.`);\r\n\t},\r\n\tunnamelockhelp: [`/unnamelock [username] - Unnamelocks the user. Requires: % @ &`],\r\n\r\n\thidetextalts: 'hidetext',\r\n\thidealttext: 'hidetext',\r\n\thidealtstext: 'hidetext',\r\n\thtext: 'hidetext',\r\n\tforcehidetext: 'hidetext',\r\n\thidelines: 'hidetext',\r\n\thlines: 'hidetext',\r\n\tcleartext: 'hidetext',\r\n\tctext: 'hidetext',\r\n\tclearaltstext: 'hidetext',\r\n\tclearlines: 'hidetext',\r\n\tforcecleartext: 'hidetext',\r\n\thidetext(target, room, user, connection, cmd) {\r\n\t\tif (!target) return this.parse(`/help hidetext`);\r\n\t\troom = this.requireRoom();\r\n\t\tconst hasLineCount = cmd.includes('lines');\r\n\t\tconst hideRevealButton = cmd.includes('clear') || cmd === 'ctext';\r\n\t\tlet {targetUser, inputUsername, targetUsername: name, rest: reason} = this.splitUser(target);\r\n\t\tlet lineCount = 0;\r\n\t\tif (/^[0-9]+\\s*(,|$)/.test(reason)) {\r\n\t\t\tif (hasLineCount) {\r\n\t\t\t\tlet lineCountString;\r\n\t\t\t\t[lineCountString, reason] = Utils.splitFirst(reason, ',').map(p => p.trim());\r\n\t\t\t\tlineCount = parseInt(lineCountString);\r\n\t\t\t} else if (!cmd.includes('force')) {\r\n\t\t\t\treturn this.errorReply(`Your reason was a number; use /hidelines if you wanted to clear a specific number of lines, or /forcehidetext if you really wanted your reason to be a number.`);\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst showAlts = cmd.includes('alt');\r\n\t\tif (!lineCount && hasLineCount) {\r\n\t\t\treturn this.errorReply(`You must specify a number of messages to clear. To clear all messages, use /hidetext.`);\r\n\t\t}\r\n\t\tif (reason.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\r\n\t\tif (!targetUser && !room.log.hasUsername(name)) {\r\n\t\t\treturn this.errorReply(`User ${name} not found or has no roomlogs.`);\r\n\t\t}\r\n\t\tif (lineCount && showAlts) {\r\n\t\t\treturn this.errorReply(`You can't specify a line count when using /hidealtstext.`);\r\n\t\t}\r\n\t\tconst userid = toID(inputUsername);\r\n\r\n\t\tthis.checkCan('mute', null, room);\r\n\r\n\t\t// if the user hiding their own text, it would clear the \"cleared\" message,\r\n\t\t// so we can't attribute it in that case\r\n\t\t// and sending the message after `|unlink|` puts the \"show lines\" button in the wrong place\r\n\t\tconst sender = user === targetUser ? null : user;\r\n\r\n\t\tlet message = '';\r\n\t\tif (targetUser && showAlts) {\r\n\t\t\tmessage = `${name}'s alts messages were cleared from ${room.title} by ${user.name}.${(reason ? ` (${reason})` : ``)}`;\r\n\t\t\troom.sendByUser(sender, message);\r\n\t\t\tthis.modlog('HIDEALTSTEXT', targetUser, reason, {noip: 1});\r\n\t\t\troom.hideText([\r\n\t\t\t\tuserid,\r\n\t\t\t\t...targetUser.previousIDs,\r\n\t\t\t\t...targetUser.getAltUsers(true).map((curUser: User) => curUser.getLastId()),\r\n\t\t\t] as ID[]);\r\n\t\t} else {\r\n\t\t\tif (lineCount > 0) {\r\n\t\t\t\tmessage = `${lineCount} of ${name}'s messages were cleared from ${room.title} by ${user.name}.${(reason ? ` (${reason})` : ``)}`;\r\n\t\t\t\troom.sendByUser(sender, message);\r\n\t\t\t} else {\r\n\t\t\t\tmessage = `${name}'s messages were cleared from ${room.title} by ${user.name}.${(reason ? ` (${reason})` : ``)}`;\r\n\t\t\t\troom.sendByUser(sender, message);\r\n\t\t\t}\r\n\t\t\tthis.modlog('HIDETEXT', targetUser || userid, reason, {noip: 1, noalts: 1});\r\n\t\t\troom.hideText([userid], lineCount, hideRevealButton);\r\n\t\t\tthis.roomlog(`|c|${user.getIdentity()}|/log ${message}`);\r\n\t\t}\r\n\t},\r\n\thidetexthelp: [\r\n\t\t`/hidetext [username], [optional reason] - Removes a user's messages from chat, with an optional reason. Requires: % @ # &`,\r\n\t\t`/hidealtstext [username], [optional reason] - Removes a user's messages and their alternate accounts' messages from the chat, with an optional reason. Requires: % @ # &`,\r\n\t\t`/hidelines [username], [number], [optional reason] - Removes the [number] most recent messages from a user, with an optional reason. Requires: % @ # &`,\r\n\t\t`Use /cleartext, /clearaltstext, and /clearlines to remove messages without displaying a button to reveal them.`,\r\n\t],\r\n\r\n\tab: 'blacklist',\r\n\tbl: 'blacklist',\r\n\tforceblacklist: 'blacklist',\r\n\tforcebl: 'blacklist',\r\n\tblacklist(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help blacklist');\r\n\t\tthis.checkChat();\r\n\t\tif (toID(target) === 'show') return this.errorReply(`You're looking for /showbl`);\r\n\r\n\t\tconst {targetUser, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tif (!targetUser) {\r\n\t\t\tthis.errorReply(`User ${targetUsername} not found.`);\r\n\t\t\treturn this.errorReply(`If you want to blacklist an offline account by name (not IP), consider /blacklistname`);\r\n\t\t}\r\n\t\tthis.checkCan('editroom', targetUser, room);\r\n\t\tif (!room.persist) {\r\n\t\t\treturn this.errorReply(`This room is not going to last long enough for a blacklist to matter - just ban the user`);\r\n\t\t}\r\n\t\tconst punishment = Punishments.isRoomBanned(targetUser, room.roomid);\r\n\t\tif (punishment && punishment.type === 'BLACKLIST') {\r\n\t\t\treturn this.errorReply(`This user is already blacklisted from this room.`);\r\n\t\t}\r\n\t\tconst force = cmd === 'forceblacklist' || cmd === 'forcebl';\r\n\t\tif (targetUser.trusted) {\r\n\t\t\tif (!force) {\r\n\t\t\t\treturn this.sendReply(\r\n\t\t\t\t\t`${targetUser.name} is a trusted user. If you are sure you would like to blacklist them use /forceblacklist.`\r\n\t\t\t\t);\r\n\t\t\t}\r\n\t\t} else if (force) {\r\n\t\t\treturn this.errorReply(`Use /blacklist; ${targetUser.name} is not a trusted user.`);\r\n\t\t}\r\n\t\tif (!reason && REQUIRE_REASONS) {\r\n\t\t\treturn this.errorReply(`Blacklists require a reason.`);\r\n\t\t}\r\n\t\tif (reason.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tconst name = targetUser.getLastName();\r\n\t\tconst userid = targetUser.getLastId();\r\n\r\n\t\tif (targetUser.trusted && room.settings.isPrivate !== true) {\r\n\t\t\tMonitor.log(`[CrisisMonitor] Trusted user ${targetUser.name}${targetUser.trusted !== targetUser.id ? ` (${targetUser.trusted})` : ''} was blacklisted from ${room.roomid} by ${user.name}, and should probably be demoted.`);\r\n\t\t}\r\n\r\n\t\tif (targetUser.id in room.users || user.can('lock')) {\r\n\t\t\ttargetUser.popup(\r\n\t\t\t\t`|modal||html|

${Utils.escapeHTML(user.name)} has blacklisted you from the room ${room.roomid}${(room.subRooms ? ` and its subrooms` : '')}. Reason: ${Utils.escapeHTML(reason)}

` +\r\n\t\t\t\t`

To appeal the ban, PM the staff member that blacklisted you${room.persist ? ` or a room owner.

` : `.

`}`\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tthis.privateModAction(`${name} was blacklisted from ${room.title} by ${user.name}.${reason ? ` (${reason})` : ''}`);\r\n\r\n\t\tconst affected = Punishments.roomBlacklist(room, targetUser, null, null, reason);\r\n\r\n\t\tif (!room.settings.isPrivate && room.persist) {\r\n\t\t\tconst acAccount = (targetUser.autoconfirmed !== userid && targetUser.autoconfirmed);\r\n\t\t\tlet displayMessage = '';\r\n\t\t\tif (affected.length > 1) {\r\n\t\t\t\tdisplayMessage = `${name}'s ${(acAccount ? ` ac account: ${acAccount},` : '')} blacklisted alts: ${affected.slice(1).map(curUser => curUser.getLastName()).join(\", \")}`;\r\n\t\t\t\tthis.privateModAction(displayMessage);\r\n\t\t\t} else if (acAccount) {\r\n\t\t\t\tdisplayMessage = `${name}'s ac account: ${acAccount}`;\r\n\t\t\t\tthis.privateModAction(displayMessage);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (!room.settings.isPrivate && room.persist) {\r\n\t\t\tthis.globalModlog(\"BLACKLIST\", targetUser, reason);\r\n\t\t} else {\r\n\t\t\t// Room modlog only\r\n\t\t\tthis.modlog(\"BLACKLIST\", targetUser, reason);\r\n\t\t}\r\n\t\treturn true;\r\n\t},\r\n\tblacklisthelp: [\r\n\t\t`/blacklist [username], [reason] - Blacklists the user from the room you are in for a year. Requires: # &`,\r\n\t\t`/unblacklist [username] - Unblacklists the user from the room you are in. Requires: # &`,\r\n\t\t`/showblacklist OR /showbl - show a list of blacklisted users in the room. Requires: % @ # &`,\r\n\t\t`/expiringblacklists OR /expiringbls - show a list of blacklisted users from the room whose blacklists are expiring in 3 months or less. Requires: % @ # &`,\r\n\t],\r\n\r\n\tforcebattleban: 'battleban',\r\n\tasync battleban(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse(`/help battleban`);\r\n\r\n\t\tconst {targetUser, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tif (!targetUser) return this.errorReply(`User ${targetUsername} not found.`);\r\n\t\tif (target.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\t\tif (!reason) {\r\n\t\t\treturn this.errorReply(`Battle bans require a reason.`);\r\n\t\t}\r\n\t\tconst includesUrl = reason.includes(`.${Config.routes.root}/`); // lgtm [js/incomplete-url-substring-sanitization]\r\n\t\tif (!room.battle && !includesUrl && cmd !== 'forcebattleban') {\r\n\t\t\t return this.errorReply(`Battle bans require a battle replay if used outside of a battle; if the battle has expired, use /forcebattleban.`);\r\n\t\t}\r\n\t\tif (!user.can('rangeban', targetUser)) {\r\n\t\t\tthis.errorReply(`Battlebans have been deprecated. Alternatives:`);\r\n\t\t\tthis.errorReply(`- timerstalling and bragging about it: lock`);\r\n\t\t\tthis.errorReply(`- other timerstalling: they're not timerstalling, leave them alone`);\r\n\t\t\tthis.errorReply(`- bad nicknames: lock, locks prevent nicknames from appearing; you should always have been locking for this`);\r\n\t\t\tthis.errorReply(`- ladder cheating: gban, get a moderator if necessary`);\r\n\t\t\tthis.errorReply(`- serious ladder cheating: permaban, get an administrator`);\r\n\t\t\tthis.errorReply(`- other: get an administrator`);\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (Punishments.isBattleBanned(targetUser)) {\r\n\t\t\treturn this.errorReply(`User '${targetUser.name}' is already banned from battling.`);\r\n\t\t}\r\n\t\tthis.privateGlobalModAction(`${targetUser.name} was banned from starting new battles by ${user.name} (${reason})`);\r\n\r\n\t\tif (targetUser.trusted) {\r\n\t\t\tMonitor.log(`[CrisisMonitor] Trusted user ${targetUser.name} was banned from battling by ${user.name}, and should probably be demoted.`);\r\n\t\t}\r\n\r\n\t\tthis.globalModlog(\"BATTLEBAN\", targetUser, reason);\r\n\t\tLadders.cancelSearches(targetUser);\r\n\t\tawait Punishments.battleban(targetUser, null, null, reason);\r\n\t\ttargetUser.popup(`|modal|${user.name} has prevented you from starting new battles for 2 days (${reason})`);\r\n\r\n\t\t// Automatically upload replays as evidence/reference to the punishment\r\n\t\tif (room.battle) this.parse('/savereplay forpunishment');\r\n\t\treturn true;\r\n\t},\r\n\tbattlebanhelp: [\r\n\t\t`/battleban [username], [reason] - [DEPRECATED]`,\r\n\t\t`Prevents the user from starting new battles for 2 days and shows them the [reason]. Requires: &`,\r\n\t],\r\n\r\n\tunbattleban(target, room, user) {\r\n\t\tif (!target) return this.parse('/help unbattleban');\r\n\t\tthis.checkCan('lock');\r\n\r\n\t\tconst targetUser = Users.get(target);\r\n\t\tconst unbanned = Punishments.unbattleban(target);\r\n\r\n\t\tif (unbanned) {\r\n\t\t\tthis.addModAction(`${unbanned} was allowed to battle again by ${user.name}.`);\r\n\t\t\tthis.globalModlog(\"UNBATTLEBAN\", toID(target));\r\n\t\t\tif (targetUser) targetUser.popup(`${user.name} has allowed you to battle again.`);\r\n\t\t} else {\r\n\t\t\tthis.errorReply(`User ${target} is not banned from battling.`);\r\n\t\t}\r\n\t},\r\n\tunbattlebanhelp: [`/unbattleban [username] - [DEPRECATED] Allows a user to battle again. Requires: % @ &`],\r\n\r\n\tmonthgroupchatban: 'groupchatban',\r\n\tmonthgcban: 'groupchatban',\r\n\tgcban: 'groupchatban',\r\n\tasync groupchatban(target, room, user, connection, cmd) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse(`/help groupchatban`);\r\n\t\tif (!user.can('rangeban')) {\r\n\t\t\treturn this.errorReply(\r\n\t\t\t\t`/groupchatban has been deprecated.\\n` +\r\n\t\t\t\t`For future groupchat misuse, lock the creator, it will take away their trusted status and their ability to make groupchats.`\r\n\t\t\t);\r\n\t\t}\r\n\r\n\t\tconst {targetUser, targetUsername, rest: reason} = this.splitUser(target);\r\n\t\tif (!targetUser) return this.errorReply(`User ${targetUsername} not found.`);\r\n\t\tif (target.length > MAX_REASON_LENGTH) {\r\n\t\t\treturn this.errorReply(`The reason is too long. It cannot exceed ${MAX_REASON_LENGTH} characters.`);\r\n\t\t}\r\n\r\n\t\tconst isMonth = cmd.startsWith('month');\r\n\r\n\t\tif (!isMonth && Punishments.isGroupchatBanned(targetUser)) {\r\n\t\t\treturn this.errorReply(`User '${targetUser.name}' is already banned from using groupchats.`);\r\n\t\t}\r\n\r\n\t\tconst reasonText = reason ? `: ${reason}` : ``;\r\n\t\tthis.privateGlobalModAction(`${targetUser.name} was banned from using groupchats for a ${isMonth ? 'month' : 'week'} by ${user.name}${reasonText}.`);\r\n\r\n\t\tif (targetUser.trusted) {\r\n\t\t\tMonitor.log(`[CrisisMonitor] Trusted user ${targetUser.name} was banned from using groupchats by ${user.name}, and should probably be demoted.`);\r\n\t\t}\r\n\r\n\t\tconst createdGroupchats = await Punishments.groupchatBan(\r\n\t\t\ttargetUser, (isMonth ? Date.now() + 30 * DAY : null), null, reason\r\n\t\t);\r\n\t\ttargetUser.popup(`|modal|${user.name} has banned you from using groupchats for a ${isMonth ? 'month' : 'week'}${reasonText}`);\r\n\t\tthis.globalModlog(\"GROUPCHATBAN\", targetUser, ` by ${user.id}${reasonText}`);\r\n\r\n\t\tfor (const roomid of createdGroupchats) {\r\n\t\t\tconst targetRoom = Rooms.get(roomid);\r\n\t\t\tif (!targetRoom) continue;\r\n\t\t\tconst participants = targetRoom.warnParticipants?.(\r\n\t\t\t\t`This groupchat (${targetRoom.title}) has been deleted due to inappropriate conduct by its creator, ${targetUser.name}.` +\r\n\t\t\t\t` Do not attempt to recreate it, or you may be punished.${reason ? ` (reason: ${reason})` : ``}`\r\n\t\t\t);\r\n\r\n\t\t\tif (participants) {\r\n\t\t\t\tconst modlogEntry = {\r\n\t\t\t\t\taction: 'NOTE',\r\n\t\t\t\t\tloggedBy: user.id,\r\n\t\t\t\t\tisGlobal: true,\r\n\t\t\t\t\tnote: `participants in ${roomid} (creator: ${targetUser.id}): ${participants.join(', ')}`,\r\n\t\t\t\t};\r\n\t\t\t\ttargetRoom.modlog(modlogEntry);\r\n\t\t\t}\r\n\r\n\t\t\ttargetRoom.destroy();\r\n\t\t}\r\n\t},\r\n\tgroupchatbanhelp: [\r\n\t\t`/groupchatban [user], [optional reason]`,\r\n\t\t`/monthgroupchatban [user], [optional reason]`,\r\n\t\t`Bans the user from joining or creating groupchats for a week (or month). Requires: % @ &`,\r\n\t],\r\n\r\n\tungcban: 'ungroupchatban',\r\n\tgcunban: 'ungroupchatban',\r\n\tgroucphatunban: 'ungroupchatban',\r\n\tungroupchatban(target, room, user) {\r\n\t\tif (!target) return this.parse('/help ungroupchatban');\r\n\t\tthis.checkCan('lock');\r\n\r\n\t\tconst targetUser = Users.get(target);\r\n\t\tconst unbanned = Punishments.groupchatUnban(targetUser || toID(target));\r\n\r\n\t\tif (unbanned) {\r\n\t\t\tthis.addGlobalModAction(`${unbanned} was ungroupchatbanned by ${user.name}.`);\r\n\t\t\tthis.globalModlog(\"UNGROUPCHATBAN\", toID(target), ` by ${user.id}`);\r\n\t\t\tif (targetUser) targetUser.popup(`${user.name} has allowed you to use groupchats again.`);\r\n\t\t} else {\r\n\t\t\tthis.errorReply(`User ${target} is not banned from using groupchats.`);\r\n\t\t}\r\n\t},\r\n\tungroupchatbanhelp: [`/ungroupchatban [user] - Allows a groupchatbanned user to use groupchats again. Requires: % @ &`],\r\n\r\n\tnameblacklist: 'blacklistname',\r\n\tblacklistname(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help blacklistname');\r\n\t\tthis.checkChat();\r\n\t\tthis.checkCan('editroom', null, room);\r\n\t\tif (!room.persist) {\r\n\t\t\treturn this.errorReply(\"This room is not going to last long enough for a blacklist to matter - just ban the user\");\r\n\t\t}\r\n\r\n\t\tconst [targetStr, reason] = target.split('|').map(val => val.trim());\r\n\t\tif (!targetStr || (!reason && REQUIRE_REASONS)) {\r\n\t\t\treturn this.errorReply(\"Usage: /blacklistname name1, name2, ... | reason\");\r\n\t\t}\r\n\r\n\t\tconst targets = targetStr.split(',').map(s => toID(s));\r\n\r\n\t\tconst duplicates = targets.filter(userid => (\r\n\t\t\t// can be asserted, room should always exist\r\n\t\t\tPunishments.roomUserids.nestedGetByType(room!.roomid, userid, 'BLACKLIST')\r\n\t\t));\r\n\t\tif (duplicates.length) {\r\n\t\t\treturn this.errorReply(`[${duplicates.join(', ')}] ${Chat.plural(duplicates, \"are\", \"is\")} already blacklisted.`);\r\n\t\t}\r\n\r\n\t\tfor (const userid of targets) {\r\n\t\t\tif (!userid) return this.errorReply(`User '${userid}' is not a valid userid.`);\r\n\t\t\tif (!Users.Auth.hasPermission(user, 'ban', room.auth.get(userid), room)) {\r\n\t\t\t\treturn this.errorReply(`/blacklistname - Access denied: ${userid} is of equal or higher authority than you.`);\r\n\t\t\t}\r\n\r\n\t\t\tPunishments.roomBlacklist(room, userid, null, null, reason);\r\n\r\n\t\t\tconst trusted = Users.isTrusted(userid);\r\n\t\t\tif (trusted && room.settings.isPrivate !== true) {\r\n\t\t\t\tMonitor.log(`[CrisisMonitor] Trusted user ${userid}${(trusted !== userid ? ` (${trusted})` : ``)} was nameblacklisted from ${room.roomid} by ${user.name}, and should probably be demoted.`);\r\n\t\t\t}\r\n\t\t\tif (!room.settings.isPrivate && room.persist) {\r\n\t\t\t\tthis.globalModlog(\"NAMEBLACKLIST\", userid, reason);\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tthis.privateModAction(\r\n\t\t\t`${targets.join(', ')}${Chat.plural(targets, \" were\", \" was\")} nameblacklisted from ${room.title} by ${user.name}.`\r\n\t\t);\r\n\t\treturn true;\r\n\t},\r\n\tblacklistnamehelp: [\r\n\t\t`/blacklistname OR /nameblacklist [name1, name2, etc.] | reason - Blacklists all name(s) from the room you are in for a year. Requires: # &`,\r\n\t],\r\n\r\n\tunab: 'unblacklist',\r\n\tunblacklist(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tif (!target) return this.parse('/help unblacklist');\r\n\t\tthis.checkCan('editroom', null, room);\r\n\r\n\t\tconst name = Punishments.roomUnblacklist(room, target);\r\n\r\n\t\tif (name) {\r\n\t\t\tthis.privateModAction(`${name} was unblacklisted by ${user.name}.`);\r\n\t\t\tif (!room.settings.isPrivate && room.persist) {\r\n\t\t\t\tthis.globalModlog(\"UNBLACKLIST\", name);\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tthis.errorReply(`User '${target}' is not blacklisted.`);\r\n\t\t}\r\n\t},\r\n\tunblacklisthelp: [`/unblacklist [username] - Unblacklists the user from the room you are in. Requires: # &`],\r\n\r\n\tunblacklistall(target, room, user) {\r\n\t\troom = this.requireRoom();\r\n\t\tthis.checkCan('editroom', null, room);\r\n\r\n\t\tif (!target) {\r\n\t\t\tuser.lastCommand = '/unblacklistall';\r\n\t\t\tthis.errorReply(\"THIS WILL UNBLACKLIST ALL BLACKLISTED USERS IN THIS ROOM.\");\r\n\t\t\tthis.errorReply(\"To confirm, use: /unblacklistall confirm\");\r\n\t\t\treturn;\r\n\t\t}\r\n\t\tif (user.lastCommand !== '/unblacklistall' || target !== 'confirm') {\r\n\t\t\treturn this.parse('/help unblacklistall');\r\n\t\t}\r\n\t\tuser.lastCommand = '';\r\n\t\tconst unblacklisted = Punishments.roomUnblacklistAll(room);\r\n\t\tif (!unblacklisted) return this.errorReply(\"No users are currently blacklisted in this room to unblacklist.\");\r\n\t\tthis.addModAction(`All blacklists in this room have been lifted by ${user.name}.`);\r\n\t\tthis.modlog('UNBLACKLISTALL');\r\n\t\tthis.roomlog(`Unblacklisted users: ${unblacklisted.join(', ')}`);\r\n\t},\r\n\tunblacklistallhelp: [`/unblacklistall - Unblacklists all blacklisted users in the current room. Requires: # &`],\r\n\r\n\texpiringbls: 'showblacklist',\r\n\texpiringblacklists: 'showblacklist',\r\n\tblacklists: 'showblacklist',\r\n\tshowbl: 'showblacklist',\r\n\tshowblacklist(target, room, user, connection, cmd) {\r\n\t\tif (target) room = Rooms.search(target)!;\r\n\t\tif (!room) return this.errorReply(`The room \"${target}\" was not found.`);\r\n\t\tthis.checkCan('mute', null, room);\r\n\t\tconst SOON_EXPIRING_TIME = 3 * 30 * 24 * 60 * 60 * 1000; // 3 months\r\n\r\n\t\tif (!room.persist) return this.errorReply(\"This room does not support blacklists.\");\r\n\r\n\t\tconst roomUserids = Punishments.roomUserids.get(room.roomid);\r\n\t\tif (!roomUserids || roomUserids.size === 0) {\r\n\t\t\treturn this.sendReply(\"This room has no blacklisted users.\");\r\n\t\t}\r\n\t\tconst blMap = new Map();\r\n\t\tlet ips = '';\r\n\r\n\t\tfor (const [userid, punishmentList] of roomUserids) {\r\n\t\t\tfor (const punishment of punishmentList) {\r\n\t\t\t\tconst {type, id, expireTime} = punishment;\r\n\t\t\t\tif (type === 'BLACKLIST') {\r\n\t\t\t\t\tif (!blMap.has(id)) blMap.set(id, [expireTime]);\r\n\t\t\t\t\tif (id !== userid) blMap.get(id)!.push(userid);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tif (user.can('ip')) {\r\n\t\t\tconst roomIps = Punishments.roomIps.get(room.roomid);\r\n\r\n\t\t\tif (roomIps) {\r\n\t\t\t\tips = '/ips';\r\n\t\t\t\tfor (const [ip, punishments] of roomIps) {\r\n\t\t\t\t\tfor (const punishment of punishments) {\r\n\t\t\t\t\t\tconst {type, id} = punishment;\r\n\t\t\t\t\t\tif (type === 'BLACKLIST') {\r\n\t\t\t\t\t\t\tif (!blMap.has(id)) blMap.set(id, []);\r\n\t\t\t\t\t\t\tblMap.get(id)!.push(ip);\r\n\t\t\t\t\t\t}\r\n\t\t\t\t\t}\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t}\r\n\r\n\t\tconst soonExpiring = (cmd === 'expiringblacklists' || cmd === 'expiringbls');\r\n\t\tlet buf = Utils.html`Blacklist for ${room.title}${soonExpiring ? ` (expiring within 3 months)` : ''}:
`;\r\n\r\n\t\tfor (const [userid, data] of blMap) {\r\n\t\t\tconst [expireTime, ...alts] = data;\r\n\t\t\tif (soonExpiring && expireTime > Date.now() + SOON_EXPIRING_TIME) continue;\r\n\t\t\tconst expiresIn = new Date(expireTime).getTime() - Date.now();\r\n\t\t\tconst expiresDays = Math.round(expiresIn / 1000 / 60 / 60 / 24);\r\n\t\t\tbuf += `- ${userid}, for ${Chat.count(expiresDays, \"days\")}`;\r\n\t\t\tif (alts.length) buf += `, alts${ips}: ${alts.join(', ')}`;\r\n\t\t\tbuf += `
`;\r\n\t\t}\r\n\r\n\t\tthis.sendReplyBox(buf);\r\n\t},\r\n\tshowblacklisthelp: [\r\n\t\t`/showblacklist OR /showbl - show a list of blacklisted users in the room. Requires: % @ # &`,\r\n\t\t`/expiringblacklists OR /expiringbls - show a list of blacklisted users from the room whose blacklists are expiring in 3 months or less. Requires: % @ # &`,\r\n\t],\r\n};\r\n"], "mappings": "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", "names": ["sectionid"] }