/**
* A sample teams plugin
*
* @author Kris
*/
import {FS, Utils} from "../../lib";
const SAMPLE_TEAMS = 'config/chat-plugins/sample-teams.json';
interface SampleTeamsData {
whitelist: {[formatid: string]: RoomID[]};
/** Teams are stored in the packed format */
teams: {
[formatid: string]: {
uncategorized: {[k: string]: string},
[category: string]: {[teamName: string]: string},
},
};
}
export const teamData: SampleTeamsData = (() => {
try {
return JSON.parse(FS(SAMPLE_TEAMS).readIfExistsSync());
} catch {
return {
whitelist: {},
teams: {},
};
}
})();
function save() {
FS(SAMPLE_TEAMS).writeUpdate(() => JSON.stringify(teamData));
}
for (const formatid in teamData.teams) {
if (!teamData.teams[formatid].uncategorized) teamData.teams[formatid].uncategorized = {};
}
save();
export const SampleTeams = new class SampleTeams {
private isRoomStaff(user: User, roomids: RoomID[]) {
let matched = false;
if (!roomids?.length) return false;
for (const roomid of roomids) {
const room = Rooms.search(roomid);
// Malformed entry from botched room rename
if (!room) continue;
matched = room.auth.isStaff(user.id);
if (matched) break;
}
return matched;
}
isDevMod(user: User) {
return !!Rooms.get('development')?.auth.atLeast(user, '@');
}
checkPermissions(user: User, roomids: RoomID[]) {
// Give Development room mods access to help fix crashes
return this.isRoomStaff(user, roomids) || user.can('bypassall') || this.isDevMod(user);
}
whitelistedRooms(formatid: string, names = false) {
formatid = this.sanitizeFormat(formatid);
if (!teamData.whitelist[formatid]?.length) return null;
return Utils.sortBy(teamData.whitelist[formatid], (x) => {
if (!names) return x;
const room = Rooms.search(x);
if (!room) return x;
return room.title;
});
}
whitelistRooms(formatids: string[], roomids: string[]) {
for (const unsanitizedFormatid of formatids) {
const formatid = this.sanitizeFormat(unsanitizedFormatid);
if (!teamData.whitelist[formatid]) teamData.whitelist[formatid] = [];
for (const roomid of roomids) {
const targetRoom = Rooms.search(roomid);
if (!targetRoom?.persist) {
throw new Chat.ErrorMessage(`Room ${roomid} not found. Check spelling?`);
}
if (teamData.whitelist[formatid].includes(targetRoom.roomid)) {
throw new Chat.ErrorMessage(`Room ${targetRoom.title} is already added.`);
}
teamData.whitelist[formatid].push(targetRoom.roomid);
save();
}
}
}
unwhitelistRoom(formatid: string, roomid: string) {
formatid = this.sanitizeFormat(formatid, false);
const targetRoom = Rooms.search(roomid);
if (!targetRoom?.persist) throw new Chat.ErrorMessage(`Room ${roomid} not found. Check spelling?`);
if (!teamData.whitelist[formatid]?.length) throw new Chat.ErrorMessage(`No rooms are whitelisted for ${formatid}.`);
if (!teamData.whitelist[formatid].includes(targetRoom.roomid)) {
throw new Chat.ErrorMessage(`Room ${targetRoom.title} isn't whitelisted.`);
}
const index = teamData.whitelist[formatid].indexOf(targetRoom.roomid);
teamData.whitelist[formatid].splice(index, 1);
if (!teamData.whitelist[formatid].length) delete teamData.whitelist[formatid];
save();
}
sanitizeFormat(formatid: string, checkExists = false) {
const format = Dex.formats.get(formatid);
if (checkExists && !format.exists) {
throw new Chat.ErrorMessage(`Format "${formatid.trim()}" not found. Check spelling?`);
}
if (format.team) {
throw new Chat.ErrorMessage(`Formats with computer-generated teams can't have team storage.`);
}
return format.id;
}
initializeFormat(formatid: string) {
if (!teamData.teams[formatid]) {
teamData.teams[formatid] = {uncategorized: {}};
save();
}
}
addCategory(user: User, formatid: string, category: string) {
formatid = this.sanitizeFormat(formatid);
if (!this.checkPermissions(user, teamData.whitelist[formatid])) {
let rankNeeded = `a global administrator`;
if (teamData.whitelist[formatid]) {
rankNeeded = `staff in ${Chat.toListString(teamData.whitelist[formatid], "or")}`;
}
throw new Chat.ErrorMessage(`Access denied. You need to be ${rankNeeded} to add teams for ${formatid}`);
}
category = category.trim();
this.initializeFormat(formatid);
if (this.findCategory(formatid, category)) {
throw new Chat.ErrorMessage(`The category named ${category} already exists.`);
}
teamData.teams[formatid][category] = {};
save();
}
removeCategory(user: User, formatid: string, category: string) {
formatid = this.sanitizeFormat(formatid, false);
if (!this.checkPermissions(user, teamData.whitelist[formatid])) {
let rankNeeded = `a global administrator`;
if (teamData.whitelist[formatid]) {
rankNeeded = `staff in ${Chat.toListString(teamData.whitelist[formatid], "or")}`;
}
throw new Chat.ErrorMessage(`Access denied. You need to be ${rankNeeded} to add teams for ${formatid}`);
}
const categoryName = this.findCategory(formatid, category);
if (!categoryName) {
throw new Chat.ErrorMessage(`There's no category named "${category.trim()}" for the format ${formatid}.`);
}
delete teamData.teams[formatid][categoryName];
save();
}
/**
* @param user
* @param formatid
* @param teamName
* @param team - Can be a team in the packed, JSON, or exported format
* @param category - Category the team will go in, defaults to uncategorized
*/
addTeam(user: User, formatid: string, teamName: string, team: string, category = "uncategorized") {
formatid = this.sanitizeFormat(formatid);
if (!this.checkPermissions(user, teamData.whitelist[formatid])) {
let rankNeeded = `a global administrator`;
if (teamData.whitelist[formatid]?.length) {
rankNeeded = `staff in ${Chat.toListString(teamData.whitelist[formatid], "or")}`;
}
throw new Chat.ErrorMessage(`Access denied. You need to be ${rankNeeded} to add teams for ${formatid}`);
}
teamName = teamName.trim();
category = category.trim();
this.initializeFormat(formatid);
if (this.findTeamName(formatid, category, teamName)) {
throw new Chat.ErrorMessage(`There is already a team for ${formatid} with the name ${teamName} in the ${category} category.`);
}
if (!teamData.teams[formatid][category]) this.addCategory(user, formatid, category);
teamData.teams[formatid][category][teamName] = Teams.pack(Teams.import(team.trim()));
save();
return teamData.teams[formatid][category][teamName];
}
removeTeam(user: User, formatid: string, teamid: string, category: string) {
formatid = this.sanitizeFormat(formatid, false);
category = category.trim();
if (!this.checkPermissions(user, teamData.whitelist[formatid])) {
let required = `an administrator`;
if (teamData.whitelist[formatid]) {
required = `staff in ${Chat.toListString(teamData.whitelist[formatid], "or")}`;
}
throw new Chat.ErrorMessage(`Access denied. You need to be ${required} to add teams for ${formatid}`);
}
const categoryName = this.findCategory(formatid, category);
if (!categoryName) {
throw new Chat.ErrorMessage(`There are no teams for ${formatid} under the category ${category.trim()}. Check spelling?`);
}
const teamName = this.findTeamName(formatid, category, teamid);
if (!teamName) {
throw new Chat.ErrorMessage(`There is no team for ${formatid} with the name of "${teamid}". Check spelling?`);
}
const oldTeam = teamData.teams[formatid][categoryName][teamName];
delete teamData.teams[formatid][categoryName][teamName];
if (!Object.keys(teamData.teams[formatid][categoryName]).length) delete teamData.teams[formatid][categoryName];
if (!Object.keys(teamData.teams[formatid]).filter(x => x !== 'uncategorized').length) delete teamData.teams[formatid];
save();
return oldTeam;
}
formatTeam(teamName: string, teamStr: string, broadcasting = false) {
const team = Teams.unpack(teamStr);
if (!team) return `Team is not correctly formatted. PM room staff to fix the formatting.`;
let buf = ``;
if (!broadcasting) {
buf += `