diff --git a/bots/discord/.gitignore b/bots/discord/.gitignore index b9c3d9f..f742463 100644 --- a/bots/discord/.gitignore +++ b/bots/discord/.gitignore @@ -181,6 +181,7 @@ config.ts *.db *.sqlite *.sqlite3 +.drizzle # Auto-generated files src/commands/index.ts diff --git a/bots/discord/Dockerfile b/bots/discord/Dockerfile index 96ca47b..f5b2626 100644 --- a/bots/discord/Dockerfile +++ b/bots/discord/Dockerfile @@ -15,4 +15,4 @@ COPY --from=build /build/bots/discord/dist /app USER 1000:1000 -ENTRYPOINT [ "bun", "run", "src/index.js" ] +ENTRYPOINT [ "bun", "run", "index.js" ] diff --git a/bots/discord/docs/3_running_and_deploying.md b/bots/discord/docs/3_running_and_deploying.md index 44f87b8..6532ece 100644 --- a/bots/discord/docs/3_running_and_deploying.md +++ b/bots/discord/docs/3_running_and_deploying.md @@ -29,9 +29,8 @@ The distribution files will be placed inside the `dist` directory. Inside will i To deploy the bot, you'll need to: -1. Replace the `config.ts` file with your own configuration _(optional)_ -2. [Build the bot as seen in the previous step](#-building) -3. Run the `reload-slash-commands` script +1. [Build the bot as seen in the previous step](#-building) +2. Run the `reload-slash-commands` script This is to ensure all commands are registered, so they can be used. **It may take up to 2 hours until **global** commands are updated. This is a Discord limitation.** @@ -40,7 +39,7 @@ To deploy the bot, you'll need to: bun run scripts/reload-slash-commands.ts ``` -4. Copy contents of the `dist` directory +3. Copy contents of the `dist` directory ```sh # For instance, we'll copy them both to /usr/src/discord-bot @@ -48,22 +47,14 @@ To deploy the bot, you'll need to: cp -R ./dist/* /usr/src/discord-bot ``` -5. Copy the empty database (or use your own existing database) - - ```sh - # By default, the build script creates the database called "db.sqlite3" - # Unless you specify otherwise via the "DATABASE_PATH" environment variable - cp ./db.sqlite3 /usr/src/discord-bot - ``` - -6. Configure environment variables +4. Configure environment variables As seen in [`.env.example`](../.env.example). You can also optionally use a `.env` file which **Bun will automatically load**. -7. Finally, run the bot +5. Finally, run the bot ```sh cd /usr/src/discord-bot - bun run src/index.js + bun run index.js ``` ## ⏭️ What's next diff --git a/bots/discord/drizzle.config.ts b/bots/discord/drizzle.config.ts index d9a9a69..bebe08d 100644 --- a/bots/discord/drizzle.config.ts +++ b/bots/discord/drizzle.config.ts @@ -3,6 +3,7 @@ import { defineConfig } from 'drizzle-kit' export default defineConfig({ dialect: 'sqlite', schema: './src/database/schemas.ts', + out: './.drizzle', dbCredentials: { url: process.env['DATABASE_PATH'] ? `file:./${process.env['DATABASE_PATH']}` : 'file:./db.sqlite3', }, diff --git a/bots/discord/package.json b/bots/discord/package.json index 87ba25b..42fc321 100644 --- a/bots/discord/package.json +++ b/bots/discord/package.json @@ -9,10 +9,9 @@ "register": "bun run scripts/reload-slash-commands.ts", "start": "bun prepare && bun run src/index.ts", "dev": "bun prepare && bun --watch src/index.ts", - "build:config": "bun build config.ts --outdir=dist", - "build": "bun prepare && bun build:config && bun build src/index.ts -e ./config.js --target=bun --outdir=dist/src", + "build": "bun prepare && bun run scripts/build.ts", "watch": "bun dev", - "prepare": "bun run scripts/generate-indexes.ts && drizzle-kit push" + "prepare": "bun run scripts/generate-indexes.ts && drizzle-kit generate --name=schema" }, "repository": { "type": "git", @@ -44,4 +43,4 @@ "discord-api-types": "^0.37.92", "drizzle-kit": "^0.22.8" } -} \ No newline at end of file +} diff --git a/bots/discord/scripts/build.ts b/bots/discord/scripts/build.ts new file mode 100644 index 0000000..58e81c0 --- /dev/null +++ b/bots/discord/scripts/build.ts @@ -0,0 +1,24 @@ +import { createLogger } from '@revanced/bot-shared' +import { cp, rm } from 'fs/promises' + +const logger = createLogger() + +logger.warn('Cleaning previous build...') +await rm('./dist', { recursive: true }) +await rm('./.drizzle', { recursive: true }) + +logger.info('Building bot...') +await Bun.build({ + entrypoints: ['./src/index.ts'], + outdir: './dist', + target: 'bun', + external: ['./config.js'], + minify: true, + sourcemap: 'external', +}) + +logger.info('Copying config...') +await cp('config.js', 'dist/config.js') + +logger.info('Copying database schema...') +await cp('.drizzle', 'dist/.drizzle', { recursive: true }) diff --git a/bots/discord/src/context.ts b/bots/discord/src/context.ts index a4806ee..74256be 100644 --- a/bots/discord/src/context.ts +++ b/bots/discord/src/context.ts @@ -1,4 +1,6 @@ import { Database } from 'bun:sqlite' +import { existsSync, readFileSync, readdirSync } from 'fs' +import { join } from 'path' import { Client as APIClient } from '@revanced/bot-api' import { createLogger } from '@revanced/bot-shared' import { ActivityType, Client as DiscordClient, Partials } from 'discord.js' @@ -29,7 +31,33 @@ export const api = { disconnectCount: 0, } -const db = new Database(process.env['DATABASE_PATH']) +const DatabasePath = process.env['DATABASE_PATH'] +const DatabaseSchemaDir = join(import.meta.dir, '.drizzle') + +let dbSchemaFileName: string | undefined + +if (DatabasePath && !existsSync(DatabasePath)) { + logger.warn('Database file not found, trying to create from schema...') + + try { + const file = readdirSync(DatabaseSchemaDir, { withFileTypes: true }) + .filter(file => file.isFile() && file.name.endsWith('.sql')) + .sort() + .at(-1) + + if (!file) throw new Error('No schema file found') + + dbSchemaFileName = file.name + logger.debug(`Using schema file: ${dbSchemaFileName}`) + } catch (e) { + logger.fatal('Could not create database from schema, check if the schema file exists and is accessible') + logger.fatal(e) + process.exit(1) + } +} + +const db = new Database(DatabasePath) +if (dbSchemaFileName) db.run(readFileSync(join(DatabaseSchemaDir, dbSchemaFileName)).toString()) export const database = drizzle(db, { schema: schemas,