{ "version": 3, "sources": ["../../../../server/chat-plugins/teams.ts"], "sourcesContent": ["/**\n * Plugin for sharing / storing teams in a database.\n * By Mia.\n * @author mia-pi-git\n */\n\nimport {PostgresDatabase, FS, Utils} from '../../lib';\n\n/** Maximum amount of teams a user can have stored at once. */\nconst MAX_TEAMS = 200;\n/** Max teams that can be viewed in a search */\nconst MAX_SEARCH = 3000;\nconst ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'.split('');\n\nexport interface StoredTeam {\n\tteamid: string;\n\tteam: string;\n\townerid: ID;\n\tformat: ID;\n\ttitle: string | null;\n\tdate: Date;\n\t/** password */\n\tprivate: string | null;\n\tviews: number;\n}\n\ninterface TeamSearch {\n\tformat?: string;\n\towner?: string;\n\tpokemon?: string[];\n\tmoves?: string[];\n\tabilities?: string[];\n\tgen?: number;\n}\n\nfunction refresh(context: Chat.PageContext) {\n\treturn (\n\t\t``\n\t);\n}\n\nexport const TeamsHandler = new class {\n\tdatabase = new PostgresDatabase();\n\treadyPromise: Promise | null = Config.usepostgres ? (async () => {\n\t\ttry {\n\t\t\tawait this.database.query('SELECT * FROM teams LIMIT 1');\n\t\t} catch {\n\t\t\tawait this.database.query(FS(`databases/schemas/teams.sql`).readSync());\n\t\t}\n\t})() : null;\n\tdestroy() {\n\t\tvoid this.database.destroy();\n\t}\n\n\tasync search(search: TeamSearch, user: User, count = 10, includePrivate = false) {\n\t\tconst args = [];\n\t\tconst where = [];\n\t\tif (count > 500) {\n\t\t\tthrow new Chat.ErrorMessage(\"Cannot search more than 500 teams.\");\n\t\t}\n\t\tif (search.format) {\n\t\t\twhere.push(`format = $${args.length + 1}`);\n\t\t\targs.push(toID(search.format));\n\t\t}\n\t\tif (search.owner) {\n\t\t\twhere.push(`ownerid = $${args.length + 1}`);\n\t\t\targs.push(toID(search.owner));\n\t\t}\n\t\tif (search.gen) {\n\t\t\twhere.push(`format LIKE 'gen${search.gen}%'`);\n\t\t}\n\t\tif (!includePrivate) where.push('private IS NULL');\n\n\t\tconst result = await this.query(\n\t\t\t`SELECT * FROM teams${where.length ? ` WHERE ${where.join(' AND ')}` : ''} ORDER BY date DESC LIMIT ${count}`,\n\t\t\targs,\n\t\t);\n\t\treturn result.filter(row => {\n\t\t\tconst team = Teams.unpack(row.team)!;\n\t\t\tif (row.private && row.ownerid !== user.id) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tlet match = true;\n\t\t\tif (search.pokemon?.length) {\n\t\t\t\tmatch = search.pokemon.some(\n\t\t\t\t\tpokemon => team.some(set => toID(set.species) === toID(pokemon))\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!match) return false;\n\t\t\tif (search.moves?.length) {\n\t\t\t\tmatch = search.moves.some(\n\t\t\t\t\tmove => team.some(set => set.moves.some(m => toID(m) === toID(move)))\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!match) return false;\n\t\t\tif (search.abilities?.length) {\n\t\t\t\tmatch = search.abilities.some(\n\t\t\t\t\tability => team.some(set => toID(set.ability) === toID(ability))\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn match;\n\t\t});\n\t}\n\n\tasync query(statement: string, values: any[] = []) {\n\t\tif (this.readyPromise) await this.readyPromise;\n\t\treturn this.database.query(statement, values) as Promise;\n\t}\n\n\tasync save(\n\t\tcontext: Chat.CommandContext,\n\t\tformatName: string,\n\t\trawTeam: string,\n\t\tteamName: string | null = null,\n\t\tisPrivate?: string | null,\n\t\tisUpdate?: number\n\t) {\n\t\tconst connection = context.connection;\n\t\tthis.validateAccess(connection, true);\n\n\t\tif (Monitor.countPrepBattle(connection.ip, connection)) {\n\t\t\treturn null;\n\t\t}\n\t\tconst user = connection.user;\n\t\tconst format = Dex.formats.get(toID(formatName));\n\t\tif (!format.exists || format.team) {\n\t\t\tconnection.popup(\"Invalid format:\\n\\n\" + formatName);\n\t\t\treturn null;\n\t\t}\n\t\tlet existing = null;\n\t\tif (isUpdate) {\n\t\t\texisting = await this.get(isUpdate);\n\t\t\tif (!existing) {\n\t\t\t\tconnection.popup(\"You're trying to edit a team that doesn't exist.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (context.user.id !== existing.ownerid) {\n\t\t\t\tconnection.popup(\"This is not your team.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\n\t\tconst team = Teams.import(rawTeam, true);\n\t\tif (!team) {\n\t\t\tconnection.popup('Invalid team:\\n\\n' + rawTeam);\n\t\t\treturn null;\n\t\t}\n\t\tif (team.length > 24) {\n\t\t\tconnection.popup(\"Your team has too many Pokemon.\");\n\t\t}\n\t\tlet unownWord = '';\n\t\t// now, we purge invalid nicknames and make sure it's an actual team\n\t\t// gotta use the validated team so that nicknames are removed\n\t\tfor (const set of team) {\n\t\t\tconst namedSpecies = Dex.species.get(set.name);\n\t\t\t// allow nicknames named after other mons - to support those OMs\n\t\t\tif (!namedSpecies.exists) {\n\t\t\t\tset.name = set.species;\n\t\t\t}\n\t\t\tif (!Dex.species.get(set.species).exists) {\n\t\t\t\tconnection.popup(`Invalid Pokemon ${set.species} in team.`);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst speciesid = toID(set.species);\n\t\t\tif (speciesid.length <= 6 && speciesid.startsWith('unown')) {\n\t\t\t\tunownWord += speciesid.charAt(5) || 'a';\n\t\t\t}\n\t\t\tif (set.moves.length > 24) {\n\t\t\t\tconnection.popup(\"Only 24 moves are allowed per set.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tfor (const m of set.moves) {\n\t\t\t\tif (!Dex.moves.get(m).exists) {\n\t\t\t\t\tconnection.popup(`Invalid move ${m} on ${set.species}.`);\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// i have no idea how people are getting this, but we got enough reports that\n\t\t\t// i guess it's worth handling\n\t\t\tif (toID(set.ability) === 'none') {\n\t\t\t\tset.ability = 'No Ability';\n\t\t\t}\n\t\t\tif (set.ability && !Dex.abilities.get(set.ability).exists) {\n\t\t\t\tconnection.popup(`Invalid ability ${set.ability} on ${set.species}.`);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (set.item && !Dex.items.get(set.item).exists) {\n\t\t\t\tconnection.popup(`Invalid item ${set.item} on ${set.species}.`);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (set.nature && !Dex.natures.get(set.nature).exists) {\n\t\t\t\tconnection.popup(`Invalid nature ${set.nature} on ${set.species}.`);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (set.teraType && !Dex.types.get(set.teraType).exists) {\n\t\t\t\tconnection.popup(`Invalid Tera Type ${set.nature} on ${set.species}.`);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tif (unownWord) {\n\t\t\tconst filtered = Chat.nicknamefilter(unownWord, user);\n\t\t\tif (!filtered || filtered !== unownWord) {\n\t\t\t\tconnection.popup(\n\t\t\t\t\t`Your team was rejected for the following reason:\\n\\n` +\n\t\t\t\t\t`- Your Unowns spell out a banned word: ${unownWord.toUpperCase()}`\n\t\t\t\t);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tif (teamName) {\n\t\t\tif (teamName.length > 100) {\n\t\t\t\tconnection.popup(\"Your team's name is too long.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst filtered = context.filter(teamName);\n\t\t\tif (!filtered || filtered?.trim() !== teamName.trim()) {\n\t\t\t\tconnection.popup(`Your team's name has a filtered word.`);\n\t\t\t\treturn null;\n\t\t\t}\n\t\t}\n\t\tconst count = await this.count(user);\n\t\tif (count >= MAX_TEAMS) {\n\t\t\tconnection.popup(`You have too many teams stored. If you wish to upload this team, delete some first.`);\n\t\t\treturn null;\n\t\t}\n\t\trawTeam = Teams.pack(team);\n\t\t// the && existing doesn't really matter because we've verified it above, this is just for TS\n\t\tif (isUpdate && existing) {\n\t\t\tconst differenceExists = (\n\t\t\t\texisting.team !== rawTeam ||\n\t\t\t\t(teamName && teamName !== existing.title) ||\n\t\t\t\tformat.id !== existing.format ||\n\t\t\t\texisting.private !== isPrivate\n\t\t\t);\n\t\t\tif (!differenceExists) {\n\t\t\t\tconnection.popup(\"Your team was not saved as no changes were made.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tawait this.query(\n\t\t\t\t'UPDATE teams SET team = $1, title = $2, private = $3, format = $4 WHERE teamid = $5',\n\t\t\t\t[rawTeam, teamName, isPrivate, format.id, isUpdate]\n\t\t\t);\n\t\t\treturn isUpdate;\n\t\t} else {\n\t\t\tconst exists = await this.query('SELECT * FROM teams WHERE ownerid = $1 AND team = $2', [user.id, rawTeam]);\n\t\t\tif (exists.length) {\n\t\t\t\tconnection.popup(\"You've already uploaded that team.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tconst loaded = await this.query(\n\t\t\t\t`INSERT INTO teams (ownerid, team, date, format, views, title, private) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING teamid`,\n\t\t\t\t[user.id, rawTeam, new Date(), format.id, 0, teamName, isPrivate]\n\t\t\t);\n\t\t\treturn loaded?.[0].teamid;\n\t\t}\n\t}\n\tgeneratePassword(len = 20) {\n\t\tlet pw = '';\n\t\tfor (let i = 0; i < len; i++) pw += ALPHABET[Math.floor(Math.random() * ALPHABET.length)];\n\t\treturn pw;\n\t}\n\tupdateViews(teamid: string) {\n\t\treturn this.query(`UPDATE teams SET views = views + 1 WHERE teamid = $1`, [teamid]);\n\t}\n\tlist(userid: ID, count: number, publicOnly = false) {\n\t\tlet query = `SELECT * FROM teams WHERE ownerid = $1 `;\n\t\tif (publicOnly) {\n\t\t\tquery += `AND private IS NULL `;\n\t\t}\n\t\tquery += `ORDER BY date DESC LIMIT $2`;\n\t\treturn this.query(\n\t\t\tquery, [userid, count]\n\t\t);\n\t}\n\tpreview(teamData: StoredTeam, user?: User | null, isFull = false) {\n\t\tlet buf = Utils.html`${teamData.title || `Untitled ${teamData.teamid}`}`;\n\t\tif (teamData.private) buf += ` (Private)`;\n\t\tbuf += `
`;\n\t\tbuf += `Uploaded by: ${teamData.ownerid}
`;\n\t\tbuf += `Uploaded on: ${Chat.toTimestamp(teamData.date, {human: true})}
`;\n\t\tbuf += `Format: ${Dex.formats.get(teamData.format).name}
`;\n\t\tbuf += `Views: ${teamData.views === -1 ? 0 : teamData.views}`;\n\t\tconst team = Teams.unpack(teamData.team)!;\n\t\tlet link = `view-team-${teamData.teamid}`;\n\t\tif (teamData.private) {\n\t\t\tlink += `-${teamData.private}`;\n\t\t}\n\t\tbuf += `
`;\n\t\tbuf += team.map(set => ``).join(' ');\n\t\tbuf += `
${isFull ? 'View full team' : 'Shareable link to team'}`;\n\t\tbuf += ` (or copy/paste <<${link}>> in chat to share!)`;\n\n\t\tif (user && (teamData.ownerid === user.id || user.can('rangeban'))) {\n\t\t\tbuf += `
`;\n\t\t\tbuf += `
Manage (edit/delete/etc)`;\n\t\t\tbuf += `
`;\n\t\t\tbuf += `
`;\n\t\t\tbuf += ``;\n\t\t\tbuf += `
`;\n\t\t}\n\t\treturn buf;\n\t}\n\trenderTeam(teamData: StoredTeam, user?: User) {\n\t\tlet buf = this.preview(teamData, user, true);\n\t\tbuf += `
`;\n\t\tconst team = Teams.unpack(teamData.team)!;\n\t\tbuf += team.map(set => {\n\t\t\tlet teamBuf = Teams.exportSet(set).replace(/\\n/g, '
');\n\t\t\tif (set.name && set.name !== set.species) {\n\t\t\t\tteamBuf = teamBuf.replace(set.name, Utils.html`
${set.name}`);\n\t\t\t} else {\n\t\t\t\tteamBuf = teamBuf.replace(set.species, `
${set.species}`);\n\t\t\t}\n\t\t\tif (set.item) {\n\t\t\t\tconst tester = new RegExp(`${Utils.escapeRegex(set.item)}\\\\b`);\n\t\t\t\tteamBuf = teamBuf.replace(tester, `${set.item} `);\n\t\t\t}\n\t\t\treturn teamBuf;\n\t\t}).join('
');\n\t\treturn buf;\n\t}\n\tvalidateAccess(conn: Connection, popup = false) {\n\t\tconst user = conn.user;\n\t\t// if there's no user, they've disconnected, so it's safe to just interrupt here\n\t\tif (!user) throw new Chat.Interruption();\n\t\tconst err = (message: string): never => {\n\t\t\tif (popup) {\n\t\t\t\tconn.popup(message);\n\t\t\t\tthrow new Chat.Interruption();\n\t\t\t}\n\t\t\tthrow new Chat.ErrorMessage(message);\n\t\t};\n\n\t\tif (!Config.usepostgres || !Config.usepostgresteams) {\n\t\t\terr(`The teams database is currently disabled.`);\n\t\t}\n\t\tif (!Users.globalAuth.atLeast(user, Config.usepostgresteams)) {\n\t\t\terr(\"You cannot currently use the teams database.\");\n\t\t}\n\t\tif (user.locked || user.semilocked) err(\"You cannot use the teams database while locked.\");\n\t\tif (!user.autoconfirmed) err(\"You must be autoconfirmed to use the teams database.\");\n\t}\n\tasync count(user: string | User) {\n\t\tconst id = toID(user);\n\t\tconst result = await this.query<{count: number}>(`SELECT count(*) AS count FROM teams WHERE ownerid = $1`, [id]);\n\t\treturn result?.[0]?.count || 0;\n\t}\n\tasync get(teamid: number | string): Promise {\n\t\tteamid = Number(teamid);\n\t\tif (isNaN(teamid)) {\n\t\t\tthrow new Chat.ErrorMessage(`Invalid team ID.`);\n\t\t}\n\t\tconst rows = await this.query(\n\t\t\t`SELECT * FROM teams WHERE teamid = $1`, [teamid],\n\t\t);\n\t\tif (!rows.length) return null;\n\t\treturn rows[0] as StoredTeam;\n\t}\n\tasync delete(id: string | number) {\n\t\tid = Number(id);\n\t\tif (isNaN(id)) {\n\t\t\tthrow new Chat.ErrorMessage(\"Invalid team ID\");\n\t\t}\n\t\tawait this.query(\n\t\t\t`DELETE FROM teams WHERE teamid = $1`, [id],\n\t\t);\n\t}\n};\n\nexport const destroy = () => TeamsHandler.destroy();\n\nexport const commands: Chat.ChatCommands = {\n\tteams: {\n\t\tupload() {\n\t\t\treturn this.parse('/j view-teams-upload');\n\t\t},\n\t\tupdate: 'save',\n\t\tasync save(target, room, user, connection, cmd) {\n\t\t\tTeamsHandler.validateAccess(connection, true);\n\t\t\tconst targets = Utils.splitFirst(target, ',', 5);\n\t\t\tconst isEdit = cmd === 'update';\n\t\t\tconst rawTeamID = isEdit ? targets.shift() : undefined;\n\t\t\tlet [teamName, formatid, rawPrivacy, rawTeam] = targets;\n\t\t\tconst teamID = Number(rawTeamID);\n\t\t\tif (isEdit && (!rawTeamID?.length || isNaN(teamID))) {\n\t\t\t\tconnection.popup(\"Invalid team ID provided.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tif (rawTeam.includes('\\n')) {\n\t\t\t\trawTeam = Teams.pack(Teams.import(rawTeam, true));\n\t\t\t}\n\t\t\tif (!rawTeam) {\n\t\t\t\tconnection.popup(\"Invalid team.\");\n\t\t\t\treturn null;\n\t\t\t}\n\t\t\tformatid = toID(formatid);\n\t\t\tteamName = toID(teamName) ? teamName : null!;\n\t\t\tconst privacy = toID(rawPrivacy) === '1' ? TeamsHandler.generatePassword() : null;\n\t\t\tconst id = await TeamsHandler.save(\n\t\t\t\tthis, formatid, rawTeam, teamName, privacy, isEdit ? teamID : undefined\n\t\t\t);\n\n\t\t\tconst page = isEdit ? 'edit' : 'upload';\n\t\t\tif (id) {\n\t\t\t\tconnection.send(`|queryresponse|teamupload|` + JSON.stringify({teamid: id, teamName}));\n\t\t\t\tconnection.send(`>view-teams-${page}\\n|deinit`);\n\t\t\t\tthis.parse(`/join view-teams-view-${id}-${id}`);\n\t\t\t} else {\n\t\t\t\tthis.parse(`/join view-teams-${page}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t},\n\t\t''(target) {\n\t\t\treturn this.parse('/teams user ' + toID(target) || this.user.id);\n\t\t},\n\t\tlatest() {\n\t\t\treturn this.parse(`/j view-teams-filtered-latest`);\n\t\t},\n\t\tviews: 'mostviews',\n\t\tmostviews() {\n\t\t\treturn this.parse(`/j view-teams-filtered-views`);\n\t\t},\n\t\tuser: 'view',\n\t\tfor: 'view',\n\t\tview(target) {\n\t\t\tconst [name, rawNum] = target.split(',').map(toID);\n\t\t\tconst num = parseInt(rawNum);\n\t\t\tif (rawNum && isNaN(num)) {\n\t\t\t\treturn this.popupReply(`Invalid count.`);\n\t\t\t}\n\t\t\tlet page = 'view';\n\t\t\tswitch (this.cmd) {\n\t\t\tcase 'for': case 'user':\n\t\t\t\tpage = 'all';\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\treturn this.parse(`/j view-teams-${page}-${toID(name)}${num ? `-${num}` : ''}`);\n\t\t},\n\t\tasync delete(target, room, user, connection) {\n\t\t\tTeamsHandler.validateAccess(connection, true);\n\t\t\tconst teamid = Number(toID(target));\n\t\t\tif (isNaN(teamid)) return this.popupReply(`Invalid team ID.`);\n\t\t\tconst teamData = await TeamsHandler.get(teamid);\n\t\t\tif (!teamData) return this.popupReply(`Team not found.`);\n\t\t\tif (teamData.ownerid !== user.id && !user.can('rangeban')) {\n\t\t\t\treturn this.errorReply(\"You cannot delete teams you do not own.\");\n\t\t\t}\n\t\t\tawait TeamsHandler.delete(teamid);\n\t\t\tthis.popupReply(`Team ${teamid} deleted.`);\n\t\t\tfor (const page of connection.openPages || new Set()) {\n\t\t\t\tif (page.startsWith('teams-')) this.refreshPage(page);\n\t\t\t}\n\t\t},\n\t\tasync setprivacy(target, room, user, connection) {\n\t\t\tTeamsHandler.validateAccess(connection, true);\n\t\t\tconst [teamId, rawPrivacy] = target.split(',').map(toID);\n\t\t\tlet privacy: string | null;\n\t\t\tif (!teamId.length) {\n\t\t\t\treturn this.popupReply('Invalid team ID.');\n\t\t\t}\n\t\t\t// these if checks may seem bit redundant but we want to ensure the user is certain about this\n\t\t\t// if it might be invalid, we want them to know that\n\t\t\tif (this.meansYes(rawPrivacy)) {\n\t\t\t\tprivacy = TeamsHandler.generatePassword();\n\t\t\t} else if (this.meansNo(rawPrivacy)) {\n\t\t\t\tprivacy = null;\n\t\t\t} else {\n\t\t\t\treturn this.popupReply(`Invalid privacy setting.`);\n\t\t\t}\n\t\t\tconst team = await TeamsHandler.get(teamId);\n\t\t\tif (!team) return this.popupReply(`Team not found.`);\n\t\t\tif (team.ownerid !== user.id && !user.can('rangeban')) {\n\t\t\t\treturn this.popupReply(`You cannot change privacy for a team you don't own.`);\n\t\t\t}\n\t\t\tawait TeamsHandler.query(`UPDATE teams SET private = $1 WHERE teamid = $2`, [privacy, teamId]);\n\t\t\tfor (const pageid of this.connection.openPages || new Set()) {\n\t\t\t\tif (pageid.startsWith('teams-')) {\n\t\t\t\t\tthis.refreshPage(pageid);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn this.popupReply(privacy ? `Team set to private. Password: ${privacy}` : `Team set to public.`);\n\t\t},\n\t\tsearch(target, room, user) {\n\t\t\treturn this.parse(`/j view-teams-searchpersonal`);\n\t\t},\n\t\tbrowse(target, room, user) {\n\t\t\treturn this.parse(`/j view-teams-browse${target ? `-${target}` : ''}`);\n\t\t},\n\t\thelp() {\n\t\t\treturn this.parse('/help teams');\n\t\t},\n\t},\n\tteamshelp: [\n\t\t`/teams OR /teams for [user]- View the (public) teams of the given [user].`,\n\t\t`/teams upload - Open the page to upload a team.`,\n\t\t`/teams setprivacy [team id], [privacy] - Set the privacy of the team matching the [teamid].`,\n\t\t`/teams delete [team id] - Delete the team matching the [teamid].`,\n\t\t`/teams search - Opens the page to search your teams`,\n\t\t`/teams mostviews - Views public teams, sorted by most views.`,\n\t\t`/teams view [team ID] - View the team matching the given [team ID]`,\n\t\t`/teams browse - Opens a list of public teams uploaded by other users.`,\n\t],\n};\n\nexport const pages: Chat.PageTable = {\n\t// support view-team-${teamid}\n\tteam(query, user, connection) {\n\t\treturn ((pages.teams as Chat.PageTable).view as Chat.PageHandler).call(this, query, user, connection);\n\t},\n\tteams: {\n\t\tasync all(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tTeamsHandler.validateAccess(connection);\n\t\t\tconst targetUserid = toID(query.shift()) || user.id;\n\t\t\tlet count = Number(query.shift()) || 10;\n\t\t\tif (count > MAX_TEAMS) count = MAX_TEAMS;\n\t\t\tthis.title = `[Teams] ${targetUserid}`;\n\t\t\tconst teams = await TeamsHandler.list(targetUserid, count, user.id !== targetUserid);\n\t\t\tlet buf = `

${targetUserid}'s last ${Chat.count(count, \"teams\")}

`;\n\t\t\tbuf += refresh(this);\n\t\t\tbuf += `
Search your teams `;\n\t\t\tbuf += `Browse public teams
`;\n\t\t\tif (targetUserid === user.id) {\n\t\t\t\tbuf += `Upload new`;\n\t\t\t}\n\t\t\tbuf += `
`;\n\t\t\tfor (const team of teams) {\n\t\t\t\tbuf += TeamsHandler.preview(team, user);\n\t\t\t\tbuf += `
`;\n\t\t\t}\n\t\t\tconst total = await TeamsHandler.count(user.id);\n\t\t\tif (total > count) {\n\t\t\t\tbuf += ``;\n\t\t\t}\n\t\t\treturn buf;\n\t\t},\n\t\tasync filtered(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tconst type = query.shift() || \"\";\n\t\t\tTeamsHandler.validateAccess(connection);\n\t\t\tlet count = Number(query.shift()) || 50;\n\t\t\tif (count > MAX_TEAMS) count = MAX_TEAMS;\n\t\t\tlet teams: StoredTeam[] = [], title = '';\n\t\t\tconst buttons: {[k: string]: string} = {\n\t\t\t\tviews: ``,\n\t\t\t\tlatest: ``,\n\t\t\t};\n\t\t\tswitch (type) {\n\t\t\tcase 'views':\n\t\t\t\tthis.title = `[Most Viewed Teams]`;\n\t\t\t\tteams = await TeamsHandler.query(\n\t\t\t\t\t`SELECT * FROM teams WHERE private IS NULL ORDER BY views DESC LIMIT $1`, [count]\n\t\t\t\t);\n\t\t\t\ttitle = `Most viewed teams:`;\n\t\t\t\tdelete buttons.views;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthis.title = `[Latest Teams]`;\n\t\t\t\tteams = await TeamsHandler.query(\n\t\t\t\t\t`SELECT * FROM teams WHERE private IS NULL ORDER BY date DESC LIMIT $1`, [count]\n\t\t\t\t);\n\t\t\t\ttitle = `Recently uploaded teams:`;\n\t\t\t\tdelete buttons.latest;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tlet buf = `

${title}

${refresh(this)}`;\n\t\t\tbuf += Object.values(buttons).join('
');\n\t\t\tbuf += `
`;\n\t\t\tbuf += teams.map(team => TeamsHandler.preview(team, user)).join('
');\n\t\t\tbuf += `
`;\n\t\t\treturn buf;\n\t\t},\n\t\tasync view(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tTeamsHandler.validateAccess(connection);\n\t\t\tconst rawTeamid = toID(query.shift() || \"\");\n\t\t\tconst password = toID(query.shift());\n\t\t\tthis.title = `[View Team]`;\n\t\t\tconst teamid = Number(rawTeamid);\n\t\t\tif (isNaN(teamid)) {\n\t\t\t\tthrow new Chat.ErrorMessage(`Invalid team ID.`);\n\t\t\t}\n\t\t\tconst team = await TeamsHandler.get(teamid);\n\t\t\tif (!team) {\n\t\t\t\tthis.title = `[Invalid Team]`;\n\t\t\t\treturn this.errorReply(`No team with the ID ${teamid} was found.`);\n\t\t\t}\n\t\t\tif (team?.private && user.id !== team.ownerid && password !== team.private) {\n\t\t\t\tthis.title = `[Private Team]`;\n\t\t\t\treturn this.errorReply(`That team is private.`);\n\t\t\t}\n\t\t\tthis.title = `[Team] ${team.teamid}`;\n\t\t\tif (user.id !== team.ownerid && team.views >= 0) {\n\t\t\t\tvoid TeamsHandler.updateViews(team.teamid);\n\t\t\t}\n\t\t\treturn `
` + TeamsHandler.renderTeam(team, user) + \"
\";\n\t\t},\n\t\tupload(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tTeamsHandler.validateAccess(connection);\n\t\t\tthis.title = `[Upload Team]`;\n\t\t\tlet buf = `

Upload a team

${refresh(this)}
`;\n\t\t\t// let [teamName, formatid, rawPrivacy, rawTeam] = Utils.splitFirst(target, ',', 4);\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += `What's the name of the team?
`;\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += `What's the team's format?
`;\n\t\t\tbuf += `[Gen ${Dex.gen} OU]
`;\n\n\t\t\tbuf += `Should the team be private? (yes/no)
`;\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += `Provide the team:
`;\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += ``;\n\t\t\tbuf += `
`;\n\t\t\treturn buf;\n\t\t},\n\t\tasync edit(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tTeamsHandler.validateAccess(connection);\n\t\t\tconst teamID = toID(query.shift() || \"\");\n\t\t\tif (!teamID.length) {\n\t\t\t\treturn this.errorReply(`Invalid team ID.`);\n\t\t\t}\n\t\t\tthis.title = `[Edit Team] ${teamID}`;\n\t\t\tconst data = await TeamsHandler.get(teamID);\n\t\t\tif (!data) {\n\t\t\t\treturn this.errorReply(`Team ${teamID} not found.`);\n\t\t\t}\n\t\t\tlet buf = `

Edit team ${teamID}

${refresh(this)}
`;\n\t\t\t// let [teamName, formatid, rawPrivacy, rawTeam] = Utils.splitFirst(target, ',', 4);\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += `Team name
`;\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += `Team format
`;\n\t\t\tbuf += ``;\n\t\t\tbuf += `${Dex.formats.get(data.format).name}
`;\n\n\t\t\tbuf += `Team privacy
`;\n\t\t\tconst privacy = ['1', '0'];\n\t\t\tif (!data.private) {\n\t\t\t\tprivacy.reverse(); // first option is the one shown by default so we gotta match it\n\t\t\t}\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += `Team:
`;\n\t\t\tconst teamStr = Teams.export(Teams.import(data.team)!).replace(/\\n/g, ' ');\n\t\t\tbuf += `
`;\n\n\t\t\tbuf += ``;\n\t\t\tbuf += `
`;\n\t\t\treturn buf;\n\t\t},\n\t\tasync searchpublic(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tTeamsHandler.validateAccess(connection, true);\n\t\t\tthis.title = '[Teams] Search';\n\t\t\tlet buf = '
';\n\t\t\tbuf += refresh(this);\n\t\t\tbuf += '

Search all teams

';\n\t\t\tconst type = this.pageid.split('-')[2];\n\t\t\tconst isPersonal = type === 'searchpersonal';\n\t\t\tquery = query.join('-').split('--');\n\t\t\tif (!query.map(toID).filter(Boolean).length || (isPersonal && query.length === 1)) {\n\t\t\t\tbuf += `
`;\n\t\t\t\tbuf += `
`;\n\t\t\t\tbuf += `Search metadata:
`;\n\t\t\t\tbuf += ``;\n\t\t\t\tbuf += `
`;\n\t\t\t\tbuf += `Team format: [Gen ${Dex.gen}] OU

`;\n\t\t\t\tbuf += `Search in team: (separate different searches with commas)
`;\n\t\t\t\tbuf += `Generation:
`;\n\t\t\t\tbuf += `Pokemon:
`;\n\t\t\t\tbuf += `Abilities:
`;\n\t\t\t\tbuf += `Moves:

`;\n\t\t\t\tbuf += ``;\n\t\t\t\treturn buf;\n\t\t\t}\n\t\t\tconst [rawOwner, rawFormat, rawPokemon, rawMoves, rawAbilities, rawGen] = query;\n\t\t\tconst owner = toID(rawOwner);\n\t\t\tif (owner.length > 18) {\n\t\t\t\treturn this.errorReply(`Invalid owner name. Names must be under 18 characters long.`);\n\t\t\t}\n\t\t\tconst format = toID(rawFormat);\n\t\t\tif (format && !Dex.formats.get(format).exists) {\n\t\t\t\treturn this.errorReply(`Format ${format} not found.`);\n\t\t\t}\n\t\t\tconst gen = Number(rawGen);\n\t\t\tif (rawGen && (isNaN(gen) || (gen < 1 || gen > Dex.gen))) {\n\t\t\t\treturn this.errorReply(`Invalid generation: '${rawGen}'`);\n\t\t\t}\n\n\t\t\tconst pokemon = rawPokemon?.split(',').map(toID).filter(Boolean);\n\t\t\tconst moves = rawMoves?.split(',').map(toID).filter(Boolean);\n\t\t\tconst abilities = rawAbilities?.split(',').map(toID).filter(Boolean);\n\n\t\t\tconst search = {\n\t\t\t\tpokemon, moves, format, owner, abilities, gen: gen || undefined,\n\t\t\t} as TeamSearch;\n\t\t\tconst results = await TeamsHandler.search(search, user, 50, isPersonal);\n\n\t\t\t// empty arrays will be falsy strings so this saves space\n\t\t\tbuf += `Search: ` + Object.entries(search)\n\t\t\t\t.filter(([, v]) => !!(v?.toString()))\n\t\t\t\t.map(([k, v]) => `${k.charAt(0).toUpperCase() + k.slice(1)}: ${v}`)\n\t\t\t\t.join(', ');\n\n\t\t\tbuf += `
`;\n\t\t\tif (!results.length) {\n\t\t\t\tbuf += `
No results found.
`;\n\t\t\t\treturn buf;\n\t\t\t}\n\n\t\t\tbuf += results.map(t => TeamsHandler.preview(t, user)).join('
');\n\t\t\treturn buf;\n\t\t},\n\t\tasync searchpersonal(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tthis.pageid = 'view-teams-searchpersonal';\n\n\t\t\treturn ((pages.teams as Chat.PageTable).searchpublic as import('../chat').PageHandler).call(\n\t\t\t\tthis, `${user.id}${query.join('-')}`.split('-'), user, connection\n\t\t\t);\n\t\t},\n\t\tasync browse(query, user, connection) {\n\t\t\tif (!user.named) return Rooms.RETRY_AFTER_LOGIN;\n\t\t\tTeamsHandler.validateAccess(connection, true);\n\t\t\tconst sorter = toID(query.shift()) || 'latest';\n\t\t\tlet count = Number(toID(query.shift())) || 50;\n\t\t\tif (count > MAX_SEARCH) {\n\t\t\t\tcount = MAX_SEARCH;\n\t\t\t}\n\t\t\tlet queryStr = 'SELECT * FROM teams WHERE private IS NULL';\n\t\t\tlet name = sorter;\n\t\t\tswitch (sorter) {\n\t\t\tcase 'views':\n\t\t\t\tqueryStr += ` ORDER BY views DESC `;\n\t\t\t\tname = 'most viewed';\n\t\t\t\tbreak;\n\t\t\tcase 'latest':\n\t\t\t\tqueryStr += ` ORDER BY date DESC`;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn this.errorReply(`Invalid sort term '${sorter}'. Must be either 'views' or 'latest'.`);\n\t\t\t}\n\t\t\tqueryStr += ` LIMIT ${count}`;\n\t\t\tlet buf = `

Browse ${name} teams

`;\n\t\t\tbuf += refresh(this);\n\t\t\tbuf += `
Search`;\n\t\t\tconst opposite = sorter === 'views' ? 'latest' : 'views';\n\t\t\tbuf += ``;\n\t\t\tbuf += `
`;\n\n\t\t\tconst results = await TeamsHandler.query(queryStr, []);\n\t\t\tif (!results.length) {\n\t\t\t\tbuf += `
None found.
`;\n\t\t\t\treturn buf;\n\t\t\t}\n\t\t\tfor (const team of results) {\n\t\t\t\tbuf += TeamsHandler.preview(team, user);\n\t\t\t\tbuf += `
`;\n\t\t\t}\n\t\t\tif (count < MAX_SEARCH) {\n\t\t\t\tbuf += ``;\n\t\t\t}\n\t\t\treturn buf;\n\t\t},\n\t},\n};\n\nprocess.nextTick(() => {\n\tChat.multiLinePattern.register('/teams save ', '/teams update ');\n});\n"], "mappings": "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", "names": [] }