GiveawayBot persists all data in a single SQLite file using theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/resynceddesign/giveawaybot/llms.txt
Use this file to discover all available pages before exploring further.
better-sqlite3 package. No external database server is required — the file is created automatically at ./src/database/data/database.db relative to the project root when the bot first starts.
Architecture
The database layer is built as a three-class hierarchy. Each layer adds functionality on top of the one below it.DatabaseManager (base class)
DatabaseManager wraps the raw better-sqlite3 connection and exposes a set of protected helper methods used by the subclasses:
| Method | Description |
|---|---|
runQuery(query, params) | Executes a statement with no return value (INSERT, UPDATE, DELETE). |
getOne(query, params) | Returns a single row object, or undefined if no match. |
getAll(query, params) | Returns an array of all matching rows. |
insert(tableName, data) | Builds and runs a parameterised INSERT from a key-value object. |
createTable(tableName, schema) | Runs CREATE TABLE IF NOT EXISTS with identifier validation. |
dropTable(tableName) | Runs DROP TABLE IF EXISTS with identifier validation. |
GiveawayManager extends DatabaseManager
Manages the giveaways table. Instantiated once in functions.ts and used by the giveaway lifecycle loop and button interaction handler. See the schema reference for its full public API.
GuildManager extends DatabaseManager
Manages the guilds table. Instantiated once in functions.ts alongside GiveawayManager. Stores per-server configuration that controls embed appearance and ping behaviour. See the schema reference for its full public API.
Giveaway lifecycle
Creation
A user runs
/gcreate. The command handler calls GiveawayManager.createGiveaway(), which inserts a row into the giveaways table with status = 1 (active) and an empty entries JSON array ([]).Polling
processGiveaways() is called on a 1-second interval. Each tick calls GiveawayManager.checkEnding(), which loads all active giveaways and compares createdAt + duration * 1000 against the current Unix timestamp. Any giveaway whose end time has passed has its ID added to the returned array.Ending
For each expired giveaway ID,
processGiveaways() calls GiveawayManager.pickWinners() to randomly select winners from the entries array, then calls GiveawayManager.endGiveaway() to set status = 0. The bot then edits the original embed and sends winner announcements.Entry
When a user clicks the entry button on a giveaway embed, the interaction handler calls
GiveawayManager.addEntry(). This method reads the current entries JSON array, checks for a duplicate user ID, appends the new ID if absent, and writes the updated array back. It returns false without writing if the user has already entered.Guild settings lifecycle
When GiveawayBot joins a new server, theguildCreate Discord event fires and calls GuildManager.createGuild(), which inserts a row for that guild with the default embed color (#ff8e4d), no @everyone ping, and the 🎊 emoji. If a row already exists for that guild, the INSERT OR IGNORE statement is a no-op.
Server administrators can change these defaults at any time with /gconfig. Each config option maps to a dedicated update method:
/gconfig option | Method called |
|---|---|
color | GuildManager.updateColor() |
emoji | GuildManager.updateEmoji() |
everyone | GuildManager.updatePing() |
Database file location
The database file is stored at:This path is relative to the project root. The
data/ directory and the database file are created automatically on first run — you do not need to create them manually.WAL mode
On startup,DatabaseManager sets journal_mode = WAL (Write-Ahead Logging) via a pragma: