{ "version": 3, "sources": ["../../../../server/chat-plugins/sample-teams.ts"], "sourcesContent": ["/**\r\n * A sample teams plugin\r\n *\r\n * @author Kris\r\n */\r\n\r\nimport {FS, Utils} from \"../../lib\";\r\n\r\nconst SAMPLE_TEAMS = 'config/chat-plugins/sample-teams.json';\r\n\r\ninterface SampleTeamsData {\r\n\twhitelist: {[formatid: string]: RoomID[]};\r\n\t/** Teams are stored in the packed format */\r\n\tteams: {\r\n\t\t[formatid: string]: {\r\n\t\t\tuncategorized: {[k: string]: string},\r\n\t\t\t[category: string]: {[teamName: string]: string},\r\n\t\t},\r\n\t};\r\n}\r\n\r\nexport const teamData: SampleTeamsData = (() => {\r\n\ttry {\r\n\t\treturn JSON.parse(FS(SAMPLE_TEAMS).readIfExistsSync());\r\n\t} catch {\r\n\t\treturn {\r\n\t\t\twhitelist: {},\r\n\t\t\tteams: {},\r\n\t\t};\r\n\t}\r\n})();\r\n\r\nfunction save() {\r\n\tFS(SAMPLE_TEAMS).writeUpdate(() => JSON.stringify(teamData));\r\n}\r\n\r\nfor (const formatid in teamData.teams) {\r\n\tif (!teamData.teams[formatid].uncategorized) teamData.teams[formatid].uncategorized = {};\r\n}\r\nsave();\r\n\r\nexport const SampleTeams = new class SampleTeams {\r\n\tprivate isRoomStaff(user: User, roomids: RoomID[]) {\r\n\t\tlet matched = false;\r\n\t\tif (!roomids?.length) return false;\r\n\t\tfor (const roomid of roomids) {\r\n\t\t\tconst room = Rooms.search(roomid);\r\n\t\t\t// Malformed entry from botched room rename\r\n\t\t\tif (!room) continue;\r\n\t\t\tmatched = room.auth.isStaff(user.id);\r\n\t\t\tif (matched) break;\r\n\t\t}\r\n\t\treturn matched;\r\n\t}\r\n\r\n\tisDevMod(user: User) {\r\n\t\treturn !!Rooms.get('development')?.auth.atLeast(user, '@');\r\n\t}\r\n\r\n\tcheckPermissions(user: User, roomids: RoomID[]) {\r\n\t\t// Give Development room mods access to help fix crashes\r\n\t\treturn this.isRoomStaff(user, roomids) || user.can('bypassall') || this.isDevMod(user);\r\n\t}\r\n\r\n\twhitelistedRooms(formatid: string, names = false) {\r\n\t\tformatid = this.sanitizeFormat(formatid);\r\n\t\tif (!teamData.whitelist[formatid]?.length) return null;\r\n\t\treturn Utils.sortBy(teamData.whitelist[formatid], (x) => {\r\n\t\t\tif (!names) return x;\r\n\t\t\tconst room = Rooms.search(x);\r\n\t\t\tif (!room) return x;\r\n\t\t\treturn room.title;\r\n\t\t});\r\n\t}\r\n\r\n\twhitelistRooms(formatids: string[], roomids: string[]) {\r\n\t\tfor (const unsanitizedFormatid of formatids) {\r\n\t\t\tconst formatid = this.sanitizeFormat(unsanitizedFormatid);\r\n\t\t\tif (!teamData.whitelist[formatid]) teamData.whitelist[formatid] = [];\r\n\t\t\tfor (const roomid of roomids) {\r\n\t\t\t\tconst targetRoom = Rooms.search(roomid);\r\n\t\t\t\tif (!targetRoom?.persist) {\r\n\t\t\t\t\tthrow new Chat.ErrorMessage(`Room ${roomid} not found. Check spelling?`);\r\n\t\t\t\t}\r\n\t\t\t\tif (teamData.whitelist[formatid].includes(targetRoom.roomid)) {\r\n\t\t\t\t\tthrow new Chat.ErrorMessage(`Room ${targetRoom.title} is already added.`);\r\n\t\t\t\t}\r\n\t\t\t\tteamData.whitelist[formatid].push(targetRoom.roomid);\r\n\t\t\t\tsave();\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\r\n\tunwhitelistRoom(formatid: string, roomid: string) {\r\n\t\tformatid = this.sanitizeFormat(formatid, false);\r\n\t\tconst targetRoom = Rooms.search(roomid);\r\n\t\tif (!targetRoom?.persist) throw new Chat.ErrorMessage(`Room ${roomid} not found. Check spelling?`);\r\n\t\tif (!teamData.whitelist[formatid]?.length) throw new Chat.ErrorMessage(`No rooms are whitelisted for ${formatid}.`);\r\n\t\tif (!teamData.whitelist[formatid].includes(targetRoom.roomid)) {\r\n\t\t\tthrow new Chat.ErrorMessage(`Room ${targetRoom.title} isn't whitelisted.`);\r\n\t\t}\r\n\t\tconst index = teamData.whitelist[formatid].indexOf(targetRoom.roomid);\r\n\t\tteamData.whitelist[formatid].splice(index, 1);\r\n\t\tif (!teamData.whitelist[formatid].length) delete teamData.whitelist[formatid];\r\n\t\tsave();\r\n\t}\r\n\r\n\tsanitizeFormat(formatid: string, checkExists = false) {\r\n\t\tconst format = Dex.formats.get(formatid);\r\n\t\tif (checkExists && !format.exists) {\r\n\t\t\tthrow new Chat.ErrorMessage(`Format \"${formatid.trim()}\" not found. Check spelling?`);\r\n\t\t}\r\n\t\tif (format.team) {\r\n\t\t\tthrow new Chat.ErrorMessage(`Formats with computer-generated teams can't have team storage.`);\r\n\t\t}\r\n\t\treturn format.id;\r\n\t}\r\n\r\n\tinitializeFormat(formatid: string) {\r\n\t\tif (!teamData.teams[formatid]) {\r\n\t\t\tteamData.teams[formatid] = {uncategorized: {}};\r\n\t\t\tsave();\r\n\t\t}\r\n\t}\r\n\r\n\taddCategory(user: User, formatid: string, category: string) {\r\n\t\tformatid = this.sanitizeFormat(formatid);\r\n\t\tif (!this.checkPermissions(user, teamData.whitelist[formatid])) {\r\n\t\t\tlet rankNeeded = `a global administrator`;\r\n\t\t\tif (teamData.whitelist[formatid]) {\r\n\t\t\t\trankNeeded = `staff in ${Chat.toListString(teamData.whitelist[formatid], \"or\")}`;\r\n\t\t\t}\r\n\t\t\tthrow new Chat.ErrorMessage(`Access denied. You need to be ${rankNeeded} to add teams for ${formatid}`);\r\n\t\t}\r\n\t\tcategory = category.trim();\r\n\t\tthis.initializeFormat(formatid);\r\n\t\tif (this.findCategory(formatid, category)) {\r\n\t\t\tthrow new Chat.ErrorMessage(`The category named ${category} already exists.`);\r\n\t\t}\r\n\t\tteamData.teams[formatid][category] = {};\r\n\t\tsave();\r\n\t}\r\n\r\n\tremoveCategory(user: User, formatid: string, category: string) {\r\n\t\tformatid = this.sanitizeFormat(formatid, false);\r\n\t\tif (!this.checkPermissions(user, teamData.whitelist[formatid])) {\r\n\t\t\tlet rankNeeded = `a global administrator`;\r\n\t\t\tif (teamData.whitelist[formatid]) {\r\n\t\t\t\trankNeeded = `staff in ${Chat.toListString(teamData.whitelist[formatid], \"or\")}`;\r\n\t\t\t}\r\n\t\t\tthrow new Chat.ErrorMessage(`Access denied. You need to be ${rankNeeded} to add teams for ${formatid}`);\r\n\t\t}\r\n\t\tconst categoryName = this.findCategory(formatid, category);\r\n\t\tif (!categoryName) {\r\n\t\t\tthrow new Chat.ErrorMessage(`There's no category named \"${category.trim()}\" for the format ${formatid}.`);\r\n\t\t}\r\n\t\tdelete teamData.teams[formatid][categoryName];\r\n\t\tsave();\r\n\t}\r\n\r\n\t/**\r\n\t * @param user\r\n\t * @param formatid\r\n\t * @param teamName\r\n\t * @param team - Can be a team in the packed, JSON, or exported format\r\n\t * @param category - Category the team will go in, defaults to uncategorized\r\n\t */\r\n\taddTeam(user: User, formatid: string, teamName: string, team: string, category = \"uncategorized\") {\r\n\t\tformatid = this.sanitizeFormat(formatid);\r\n\t\tif (!this.checkPermissions(user, teamData.whitelist[formatid])) {\r\n\t\t\tlet rankNeeded = `a global administrator`;\r\n\t\t\tif (teamData.whitelist[formatid]?.length) {\r\n\t\t\t\trankNeeded = `staff in ${Chat.toListString(teamData.whitelist[formatid], \"or\")}`;\r\n\t\t\t}\r\n\t\t\tthrow new Chat.ErrorMessage(`Access denied. You need to be ${rankNeeded} to add teams for ${formatid}`);\r\n\t\t}\r\n\t\tteamName = teamName.trim();\r\n\t\tcategory = category.trim();\r\n\t\tthis.initializeFormat(formatid);\r\n\t\tif (this.findTeamName(formatid, category, teamName)) {\r\n\t\t\tthrow new Chat.ErrorMessage(`There is already a team for ${formatid} with the name ${teamName} in the ${category} category.`);\r\n\t\t}\r\n\t\tif (!teamData.teams[formatid][category]) this.addCategory(user, formatid, category);\r\n\t\tteamData.teams[formatid][category][teamName] = Teams.pack(Teams.import(team.trim()));\r\n\t\tsave();\r\n\t\treturn teamData.teams[formatid][category][teamName];\r\n\t}\r\n\r\n\tremoveTeam(user: User, formatid: string, teamid: string, category: string) {\r\n\t\tformatid = this.sanitizeFormat(formatid, false);\r\n\t\tcategory = category.trim();\r\n\t\tif (!this.checkPermissions(user, teamData.whitelist[formatid])) {\r\n\t\t\tlet required = `an administrator`;\r\n\t\t\tif (teamData.whitelist[formatid]) {\r\n\t\t\t\trequired = `staff in ${Chat.toListString(teamData.whitelist[formatid], \"or\")}`;\r\n\t\t\t}\r\n\t\t\tthrow new Chat.ErrorMessage(`Access denied. You need to be ${required} to add teams for ${formatid}`);\r\n\t\t}\r\n\t\tconst categoryName = this.findCategory(formatid, category);\r\n\t\tif (!categoryName) {\r\n\t\t\tthrow new Chat.ErrorMessage(`There are no teams for ${formatid} under the category ${category.trim()}. Check spelling?`);\r\n\t\t}\r\n\t\tconst teamName = this.findTeamName(formatid, category, teamid);\r\n\t\tif (!teamName) {\r\n\t\t\tthrow new Chat.ErrorMessage(`There is no team for ${formatid} with the name of \"${teamid}\". Check spelling?`);\r\n\t\t}\r\n\t\tconst oldTeam = teamData.teams[formatid][categoryName][teamName];\r\n\t\tdelete teamData.teams[formatid][categoryName][teamName];\r\n\t\tif (!Object.keys(teamData.teams[formatid][categoryName]).length) delete teamData.teams[formatid][categoryName];\r\n\t\tif (!Object.keys(teamData.teams[formatid]).filter(x => x !== 'uncategorized').length) delete teamData.teams[formatid];\r\n\t\tsave();\r\n\t\treturn oldTeam;\r\n\t}\r\n\r\n\tformatTeam(teamName: string, teamStr: string, broadcasting = false) {\r\n\t\tconst team = Teams.unpack(teamStr);\r\n\t\tif (!team) return `Team is not correctly formatted. PM room staff to fix the formatting.`;\r\n\t\tlet buf = ``;\r\n\t\tif (!broadcasting) {\r\n\t\t\tbuf += `
${Teams.export(team).trim().replace(/\\n/g, '
')}No rooms are whitelisted for any formats.
`;\r\n\t\t\t}\r\n\t\t\tif (query[0] === 'add') {\r\n\t\t\t\tbuf += ``;\r\n\t\t\t\tbuf += `No teams found.
No teams for ${name} were found.
`;\r\n\t\t\t} else if (!query[1] || (!SampleTeams.findCategory(query[0], query[1]) && query[1] !== 'allteams')) {\r\n\t\t\t\tbuf += `