1 GrumpyEvents EN
darksoon edited this page 2026-07-11 01:05:01 +02:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Events — event scheduling with RSVP

GrumpyEvents schedules events with RSVP buttons (Yes/Maybe/No), posts a live-updated embed overview, and automatically pings everyone who RSVP'd yes when the event starts.


Activation

In configs/config.yml:

addons:
  events: true

There is no dedicated configs/modules/events.yml — this module has no Zod settings file and no configurable parameters beyond the addons.events toggle itself. Everything (title, time, cap, channel) is set per event via the /event create command and stored in the database, not in a YAML file.


Commands

/event create

Creates a new event and posts the embed card with RSVP buttons in the chosen channel.

Option Required Description
title Event title (max 256 characters)
in Time as a duration from now, e.g. 2h, 3d, 1d12h
description Details (max 1000 characters)
max-participants Cap on yes-RSVPs. 0/omitted = unlimited, 11000
channel Target channel (text/announcement). Default: current channel
/event create title:"Raid Night" in:2h
/event create title:"Community Tournament" in:3d description:"Bring your squad!" max-participants:20 channel:#events

Permission: Manage Server (Discord default via setDefaultMemberPermissions, additionally checked at runtime — an admin can override the Discord default per role/channel, but the runtime check still applies).

The in format accepts a plain number (= minutes) or combinations of Xs/Xm/Xh/Xd (e.g. 1d12h).


/event list

Lists all upcoming (not yet started) events on the server, ephemeral. Shows ID, title, channel, and relative time.

/event list

/event cancel <id>

Cancels an event: deletes the DB entry and the posted event message.

Option Required Description
id Event ID (autocomplete by title/ID)
/event cancel id:12

Permission: the event's host or Manage Server.


RSVP buttons

Every event message has three buttons:

Button Emoji Style Meaning
Yes Success (green) yes
Maybe Secondary (gray) maybe
No Danger (red) no

Clicking updates the RSVP live in the database (upsert — a user always has exactly one current status), and the public embed card is immediately re-rendered (names per category, counts in the field headings).

Cap behavior (max-participants): Once the limit of yes-RSVPs is reached, a further yes click is rejected ( "This event is full — no more yes-RSVPs accepted."); maybe/no remain unlimited. The check runs inside a DB transaction (count + write atomically) so that simultaneous clicks for the last free slot can't overbook the cap.

After the event starts (see below), the buttons are disabled.


Event start: the 1-minute runner

A background task checks every 60 seconds whether events are due (eventTime <= now and not yet started):

  1. Atomic claiming: For each due row, an updateMany with where: { started: false } — so an overlapping second tick can't claim the same row twice, meaning the start ping can't fire twice.
  2. Embed update: The event message is re-rendered and the buttons are disabled.
  3. Ping of yes-RSVPs: All users with status yes are pinged in a new message in the event channel: "📅 {Title} is starting now! @User1 @User2 …". If there are no yes-RSVPs, a message is still posted without mentions.

Mention limit: Discord caps allowed_mentions.users at 100 entries per message — if there are more yes-RSVPs, the list is split across multiple messages of 100 pings each so nobody is silently skipped.


Embed layout

📅 <Title>

<Description, if set>

✅ Yes (N/Cap)     ❔ Maybe (N)     ❌ No (N)
@User1, @User2 …   @User3 …        @User4 …

When
<Date/Time> (<relative time>)

Host
@Host

Click below to respond

Color: #5865F2 (Discord Blurple). If a cap is set, /<max-participants> is shown next to the yes count.


Notes

  • Cancel ordering: /event cancel checks permissions before deleting (not delete-then-rollback), so a rejected request can never accidentally leave a second DB row with a different ID that the old RSVP buttons (bound to the original ID) would no longer match.
  • Events are stored via Prisma/DB (Event, EventRsvp) — no in-memory state, survives restarts.
  • If posting the initial event message fails (e.g. missing permissions), /event create aborts with an error without deleting the DB entry — the event row then exists without a messageId.