Skip to main content

Documentation 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.

GiveawayBot persists all data in a single SQLite file using the 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:
MethodDescription
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.
All query parameters are passed through prepared statements — the base class rejects table and column names that contain anything other than alphanumeric characters and underscores before interpolating them into queries.

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

1

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 ([]).
2

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.
3

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.
4

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, the guildCreate 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 optionMethod called
colorGuildManager.updateColor()
emojiGuildManager.updateEmoji()
everyoneGuildManager.updatePing()

Database file location

The database file is stored at:
./src/database/data/database.db
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.
You can inspect the database contents at any time using DB Browser for SQLite, a free cross-platform GUI for SQLite files. Open the file at the path above to browse rows, run queries, or verify entries.

WAL mode

On startup, DatabaseManager sets journal_mode = WAL (Write-Ahead Logging) via a pragma:
this.db.pragma("journal_mode = WAL");
WAL mode allows read queries to run concurrently with a write in progress, which reduces lock contention when the bot is polling for ending giveaways at the same time as users are clicking entry buttons.

Build docs developers (and LLMs) love