mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-04-26 02:39:38 -05:00
Some checks failed
Node.js CI / build (18.x) (push) Has been cancelled
This minimizes side effects of import/require across the codebase, and lets the caller be responsible of initializing child processeses, as well as other async logic, such as restoring saved battles.
214 lines
7.7 KiB
TypeScript
214 lines
7.7 KiB
TypeScript
/*
|
|
* Announcements chat plugin
|
|
* By Spandamn
|
|
*/
|
|
|
|
export interface AnnouncementOptions {
|
|
activityNumber?: number;
|
|
source: string;
|
|
timeoutMins?: number;
|
|
timerEnd?: number;
|
|
}
|
|
|
|
export interface AnnouncementData extends AnnouncementOptions {
|
|
readonly activityid: 'announcement';
|
|
}
|
|
|
|
export class Announcement extends Rooms.MinorActivity {
|
|
readonly activityid = 'announcement' as ID;
|
|
name = 'Announcement';
|
|
activityNumber: number;
|
|
source: string;
|
|
constructor(room: Room, options: AnnouncementOptions) {
|
|
super(room);
|
|
this.activityNumber = options.activityNumber || room.nextGameNumber();
|
|
this.source = options.source;
|
|
this.setTimer(options);
|
|
}
|
|
|
|
generateAnnouncement() {
|
|
return `<div class="broadcast-blue"><p style="margin: 2px 0 5px 0"><strong style="font-size:11pt">${this.source}</strong></p></div>`;
|
|
}
|
|
|
|
displayTo(user: User, connection: Connection | null = null) {
|
|
const recipient = connection || user;
|
|
recipient.sendTo(this.room, `|uhtml|announcement${this.activityNumber}|${this.generateAnnouncement()}`);
|
|
}
|
|
|
|
display() {
|
|
const announcement = this.generateAnnouncement();
|
|
for (const id in this.room.users) {
|
|
const thisUser = this.room.users[id];
|
|
thisUser.sendTo(this.room, `|uhtml|announcement${this.activityNumber}|${announcement}`);
|
|
}
|
|
}
|
|
|
|
override onConnect(user: User, connection: Connection | null = null) {
|
|
this.displayTo(user, connection);
|
|
}
|
|
|
|
destroy() {
|
|
this.room.send(`|uhtmlchange|announcement${this.activityNumber}|<div class="infobox">(${this.room.tr`The announcement has ended.`})</div>`);
|
|
this.room.setMinorActivity(null);
|
|
}
|
|
|
|
toJSON(): AnnouncementData {
|
|
return {
|
|
source: this.source,
|
|
activityNumber: this.activityNumber,
|
|
timeoutMins: this.timeoutMins,
|
|
timerEnd: this.timerEnd,
|
|
activityid: 'announcement',
|
|
};
|
|
}
|
|
|
|
save() {
|
|
this.room.settings.minorActivity = this.toJSON();
|
|
this.room.saveSettings();
|
|
}
|
|
}
|
|
|
|
export const commands: Chat.ChatCommands = {
|
|
announcement: {
|
|
htmlcreate: 'new',
|
|
create: 'new',
|
|
new(target, room, user, connection, cmd, message) {
|
|
room = this.requireRoom();
|
|
if (!target) return this.parse('/help announcement new');
|
|
target = target.trim();
|
|
if (room.battle) throw new Chat.ErrorMessage(this.tr`Battles do not support announcements.`);
|
|
|
|
const text = this.filter(target);
|
|
if (target !== text) throw new Chat.ErrorMessage(this.tr`You are not allowed to use filtered words in announcements.`);
|
|
|
|
const supportHTML = cmd === 'htmlcreate';
|
|
|
|
this.checkCan('minigame', null, room);
|
|
if (supportHTML) this.checkCan('declare', null, room);
|
|
this.checkChat();
|
|
if (room.minorActivity) {
|
|
throw new Chat.ErrorMessage(this.tr`There is already a poll or announcement in progress in this room.`);
|
|
}
|
|
|
|
const source = supportHTML ? this.checkHTML(Chat.collapseLineBreaksHTML(target)) : Chat.formatText(target, true);
|
|
|
|
room.setMinorActivity(new Announcement(room, { source }));
|
|
|
|
this.roomlog(`${user.name} used ${message}`);
|
|
this.modlog('ANNOUNCEMENT');
|
|
return this.privateModAction(room.tr`An announcement was started by ${user.name}.`);
|
|
},
|
|
newhelp: [`/announcement create [announcement] - Creates an announcement. Requires: % @ # ~`],
|
|
|
|
htmledit: 'edit',
|
|
edit(target, room, user, connection, cmd, message) {
|
|
room = this.requireRoom();
|
|
const announcement = this.requireMinorActivity(Announcement);
|
|
|
|
if (!target) return this.parse('/help announcement edit');
|
|
target = target.trim();
|
|
const text = this.filter(target);
|
|
if (target !== text) throw new Chat.ErrorMessage(this.tr`You are not allowed to use filtered words in announcements.`);
|
|
|
|
const supportHTML = cmd === 'htmledit';
|
|
|
|
this.checkCan('minigame', null, room);
|
|
if (supportHTML) this.checkCan('declare', null, room);
|
|
this.checkChat();
|
|
|
|
const source = supportHTML ? this.checkHTML(Chat.collapseLineBreaksHTML(target)) : Chat.formatText(target, true);
|
|
announcement.source = source;
|
|
announcement.save();
|
|
|
|
this.roomlog(`${user.name} used ${message}`);
|
|
this.modlog('ANNOUNCEMENT EDIT');
|
|
this.privateModAction(room.tr`The announcement was edited by ${user.name}.`);
|
|
this.parse('/announcement display');
|
|
},
|
|
edithelp: [`/announcement edit [announcement] - Edits the announcement. Requires: % @ # ~`],
|
|
|
|
timer(target, room, user) {
|
|
room = this.requireRoom();
|
|
const announcement = this.requireMinorActivity(Announcement);
|
|
|
|
if (target) {
|
|
this.checkCan('minigame', null, room);
|
|
if (target === 'clear') {
|
|
if (!announcement.endTimer()) throw new Chat.ErrorMessage(this.tr`There is no timer to clear.`);
|
|
return this.add(this.tr`The announcement timer was turned off.`);
|
|
}
|
|
const timeoutMins = parseFloat(target);
|
|
if (isNaN(timeoutMins) || timeoutMins <= 0 || timeoutMins > 7 * 24 * 60) {
|
|
throw new Chat.ErrorMessage(this.tr`Time should be a number of minutes less than one week.`);
|
|
}
|
|
announcement.setTimer({ timeoutMins });
|
|
room.add(`The announcement timer was turned on: the announcement will end in ${timeoutMins} minute${Chat.plural(timeoutMins)}.`);
|
|
this.modlog('ANNOUNCEMENT TIMER', null, `${timeoutMins} minutes`);
|
|
return this.privateModAction(`The announcement timer was set to ${timeoutMins} minute${Chat.plural(timeoutMins)} by ${user.name}.`);
|
|
} else {
|
|
if (!this.runBroadcast()) return;
|
|
if (announcement.timeout) {
|
|
return this.sendReply(`The announcement timer is on and will end in ${announcement.timeoutMins} minute${Chat.plural(announcement.timeoutMins)}.`);
|
|
} else {
|
|
return this.sendReply(this.tr`The announcement timer is off.`);
|
|
}
|
|
}
|
|
},
|
|
timerhelp: [
|
|
`/announcement timer [minutes] - Sets the announcement to automatically end after [minutes] minutes. Requires: % @ # ~`,
|
|
`/announcement timer clear - Clears the announcement's timer. Requires: % @ # ~`,
|
|
],
|
|
|
|
close: 'end',
|
|
stop: 'end',
|
|
end(target, room, user) {
|
|
room = this.requireRoom();
|
|
this.checkCan('minigame', null, room);
|
|
this.checkChat();
|
|
const announcement = this.requireMinorActivity(Announcement);
|
|
announcement.end(room);
|
|
this.modlog('ANNOUNCEMENT END');
|
|
this.privateModAction(room.tr`The announcement was ended by ${user.name}.`);
|
|
},
|
|
endhelp: [`/announcement end - Ends a announcement and displays the results. Requires: % @ # ~`],
|
|
|
|
show: '',
|
|
display: '',
|
|
''(target, room, user, connection) {
|
|
room = this.requireRoom();
|
|
const announcement = this.requireMinorActivity(Announcement);
|
|
if (!this.runBroadcast()) return;
|
|
room.update();
|
|
|
|
if (this.broadcasting) {
|
|
announcement.display();
|
|
} else {
|
|
announcement.displayTo(user, connection);
|
|
}
|
|
},
|
|
displayhelp: [`/announcement display - Displays the announcement`],
|
|
},
|
|
announcementhelp: [
|
|
`/announcement allows rooms to run their own announcements. These announcements are limited to one announcement at a time per room.`,
|
|
`Accepts the following commands:`,
|
|
`/announcement create [announcement] - Creates a announcement. Requires: % @ # ~`,
|
|
`/announcement htmlcreate [announcement] - Creates a announcement, with HTML allowed. Requires: # ~`,
|
|
`/announcement edit [announcement] - Edits the announcement. Requires: % @ # ~`,
|
|
`/announcement htmledit [announcement] - Edits the announcement, with HTML allowed. Requires: # ~`,
|
|
`/announcement timer [minutes] - Sets the announcement to automatically end after [minutes]. Requires: % @ # ~`,
|
|
`/announcement display - Displays the announcement`,
|
|
`/announcement end - Ends a announcement. Requires: % @ # ~`,
|
|
],
|
|
};
|
|
|
|
// should handle restarts and also hotpatches
|
|
export function start() {
|
|
Chat.multiLinePattern.register('/announcement (new|create|htmlcreate|edit|htmledit) ');
|
|
|
|
for (const room of Rooms.rooms.values()) {
|
|
if (room.settings.minorActivity?.activityid === 'announcement') {
|
|
room.setMinorActivity(new Announcement(room, room.settings.minorActivity), true);
|
|
}
|
|
}
|
|
}
|