mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-08-28 12:04:28 -05:00
Roomevents: Support event categories (#6820)
This commit is contained in:
@@ -8,9 +8,33 @@
|
||||
*/
|
||||
import {Utils} from '../../lib/utils';
|
||||
|
||||
type RoomEvent = NonNullable<import('../rooms').RoomSettings['events']>[''];
|
||||
export interface RoomEvent {
|
||||
eventName: string;
|
||||
date: string;
|
||||
desc: string;
|
||||
started: boolean;
|
||||
}
|
||||
|
||||
function formatEvent(event: RoomEvent, showAliases?: boolean) {
|
||||
export interface RoomEventAlias {
|
||||
eventID: ID;
|
||||
}
|
||||
|
||||
export interface RoomEventCategory {
|
||||
events: ID[];
|
||||
}
|
||||
|
||||
function convertAliasFormat(room: Room) {
|
||||
if (!room.settings.events) return;
|
||||
for (const event of Object.values(room.settings.events) as AnyObject[]) {
|
||||
if (!event.aliases) continue;
|
||||
for (const alias of event.aliases) {
|
||||
room.settings.events[alias] = {eventID: toID(event.eventName)};
|
||||
}
|
||||
delete event.aliases;
|
||||
}
|
||||
}
|
||||
|
||||
function formatEvent(room: Room, event: RoomEvent, showAliases?: boolean, showCategories?: boolean) {
|
||||
const timeRemaining = new Date(event.date).getTime() - new Date().getTime();
|
||||
let explanation = timeRemaining.toString();
|
||||
if (!timeRemaining) explanation = "The time remaining for this event is not available";
|
||||
@@ -19,30 +43,57 @@ function formatEvent(event: RoomEvent, showAliases?: boolean) {
|
||||
if (!isNaN(timeRemaining)) {
|
||||
explanation = `This event will start in: ${Chat.toDurationString(timeRemaining, {precision: 2})}`;
|
||||
}
|
||||
|
||||
const eventID = toID(event.eventName);
|
||||
const aliases = getAliases(room, eventID);
|
||||
const categories = getAllCategories(room).filter(
|
||||
category => (room.settings.events![category] as RoomEventCategory).events.includes(eventID)
|
||||
);
|
||||
|
||||
let ret = `<tr title="${explanation}">`;
|
||||
ret += Utils.html`<td>${event.eventName}</td>`;
|
||||
ret += showAliases ? Utils.html`<td>${event.aliases?.join(", ")}</td>` : ``;
|
||||
if (showAliases) ret += Utils.html`<td>${aliases.join(", ")}</td>`;
|
||||
if (showCategories) ret += Utils.html`<td>${categories.join(", ")}</td>`;
|
||||
ret += `<td>${Chat.formatText(event.desc, true)}</td>`;
|
||||
ret += Utils.html`<td><time>${event.date}</time></td></tr>`;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function getAllAliases(room: Room) {
|
||||
function getAliases(room: Room, eventID?: ID) {
|
||||
if (!room.settings.events) return [];
|
||||
const aliases: string[] = [];
|
||||
for (const event of Object.values(room.settings.events)) {
|
||||
if (event.aliases) aliases.push(...event.aliases);
|
||||
for (const aliasID in room.settings.events) {
|
||||
if (
|
||||
'eventID' in room.settings.events[aliasID] &&
|
||||
(!eventID || (room.settings.events[aliasID] as RoomEventAlias).eventID === eventID)
|
||||
) aliases.push(aliasID);
|
||||
}
|
||||
return aliases;
|
||||
}
|
||||
|
||||
function getAllCategories(room: Room) {
|
||||
if (!room.settings.events) return [];
|
||||
const categories: string[] = [];
|
||||
for (const categoryID in room.settings.events) {
|
||||
if ('events' in room.settings.events[categoryID]) categories.push(categoryID);
|
||||
}
|
||||
return categories;
|
||||
}
|
||||
|
||||
function getAllEvents(room: Room) {
|
||||
if (!room.settings.events) return [];
|
||||
const events: RoomEvent[] = [];
|
||||
for (const event of Object.values(room.settings.events)) {
|
||||
if ('eventName' in event) events.push(event);
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
function getEventID(nameOrAlias: string, room: Room): ID {
|
||||
let id = toID(nameOrAlias);
|
||||
if (room.settings.events && !room.settings.events[id]) {
|
||||
for (const possibleEvent in room.settings.events) {
|
||||
if (room.settings.events[possibleEvent].aliases?.includes(id)) {
|
||||
id = toID(possibleEvent);
|
||||
}
|
||||
}
|
||||
const event = room.settings.events?.[id];
|
||||
if (event && 'eventID' in event) {
|
||||
id = event.eventID;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@@ -57,12 +108,18 @@ export const commands: ChatCommands = {
|
||||
return this.errorReply("There are currently no planned upcoming events for this room.");
|
||||
}
|
||||
if (!this.runBroadcast()) return;
|
||||
const hasAliases = getAllAliases(room).length > 0;
|
||||
convertAliasFormat(room);
|
||||
const hasAliases = getAliases(room).length > 0;
|
||||
const hasCategories = getAllCategories(room).length > 0;
|
||||
|
||||
let buff = '<table border="1" cellspacing="0" cellpadding="3">';
|
||||
buff += `<th>Event Name:</th>${hasAliases ? `<th>Event Aliases:</th>` : ``}<th>Event Description:</th><th>Event Date:</th>`;
|
||||
for (const i in room.settings.events) {
|
||||
buff += formatEvent(room.settings.events[i], hasAliases);
|
||||
buff += '<th>Event Name:</th>';
|
||||
if (hasAliases) buff += '<th>Event Aliases:</th>';
|
||||
if (hasCategories) buff += '<th>Event Categories:</th>';
|
||||
buff += '<th>Event Description:</th><th>Event Date:</th>';
|
||||
|
||||
for (const event of getAllEvents(room)) {
|
||||
buff += formatEvent(room, event, hasAliases, hasCategories);
|
||||
}
|
||||
buff += '</table>';
|
||||
return this.sendReply(`|raw|<div class="infobox-limited">${buff}</div>`);
|
||||
@@ -75,11 +132,12 @@ export const commands: ChatCommands = {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
if (!this.can('ban', null, room)) return false;
|
||||
if (!room.settings.events) room.settings.events = Object.create(null);
|
||||
convertAliasFormat(room);
|
||||
const events = room.settings.events!;
|
||||
const [eventName, date, ...desc] = target.split(target.includes('|') ? '|' : ',');
|
||||
|
||||
if (!(eventName && date && desc)) {
|
||||
return this.errorReply("You're missing a command parameter - see /help roomevents for this command's syntax.");
|
||||
return this.errorReply("You're missing a command parameter - to see this command's syntax, use /help roomevents.");
|
||||
}
|
||||
|
||||
const dateActual = date.trim();
|
||||
@@ -92,7 +150,9 @@ export const commands: ChatCommands = {
|
||||
const eventId = getEventID(eventName, room);
|
||||
if (!eventId) return this.errorReply("Event names must contain at least one alphanumerical character.");
|
||||
|
||||
const oldEvent = events[eventId];
|
||||
const oldEvent = room.settings.events?.[eventId] as RoomEvent;
|
||||
if (oldEvent && 'events' in oldEvent) return this.errorReply(`"${eventId}" is already the name of a category.`);
|
||||
|
||||
const eventNameActual = (oldEvent ? oldEvent.eventName : eventName.trim());
|
||||
this.privateModAction(`(${user.name} ${oldEvent ? "edited the" : "added a"} roomevent titled "${eventNameActual}".)`);
|
||||
this.modlog('ROOMEVENT', null, `${oldEvent ? "edited" : "added"} "${eventNameActual}"`);
|
||||
@@ -101,7 +161,6 @@ export const commands: ChatCommands = {
|
||||
date: dateActual,
|
||||
desc: descString,
|
||||
started: false,
|
||||
aliases: oldEvent?.aliases,
|
||||
};
|
||||
room.saveSettings();
|
||||
},
|
||||
@@ -112,19 +171,21 @@ export const commands: ChatCommands = {
|
||||
let [oldName, newName] = target.split(target.includes('|') ? '|' : ',');
|
||||
if (!(oldName && newName)) return this.errorReply("Usage: /roomevents rename [old name], [new name]");
|
||||
|
||||
convertAliasFormat(room);
|
||||
newName = newName.trim();
|
||||
const newID = toID(newName);
|
||||
const oldID = (getAllAliases(room).includes(toID(oldName)) ? getEventID(oldName, room) : toID(oldName));
|
||||
const oldID = (getAliases(room).includes(toID(oldName)) ? getEventID(oldName, room) : toID(oldName));
|
||||
if (newID === oldID) return this.errorReply("The new name must be different from the old one.");
|
||||
if (!newID) return this.errorReply("Event names must contain at least one alphanumeric character.");
|
||||
if (newName.length > 50) return this.errorReply("Event names should not exceed 50 characters.");
|
||||
|
||||
const events = room.settings.events!;
|
||||
const eventData = events?.[oldID];
|
||||
if (!eventData) return this.errorReply(`There is no event titled "${oldName}".`);
|
||||
if (events[newID] || getAllAliases(room).includes(newID)) {
|
||||
return this.errorReply(`"${newName}" is already an event or alias.`);
|
||||
if (!(eventData && 'eventName' in eventData)) return this.errorReply(`There is no event titled "${oldName}".`);
|
||||
if (events?.[newID]) {
|
||||
return this.errorReply(`"${newName}" is already an event, alias, or category.`);
|
||||
}
|
||||
|
||||
const originalName = eventData.eventName;
|
||||
eventData.eventName = newName;
|
||||
events[newID] = eventData;
|
||||
@@ -143,9 +204,11 @@ export const commands: ChatCommands = {
|
||||
return this.errorReply("There are currently no planned upcoming events for this room to start.");
|
||||
}
|
||||
if (!target) return this.errorReply("Usage: /roomevents start [event name]");
|
||||
convertAliasFormat(room);
|
||||
|
||||
target = toID(target);
|
||||
const event = room.settings.events[getEventID(target, room)];
|
||||
if (!event) return this.errorReply(`There is no event titled '${target}'. Check spelling?`);
|
||||
if (!(event && 'eventName' in event)) return this.errorReply(`There is no event titled '${target}'. Check spelling?`);
|
||||
if (event.started) {
|
||||
return this.errorReply(`The event ${event.eventName} has already started.`);
|
||||
}
|
||||
@@ -175,35 +238,82 @@ export const commands: ChatCommands = {
|
||||
return this.errorReply("There are currently no planned upcoming events for this room to remove.");
|
||||
}
|
||||
if (!target) return this.errorReply("Usage: /roomevents remove [event name]");
|
||||
target = toID(target);
|
||||
if (getAllAliases(room).includes(target)) return this.errorReply("To delete aliases, use /roomevents removealias.");
|
||||
if (!room.settings.events[target]) return this.errorReply(`There is no event titled '${target}'. Check spelling?`);
|
||||
const eventID = toID(target);
|
||||
convertAliasFormat(room);
|
||||
if (getAliases(room).includes(eventID)) return this.errorReply("To delete aliases, use /roomevents removealias.");
|
||||
if (!(room.settings.events[eventID] && 'eventName' in room.settings.events[eventID])) {
|
||||
return this.errorReply(`There is no event titled '${target}'. Check spelling?`);
|
||||
}
|
||||
|
||||
delete room.settings.events[target];
|
||||
for (const alias of getAliases(room, eventID)) {
|
||||
delete room.settings.events[alias];
|
||||
}
|
||||
|
||||
this.privateModAction(`(${user.name} removed a roomevent titled "${target}".)`);
|
||||
this.modlog('ROOMEVENT', null, `removed "${target}"`);
|
||||
room.saveSettings();
|
||||
},
|
||||
|
||||
view(target, room, user) {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
if (!room.settings.events || !Object.keys(room.settings.events).length) {
|
||||
return this.errorReply("There are currently no planned upcoming events for this room.");
|
||||
}
|
||||
|
||||
if (!target) return this.errorReply("Usage: /roomevents view [event name]");
|
||||
target = toID(target);
|
||||
const event = room.settings.events[getEventID(target, room)];
|
||||
if (!event) return this.errorReply(`There is no event titled '${target}'. Check spelling?`);
|
||||
if (!target) return this.errorReply("Usage: /roomevents view [event name, alias, or category]");
|
||||
convertAliasFormat(room);
|
||||
target = getEventID(target, room);
|
||||
|
||||
let events: RoomEvent[] = [];
|
||||
if (getAllCategories(room).includes(target)) {
|
||||
for (const categoryID of Object.keys(room.settings.events)) {
|
||||
const category = room.settings.events[categoryID];
|
||||
if ('events' in category && categoryID === target) {
|
||||
events = category.events.map(e => room.settings.events?.[e] as RoomEvent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (room.settings.events[target] && 'eventName' in room.settings.events[target]) {
|
||||
events.push(room.settings.events[target] as RoomEvent);
|
||||
} else {
|
||||
return this.errorReply(`There is no event or category titled '${target}'. Check spelling?`);
|
||||
}
|
||||
if (!this.runBroadcast()) return;
|
||||
const hasAliases = event.aliases && event.aliases.length > 0;
|
||||
const buff = `<table border="1" cellspacing="0" cellpadding="3">${formatEvent(event, hasAliases)}</table>`;
|
||||
let hasAliases = false;
|
||||
let hasCategories = false;
|
||||
|
||||
for (const event of events) {
|
||||
if (getAliases(room, toID(event.eventName)).length) hasAliases = true;
|
||||
}
|
||||
|
||||
for (const potentialCategory of getAllCategories(room)) {
|
||||
if (
|
||||
events.map(event => toID(event.eventName))
|
||||
.filter(id => (room.settings.events?.[potentialCategory] as RoomEventCategory).events.includes(id)).length
|
||||
) hasCategories = true; break;
|
||||
}
|
||||
|
||||
let buff = '<table border="1" cellspacing="0" cellpadding="3">';
|
||||
buff += '<th>Event Name:</th>';
|
||||
if (hasAliases) buff += '<th>Event Aliases:</th>';
|
||||
if (hasCategories) buff += '<th>Event Categories:</th>';
|
||||
buff += '<th>Event Description:</th><th>Event Date:</th>';
|
||||
for (const event of events) {
|
||||
buff += formatEvent(room, event, hasAliases, hasCategories);
|
||||
}
|
||||
buff += '</table>';
|
||||
|
||||
this.sendReply(`|raw|<div class="infobox-limited">${buff}</div>`);
|
||||
if (!this.broadcasting && user.can('ban', null, room)) {
|
||||
if (!this.broadcasting && user.can('ban', null, room) && events.length === 1) {
|
||||
const event = events[0];
|
||||
this.sendReplyBox(
|
||||
Utils.html`<code>/roomevents add ${event.eventName} |` +
|
||||
Utils.html`${event.date} | ${event.desc}</code>`
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
alias: 'addalias',
|
||||
addalias(target, room, user) {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
@@ -215,39 +325,144 @@ export const commands: ChatCommands = {
|
||||
if (!room.settings.events || Object.keys(room.settings.events).length === 0) {
|
||||
return this.errorReply(`There are currently no scheduled events.`);
|
||||
}
|
||||
convertAliasFormat(room);
|
||||
const event = room.settings.events[eventId];
|
||||
if (!event) return this.errorReply(`There is no event titled "${eventId}".`);
|
||||
if (!(event && 'eventName' in event)) return this.errorReply(`There is no event titled "${eventId}".`);
|
||||
if (room.settings.events[alias]) return this.errorReply(`"${alias}" is already an event, alias, or category.`);
|
||||
|
||||
if (getAllAliases(room).includes(alias) || room.settings.events[alias]) {
|
||||
return this.errorReply(`"${alias}" is already an event or an alias of an event.`);
|
||||
}
|
||||
if (!event.aliases) event.aliases = [];
|
||||
event.aliases.push(alias);
|
||||
room.settings.events[alias] = {eventID: eventId};
|
||||
this.privateModAction(`(${user.name} added an alias "${alias}" for the roomevent "${eventId}".)`);
|
||||
this.modlog('ROOMEVENT', null, `alias for "${eventId}": "${alias}"`);
|
||||
room.saveSettings();
|
||||
},
|
||||
|
||||
deletealias: 'removealias',
|
||||
removealias(target, room, user) {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
if (!this.can('ban', null, room)) return false;
|
||||
target = toID(target);
|
||||
if (!target) return this.errorReply("Usage: /roomevents removealias <alias>");
|
||||
if (!getAllAliases(room).includes(target)) return this.errorReply(`${target} isn't an alias.`);
|
||||
|
||||
const event = room.settings.events![getEventID(target, room)];
|
||||
if (event.aliases) {
|
||||
event.aliases = event.aliases.filter(alias => alias !== target);
|
||||
if (!event.aliases.length) event.aliases = undefined;
|
||||
if (!room.settings.events || Object.keys(room.settings.events).length === 0) {
|
||||
return this.errorReply(`There are currently no scheduled events.`);
|
||||
}
|
||||
convertAliasFormat(room);
|
||||
if (!(room.settings.events[target] && 'eventID' in room.settings.events[target])) {
|
||||
return this.errorReply(`${target} isn't an alias.`);
|
||||
}
|
||||
delete room.settings.events[target];
|
||||
|
||||
this.privateModAction(`(${user.name} removed the alias "${target}")`);
|
||||
this.modlog('ROOMEVENT', null, `removed the alias "${target}"`);
|
||||
room.saveSettings();
|
||||
},
|
||||
|
||||
addtocategory(target, room, user) {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
if (!this.can('ban', null, room)) return false;
|
||||
const [eventId, categoryId] = target.split(target.includes('|') ? '|' : ',').map(argument => toID(argument));
|
||||
if (!(eventId && categoryId)) return this.errorReply("Usage: /roomevents addtocategory [event name], [category].");
|
||||
if (!room.settings.events || Object.keys(room.settings.events).length === 0) {
|
||||
return this.errorReply(`There are currently no scheduled events.`);
|
||||
}
|
||||
convertAliasFormat(room);
|
||||
const event = room.settings.events[getEventID(eventId, room)];
|
||||
if (!(event && 'eventName' in event)) return this.errorReply(`There is no event or alias titled "${eventId}".`);
|
||||
const category = room.settings.events[categoryId];
|
||||
if (category && !('events' in category)) {
|
||||
return this.errorReply(`There is already an event or alias titled "${categoryId}".`);
|
||||
}
|
||||
if (!category) {
|
||||
return this.errorReply(`There is no category titled "${categoryId}". To create it, use /roomevents addcategory ${categoryId}.`);
|
||||
}
|
||||
if (category.events.includes(toID(event.eventName))) {
|
||||
return this.errorReply(`The event "${eventId}" is already in the "${categoryId}" category.`);
|
||||
}
|
||||
category.events.push(toID(event.eventName));
|
||||
room.settings.events[categoryId] = category;
|
||||
|
||||
this.privateModAction(`(${user.name} added the roomevent "${eventId}" to the category "${categoryId}".)`);
|
||||
this.modlog('ROOMEVENT', null, `category for "${eventId}": "${categoryId}"`);
|
||||
|
||||
room.saveSettings();
|
||||
},
|
||||
|
||||
removefromcategory(target, room, user) {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
if (!this.can('ban', null, room)) return false;
|
||||
const [eventId, categoryId] = target.split(target.includes('|') ? '|' : ',').map(argument => toID(argument));
|
||||
if (!(eventId && categoryId)) {
|
||||
return this.errorReply("Usage: /roomevents removefromcategory [event name], [category].");
|
||||
}
|
||||
if (!room.settings.events || Object.keys(room.settings.events).length === 0) {
|
||||
return this.errorReply(`There are currently no scheduled events.`);
|
||||
}
|
||||
convertAliasFormat(room);
|
||||
const event = room.settings.events[getEventID(eventId, room)];
|
||||
if (!(event && 'eventName' in event)) return this.errorReply(`There is no event or alias titled "${eventId}".`);
|
||||
|
||||
const category = room.settings.events[categoryId];
|
||||
if (category && !('events' in category)) {
|
||||
return this.errorReply(`There is already an event or alias titled "${categoryId}".`);
|
||||
}
|
||||
if (!category) return this.errorReply(`There is no category titled "${categoryId}".`);
|
||||
|
||||
if (!category.events.includes(toID(event.eventName))) {
|
||||
return this.errorReply(`The event "${eventId}" isn't in the "${categoryId}" category.`);
|
||||
}
|
||||
category.events = category.events.filter(e => e !== eventId);
|
||||
room.settings.events[categoryId] = category;
|
||||
|
||||
this.privateModAction(`(${user.name} removed the roomevent "${eventId}" from the category "${categoryId}".)`);
|
||||
this.modlog('ROOMEVENT', null, `category for "${eventId}": removed "${categoryId}"`);
|
||||
|
||||
room.saveSettings();
|
||||
},
|
||||
|
||||
addcat: 'addcategory',
|
||||
addcategory(target, room, user) {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
if (!this.can('ban', null, room)) return false;
|
||||
const categoryId = toID(target);
|
||||
if (!target) {
|
||||
return this.errorReply("Usage: /roomevents addcategory [category name]. Categories must contain at least one alphanumeric character.");
|
||||
}
|
||||
convertAliasFormat(room);
|
||||
if (!room.settings.events) room.settings.events = Object.create(null);
|
||||
if (room.settings.events?.[categoryId]) return this.errorReply(`The category "${target}" already exists.`);
|
||||
|
||||
room.settings.events![categoryId] = {events: []};
|
||||
|
||||
this.privateModAction(`(${user.name} added the category "${categoryId}".)`);
|
||||
this.modlog('ROOMEVENT', null, `category: added "${categoryId}"`);
|
||||
|
||||
room.saveSettings();
|
||||
},
|
||||
|
||||
deletecategory: 'removecategory',
|
||||
deletecat: 'removecategory',
|
||||
removecat: 'removecategory',
|
||||
rmcat: 'removecategory',
|
||||
removecategory(target, room, user) {
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
if (!this.can('ban', null, room)) return false;
|
||||
const categoryId = toID(target);
|
||||
if (!target) return this.errorReply("Usage: /roomevents removecategory [category name].");
|
||||
convertAliasFormat(room);
|
||||
if (!room.settings.events) room.settings.events = Object.create(null);
|
||||
if (!room.settings.events?.[categoryId]) return this.errorReply(`The category "${target}" doesn't exist.`);
|
||||
|
||||
delete room.settings.events?.[categoryId];
|
||||
|
||||
this.privateModAction(`(${user.name} removed the category "${categoryId}".)`);
|
||||
this.modlog('ROOMEVENT', null, `category: removed "${categoryId}"`);
|
||||
|
||||
room.saveSettings();
|
||||
},
|
||||
|
||||
help(target, room, user) {
|
||||
return this.parse('/help roomevents');
|
||||
},
|
||||
|
||||
sortby(target, room, user) {
|
||||
// preconditions
|
||||
if (!room.persist) return this.errorReply("This command is unavailable in temporary rooms.");
|
||||
@@ -260,7 +475,9 @@ export const commands: ChatCommands = {
|
||||
let multiplier = 1;
|
||||
let columnName = "";
|
||||
const delimited = target.split(target.includes('|') ? '|' : ',');
|
||||
const sortable = Object.values(room.settings.events);
|
||||
const sortable = Object.values(room.settings.events)
|
||||
.filter(event => 'eventName' in event)
|
||||
.map(event => event as RoomEvent);
|
||||
|
||||
// id tokens
|
||||
if (delimited.length === 1) {
|
||||
@@ -304,8 +521,7 @@ export const commands: ChatCommands = {
|
||||
return this.errorReply("No or invalid column name specified. Please use one of: date, eventdate, desc, description, eventdescription, eventname, name.");
|
||||
}
|
||||
|
||||
// rebuild the room.events object
|
||||
room.settings.events = {};
|
||||
// rebuild the room.settings.events object
|
||||
for (const sortedObj of sortable) {
|
||||
const eventId = toID(sortedObj.eventName);
|
||||
room.settings.events[eventId] = sortedObj;
|
||||
@@ -319,15 +535,23 @@ export const commands: ChatCommands = {
|
||||
return this.sendReply(resultString);
|
||||
},
|
||||
},
|
||||
roomeventshelp: [
|
||||
`/roomevents - Displays a list of upcoming room-specific events.`,
|
||||
`/roomevents add [event name] | [event date/time] | [event description] - Adds a room event. A timestamp in event date/time field like YYYY-MM-DD HH:MM±hh:mm will be displayed in user's timezone. Requires: @ # &`,
|
||||
`/roomevents start [event name] - Declares to the room that the event has started. Requires: @ # &`,
|
||||
`/roomevents remove [event name] - Deletes an event. Requires: @ # &`,
|
||||
`/roomevents rename [old event name] | [new name] - Renames an event. Requires: @ # &`,
|
||||
`/roomevents addalias [alias] | [event name] - Adds an alias for the event. Requires: @ # &`,
|
||||
`/roomevents removealias [alias] - Removes an event alias. Requires: @ # &`,
|
||||
`/roomevents sortby [column name] | [asc/desc (optional)] - Sorts events table by column name and an optional argument to ascending or descending order. Ascending order is default. Requires: @ # &`,
|
||||
`/roomevents view [event name] - Displays information about a specific event.`,
|
||||
],
|
||||
roomeventshelp() {
|
||||
this.sendReply(
|
||||
`|html|<details class="readmore"><summary>Commands to manage room events.</summary>` +
|
||||
`<code>/roomevents</code>: displays a list of upcoming room-specific events.<br />` +
|
||||
`<code>/roomevents add [event name] | [event date/time] | [event description]</code>: adds a room event. A timestamp in event date/time field like YYYY-MM-DD HH:MM±hh:mm will be displayed in user's timezone. Requires: @ # &<br />` +
|
||||
`<code>/roomevents start [event name]</code>: declares to the room that the event has started. Requires: @ # &<br />` +
|
||||
`<code>/roomevents remove [event name]</code>: deletes an event. Requires: @ # &<br />` +
|
||||
`<code>/roomevents rename [old event name] | [new name]</code>: renames an event. Requires: @ # &<br />` +
|
||||
`<code>/roomevents addalias [alias] | [event name]</code>: adds an alias for the event. Requires: @ # &<br />` +
|
||||
`<code>/roomevents removealias [alias]</code>: removes an event alias. Requires: @ # &<br />` +
|
||||
`<code>/roomevents addcategory [category]</code>: adds an event category. Requires: @ # &<br />` +
|
||||
`<code>/roomevents removecategory [category]</code>: removes an event category. Requires: @ # &<br />` +
|
||||
`<code>/roomevents addtocategory [event name] | [category]</code>: adds the event to a category. Requires: @ # &<br />` +
|
||||
`<code>/roomevents removefromcategory [event name] | [category]</code>: removes the event from a category. Requires: @ # &<br />` +
|
||||
`<code>/roomevents sortby [column name] | [asc/desc (optional)]</code> sorts events table by column name and an optional argument to ascending or descending order. Ascending order is default. Requires: @ # &<br />` +
|
||||
`<code>/roomevents view [event name or category]</code>: displays information about a specific event or category of events.` +
|
||||
`</details>`
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -80,7 +80,7 @@ export interface RoomSettings {
|
||||
staffRoom?: boolean;
|
||||
language?: string | false;
|
||||
slowchat?: number | false;
|
||||
events?: {[k: string]: {eventName: string, date: string, desc: string, started: boolean, aliases?: string[]}};
|
||||
events?: {[k: string]: RoomEvent | RoomEventAlias | RoomEventCategory};
|
||||
filterStretching?: boolean;
|
||||
filterEmojis?: boolean;
|
||||
filterCaps?: boolean;
|
||||
@@ -117,6 +117,9 @@ export interface RoomSettings {
|
||||
export type Room = GlobalRoom | GameRoom | ChatRoom;
|
||||
type Poll = import('./chat-plugins/poll').Poll;
|
||||
type Announcement = import('./chat-plugins/announcements').Announcement;
|
||||
type RoomEvent = import('./chat-plugins/room-events').RoomEvent;
|
||||
type RoomEventAlias = import('./chat-plugins/room-events').RoomEventAlias;
|
||||
type RoomEventCategory = import('./chat-plugins/room-events').RoomEventCategory;
|
||||
type Tournament = import('./tournaments/index').Tournament;
|
||||
|
||||
export abstract class BasicRoom {
|
||||
@@ -540,6 +543,7 @@ export class GlobalRoom extends BasicRoom {
|
||||
Monitor.warn(`ERROR: Room number ${i} has no data and could not be loaded.`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// We're okay with assinging type `ID` to `RoomID` here
|
||||
// because the hyphens in chatrooms don't have any special
|
||||
// meaning, unlike in helptickets, groupchats, battles etc
|
||||
@@ -552,6 +556,7 @@ export class GlobalRoom extends BasicRoom {
|
||||
Rooms.aliases.set(alias, id);
|
||||
}
|
||||
}
|
||||
|
||||
this.chatRooms.push(room);
|
||||
if (room.settings.autojoin) this.autojoinList.push(id);
|
||||
if (room.settings.staffAutojoin) this.staffAutojoinList.push(id);
|
||||
|
||||
Reference in New Issue
Block a user