Giveaway System
Relevant source files
The following files were used as context for generating this wiki page:
The Giveaway System is a robust module within the Poixpixel Discord Bot designed to facilitate community engagement through automated prize distributions. It provides a multi-step interactive builder for administrators to configure rewards, durations, and complex entry requirements including level thresholds, specific roles, and message counts.
The system integrates directly with a PostgreSQL database via Drizzle ORM for persistent storage and utilizes Redis for session management during the giveaway creation process. It supports automated scheduling to end giveaways at specific times, winner selection with bonus entry logic, and manual management tools such as rerolling or ending giveaways early.
Sources: src/util/giveaways/giveawayManager.ts, src/util/giveaways/builder.ts, src/db/functions/giveawayFunctions.ts
System Architecture
The system is divided into four primary layers: the Command Layer for user interaction, the Builder Layer for guided configuration, the Manager Layer for scheduling and execution, and the Database Layer for persistence.
Data Flow for Giveaway Creation
The creation process follows a stateful multi-step flow where data is temporarily stored in Redis before being committed to the database.
Giveaway Builder
The builder.ts module manages a 5-step interactive process using Discord's Ephemeral messages, buttons, and modals.
| Step | Focus | Components |
|---|---|---|
| 1 | Basics | Prize input, Duration selection, Winner count |
| 2 | Requirements | Minimum level, required role, message count thresholds |
| 3 | Channel | Target text channel for the giveaway message |
| 4 | Bonuses | Configurable extra entries for active or high-level users |
| 5 | Finalization | Ping role configuration and publishing |
Sources: src/util/giveaways/builder.ts:110-270, src/util/giveaways/modals.ts:10-140
Session Management
User progress is tracked using a GiveawaySession object stored in Redis with a specific timeout. This allows the bot to handle multiple concurrent users creating giveaways without cross-contamination of data.
export async function saveSession(userId: string, data: GiveawaySession): Promise<void> {
const sessionToStore = { ...data, endTime: data.endTime?.toISOString() };
await setJson(`${SESSION_PREFIX}${userId}`, sessionToStore, SESSION_TIMEOUT);
}
Sources: src/util/giveaways/utils.ts:100-110, src/util/giveaways/utils.ts:12-14
Entry and Requirements Logic
The system supports complex entry validation. Users must meet specific criteria defined during the builder phase to participate.
Requirement Evaluation
The checkUserRequirements function validates a user's eligibility based on:
- Level: Fetched from the internal leveling system database.
- Roles: Checked against the user's current roles in the Discord guild.
- Message Count: Validated against the user's total message statistics.
Sources: src/util/giveaways/utils.ts:58-95
Bonus Entries
Bonus entries allow certain users to have a higher probability of winning. These are calculated at the time of entry and stored in the database.
| Bonus Type | Description |
|---|---|
| Role Bonus | Adds X entries if user has a specific Role ID |
| Level Bonus | Adds X entries if user level >= Threshold |
| Message Bonus | Adds X entries if user message count >= Threshold |
Sources: src/util/giveaways/handlers.ts:53-76, src/util/giveaways/utils.ts:168-195
Manager and Execution
The GiveawayManager handles the lifecycle of a giveaway from publication to winner announcement.
Scheduled Completion
On bot startup, scheduleGiveaways fetches all active giveaways from the database. It calculates the remaining time and sets a setTimeout for each. If a giveaway's end time has already passed while the bot was offline, it is processed immediately.
Winner Selection
Winners are selected using a random shuffle of the participant array. The logic accounts for:
- Uniqueness: Each user can only win once per giveaway.
- Exclusion: When rerolling, previous winners are excluded from the new selection pool.
- Winner Count: Ensuring the number of winners does not exceed the number of unique participants.
Sources: src/util/giveaways/utils.ts:21-42, src/db/functions/giveawayFunctions.ts:200-220
Database Schema and Functions
The system uses a dedicated table giveawayTable to store giveaway state.
Key Database Operations
createGiveaway: Inserts a new giveaway record with status 'active'.addGiveawayParticipant: Appends a user ID to the participants array multiple times based on their earned entries.endGiveaway: Updates status to 'ended' and persists the selectedwinnersIds.rerollGiveaway: Selects new winners from the existing participant pool while excluding current winners.
Sources: src/db/functions/giveawayFunctions.ts:25-245
Summary
The Giveaway System provides a high degree of control for server administrators, combining a user-friendly configuration builder with a precise backend that manages requirements and bonus entries. By leveraging Redis for sessions and PostgreSQL for long-term storage, the system ensures reliability across bot restarts and complex user interactions.
Sources: src/util/giveaways/giveawayManager.ts, src/commands/fun/giveaway.ts