Events Plugin
The events plugin provides an in-game event calendar with RSVP tracking.
Players can browse upcoming events and reserve spots. Staff create and manage
events.
Note: This is the event calendar plugin (
+eventcommands). It is
separate fromu.events, the server-wide pub/sub system.
Overview
Events have a title, description, date/time, optional location and capacity,
and a status. Players can RSVP as attending, maybe, or declined.
The plugin auto-loads when src/plugins/events/ exists. No configuration needed.
Player Commands
+event / +event/list
List all upcoming (and active) events.
> +event
+events
# Title Date RSVPs Status
--------------------------------------------------------------------
1 Midsummer Festival 2026-06-21 20:00 5/20 upcoming
2 Guild Hall Opening 2026-04-01 19:00 3 upcoming
Use "+event/view <#>" to see details and RSVP.
Cancelled events are hidden unless you are staff.
+event/view <#>
View event details and the full RSVP list.
> +event/view 1
+event #1: Midsummer Festival
Status : upcoming
Date : 2026-06-21 20:00
Where : The Grand Courtyard
Tags : festival, seasonal
Host : Gwyneira
Desc : Annual midsummer celebration with music and dancing.
RSVPs: 5/20 attending, 2 maybe
Attending: Alice, Bob, Carol, Diana, Eve
Maybe : Frank, Grace
Use "+event/rsvp 1" to RSVP, "+event/rsvp 1=maybe" for maybe.
+event/rsvp <#>[=attending|maybe|decline]
RSVP to an event. Default status is attending.
> +event/rsvp 1
RSVP'd attending for "Midsummer Festival".
> +event/rsvp 1=maybe
RSVP updated to maybe for "Midsummer Festival".
> +event/rsvp 1=decline
RSVP updated to declined for "Midsummer Festival".
If the event has a maxAttendees cap and it’s full, attending RSVPs are blocked.
+event/unrsvp <#>
Cancel your RSVP.
> +event/unrsvp 1
RSVP cancelled for "Midsummer Festival".
Staff Commands
All staff commands require admin, wizard, or superuser flag.
+event/create <title>=<date>/<description>
Create a new event. Date format: YYYY-MM-DD or YYYY-MM-DD HH:MM.
> +event/create Midsummer Festival=2026-06-21 20:00/Annual midsummer celebration with music and dancing.
+event: Event #1 "Midsummer Festival" created for 2026-06-21 20:00.
+event/edit <#>/<field>=<value>
Edit any event field.
> +event/edit 1/location=The Grand Courtyard
+event: Event #1 field "location" updated.
> +event/edit 1/maxAttendees=20
+event: Event #1 field "maxAttendees" updated.
> +event/edit 1/tags=festival,seasonal
+event: Event #1 field "tags" updated.
> +event/edit 1/endTime=2026-06-21 23:00
+event: Event #1 field "endTime" updated.
Editable fields:
| Field | Type | Description |
|---|---|---|
title |
string | Event name |
description |
string | Full description |
location |
string | Where it’s happening |
startTime |
date string | YYYY-MM-DD or YYYY-MM-DD HH:MM |
endTime |
date string | Optional end time |
tags |
comma-separated | Comma-separated tag list |
maxAttendees |
number | 0 = unlimited |
status |
status string | See status table |
+event/cancel <#>
Mark an event as cancelled. Cancelled events are hidden from players.
> +event/cancel 1
+event: Event #1 "Midsummer Festival" cancelled.
+event/delete <#>
Permanently delete an event and all its RSVPs.
> +event/delete 1
+event: Event #1 "Midsummer Festival" deleted.
+event/status <#>=<status>
Set a status explicitly. Useful for marking events as active or completed.
> +event/status 1=active
+event: Event #1 status set to active.
> +event/status 1=completed
+event: Event #1 status set to completed.
Event Statuses
| Status | Visible to players | RSVP allowed |
|---|---|---|
upcoming |
Yes | Yes |
active |
Yes | Yes |
completed |
Yes | No |
cancelled |
No (staff only) | No |
eventHooks
Subscribe to event lifecycle changes in your plugin.
import { eventHooks } from "../../plugins/events/hooks.ts";
// Notify Discord when an event is created
eventHooks.on("event:created", ({ eventId, name, startTime, createdBy }) => {
console.log(`[events] New event "${name}" created by ${createdBy}`);
});
// Track RSVPs for reporting
eventHooks.on("event:rsvp", ({ eventId, playerId, status }) => {
console.log(`[events] ${playerId} RSVPd ${status} to event ${eventId}`);
});
// Announce cancellations to all players
eventHooks.on("event:cancelled", async ({ eventId, name }) => {
// Broadcast or send mail to all RSVPd players
});
Event payloads
| Event | Key payload fields |
|---|---|
event:created |
eventId, name, startTime, createdBy |
event:updated |
eventId, changes |
event:deleted |
eventId |
event:started |
eventId, name |
event:ended |
eventId, name |
event:rsvp |
eventId, playerId, status |
event:cancelled |
eventId, name |
REST API
The events plugin mounts a REST API at /api/v1/events. Authentication
required on all endpoints (Authorization: Bearer <jwt>).
GET /api/v1/events
List all events. Staff see cancelled events; players do not.
curl -H "Authorization: Bearer $TOKEN" http://localhost:4202/api/v1/events
Response:
[
{
"id": "ev-1",
"number": 1,
"title": "Midsummer Festival",
"description": "Annual midsummer celebration.",
"startTime": 1750536000000,
"location": "The Grand Courtyard",
"tags": ["festival", "seasonal"],
"maxAttendees": 20,
"status": "upcoming",
"createdByName": "Gwyneira"
}
]
GET /api/v1/events/:id
Get a single event with its RSVP list.
curl -H "Authorization: Bearer $TOKEN" http://localhost:4202/api/v1/events/ev-1
POST /api/v1/events
Staff only. Create a new event.
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Guild Meeting",
"description": "Monthly guild meeting.",
"startTime": 1750536000000
}' \
http://localhost:4202/api/v1/events
PATCH /api/v1/events/:id
Staff only. Update an event.
curl -X PATCH \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "cancelled"}' \
http://localhost:4202/api/v1/events/ev-1
DELETE /api/v1/events/:id
Staff only. Delete an event.
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
http://localhost:4202/api/v1/events/ev-1
POST /api/v1/events/:id/rsvp
RSVP to an event (as the authenticated player).
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "attending"}' \
http://localhost:4202/api/v1/events/ev-1/rsvp
DELETE /api/v1/events/:id/rsvp
Cancel RSVP.
curl -X DELETE \
-H "Authorization: Bearer $TOKEN" \
http://localhost:4202/api/v1/events/ev-1/rsvp