diff --git a/server/chat-commands/moderation.ts b/server/chat-commands/moderation.ts index 0815ebb30f..2fef4c15dc 100644 --- a/server/chat-commands/moderation.ts +++ b/server/chat-commands/moderation.ts @@ -126,9 +126,13 @@ export function runCrisisDemote(userid: ID) { return from; } -Punishments.addPunishmentType('YEARLOCK', "Locked for a year", (user, punishment) => { - user.locked = user.id; - Chat.punishmentfilter(user, punishment); +Punishments.addPunishmentType({ + type: 'YEARLOCK', + desc: "Locked for a year", + onActivate: (user, punishment) => { + user.locked = user.id; + Chat.punishmentfilter(user, punishment); + }, }); export const commands: Chat.ChatCommands = { diff --git a/server/chat-plugins/helptickets.ts b/server/chat-plugins/helptickets.ts index a4f7c321d7..3e1d3dd706 100644 --- a/server/chat-plugins/helptickets.ts +++ b/server/chat-plugins/helptickets.ts @@ -12,7 +12,10 @@ const REPLAY_REGEX = new RegExp( `${Utils.escapeRegex(Config.routes.replays)}/(?:[a-z0-9]-)?(?:[a-z0-9]+)-(?:[0-9]+)(?:-[a-z0-9]+pw)?`, "g" ); -Punishments.addPunishmentType('TICKETBAN', 'banned from creating help tickets'); +Punishments.addPunishmentType({ + type: 'TICKETBAN', + desc: 'banned from creating help tickets', +}); interface TicketState { creator: string; diff --git a/server/chat-plugins/mafia.ts b/server/chat-plugins/mafia.ts index 960585f165..d54a895231 100644 --- a/server/chat-plugins/mafia.ts +++ b/server/chat-plugins/mafia.ts @@ -100,8 +100,14 @@ const VALID_IMAGES = [ let MafiaData: MafiaData = Object.create(null); let logs: MafiaLog = {leaderboard: {}, mvps: {}, hosts: {}, plays: {}, leavers: {}}; -Punishments.addRoomPunishmentType('MAFIAGAMEBAN', 'banned from playing mafia games'); -Punishments.addRoomPunishmentType('MAFIAHOSTBAN', 'banned from hosting mafia games'); +Punishments.addRoomPunishmentType({ + type: 'MAFIAGAMEBAN', + desc: 'banned from playing mafia games', +}); +Punishments.addRoomPunishmentType({ + type: 'MAFIAHOSTBAN', + desc: 'banned from hosting mafia games', +}); const hostQueue: ID[] = []; diff --git a/server/punishments.ts b/server/punishments.ts index f7eb47ad04..d102d020b4 100644 --- a/server/punishments.ts +++ b/server/punishments.ts @@ -68,7 +68,9 @@ export interface Punishment { */ export interface PunishInfo { desc: string; - callback?: (user: User, punishment: Punishment, room: Room | null, isExactMatch: boolean) => void; + onActivate?: (user: User, punishment: Punishment, room: Room | null, isExactMatch: boolean) => void; + /** For room punishments - should they count for punishmentmonitor? default to no. */ + activatePunishMonitor?: boolean; } interface PunishmentEntry { @@ -289,9 +291,9 @@ export const Punishments = new class { // references to global.Punishments? are here because if you hotpatch punishments without hotpatching chat, // old punishment types won't be loaded into here, which might cause issues. This guards against that. ...(global.Punishments?.roomPunishmentTypes || []), - ['ROOMBAN', {desc: 'banned'}], - ['BLACKLIST', {desc: 'blacklisted'}], - ['MUTE', {desc: 'muted'}], + ['ROOMBAN', {desc: 'banned', activatePunishMonitor: true}], + ['BLACKLIST', {desc: 'blacklisted', activatePunishMonitor: true}], + ['MUTE', {desc: 'muted', activatePunishMonitor: true}], ]); constructor() { setImmediate(() => { @@ -874,13 +876,32 @@ export const Punishments = new class { return success; } - addRoomPunishmentType(type: string, desc: string, callback?: PunishInfo['callback']) { - this.roomPunishmentTypes.set(type, {desc, callback}); - if (!this.sortedRoomTypes.includes(type)) this.sortedRoomTypes.unshift(type); + addRoomPunishmentType( + opts: PunishInfo & {type: string} | string, + // backwards compat - todo make only PunishInfo & {type: string} + desc?: string, + callback?: PunishInfo['onActivate'] + ) { + if (typeof opts === 'string') { + if (!desc) throw new Error('Desc argument must be provided if type is string'); + opts = {onActivate: callback, desc, type: opts}; + } + this.roomPunishmentTypes.set(opts.type, opts); + if (!this.sortedRoomTypes.includes(opts.type)) this.sortedRoomTypes.unshift(opts.type); } - addPunishmentType(type: string, desc: string, callback?: PunishInfo['callback']) { - this.punishmentTypes.set(type, {desc, callback}); - if (!this.sortedTypes.includes(type)) this.sortedTypes.unshift(type); + + addPunishmentType( + opts: PunishInfo & {type: string} | string, + // backwards compat - todo make only PunishInfo & {type: string} + desc?: string, + callback?: PunishInfo['onActivate'] + ) { + if (typeof opts === 'string') { + if (!desc) throw new Error('Desc argument must be provided if type is string'); + opts = {onActivate: callback, desc, type: opts}; + } + this.punishmentTypes.set(opts.type, opts); + if (!this.sortedTypes.includes(opts.type)) this.sortedTypes.unshift(opts.type); } /********************************************************* @@ -1661,8 +1682,8 @@ export const Punishments = new class { user.notified.lock = true; user.locked = punishUserid; user.updateIdentity(); - } else if (punishmentInfo?.callback) { - punishmentInfo.callback.call(this, user, punishment, null, punishment.id === user.id); + } else if (punishmentInfo?.onActivate) { + punishmentInfo.onActivate.call(this, user, punishment, null, punishment.id === user.id); } Punishments.checkPunishmentTime(user, punishment); } @@ -1692,7 +1713,7 @@ export const Punishments = new class { } } else { const info = Punishments.punishmentTypes.get(punishment.type); - info?.callback?.call(this, user, punishment, null, punishment.id === user.id); + info?.onActivate?.call(this, user, punishment, null, punishment.id === user.id); } } } @@ -1770,8 +1791,8 @@ export const Punishments = new class { if (punishments) { for (const punishment of punishments) { const info = this.roomPunishmentTypes.get(punishment.type); - if (info?.callback) { - info.callback.call(this, user, punishment, Rooms.get(roomid)!, punishment.id === user.id); + if (info?.onActivate) { + info.onActivate.call(this, user, punishment, Rooms.get(roomid)!, punishment.id === user.id); continue; } if (punishment.type !== 'ROOMBAN' && punishment.type !== 'BLACKLIST') return null; @@ -2018,7 +2039,10 @@ export const Punishments = new class { const minPunishments = (typeof Config.monitorminpunishments === 'number' ? Config.monitorminpunishments : 3); if (!minPunishments) return; - const punishments = Punishments.getRoomPunishments(user, {checkIps: true, publicOnly: true}); + let punishments = Punishments.getRoomPunishments(user, {checkIps: true, publicOnly: true}); + punishments = punishments.filter(([room, punishment]) => ( + Punishments.roomPunishmentTypes.get(punishment.type)?.activatePunishMonitor + )); if (punishments.length >= minPunishments) { let points = 0; diff --git a/server/tournaments/index.ts b/server/tournaments/index.ts index 4c63100d1c..7b796d78bd 100644 --- a/server/tournaments/index.ts +++ b/server/tournaments/index.ts @@ -26,7 +26,10 @@ const MAX_REASON_LENGTH = 300; const MAX_CUSTOM_NAME_LENGTH = 100; const TOURBAN_DURATION = 14 * 24 * 60 * 60 * 1000; -Punishments.addRoomPunishmentType('TOURBAN', 'banned from tournaments'); +Punishments.addRoomPunishmentType({ + type: 'TOURBAN', + desc: 'banned from tournaments', +}); const TournamentGenerators = { __proto__: null,