"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); var room_settings_exports = {}; __export(room_settings_exports, { RoomSections: () => RoomSections, commands: () => commands, pages: () => pages, roomSettings: () => roomSettings, sections: () => sections }); module.exports = __toCommonJS(room_settings_exports); var import_lib = require("../../lib"); /** * Room settings commands * Pokemon Showdown - http://pokemonshowdown.com/ * * Commands for settings relating to room setting filtering. * * @license MIT */ const RANKS = Config.groupsranking; const SLOWCHAT_MINIMUM = 2; const SLOWCHAT_MAXIMUM = 60; const SLOWCHAT_USER_REQUIREMENT = 10; const sections = [ "official", "battleformats", "languages", "entertainment", "gaming", "lifehobbies", "onsitegames" ]; const RoomSections = { sectionNames: { official: "Official", battleformats: "Battle formats", languages: "Languages", entertainment: "Entertainment", gaming: "Gaming", lifehobbies: "Life & hobbies", onsitegames: "On-site games" }, sections }; const commands = { roomsetting: "roomsettings", roomsettings(target, room, user, connection) { room = this.requireRoom(); if (room.battle) return this.errorReply("This command cannot be used in battle rooms."); let uhtml = "uhtml"; if (!target) { room.update(); } else { void this.parse(`/${target}`); uhtml = "uhtmlchange"; } let output = import_lib.Utils.html`
Room Settings for ${room.title}
`; for (const handler of Chat.roomSettings) { const setting = handler(room, user, connection); if (typeof setting.permission === "string") setting.permission = user.can(setting.permission, null, room); output += `${setting.label}:
`; for (const option of setting.options) { if (option[1] === true) { output += import_lib.Utils.html` `; } else { if (!setting.permission) continue; output += import_lib.Utils.html` `; } } output += `
`; } output += "
"; user.sendTo(room, `|${uhtml}|roomsettings|${output}`); }, roomsettingshelp: [`/roomsettings - Shows current room settings with buttons to change them (if you can).`], modchat(target, room, user) { room = this.requireRoom(); if (!target) { const modchatSetting = room.settings.modchat || "OFF"; return this.sendReply(`Moderated chat is currently set to: ${modchatSetting}`); } if (user.locked) { return this.errorReply(`/modchat - Access denied.`); } else { this.checkCan("modchat", null, room); } if (room.settings.modchat && room.settings.modchat.length <= 1 && !room.auth.atLeast(user, room.settings.modchat) && // Upper Staff should probably be able to set /modchat & in secret rooms !user.can("bypassall")) { return this.errorReply(`/modchat - Access denied for changing a setting currently at ${room.settings.modchat}.`); } if (room.requestModchat) { const error = room.requestModchat(user); if (error) return this.errorReply(error); } if (room.battle?.forcedSettings.modchat && !user.can("rangeban")) { return this.errorReply( `This battle is required to have modchat on due to one of the players having a username that starts with ${room.battle.forcedSettings.modchat}.` ); } target = target.toLowerCase().trim(); const currentModchat = room.settings.modchat; switch (target) { case "off": case "false": case "no": case "disable": room.settings.modchat = null; break; case "ac": case "autoconfirmed": room.settings.modchat = "autoconfirmed"; break; case "trusted": room.settings.modchat = "trusted"; break; case "player": target = Users.PLAYER_SYMBOL; default: if (!Users.Auth.isAuthLevel(target) || ["\u203D", "!"].includes(target)) { this.errorReply(`The rank '${target}' was unrecognized as a modchat level.`); return this.parse("/help modchat"); } const modchatLevelHigherThanUserRank = !room.auth.atLeast(user, target) && !user.can("bypassall"); if (modchatLevelHigherThanUserRank || !Users.Auth.hasPermission(user, "modchat", target, room)) { return this.errorReply(`/modchat - Access denied for setting to ${target}.`); } room.settings.modchat = target; break; } if (currentModchat === room.settings.modchat) { return this.errorReply(`Modchat is already set to ${currentModchat || "off"}.`); } if (!room.settings.modchat) { this.add('|raw|
Moderated chat was disabled!
Anyone may talk now.
'); } else { const modchatSetting = import_lib.Utils.escapeHTML(room.settings.modchat); this.add(`|raw|
Moderated chat was set to ${modchatSetting}!
Only users of rank ${modchatSetting} and higher can talk.
`); } if (room.requestModchat && !room.settings.modchat) room.requestModchat(null); this.privateModAction(`${user.name} set modchat to ${room.settings.modchat || "off"}`); this.modlog("MODCHAT", null, `to ${room.settings.modchat || "false"}`); room.saveSettings(); }, modchathelp: [ `/modchat [off/autoconfirmed/trusted/+/%/@/*/player/#/&] - Set the level of moderated chat. Requires: % \u2606 for off/autoconfirmed/+ options, * @ # & for all the options` ], automodchat(target, room, user) { room = this.requireRoom(); if (!target) { if (!room.settings.autoModchat) return this.sendReply(`This room has automodchat OFF.`); const { rank: curRank, time: curTime } = room.settings.autoModchat; return this.sendReply(`Automodchat is currently set to set modchat to ${curRank} after ${curTime} minutes.`); } this.checkCan("declare", null, room); if (this.meansNo(toID(target))) { if (!room.settings.autoModchat) return this.errorReply(`Auto modchat is not set.`); delete room.settings.autoModchat; room.saveSettings(); if (room.modchatTimer) clearTimeout(room.modchatTimer); this.privateModAction(`${user.name} turned off automatic modchat.`); return this.modlog(`AUTOMODCHAT`, null, "OFF"); } let [rawTime, rank] = import_lib.Utils.splitFirst(target, ",").map((i) => i.trim()); if (!rawTime) { return this.parse(`/help automodchat`); } if (!rank) { if (room.settings.autoModchat) { rank = room.settings.autoModchat.rank; } else { return this.parse(`/help automodchat`); } } const validGroups = [...Config.groupsranking, "trusted"]; if (!validGroups.includes(rank)) { return this.errorReply(`Invalid rank.`); } const time = parseInt(rawTime); if (isNaN(time) || time > 480 || time < 5) { return this.errorReply("Invalid duration. Choose a number under 480 (in minutes) and over 5 minutes."); } room.settings.autoModchat = { rank, time, active: false }; this.privateModAction(`${user.name} set automodchat to rank ${rank} and timeout ${time} minutes.`); this.modlog(`AUTOMODCHAT`, null, `${rank}: ${time} minutes`); room.saveSettings(); }, automodchathelp: [ `/automodchat [number], [rank] - Sets modchat [rank] to automatically turn on after [number] minutes with no staff.`, `[number] must be between 5 and 480. Requires: # &`, `/automodchat off - Turns off automodchat.` ], ionext() { this.errorReply(`"ionext" is an outdated feature. Hidden battles now have password-protected URLs, making them fully secure against eavesdroppers.`); this.errorReply(`You probably want to switch from /ionext to /hidenext, and from /ioo to /hideroom`); }, ioo() { this.errorReply(`"ioo" is an outdated feature. Hidden battles now have password-protected URLs, making them fully secure against eavesdroppers.`); this.errorReply(`You probably want to switch from /ioo to /hideroom`); }, inviteonlynext(target, room, user) { const groupConfig = Config.groups[Users.PLAYER_SYMBOL]; if (!groupConfig?.editprivacy) return this.errorReply(`/ionext - Access denied.`); if (this.meansNo(target)) { user.battleSettings.inviteOnly = false; user.update(); this.sendReply("Your next battle will be publicly visible."); } else { user.battleSettings.inviteOnly = true; user.update(); this.sendReply(`Your next battle will be invite-only${Rooms.RoomBattle.battleForcedSetting(user, "privacy") ? `, unless it is rated` : ``}.`); } }, inviteonlynexthelp: [ `/inviteonlynext - Sets your next battle to be invite-only.`, `/inviteonlynext off - Sets your next battle to be publicly visible.` ], inviteonly(target, room, user, connection, cmd) { room = this.requireRoom(); if (!target) return this.parse("/help inviteonly"); if (this.meansYes(target)) { return this.parse("/modjoin %"); } else { return this.parse(`/modjoin ${target}`); } }, inviteonlyhelp: [ `/inviteonly [on|off] - Sets modjoin %. Users can't join unless invited with /invite. Requires: # &`, `/ioo - Shortcut for /inviteonly on`, `/inviteonlynext OR /ionext - Sets your next battle to be invite-only.`, `/ionext off - Sets your next battle to be publicly visible.` ], modjoin(target, room, user) { room = this.requireRoom(); if (!target) { const modjoinSetting = room.settings.modjoin === true ? "SYNC" : room.settings.modjoin || "OFF"; return this.sendReply(`Modjoin is currently set to: ${modjoinSetting}`); } if (room.battle) { this.checkCan("editprivacy", null, room); if (room.battle.forcedSettings.privacy) { return this.errorReply( `This battle is required to be public due to a player having a name prefixed by '${room.battle.forcedSettings.privacy}'.` ); } if (room.battle.inviteOnlySetter && !user.can("mute", null, room) && room.battle.inviteOnlySetter !== user.id) { return this.errorReply(`Only the person who set this battle to be invite-only can turn it off.`); } room.battle.inviteOnlySetter = user.id; } else if (room.settings.isPersonal) { this.checkCan("editroom", null, room); } else { this.checkCan("makeroom"); } if (room.tour && !room.tour.allowModjoin) { return this.errorReply(`You can't do this in tournaments where modjoin is prohibited.`); } if (target === "player") target = Users.PLAYER_SYMBOL; if (this.meansNo(target)) { if (!room.settings.modjoin) return this.errorReply(`Modjoin is already turned off in this room.`); room.settings.modjoin = null; this.add(`|raw|
This room is no longer invite only!
Anyone may now join.
`); this.addModAction(`${user.name} turned off modjoin.`); this.modlog("MODJOIN", null, "OFF"); if (room.battle) room.battle.inviteOnlySetter = null; room.saveSettings(); return; } else if (target === "sync") { if (room.settings.modjoin === true) return this.errorReply(`Modjoin is already set to sync modchat in this room.`); room.settings.modjoin = true; this.add(`|raw|
Moderated join is set to sync with modchat!
Only users who can speak in modchat can join.
`); this.addModAction(`${user.name} set modjoin to sync with modchat.`); this.modlog("MODJOIN SYNC"); } else if (target === "ac" || target === "autoconfirmed") { if (room.settings.modjoin === "autoconfirmed") return this.errorReply(`Modjoin is already set to autoconfirmed.`); room.settings.modjoin = "autoconfirmed"; this.add(`|raw|
Moderated join is set to autoconfirmed!
Users must be rank autoconfirmed or invited with /invite to join
`); this.addModAction(`${user.name} set modjoin to autoconfirmed.`); this.modlog("MODJOIN", null, "autoconfirmed"); } else if (Users.Auth.isAuthLevel(target) && !["\u203D", "!"].includes(target)) { if (room.battle && !user.can("makeroom") && !"+%".includes(target)) { return this.errorReply(`/modjoin - Access denied from setting modjoin past % in battles.`); } if (room.settings.isPersonal && !user.can("makeroom") && !"+%".includes(target)) { return this.errorReply(`/modjoin - Access denied from setting modjoin past % in group chats.`); } if (room.settings.modjoin === target) return this.errorReply(`Modjoin is already set to ${target} in this room.`); room.settings.modjoin = target; this.add(`|raw|
This room is now invite only!
Users must be rank ${target} or invited with /invite to join
`); this.addModAction(`${user.name} set modjoin to ${target}.`); this.modlog("MODJOIN", null, target); } else { this.errorReply(`Unrecognized modjoin setting.`); void this.parse("/help modjoin"); return false; } room.saveSettings(); if (target === "sync" && !room.settings.modchat) { const lowestGroup = Config.groupsranking.filter((group) => { const groupInfo = Users.Auth.getGroup(group); return groupInfo.symbol !== Users.Auth.defaultSymbol() && room.auth.atLeast(user, group) && Users.Auth.isValidSymbol(groupInfo.symbol); })[0]; if (lowestGroup) void this.parse(`/modchat ${lowestGroup}`); } if (!room.settings.isPrivate) return this.parse("/hiddenroom"); }, modjoinhelp: [ `/modjoin [+|%|@|*|player|&|#|off] - Sets modjoin. Users lower than the specified rank can't join this room unless they have a room rank. Requires: \u2606 # &`, `/modjoin [sync|off] - Sets modjoin. Only users who can speak in modchat can join this room. Requires: \u2606 # &` ], roomlanguage(target, room, user) { room = this.requireRoom(); if (!target) { return this.sendReply(`This room's primary language is ${Chat.languages.get(room.settings.language || "") || "English"}`); } this.checkCan("editroom", null, room); const targetLanguage = toID(target); if (!Chat.languages.has(targetLanguage)) return this.errorReply(`"${target}" is not a supported language.`); room.settings.language = targetLanguage === "english" ? false : targetLanguage; room.saveSettings(); this.modlog(`LANGUAGE`, null, Chat.languages.get(targetLanguage)); this.sendReply(`The room's language has been set to ${Chat.languages.get(targetLanguage)}`); }, roomlanguagehelp: [ `/roomlanguage [language] - Sets the the language for the room, which changes language of a few commands. Requires # &`, `Supported Languages: English, Spanish, Italian, French, Simplified Chinese, Traditional Chinese, Japanese, Hindi, Turkish, Dutch, German.` ], slowchat(target, room, user) { room = this.requireRoom(); if (!target) { const slowchatSetting2 = room.settings.slowchat || "OFF"; return this.sendReply(`Slow chat is currently set to: ${slowchatSetting2}`); } this.checkChat(); this.checkCan("modchat", null, room); let targetInt = parseInt(target); if (this.meansNo(target)) { if (!room.settings.slowchat) return this.errorReply(`Slow chat is already disabled in this room.`); room.settings.slowchat = false; } else if (targetInt) { if (!user.can("bypassall") && room.userCount < SLOWCHAT_USER_REQUIREMENT) { return this.errorReply(`This room must have at least ${SLOWCHAT_USER_REQUIREMENT} users to set slowchat; it only has ${room.userCount} right now.`); } if (room.settings.slowchat === targetInt) { return this.errorReply(`Slow chat is already set to ${room.settings.slowchat} seconds in this room.`); } if (targetInt < SLOWCHAT_MINIMUM) targetInt = SLOWCHAT_MINIMUM; if (targetInt > SLOWCHAT_MAXIMUM) targetInt = SLOWCHAT_MAXIMUM; room.settings.slowchat = targetInt; } else { return this.parse("/help slowchat"); } const slowchatSetting = room.settings.slowchat || "OFF"; this.privateModAction(`${user.name} set slowchat to ${slowchatSetting}`); this.modlog("SLOWCHAT", null, "" + slowchatSetting); room.saveSettings(); }, slowchathelp: [ `/slowchat [number] - Sets a limit on how often users in the room can send messages, between 2 and 60 seconds. Requires @ # &`, `/slowchat off - Disables slowchat in the room. Requires @ # &` ], permission: "permissions", permissions: { clear: "set", set(target, room, user) { let [perm, rank] = this.splitOne(target); room = this.requireRoom(); if (rank === "default") rank = ""; if (!room.persist) return this.errorReply(`This room does not allow customizing permissions.`); if (!target || !perm) return this.parse(`/permissions help`); if (rank && rank !== "whitelist" && !Config.groupsranking.includes(rank)) { return this.errorReply(`${rank} is not a valid rank.`); } const validPerms = Users.Auth.supportedRoomPermissions(room); if (!validPerms.some((p) => p === perm || p.startsWith(`${perm} `))) { return this.errorReply(`${perm} is not a valid room permission.`); } if (!room.auth.atLeast(user, "#")) { return this.errorReply(`/permissions set - You must be at least a Room Owner to set permissions.`); } if (Users.Auth.ROOM_PERMISSIONS.includes(perm) && !Users.Auth.hasPermission(user, perm, null, room)) { return this.errorReply(`/permissions set - You can't set the permission "${perm}" because you don't have it.`); } const currentPermissions = room.settings.permissions || {}; if (currentPermissions[perm] === (rank || void 0)) { return this.errorReply(`${perm} is already set to ${rank || "default"}.`); } if (rank) { currentPermissions[perm] = rank; room.settings.permissions = currentPermissions; } else { delete currentPermissions[perm]; if (!Object.keys(currentPermissions).length) delete room.settings.permissions; } room.saveSettings(); if (!rank) rank = `default`; this.modlog(`SETPERMISSION`, null, `${perm}: ${rank}`); this.refreshPage(`permissions-${room.roomid}`); return this.privateModAction(`${user.name} set the required rank for ${perm} to ${rank}.`); }, sethelp: [ `/permissions set [command], [rank symbol] - sets the required permission to use the command [command] to [rank]. Requires: # &`, `/permissions clear [command] - resets the required permission to use the command [command] to the default. Requires: # &` ], view(target, room, user) { room = this.requireRoom(); return this.parse(`/join view-permissions-${room.roomid}`); }, help: "", ""(target, room, user) { room = this.requireRoom(); const allPermissions = Users.Auth.supportedRoomPermissions(room); const permissionGroups = allPermissions.filter((perm) => !perm.startsWith("/")); const permissions = allPermissions.filter((perm) => { const handler = Chat.parseCommand(perm)?.handler; if (handler?.isPrivate && !user.can("lock")) return false; return perm.startsWith("/") && !perm.includes(" "); }); const subPermissions = allPermissions.filter((perm) => perm.startsWith("/") && perm.includes(" ")).filter((perm) => { const handler = Chat.parseCommand(perm)?.handler; if (handler?.isPrivate && !user.can("lock")) return false; return perm.startsWith("/") && perm.includes(" "); }); const subPermissionsByNamespace = {}; for (const perm of subPermissions) { const [namespace] = perm.split(" ", 1); if (!subPermissionsByNamespace[namespace]) subPermissionsByNamespace[namespace] = []; subPermissionsByNamespace[namespace].push(perm); } let buffer = `Room permissions help:
`; buffer += `

Usage:
`; buffer += `/permissions set [permission], [rank symbol]
`; buffer += `/permissions clear [permission]
`; buffer += `/permissions view

`; buffer += `

Group permissions: (will affect multiple commands or part of one command)
`; buffer += `` + permissionGroups.join(` `) + `

`; buffer += `

Single-command permissions: (will affect one command)`; buffer += `` + permissions.join(` `) + `

`; buffer += `

Sub-commands: (will affect one sub-command, like /roomevents view)`; for (const subPerms of Object.values(subPermissionsByNamespace)) { buffer += `
` + subPerms.join(` `) + `
`; } buffer += `

`; return this.sendReplyBox(buffer); } }, stretching: "stretchfilter", stretchingfilter: "stretchfilter", stretchfilter(target, room, user) { room = this.requireRoom(); if (!target) { const stretchSetting2 = room.settings.filterStretching ? "ON" : "OFF"; return this.sendReply(`This room's stretch filter is currently: ${stretchSetting2}`); } this.checkChat(); this.checkCan("editroom", null, room); if (this.meansYes(target)) { if (room.settings.filterStretching) return this.errorReply(`This room's stretch filter is already ON`); room.settings.filterStretching = true; } else if (this.meansNo(target)) { if (!room.settings.filterStretching) return this.errorReply(`This room's stretch filter is already OFF`); room.settings.filterStretching = false; } else { return this.parse("/help stretchfilter"); } const stretchSetting = room.settings.filterStretching ? "ON" : "OFF"; this.privateModAction(`${user.name} turned the stretch filter ${stretchSetting}`); this.modlog("STRETCH FILTER", null, stretchSetting); room.saveSettings(); }, stretchfilterhelp: [ `/stretchfilter [on/off] - Toggles filtering messages in the room for stretchingggggggg. Requires # &` ], capitals: "capsfilter", capitalsfilter: "capsfilter", capsfilter(target, room, user) { room = this.requireRoom(); if (!target) { const capsSetting2 = room.settings.filterCaps ? "ON" : "OFF"; return this.sendReply(`This room's caps filter is currently: ${capsSetting2}`); } this.checkChat(); this.checkCan("editroom", null, room); if (this.meansYes(target)) { if (room.settings.filterCaps) return this.errorReply(`This room's caps filter is already ON`); room.settings.filterCaps = true; } else if (this.meansNo(target)) { if (!room.settings.filterCaps) return this.errorReply(`This room's caps filter is already OFF`); room.settings.filterCaps = false; } else { return this.parse("/help capsfilter"); } const capsSetting = room.settings.filterCaps ? "ON" : "OFF"; this.privateModAction(`${user.name} turned the caps filter ${capsSetting}`); this.modlog("CAPS FILTER", null, capsSetting); room.saveSettings(); }, capsfilterhelp: [`/capsfilter [on/off] - Toggles filtering messages in the room for EXCESSIVE CAPS. Requires # &`], emojis: "emojifilter", emoji: "emojifilter", emojifilter(target, room, user) { room = this.requireRoom(); if (!target) { const emojiSetting2 = room.settings.filterEmojis ? "ON" : "OFF"; return this.sendReply(`This room's emoji filter is currently: ${emojiSetting2}`); } this.checkChat(); this.checkCan("editroom", null, room); if (this.meansYes(target)) { if (room.settings.filterEmojis) return this.errorReply(`This room's emoji filter is already ON`); room.settings.filterEmojis = true; } else if (this.meansNo(target)) { if (!room.settings.filterEmojis) return this.errorReply(`This room's emoji filter is already OFF`); room.settings.filterEmojis = false; } else { return this.parse("/help emojifilter"); } const emojiSetting = room.settings.filterEmojis ? "ON" : "OFF"; this.privateModAction(`${user.name} turned the emoji filter ${emojiSetting}`); this.modlog("EMOJI FILTER", null, emojiSetting); room.saveSettings(); }, emojifilterhelp: [`/emojifilter [on/off] - Toggles filtering messages in the room for emojis. Requires # &`], linkfilter(target, room, user) { room = this.requireRoom(); if (!target) { return this.sendReply( `This room's link filter is currently: ${room.settings.filterEmojis ? "ON" : "OFF"}` ); } this.checkChat(); this.checkCan("editroom", null, room); if (this.meansYes(target)) { if (room.settings.filterLinks) return this.errorReply(`This room's link filter is already ON`); room.settings.filterLinks = true; } else if (this.meansNo(target)) { if (!room.settings.filterLinks) return this.errorReply(`This room's link filter is already OFF`); room.settings.filterLinks = false; } else { return this.parse("/help linkfilter"); } const setting = room.settings.filterLinks ? "ON" : "OFF"; this.privateModAction(`${user.name} turned the link filter ${setting}`); this.modlog("LINK FILTER", null, setting); room.saveSettings(); }, linkfilterhelp: [`/linkfilter [on/off] - Toggles filtering messages in the room for links. Requires # &`], banwords: "banword", banword: { regexadd: "add", addregex: "add", add(target, room, user, connection, cmd) { room = this.requireRoom(); if (!target || target === " ") return this.parse("/help banword"); this.checkCan("declare", null, room); const regex = cmd.includes("regex"); if (regex && !user.can("makeroom")) return this.errorReply("Regex banwords are only allowed for administrators."); if (!room.settings.banwords) room.settings.banwords = []; let words = (regex ? target.match(/[^,]+(,\d*}[^,]*)?/g) : target.split(",")).map((word) => word.replace(/\n/g, "").trim()).filter((word) => word.length > 0); if (!words || words.length === 0) return this.parse("/help banword"); if (!regex) { words = words.map((word) => { if (/[\\^$*+?()|{}[\]]/.test(word) && user.can("rangeban")) { this.errorReply(`"${word}" might be a regular expression, did you mean "/banword addregex"?`); } return import_lib.Utils.escapeRegex(word); }); } let banwordRegexLen = room.banwordRegex instanceof RegExp ? room.banwordRegex.source.length : 32; for (const word of words) { Chat.validateRegex(word); if (room.settings.banwords.includes(word)) return this.errorReply(`${word} is already a banned phrase.`); banwordRegexLen += banwordRegexLen === 32 ? word.length : `|${word}`.length; if (banwordRegexLen >= 1 << 16 - 1) { return this.errorReply("This room has too many banned phrases to add the ones given."); } } for (const word of words) { room.settings.banwords.push(word); } room.banwordRegex = null; if (words.length > 1) { this.privateModAction(`The banwords ${words.map((w) => `'${w}'`).join(", ")} were added by ${user.name}.`); this.modlog("BANWORD", null, words.map((w) => `'${w}'`).join(", ")); this.sendReply(`Banned phrases successfully added.`); } else { this.privateModAction(`The banword '${words[0]}' was added by ${user.name}.`); this.modlog("BANWORD", null, words[0]); this.sendReply(`Banned phrase successfully added.`); } this.sendReply(`The list is currently: ${room.settings.banwords.join(", ")}`); room.saveSettings(); }, delete(target, room, user) { room = this.requireRoom(); if (!target) return this.parse("/help banword"); this.checkCan("declare", null, room); if (!room.settings.banwords) return this.errorReply("This room has no banned phrases."); const regexMatch = target.match(/[^,]+(,\d*}[^,]*)?/g); if (!regexMatch) return this.parse("/help banword"); const words = regexMatch.map((word) => word.replace(/\n/g, "").trim()).filter((word) => word.length > 0); for (const word of words) { if (!room.settings.banwords.includes(word)) return this.errorReply(`${word} is not a banned phrase in this room.`); } room.settings.banwords = room.settings.banwords.filter((w) => !words.includes(w)); room.banwordRegex = null; if (words.length > 1) { this.privateModAction(`The banwords ${words.map((w) => `'${w}'`).join(", ")} were removed by ${user.name}.`); this.modlog("UNBANWORD", null, words.map((w) => `'${w}'`).join(", ")); this.sendReply(`Banned phrases successfully deleted.`); } else { this.privateModAction(`The banword '${words[0]}' was removed by ${user.name}.`); this.modlog("UNBANWORD", null, words[0]); this.sendReply(`Banned phrase successfully deleted.`); } if (!room.settings.banwords.length) room.settings.banwords = void 0; this.sendReply( room.settings.banwords ? `The list is now: ${room.settings.banwords.join(", ")}` : `The list is now empty.` ); room.saveSettings(); }, list(target, room, user) { room = this.requireRoom(); this.checkCan("mute", null, room); if (!room.settings.banwords?.length) { return this.sendReply("This room has no banned phrases."); } return this.sendReply(`Banned phrases in room ${room.roomid}: ${room.settings.banwords.join(", ")}`); }, ""(target, room, user) { return this.parse("/help banword"); } }, banwordhelp: [ `/banword add [words] - Adds the comma-separated list of phrases to the banword list of the current room. Requires: # &`, `/banword addregex [words] - Adds the comma-separated list of regular expressions to the banword list of the current room. Requires &`, `/banword delete [words] - Removes the comma-separated list of phrases from the banword list. Requires: # &`, `/banword list - Shows the list of banned words in the current room. Requires: % @ # &` ], showapprovals(target, room, user) { room = this.requireRoom(); this.checkCan("declare", null, room); target = toID(target); if (!target) { return this.sendReply(`Approvals are currently ${room.settings.requestShowEnabled ? `ENABLED` : `DISABLED`} for ${room}.`); } if (this.meansNo(target)) { if (!room.settings.requestShowEnabled) return this.errorReply(`Approvals are already disabled.`); room.settings.requestShowEnabled = void 0; this.privateModAction(`${user.name} disabled approvals in this room.`); } else if (this.meansYes(target)) { if (room.settings.requestShowEnabled) return this.errorReply(`Approvals are already enabled.`); room.settings.requestShowEnabled = true; this.privateModAction(`${user.name} enabled the use of media approvals in this room.`); if (!room.settings.permissions || room.settings.permissions["/show"] === "@") { this.privateModAction( `Note: Due to this room's settings, Drivers aren't allowed to use /show directly, but will be able to request and approve each other's /requestshow` ); } } else { return this.errorReply(`Unrecognized setting for approvals. Use 'on' or 'off'.`); } room.saveSettings(); return this.modlog(`SHOWAPPROVALS`, null, `${this.meansYes(target) ? `ON` : `OFF`}`); }, showapprovalshelp: [ `/showapprovals [setting] - Enable or disable the use of media approvals in the current room.`, `Requires: # &` ], showmedia(target, room, user) { this.errorReply(`/showmedia has been deprecated. Use /permissions instead.`); return this.parse(`/help permissions`); }, hightraffic(target, room, user) { room = this.requireRoom(); if (!target) { return this.sendReply(`This room is: ${room.settings.highTraffic ? "high traffic" : "low traffic"}`); } this.checkCan("makeroom"); if (this.meansYes(target)) { room.settings.highTraffic = true; } else if (this.meansNo(target)) { room.settings.highTraffic = void 0; } else { return this.parse("/help hightraffic"); } room.saveSettings(); this.modlog(`HIGHTRAFFIC`, null, `${!!room.settings.highTraffic}`); this.addModAction(`This room was marked as high traffic by ${user.name}.`); }, hightraffichelp: [ `/hightraffic [on|off] - (Un)marks a room as a high traffic room. Requires &`, `When a room is marked as high-traffic, PS requires all messages sent to that room to contain at least 2 letters.` ], /********************************************************* * Room management *********************************************************/ makeprivatechatroom: "makechatroom", makepublicchatroom: "makechatroom", makechatroom(target, room, user, connection, cmd) { room = this.requireRoom(); this.checkCan("makeroom"); const id = toID(target); if (!id || this.cmd === "makechatroom") return this.parse("/help makechatroom"); if (!Rooms.global.addChatRoom(target)) { return this.errorReply(`An error occurred while trying to create the room '${target}'.`); } const targetRoom = Rooms.search(target); if (!targetRoom) throw new Error(`Error in room creation.`); if (cmd === "makeprivatechatroom") { if (!targetRoom.persist) throw new Error(`Private chat room created without settings.`); targetRoom.setPrivate(true); const upperStaffRoom = Rooms.get("upperstaff"); if (upperStaffRoom) { upperStaffRoom.add(`|raw|
Private chat room created: ${import_lib.Utils.escapeHTML(target)}
`).update(); } this.sendReply(`The private chat room '${target}' was created.`); } else { const staffRoom = Rooms.get("staff"); if (staffRoom) { staffRoom.add(`|raw|
Public chat room created: ${import_lib.Utils.escapeHTML(target)}
`).update(); } const upperStaffRoom = Rooms.get("upperstaff"); if (upperStaffRoom) { upperStaffRoom.add(`|raw|
Public chat room created: ${import_lib.Utils.escapeHTML(target)}
`).update(); } this.sendReply(`The chat room '${target}' was created.`); } }, makechatroomhelp: [ `/makeprivatechatroom [roomname] - Creates a new private room named [roomname]. Requires: &`, `/makepublicchatroom [roomname] - Creates a new public room named [roomname]. Requires: &` ], subroomgroupchat: "makegroupchat", srgc: "makegroupchat", mgc: "makegroupchat", makegroupchat(target, room, user, connection, cmd) { room = this.requireRoom(); this.checkChat(); if (!user.trusted) { return this.errorReply("You must be trusted (public room driver or global voice) to make a groupchat."); } const groupchatbanned = Punishments.isGroupchatBanned(user); if (groupchatbanned) { const expireText = Punishments.checkPunishmentExpiration(groupchatbanned); return this.errorReply(`You are banned from using groupchats ${expireText}.`); } if (cmd === "subroomgroupchat" || cmd === "srgc") { if (!user.can("mute", null, room)) { return this.errorReply("You can only create subroom groupchats for rooms you're staff in."); } if (room.battle) return this.errorReply("You cannot create a subroom of a battle."); if (room.settings.isPersonal) return this.errorReply("You cannot create a subroom of a groupchat."); } const parent = cmd === "subroomgroupchat" || cmd === "srgc" ? room.roomid : null; let title = target.trim(); if (title.length >= 32) { return this.errorReply("Title must be under 32 characters long."); } else if (!title) { title = `${Math.floor(Math.random() * 1e8)}`; } else if (this.filter(title) !== title) { return this.errorReply("Invalid title."); } if (title.includes(",") || title.includes("|") || title.includes("[") || title.includes("-")) { return this.errorReply("Room titles can't contain any of: ,|[-"); } const existingRoom = Rooms.search(toID(title)); if (existingRoom && !existingRoom.settings.modjoin) { return this.errorReply(`Your group chat name is too similar to existing chat room '${title}'.`); } let titleid = toID(title); if (!titleid) { titleid = `${Math.floor(Math.random() * 1e8)}`; } const roomid = `groupchat-${parent || user.id}-${titleid}`; if (Rooms.search(roomid)) return this.errorReply(`A group chat named '${title}' already exists.`); if (Monitor.countGroupChat(connection.ip)) { this.errorReply("Due to high load, you are limited to creating 4 group chats every hour."); return; } const titleMsg = import_lib.Utils.html`Welcome to ${parent ? room.title : user.name}'s` + import_lib.Utils.html`${!/^[0-9]+$/.test(title) ? ` ${title}` : ""}${parent ? " subroom" : ""} groupchat!`; const targetRoom = Rooms.createChatRoom(roomid, `[G] ${title}`, { isPersonal: true, isPrivate: "hidden", creationTime: Date.now(), modjoin: parent ? null : "+", parentid: parent, auth: {}, introMessage: `

${titleMsg}

Follow the Pok\xE9mon Showdown Global Rules!
Don't be disruptive to the rest of the site.

`, staffMessage: `

Groupchats are temporary rooms, and will expire if there hasn't been any activity in 40 minutes.

You can invite new users using /invite. Be careful with who you invite!

Commands: | |

As creator of this groupchat, you are entirely responsible for what occurs in this chatroom. Global rules apply at all times.

If this room is used to break global rules or disrupt other areas of the server, you as the creator will be held accountable and punished.

` }); if (!targetRoom) { return this.errorReply(`An unknown error occurred while trying to create the room '${title}'.`); } targetRoom.auth.set(user.id, parent ? "#" : Users.HOST_SYMBOL); user.joinRoom(targetRoom.roomid); user.popup(`You've just made a groupchat; it is now your responsibility, regardless of whether or not you actively partake in the room. For more info, read your groupchat's staff intro.`); if (parent) this.modlog("SUBROOMGROUPCHAT", null, title); }, makegroupchathelp: [ `/makegroupchat [roomname] - Creates an invite-only group chat named [roomname].`, `/subroomgroupchat [roomname] - Creates a subroom groupchat of the current room. Can only be used in a public room you have staff in.`, `Only users who are staff in a public room or global auth can make groupchats.` ], groupchatuptime: "roomuptime", roomuptime(target, room, user, connection, cmd) { if (!this.runBroadcast()) return; if (!room) return this.errorReply(`Can only be used in a room.`); if (!room.settings.creationTime) room.settings.creationTime = Date.now(); const uptime = Chat.toDurationString(Date.now() - room.settings.creationTime); this.sendReplyBox(`Room uptime: ${uptime}`); }, roomuptimehelp: [`/roomuptime - Displays the uptime of the room.`], deregisterchatroom(target, room, user) { this.checkCan("makeroom"); this.errorReply("NOTE: You probably want to use `/deleteroom` now that it exists."); const id = toID(target); if (!id) return this.parse("/help deregisterchatroom"); const targetRoom = Rooms.search(id); if (!targetRoom) return this.errorReply(`The room '${target}' doesn't exist.`); target = targetRoom.title || targetRoom.roomid; const isPrivate = targetRoom.settings.isPrivate; const staffRoom = Rooms.get("staff"); const upperStaffRoom = Rooms.get("upperstaff"); if (Rooms.global.deregisterChatRoom(id)) { this.sendReply(`The room '${target}' was deregistered.`); this.sendReply("It will be deleted as of the next server restart."); target = import_lib.Utils.escapeHTML(target); if (isPrivate) { if (upperStaffRoom) { upperStaffRoom.add(`|raw|
Private chat room deregistered by ${user.id}: ${target}
`).update(); } } else { if (staffRoom) { staffRoom.add(`|raw|
Public chat room deregistered: ${target}
`).update(); } if (upperStaffRoom) { upperStaffRoom.add(`|raw|
Public chat room deregistered by ${user.id}: ${target}
`).update(); } } return; } return this.errorReply(`The room "${target}" isn't registered.`); }, deregisterchatroomhelp: [ `/deregisterchatroom [roomname] - Deletes room [roomname] after the next server restart. Requires: &` ], deletechatroom: "deleteroom", deletegroupchat: "deleteroom", dgc: "deleteroom", deleteroom(target, room, user, connection, cmd) { room = this.requireRoom(); const roomid = target.trim(); if (!roomid) { if (!room.settings.isPersonal || !["deletegroupchat", "dgc"].includes(cmd)) { return this.parse(`/help deleteroom`); } } else { const targetRoom = Rooms.search(roomid); if (targetRoom !== room) { return this.parse(`/help deleteroom`); } } if (room.roomid.startsWith("groupchat-")) { this.checkCan("gamemanagement", null, room); } else { this.checkCan("makeroom"); } const title = room.title || room.roomid; if (room.persist) { if (room.settings.isPrivate) { const upperStaffRoom = Rooms.get("upperstaff"); if (upperStaffRoom) { upperStaffRoom.add( import_lib.Utils.html`|raw|
Private chat room ` + `deleted by ${user.id}: ${title}
` ).update(); } } else { const staffRoom = Rooms.get("staff"); if (staffRoom) { staffRoom.add(import_lib.Utils.html`|raw|
Public chat room deleted: ${title}
`).update(); } const upperStaffRoom = Rooms.get("upperstaff"); if (upperStaffRoom) { upperStaffRoom.add( import_lib.Utils.html`|raw|
Public chat ` + `room deleted by ${user.id}: ${title}
` ).update(); } } } room.add(`|raw|
This room has been deleted.
`); room.update(); room.send(`|expire|This room has been deleted.`); room.destroy(); }, deleteroomhelp: [ `/deleteroom [roomname] - Deletes room [roomname]. Must be typed in the room to delete. Requires: &`, `/deletegroupchat - Deletes the current room, if it's a groupchat. Requires: \u2605 # &` ], rename() { this.errorReply("Did you mean /renameroom?"); }, renamegroupchat: "renameroom", renameroom(target, room, user, connection, cmd) { room = this.requireRoom(); if (room.game || room.minorActivity || room.tour) { return this.errorReply("Cannot rename room while a tour/poll/game is running."); } if (room.battle) { return this.errorReply("Cannot rename battle rooms."); } const oldTitle = room.title; const isGroupchat = cmd === "renamegroupchat"; if (!toID(target)) return this.parse("/help renameroom"); if (room.persist && isGroupchat) return this.errorReply(`This isn't a groupchat.`); if (!room.persist && !isGroupchat) return this.errorReply(`Use /renamegroupchat instead.`); if (isGroupchat) { if (!user.can("lock")) this.checkCan("declare", null, room); const existingRoom = Rooms.search(toID(target)); if (existingRoom && !existingRoom.settings.modjoin) { return this.errorReply(`Your groupchat name is too similar to existing chat room '${existingRoom.title}'.`); } if (this.filter(target) !== target) { return this.errorReply("Invalid title."); } if (target.includes(",") || target.includes("|") || target.includes("[") || target.includes("-")) { return this.errorReply("Room titles can't contain any of: ,|[-"); } target = `[G] ${target}`; } else { this.checkCan("makeroom"); } const creatorID = room.roomid.split("-")[1]; const id = isGroupchat ? `groupchat-${creatorID}-${toID(target)}` : void 0; const oldID = room.roomid; room.rename(target, id); Chat.handleRoomRename(oldID, id || toID(target), room); this.modlog(`RENAME${isGroupchat ? "GROUPCHAT" : "ROOM"}`, null, `from ${oldTitle}`); const privacy = room.settings.isPrivate === true ? "Private" : !room.settings.isPrivate ? "Public" : `${room.settings.isPrivate.charAt(0).toUpperCase()}${room.settings.isPrivate.slice(1)}`; if (!isGroupchat) { Rooms.global.notifyRooms( room.settings.isPrivate === true ? ["upperstaff"] : ["upperstaff", "staff"], import_lib.Utils.html`|raw|
${privacy} chat room ${oldTitle} renamed to ${target}
` ); } room.add(import_lib.Utils.html`|raw|
The room has been renamed to ${target}
`).update(); }, renameroomhelp: [`/renameroom [new title] - Renames the current room to [new title]. Case-sensitive. Requires &`], hideroom: "privateroom", hiddenroom: "privateroom", secretroom: "privateroom", publicroom: "privateroom", unlistroom: "privateroom", privateroom(target, room, user, connection, cmd) { room = this.requireRoom(); if (room.battle) { this.checkCan("editprivacy", null, room); if (room.battle.forcedSettings.privacy) { return this.errorReply(`This battle is required to be public because a player has a name prefixed by '${room.battle.forcedSettings.privacy}'.`); } if (room.tour?.forcePublic) { return this.errorReply(`This battle can't be hidden, because the tournament is set to be forced public.`); } } else if (room.settings.isPersonal) { this.checkCan("editroom", null, room); } else { this.checkCan("makeroom"); } let setting; switch (cmd) { case "privateroom": return this.parse("/help privateroom"); case "publicroom": setting = false; break; case "secretroom": this.checkCan("rangeban"); setting = true; break; case "unlistroom": this.checkCan("rangeban"); setting = "unlisted"; break; default: if (room.settings.isPrivate === true && target !== "force") { return this.sendReply(`This room is a secret room. Use "/publicroom" to make it public, or "/hiddenroom force" to force it hidden.`); } setting = "hidden"; break; } if (this.meansNo(target)) { return this.errorReply(`Please specify what privacy setting you want for this room: /hiddenroom, /secretroom, or /publicroom`); } if (!setting) { if (!room.settings.isPrivate) { return this.errorReply(`This room is already public.`); } if (room.parent && room.parent.settings.isPrivate) { return this.errorReply(`This room's parent ${room.parent.title} must be public for this room to be public.`); } if (room.settings.isPersonal && !room.battle) { return this.errorReply(`This room can't be made public.`); } if (room.privacySetter && user.can("nooverride", null, room) && !user.can("makeroom")) { if (!room.privacySetter.has(user.id)) { const privacySetters = [...room.privacySetter].join(", "); return this.errorReply(`You can't make the room public since you didn't make it private - only ${privacySetters} can.`); } room.privacySetter.delete(user.id); if (room.privacySetter.size) { const privacySetters = [...room.privacySetter].join(", "); return this.sendReply(`You are no longer forcing the room to stay private, but ${privacySetters} also need${Chat.plural(room.privacySetter, "", "s")} to use /publicroom to make the room public.`); } } room.privacySetter = null; this.addModAction(`${user.name} made this room public.`); this.modlog("PUBLICROOM"); room.setPrivate(false); } else { const settingName = setting === true ? "secret" : setting; if (room.subRooms) { if (settingName === "secret") return this.errorReply("Secret rooms cannot have subrooms."); for (const subRoom of room.subRooms.values()) { if (!subRoom.settings.isPrivate) { return this.errorReply(`Subroom ${subRoom.title} must be private to make this room private.`); } } } if (room.settings.isPrivate === setting) { if (room.privacySetter && !room.privacySetter.has(user.id)) { room.privacySetter.add(user.id); return this.sendReply(`This room is already ${settingName}, but is now forced to stay that way until you use /publicroom.`); } return this.errorReply(`This room is already ${settingName}.`); } this.addModAction(`${user.name} made this room ${settingName}.`); this.modlog(`${settingName.toUpperCase()}ROOM`); if (!room.settings.isPersonal && !room.battle) room.setSection(); room.setPrivate(setting); room.privacySetter = /* @__PURE__ */ new Set([user.id]); } }, privateroomhelp: [ `/secretroom - Makes a room secret. Secret rooms are visible to & and up. Requires: &`, `/hiddenroom [on/off] - Makes a room hidden. Hidden rooms are visible to % and up, and inherit global ranks. Requires: \u2606 &`, `/publicroom - Makes a room public. Requires: \u2606 &` ], hidenext(target, room, user) { const groupConfig = Config.groups[Users.PLAYER_SYMBOL]; if (!groupConfig?.editprivacy) return this.errorReply(`/hidenext - Access denied.`); if (this.meansNo(target)) { user.battleSettings.hidden = false; user.update(); this.sendReply("Your next battle will be publicly visible."); } else { user.battleSettings.hidden = true; user.update(); this.sendReply(`Your next battle will be hidden${Rooms.RoomBattle.battleForcedSetting(user, "privacy") ? `, unless it is rated` : ``}.`); } }, hidenexthelp: [ `/hidenext - Sets your next battle to be hidden.`, `/hidenext off - Sets your next battle to be publicly visible.` ], officialchatroom: "officialroom", officialroom() { this.parse(`/setroomsection official`); }, roomspotlight(target, room, user) { this.checkCan("makeroom"); room = this.requireRoom(); if (!target) return this.parse(`/help roomspotlight`); if (!room.persist) { return this.errorReply(`/roomspotlight - You can't spotlight this room.`); } if (this.meansNo(target)) { if (!room.settings.spotlight) return this.errorReply(`This chatroom is not being spotlighted.`); this.addModAction(`${user.name} removed this chatroom from the spotlight.`); this.globalModlog("UNSPOTLIGHT"); delete room.settings.spotlight; room.saveSettings(); } else { if (room.settings.spotlight === target) return this.errorReply("This chat room is already spotlighted."); this.addModAction(`${user.name} spotlighted this room with the message "${target}".`); this.globalModlog("SPOTLIGHT"); room.settings.spotlight = target; room.saveSettings(); } }, roomspotlighthelp: [ `/roomspotlight [spotlight] - Makes the room this command is used in a spotlight room for the [spotlight] category on the roomlist. Requires: &`, `/roomspotlight off - Removes the room this command is used in from the list of spotlight rooms. Requires: &` ], setsubroom: "subroom", subroom(target, room, user) { room = this.requireRoom(); if (!user.can("makeroom")) return this.errorReply(`/subroom - Access denied. Did you mean /subrooms?`); if (!target) return this.parse("/help subroom"); if (!room.persist) return this.errorReply(`Temporary rooms cannot be subrooms.`); if (room.parent) { return this.errorReply(`This room is already a subroom. To change which room this subroom belongs to, remove the subroom first.`); } if (room.subRooms) { return this.errorReply(`This room is already a parent room, and a parent room cannot be made as a subroom.`); } const parent = Rooms.search(target); if (!parent) return this.errorReply(`The room '${target}' does not exist.`); if (parent.type !== "chat") return this.errorReply(`Parent room '${target}' must be a chat room.`); if (parent.parent) return this.errorReply(`Subrooms cannot have subrooms.`); if (parent.settings.isPrivate === true) return this.errorReply(`Only public and hidden rooms can have subrooms.`); if (parent.settings.isPrivate && !room.settings.isPrivate) { return this.errorReply(`Private rooms cannot have public subrooms.`); } if (!parent.persist) return this.errorReply(`Temporary rooms cannot be parent rooms.`); if (room === parent) return this.errorReply(`You cannot set a room to be a subroom of itself.`); const settingsList = Rooms.global.settingsList; const parentIndex = settingsList.findIndex((r) => r.title === parent.title); const index = settingsList.findIndex((r) => r.title === room.title); if (parentIndex > index) { [settingsList[parentIndex], settingsList[index]] = [settingsList[index], settingsList[parentIndex]]; } room.setParent(parent); this.modlog("SUBROOM", null, `of ${parent.title}`); return this.addModAction(`This room was set as a subroom of ${parent.title} by ${user.name}.`); }, removesubroom: "unsubroom", desubroom: "unsubroom", unsubroom(target, room, user) { room = this.requireRoom(); this.checkCan("makeroom"); if (!room.parent || !room.persist) { return this.errorReply(`This room is not currently a subroom of a public room.`); } room.setParent(null); this.modlog("UNSUBROOM"); return this.addModAction(`This room was unset as a subroom by ${user.name}.`); }, unsubroomhelp: [`/unsubroom - Unmarks the current room as a subroom. Requires: &`], parentroom: "subrooms", subrooms(target, room, user, connection, cmd) { room = this.requireRoom(); if (cmd === "parentroom") { if (!room.parent) return this.errorReply(`This room is not a subroom.`); return this.sendReply(`This is a subroom of ${room.parent.title}.`); } if (!room.persist) return this.errorReply(`Temporary rooms cannot have subrooms.`); if (!this.runBroadcast()) return; const showSecret = !this.broadcasting && user.can("mute", null, room); const subRooms = room.getSubRooms(showSecret); if (!subRooms.length) return this.sendReply(`This room doesn't have any subrooms.`); const subRoomText = subRooms.map( (subRoom) => import_lib.Utils.html`${subRoom.title}
${subRoom.settings.desc}` ); return this.sendReplyBox(`

${import_lib.Utils.escapeHTML(room.title)}'s subroom${Chat.plural(subRooms)}:

`); }, subroomhelp: [ `/subroom [room] - Marks the current room as a subroom of [room]. Requires: &`, `/unsubroom - Unmarks the current room as a subroom. Requires: &`, `/subrooms - Displays the current room's subrooms.`, `/parentroom - Displays the current room's parent room.` ], roomdesc(target, room, user) { room = this.requireRoom(); if (!target) { if (!this.runBroadcast()) return; if (!room.settings.desc) return this.sendReply(`This room does not have a description set.`); this.sendReplyBox(import_lib.Utils.html`The room description is: ${room.settings.desc}`); return; } this.checkCan("makeroom"); if (target.length > 80) { return this.errorReply(`Error: Room description is too long (must be at most 80 characters).`); } const normalizedTarget = " " + target.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim() + " "; if (normalizedTarget.includes(" welcome ")) { return this.errorReply(`Error: Room description must not contain the word "welcome".`); } if (normalizedTarget.startsWith(" discuss ")) { return this.errorReply(`Error: Room description must not start with the word "discuss".`); } if (normalizedTarget.startsWith(" talk about ") || normalizedTarget.startsWith(" talk here about ")) { return this.errorReply(`Error: Room description must not start with the phrase "talk about".`); } room.settings.desc = target; this.sendReply(`(The room description is now: ${target})`); this.privateModAction(`${user.name} changed the roomdesc to: "${target}".`); this.modlog("ROOMDESC", null, `to "${target}"`); room.saveSettings(); }, roomdeschelp: [`/roomdesc [description] - Sets the [description] of the current room. Requires: &`], topic: "roomintro", roomintro(target, room, user, connection, cmd) { room = this.requireRoom(); if (!target) { if (!this.runBroadcast()) return; if (!room.settings.introMessage) return this.sendReply("This room does not have an introduction set."); this.sendReply('|raw|
' + room.settings.introMessage.replace(/\n/g, "") + "
"); if (!this.broadcasting && user.can("declare", null, room, "roomintro") && cmd !== "topic") { const code = import_lib.Utils.escapeHTML(room.settings.introMessage).replace(/\n/g, "
"); this.sendReplyBox(`
Source:/roomintro ${code}
`); } return; } this.checkCan("editroom", null, room); if (this.meansNo(target) || target === "delete") return this.errorReply('Did you mean "/deleteroomintro"?'); this.checkHTML(target); if (!target.includes("<")) { const re = /(https?:\/\/(([\w.-]+)+(:\d+)?(\/([\w/_.]*(\?\S+)?)?)?))/g; target = target.replace(re, '$1'); } if (target.substr(0, 11) === "/roomintro ") target = target.substr(11); room.settings.introMessage = target.replace(/\r/g, ""); this.sendReply("(The room introduction has been changed to:)"); this.sendReply(`|raw|
${room.settings.introMessage.replace(/\n/g, "")}
`); this.privateModAction(`${user.name} changed the roomintro.`); this.modlog("ROOMINTRO"); this.roomlog(room.settings.introMessage.replace(/\n/g, "")); room.saveSettings(); }, roomintrohelp: [ `/roomintro - Display the room introduction of the current room.`, `/roomintro [content] - Set an introduction for the room. Requires: # &` ], deletetopic: "deleteroomintro", deleteroomintro(target, room, user) { room = this.requireRoom(); this.checkCan("declare", null, room); if (!room.settings.introMessage) return this.errorReply("This room does not have a introduction set."); this.privateModAction(`${user.name} deleted the roomintro.`); this.modlog("DELETEROOMINTRO"); this.roomlog(target); delete room.settings.introMessage; room.saveSettings(); }, deleteroomintrohelp: [`/deleteroomintro - Deletes the current room's introduction. Requires: # &`], stafftopic: "staffintro", staffintro(target, room, user, connection, cmd) { room = this.requireRoom(); if (!target) { this.checkCan("mute", null, room); if (!room.settings.staffMessage) return this.sendReply("This room does not have a staff introduction set."); this.sendReply(`|raw|
${room.settings.staffMessage.replace(/\n/g, ``)}
`); if (user.can("ban", null, room, "staffintro") && cmd !== "stafftopic") { const code = import_lib.Utils.escapeHTML(room.settings.staffMessage).replace(/\n/g, "
"); this.sendReplyBox(`
Source:/staffintro ${code}
`); } return; } this.checkCan("ban", null, room); this.checkChat(); if (this.meansNo(target) || target === "delete") return this.errorReply('Did you mean "/deletestaffintro"?'); this.checkHTML(target); if (!target.includes("<")) { const re = /(https?:\/\/(([\w.-]+)+(:\d+)?(\/([\w/_.]*(\?\S+)?)?)?))/g; target = target.replace(re, '$1'); } if (target.substr(0, 12) === "/staffintro ") target = target.substr(12); room.settings.staffMessage = target.replace(/\r/g, ""); this.sendReply("(The staff introduction has been changed to:)"); this.sendReply(`|raw|
${target.replace(/\n/g, ``)}
`); this.privateModAction(`${user.name} changed the staffintro.`); this.modlog("STAFFINTRO"); this.roomlog(room.settings.staffMessage.replace(/\n/g, ``)); room.saveSettings(); }, staffintrohelp: [`/staffintro [content] - Set an introduction for staff members. Requires: @ # &`], deletestafftopic: "deletestaffintro", deletestaffintro(target, room, user) { room = this.requireRoom(); this.checkCan("ban", null, room); if (!room.settings.staffMessage) return this.errorReply("This room does not have a staff introduction set."); this.privateModAction(`${user.name} deleted the staffintro.`); this.modlog("DELETESTAFFINTRO"); this.roomlog(target); delete room.settings.staffMessage; room.saveSettings(); }, deletestaffintrohelp: [`/deletestaffintro - Deletes the current room's staff introduction. Requires: @ # &`], roomalias(target, room, user) { room = this.requireRoom(); if (!target) { if (!this.runBroadcast()) return; if (!room.settings.aliases) return this.sendReplyBox("This room does not have any aliases."); return this.sendReplyBox(`This room has the following aliases: ${room.settings.aliases.join(", ")}`); } this.checkCan("makeroom"); if (target.includes(",")) { this.errorReply(`Invalid room alias: ${target.trim()}`); return this.parse("/help roomalias"); } const alias = toID(target); if (!alias.length) return this.errorReply("Only alphanumeric characters are valid in an alias."); if (Rooms.get(alias) || Rooms.aliases.has(alias)) { return this.errorReply("You cannot set an alias to an existing room or alias."); } if (room.settings.isPersonal) return this.errorReply("Personal rooms can't have aliases."); Rooms.aliases.set(alias, room.roomid); this.privateModAction(`${user.name} added the room alias '${alias}'.`); this.modlog("ROOMALIAS", null, alias); if (!room.settings.aliases) room.settings.aliases = []; room.settings.aliases.push(alias); room.saveSettings(); }, roomaliashelp: [ `/roomalias - displays a list of all room aliases of the room the command was entered in.`, `/roomalias [alias] - adds the given room alias to the room the command was entered in. Requires: &`, `/removeroomalias [alias] - removes the given room alias of the room the command was entered in. Requires: &` ], deleteroomalias: "removeroomalias", deroomalias: "removeroomalias", unroomalias: "removeroomalias", removeroomalias(target, room, user) { room = this.requireRoom(); if (!room.settings.aliases) return this.errorReply("This room does not have any aliases."); this.checkCan("makeroom"); if (target.includes(",")) { this.errorReply(`Invalid room alias: ${target.trim()}`); return this.parse("/help removeroomalias"); } const alias = toID(target); if (!alias || !Rooms.aliases.has(alias)) return this.errorReply("Please specify an existing alias."); if (Rooms.aliases.get(alias) !== room.roomid) { return this.errorReply("You may only remove an alias from the current room."); } this.privateModAction(`${user.name} removed the room alias '${alias}'.`); this.modlog("REMOVEALIAS", null, alias); const aliasIndex = room.settings.aliases.indexOf(alias); if (aliasIndex >= 0) { room.settings.aliases.splice(aliasIndex, 1); if (!room.settings.aliases.length) room.settings.aliases = void 0; Rooms.aliases.delete(alias); room.saveSettings(); } }, removeroomaliashelp: [ `/removeroomalias [alias] - removes the given room alias of the room the command was entered in. Requires: &` ], resettierdisplay: "roomtierdisplay", roomtierdisplay(target, room, user, connection, cmd) { room = this.requireRoom(); const resetTier = cmd === "resettierdisplay"; if (!target) { if (!this.runBroadcast()) return; return this.sendReplyBox( `This room is currently displaying ${room.settings.dataCommandTierDisplay} as the tier when using /data.` ); } this.checkCan("declare", null, room); const displayIDToName = { tiers: "tiers", doublestiers: "doubles tiers", nationaldextiers: "National Dex tiers", numbers: "numbers" }; if (!resetTier) { if (!(toID(target) in displayIDToName)) { this.errorReply(`Invalid tier display: ${target.trim()}`); return this.parse(`/help roomtierdisplay`); } room.settings.dataCommandTierDisplay = displayIDToName[toID(target)]; this.sendReply(`(The room's tier display is now: ${displayIDToName[toID(target)]})`); this.privateModAction(`${user.name} changed the room's tier display to: ${displayIDToName[toID(target)]}.`); this.modlog("ROOMTIERDISPLAY", null, `to ${displayIDToName[toID(target)]}`); } else { room.settings.dataCommandTierDisplay = "tiers"; this.sendReply(`(The room's tier display is now: tiers)`); this.privateModAction(`${user.name} reset the room's tier display.`); this.modlog("RESETTIERDISPLAY", null, `to tiers`); } room.saveSettings(); }, roomtierdisplayhelp: [ `/roomtierdisplay - displays the current room's display.`, `/roomtierdisplay [option] - changes the current room's tier display. Valid options are: tiers, doubles tiers, numbers. Requires: # &`, `/resettierdisplay - resets the current room's tier display. Requires: # &` ], setroomsection: "roomsection", roomsection(target, room, user) { room = this.requireRoom(); const sectionNames = RoomSections.sectionNames; if (!target) { if (!this.runBroadcast()) return; this.sendReplyBox(import_lib.Utils.html`This room is ${room.settings.section ? `in the ${sectionNames[room.settings.section]} section` : `not in a section`}.`); return; } this.checkCan("gdeclare"); const section = room.setSection(target); this.sendReply(`The room section is now: ${section ? sectionNames[section] : "none"}`); this.privateGlobalModAction(`${user.name} changed the room section of ${room.title} to ${section ? sectionNames[section] : "none"}.`); this.globalModlog("ROOMSECTION", null, section || "none"); }, roomsectionhelp: [ `/roomsection [section] - Sets the room this is used in to the specified [section]. Requires: &`, `Valid sections: ${sections.join(", ")}` ], roomdefaultformat(target, room, user) { room = this.requireRoom(); this.checkCan("editroom", null, room); if (!target) { this.checkBroadcast(); if (room.settings.defaultFormat) { this.sendReply(`This room's default format is ${room.settings.defaultFormat}.`); } else { this.sendReply(`This room has no default format.`); } return; } if (this.meansNo(target)) { delete room.settings.defaultFormat; room.saveSettings(); this.modlog(`DEFAULTFORMAT`, null, "off"); this.privateModAction(`${user.name} removed this room's default format.`); return; } target = toID(target); const format = Dex.formats.get(target); if (format.exists) { target = format.name; } const { isMatch } = this.extractFormat(target); if (!isMatch) throw new Chat.ErrorMessage(`Unrecognized format or mod "${target}"`); room.settings.defaultFormat = target; room.saveSettings(); this.modlog(`DEFAULTFORMAT`, null, target); this.privateModAction(`${user.name} set this room's default format to ${target}.`); }, roomdefaultformathelp: [ `/roomdefaultformat [format] or [mod] or gen[number] - Sets this room's default format/mod. Requires: # &`, `/roomdefaultformat off - Clears this room's default format/mod. Requires: # &`, `Affected commands: /details, /coverage, /effectiveness, /weakness, /learn` ] }; const roomSettings = [ // modchat (room, user) => ({ label: "Modchat", permission: "modchat", options: [ "off", "autoconfirmed", "trusted", ...RANKS.slice(1).filter((symbol) => Users.Auth.hasPermission(user, "modchat", symbol, room)) ].map((rank) => [rank, rank === (room.settings.modchat || "off") || `modchat ${rank || "off"}`]) }), (room, user) => ({ label: "Modjoin", permission: room.settings.isPersonal ? user.can("editroom", null, room) : user.can("makeroom"), options: [ "off", "autoconfirmed", // groupchat ROs can set modjoin, but only to + // first rank is for modjoin off ...RANKS.slice(1, room.settings.isPersonal && !user.can("makeroom") ? 2 : void 0) ].map((rank) => [rank, rank === (room.settings.modjoin || "off") || `modjoin ${rank || "off"}`]) }), (room) => ({ label: "Language", permission: "editroom", options: [...Chat.languages].map( ([id, name]) => [name, id === (room.settings.language || "english") || `roomlanguage ${id || "off"}`] ) }), (room) => ({ label: "Stretch filter", permission: "editroom", options: [ [`off`, !room.settings.filterStretching || "stretchfilter off"], [`on`, room.settings.filterStretching || "stretchfilter on"] ] }), (room) => ({ label: "Caps filter", permission: "editroom", options: [ [`off`, !room.settings.filterCaps || "capsfilter off"], [`on`, room.settings.filterCaps || "capsfilter on"] ] }), (room) => ({ label: "Emoji filter", permission: "editroom", options: [ [`off`, !room.settings.filterEmojis || "emojifilter off"], [`on`, room.settings.filterEmojis || "emojifilter on"] ] }), (room) => ({ label: "Link filter", permission: "editroom", options: [ [`off`, !room.settings.filterLinks || "linkfilter off"], [`on`, room.settings.filterLinks || "linkfilter on"] ] }), (room) => ({ label: "Slowchat", permission: room.userCount < SLOWCHAT_USER_REQUIREMENT ? "bypassall" : "editroom", options: ["off", 5, 10, 20, 30, 60].map( (time) => [`${time}`, time === (room.settings.slowchat || "off") || `slowchat ${time || "off"}`] ) }), (room) => ({ label: "/data Tier display", permission: "editroom", options: [ [`tiers`, (room.settings.dataCommandTierDisplay ?? "tiers") === "tiers" || `roomtierdisplay tiers`], [`doubles tiers`, room.settings.dataCommandTierDisplay === "doubles tiers" || `roomtierdisplay doubles tiers`], [ `National Dex tiers`, room.settings.dataCommandTierDisplay === "National Dex tiers" || `roomtierdisplay National Dex tiers` ], [`numbers`, room.settings.dataCommandTierDisplay === "numbers" || `roomtierdisplay numbers`] ] }), (room) => ({ label: "/requestshow", permission: "declare", options: [ [`off`, !room.settings.requestShowEnabled || `showapprovals off`], [`on`, room.settings.requestShowEnabled || `showapprovals on`] ] }) ]; const pages = { permissions(args, user, connection) { this.title = `[Permissions]`; const room = this.requireRoom(); this.checkCan("mute", null, room); const roomGroups = ["default", ...Config.groupsranking.slice(1)]; const permissions = room.settings.permissions || {}; let buf = `

Command permissions for ${room.title}

`; buf += `
`; buf += ``; let atLeastOne = false; for (const permission in permissions) { const requiredRank = permissions[permission]; atLeastOne = true; buf += ``; } if (!atLeastOne) { buf += ``; } buf += `
PermissionRequired rank
${permission}`; if (room.auth.atLeast(user, "#")) { buf += roomGroups.filter((group) => group !== Users.SECTIONLEADER_SYMBOL).map((group) => requiredRank === group ? import_lib.Utils.html`` : import_lib.Utils.html``).join(" "); } else { buf += import_lib.Utils.html``; } buf += `
You don't have any permissions configured.
`; buf += `

Use /permissions to add new permissions

`; return buf; } }; //# sourceMappingURL=room-settings.js.map