mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-05-18 03:01:00 -05:00
Previously, if you gave e.g. roomvoice to a global moderator, that would demote their room rank to voice. Now, they will remain a moderator, with "voice" only appearing in `/roomauth` and `/auth`. (Includes a refactor of Config.groups)
120 lines
3.3 KiB
TypeScript
120 lines
3.3 KiB
TypeScript
/**
|
|
* Config loader
|
|
* Pokemon Showdown - http://pokemonshowdown.com/
|
|
*
|
|
* @license MIT
|
|
*/
|
|
|
|
import * as defaults from '../config/config-example';
|
|
|
|
export interface GroupInfo {
|
|
symbol: GroupSymbol;
|
|
id: ID;
|
|
name: string;
|
|
rank: number;
|
|
inherit?: GroupSymbol;
|
|
jurisdiction?: string;
|
|
globalGroupInPersonalRoom?: GroupSymbol;
|
|
[k: string]: string | true | number | undefined;
|
|
}
|
|
|
|
export type ConfigType = typeof defaults & {
|
|
groups: {[symbol: string]: GroupInfo},
|
|
groupsranking: GroupSymbol[],
|
|
greatergroupscache: {[combo: string]: GroupSymbol},
|
|
[k: string]: any,
|
|
};
|
|
|
|
const CONFIG_PATH = require.resolve('../config/config');
|
|
|
|
export function load(invalidate = false) {
|
|
if (invalidate) delete require.cache[CONFIG_PATH];
|
|
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
const config = Object.assign({}, defaults, require('../config/config')) as ConfigType;
|
|
// config.routes is nested - we need to ensure values are set for its keys as well.
|
|
config.routes = Object.assign({}, defaults.routes, config.routes);
|
|
cacheGroupData(config);
|
|
return config;
|
|
}
|
|
|
|
export function cacheGroupData(config: ConfigType) {
|
|
if (config.groups) {
|
|
// Support for old config groups format.
|
|
// Should be removed soon.
|
|
console.error(
|
|
`You are using a deprecated version of user group specification in config.\n` +
|
|
`Support for this will be removed soon.\n` +
|
|
`Please ensure that you update your config.js to the new format (see config-example.js, line 220).\n`
|
|
);
|
|
} else {
|
|
config.punishgroups = Object.create(null);
|
|
config.groups = Object.create(null);
|
|
config.groupsranking = [];
|
|
config.greatergroupscache = Object.create(null);
|
|
}
|
|
|
|
const groups = config.groups;
|
|
const punishgroups = config.punishgroups;
|
|
const cachedGroups: {[k: string]: 'processing' | true} = {};
|
|
|
|
function cacheGroup(sym: string, groupData: GroupInfo) {
|
|
if (cachedGroups[sym] === 'processing') return false; // cyclic inheritance.
|
|
|
|
if (cachedGroups[sym] !== true && groupData['inherit']) {
|
|
cachedGroups[sym] = 'processing';
|
|
const inheritGroup = groups[groupData['inherit']];
|
|
if (cacheGroup(groupData['inherit'], inheritGroup)) {
|
|
// Add lower group permissions to higher ranked groups,
|
|
// preserving permissions specifically declared for the higher group.
|
|
for (const key in inheritGroup) {
|
|
if (key in groupData) continue;
|
|
groupData[key] = inheritGroup[key];
|
|
}
|
|
}
|
|
delete groupData['inherit'];
|
|
}
|
|
return (cachedGroups[sym] = true);
|
|
}
|
|
|
|
if (config.grouplist) { // Using new groups format.
|
|
const grouplist = config.grouplist as any;
|
|
const numGroups = grouplist.length;
|
|
for (let i = 0; i < numGroups; i++) {
|
|
const groupData = grouplist[i];
|
|
|
|
// punish groups
|
|
if (groupData.punishgroup) {
|
|
punishgroups[groupData.id] = groupData;
|
|
continue;
|
|
}
|
|
|
|
groupData.rank = numGroups - i - 1;
|
|
groups[groupData.symbol] = groupData;
|
|
config.groupsranking.unshift(groupData.symbol);
|
|
}
|
|
}
|
|
|
|
for (const sym in groups) {
|
|
const groupData = groups[sym];
|
|
cacheGroup(sym, groupData);
|
|
}
|
|
|
|
// hardcode default punishgroups.
|
|
if (!punishgroups.locked) {
|
|
punishgroups.locked = {
|
|
name: 'Locked',
|
|
id: 'locked',
|
|
symbol: '\u203d',
|
|
};
|
|
}
|
|
if (!punishgroups.muted) {
|
|
punishgroups.muted = {
|
|
name: 'Muted',
|
|
id: 'muted',
|
|
symbol: '!',
|
|
};
|
|
}
|
|
}
|
|
|
|
export const Config = load();
|