Schedule Events
The Schedule Events module manages scheduled game events with a reminder system, countdown, and automatic cleanup. Ideal for Dark War Survival events such as KvK, War Rally, or other recurring activities.
Enabling the Module
Enable the module
Dashboard → Your server → toggle Schedule Events
Create event definitions
Click Edit to create event definitions
Schedule instances
Schedule instances with commands or from the dashboard
Save
Save changes
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
default_channel_id | string / null | null | Default channel for reminders |
The server's timezone (configured in Dashboard → Settings) is used to interpret date/time inputs when scheduling events. See Server Settings for details.
Event Definitions (created in the dashboard)
Each event definition contains:
- name — event name
- template — embed template (title, description, color, image)
- channel_id — reminder channel (or null → uses default)
- reminder_offsets_minutes — list of offsets (e.g., [60, 30, 10] = 1h, 30m, 10m before)
- is_active — whether the definition is active
Dashboard — Configuration
The Schedule Events edit panel contains:
- Default Channel — dropdown
- Event Definitions — CRUD list of definitions:
- Creating a new definition (name, template, channel, offsets)
- Editing existing ones
- Deleting
- Instances — view of scheduled instances (upcoming)
Filtering
The dashboard and /event list command display only future events (status = 'scheduled' AND starts_at > now). Past/completed events are not shown.
Commands
/event schedule
Schedules a new instance of a saved event.
| Parameter | Required | Description |
|---|---|---|
event_name | ✅ | Event definition name (ILIKE search) |
date | ✅ | Date (YYYY-MM-DD) |
time_str | ✅ | Time (HH, 24h format) |
Requirements: Administrator.
Example:
/event schedule event_name:KvK date:2026-06-15 time_str:20:00Timezone
Time is interpreted in the server's configured timezone (set in Dashboard → Settings → Timezone). The instance is saved with a timezone-aware datetime.
/event list
Displays upcoming scheduled events (max 10).
Each entry contains:
- Event name
- Date/time (Discord timestamp: full + relative)
/event cancel
Cancels the next instance of an event.
| Parameter | Required | Description |
|---|---|---|
event_name | ✅ | Event name to cancel |
Requirements: Administrator.
Changes the instance status to 'cancelled'.
Reminder System
Reminders are sent automatically based on reminder_offsets_minutes:
Example: offsets = [60, 30, 10]
- 60 minutes before → embed "Event starts in 1 hour"
- 30 minutes before → embed (replaces the previous one)
- 10 minutes before → embed (replaces the previous one)
- 0 minutes (start) → embed "🚀 Event is starting NOW!" (auto-delete after 15 min)
Automatic Cleanup
- Each new reminder deletes the previous one (only 1 message per channel)
- The "starting NOW" message auto-deletes after 15 minutes
- Channel remains clean
Placeholder {countdown}
In reminder templates, you can use {countdown} — it will be replaced with a Discord relative timestamp (e.g., <t:1718474400:R> → "in 30 minutes").
Instance Statuses
| Status | Description |
|---|---|
scheduled | Scheduled, waiting to start |
started | Started ("NOW!" message sent) |
cancelled | Cancelled by admin |
missed | Missed (>1h past scheduled start without sending) |
Auto-marking "missed"
If the bot didn't manage to process the instance (e.g., was offline) and more than 1 hour has passed since starts_at, the instance is automatically marked as 'missed' instead of sending a delayed notification.
Scheduled Task
_check_loop — every 30 seconds:
- Fetches all scheduled instances within the next 24 hours
- For each, checks if it's time for:
- A reminder (within a 30s window from the offset trigger)
- Start (now >= starts_at)
- Marking as missed (>1h past start)
Calendar Message
The calendar message is an optional persistent embed in a channel that lists upcoming events. The bot auto-updates it whenever an event is scheduled or cancelled, and a background loop refreshes it every 3 minutes to update countdowns and remove ended events.
How to Enable
Dashboard → Schedule Events → toggle Calendar Message on. When enabled, the channel and title fields appear. Select a text channel for the calendar embed. When the toggle is off, the feature is disabled and no calendar message is sent — the notification system works exactly as before.
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
calendar_channel_id | string / null | null | Channel for the calendar embed. null = feature disabled |
calendar_embed_title | string | "📅 Upcoming Events" | Title of the calendar embed |
calendar_message_id | string / null | null | Auto-managed by the bot (not shown in dashboard) |
The background loop refreshes every 3 minutes (fixed, not configurable).
How It Works
Bot sends calendar embed
When calendar_channel_id is configured, the bot sends a single embed to that channel listing upcoming events (up to 10, sorted by date).
Live updates on changes
When an event is scheduled (/event schedule) or cancelled (/event cancel), the bot edits the existing calendar embed in place — no duplicate messages.
Background refresh
Every 3 minutes the _calendar_loop task updates countdown timestamps (Discord relative timestamps are dynamic, but the embed content itself is refreshed) and removes events whose starts_at has passed.
Auto-recreate on deletion
If someone deletes the calendar message, the bot detects the missing message on the next refresh and sends a new one, saving its new ID.
Event Duration (duration_hours)
Each event definition has a duration_hours field that controls how long the "starting NOW!" announcement message stays visible:
| Value | Behavior |
|---|---|
null (not set) | Start message auto-deletes after 15 minutes (default) |
3 | Start message stays for 3 hours (e.g., capital fight) |
24 | Start message stays for 24 hours (e.g., KE) |
Set duration_hours when creating or editing an event definition in the dashboard. This is per-event-definition, not per-instance.
Optional & Additive
The calendar feature is entirely optional. If calendar_channel_id is not set, everything works exactly as before — reminders, start messages, and cleanup are unaffected. The calendar is a persistent view on top of the existing system.
Recurring Events
Events can automatically repeat. When an instance ends, the bot creates a new one at the same time plus the repeat interval. The interval is counted from the start date — for example, 7 days means the next instance starts exactly 7 days after the current one started.
How to Enable
Dashboard → Schedule Events → edit an event → check Recurring Event → set days and/or hours.
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
repeat_interval_hours | float / null | null | Repeat interval in hours (days × 24 + hours). null = not recurring. |
How It Works
Instance starts
Event instance starts (status → 'started')
Instance runs
Event runs until ends_at (if set) or indefinitely
Instance ends
When instance ends (status → 'ended'), bot checks if repeat_interval_hours is set
Next instance created
If set, creates a new instance at starts_at + repeat_interval_hours with status 'scheduled'
New instance appears
New instance appears in the calendar, reminders fire as normal
End Dates
Each scheduled instance can have an optional ends_at — a specific end time for that occurrence.
How to Set
Dashboard → Schedule Events → schedule an instance → check Set End Date → pick date and time.
Behavior
- When
ends_atpasses, the instance status changes to'ended' - Required for interval reminders (see below)
- Without
ends_at, the instance stays'started'indefinitely (no automatic end)
Interval Reminders
Per-definition setting that sends a reminder embed every N minutes during an active event.
How to Set
Dashboard → Schedule Events → edit an event → set Reminder Interval (minutes).
Behavior
- Only fires for instances that have
ends_atset - Bot sends a reminder embed every N minutes between
starts_atandends_at - Uses the event's template embed with a footer showing the end-time countdown (
⏰ Event ongoing — ends <t:UNIX:R>) - Each interval reminder is a new message (no deletion of previous interval reminders)
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
reminder_interval_minutes | int / null | null | Reminder interval in minutes during active events. null = disabled. |
Optional & Additive
Recurring events, end dates, and interval reminders are all optional and additive. The existing reminder system (pre-start offsets) works unchanged — you can use any combination of these features.
Interval Reminders Require End Date
Interval reminders only fire when the instance has an ends_at set. Without an end date, the bot cannot determine when the event is over and will not send interval reminders.
Database
| Table | Description |
|---|---|
schedule_events | Event definitions (name, template, channel_id, reminder_offsets, is_active, duration_hours) |
schedule_instances | Scheduled instances (event_id, guild_id, starts_at, status, last_reminder_message_id) |
Logging
The Schedule Events module does not have a dedicated log category. Actions are tracked through instance statuses in the database.
Tips
Best Practices
- Create definitions for recurring events (KvK, Rally, etc.)
- Set 2-3 reminder offsets (e.g., 60, 30, 10 minutes before)
- Use
{countdown}in the template description — Discord will display a dynamic countdown - A dedicated channel (e.g.,
#events) will stay organized thanks to auto-cleanup
Recurring Events
For weekly recurring events, schedule several instances in advance. The dashboard allows quickly adding instances.
Dashboard Required
Event definitions are created in the dashboard. The /event schedule command is only for scheduling instances of existing definitions.