refactor: rename bot client, environment variables, and project name from Kyoko to Aurora.

This commit is contained in:
syntaxbullet
2025-12-20 11:23:39 +01:00
parent 1f7679e5a1
commit 4229e5338f
10 changed files with 27 additions and 68 deletions

View File

@@ -1,12 +1,12 @@
DB_USER=kyoko DB_USER=aurora
DB_PASSWORD=kyoko DB_PASSWORD=aurora
DB_NAME=kyoko DB_NAME=aurora
DB_PORT=5432 DB_PORT=5432
DB_HOST=db DB_HOST=db
DISCORD_BOT_TOKEN=your-discord-bot-token DISCORD_BOT_TOKEN=your-discord-bot-token
DISCORD_CLIENT_ID=your-discord-client-id DISCORD_CLIENT_ID=your-discord-client-id
DISCORD_GUILD_ID=your-discord-guild-id DISCORD_GUILD_ID=your-discord-guild-id
DATABASE_URL=postgres://kyoko:kyoko@db:5432/kyoko DATABASE_URL=postgres://aurora:aurora@db:5432/aurora
VPS_USER=your-vps-user VPS_USER=your-vps-user
VPS_HOST=your-vps-ip VPS_HOST=your-vps-ip

View File

@@ -1,42 +1 @@
# Kyoko - Discord Rpg # Aurora
A Discord bot built with [Bun](https://bun.sh), [Discord.js](https://discord.js.org/), and [Drizzle ORM](https://orm.drizzle.team/).
## Architecture
This project uses a modular architecture:
- **`src/index.ts`**: Entry point. initializes the client.
- **`src/lib/KyokoClient.ts`**: Custom Discord Client wrapper handling command loading and events.
- **`src/lib/env.ts`**: **Centralized Environment Configuration**. Validates environment variables using `zod` at startup.
- **`src/lib/DrizzleClient.ts`**: Database client instance.
- **`src/commands/`**: Command files.
- **`src/db/`**: Database schema and migrations.
## Setup
1. **Install Dependencies**:
```bash
bun install
```
2. **Environment Variables**:
Copy `.env.example` to `.env` (create one if it doesn't exist) and fill in the required values:
```env
DISCORD_BOT_TOKEN=your_token_here
DISCORD_CLIENT_ID=your_client_id
DISCORD_GUILD_ID=your_guild_id_optional
DATABASE_URL=postgres://user:pass@localhost:5432/db_name
```
*Note: The app will fail to start if `DISCORD_BOT_TOKEN` or `DATABASE_URL` are missing or invalid.*
3. **Run Development**:
```bash
bun run dev
```
4. **Database Migrations**:
```bash
bun run db:push # Apply schema changes
bun run generate # Generate migrations
```

View File

@@ -13,7 +13,7 @@ services:
- ./src/db/log:/var/log/postgresql - ./src/db/log:/var/log/postgresql
app: app:
container_name: aurora_app container_name: aurora_app
image: kyoko-app image: aurora-app
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile
@@ -39,7 +39,7 @@ services:
studio: studio:
container_name: aurora_studio container_name: aurora_studio
image: kyoko-app image: aurora-app
build: build:
context: . context: .
dockerfile: Dockerfile dockerfile: Dockerfile

View File

@@ -2,7 +2,7 @@ import { createCommand } from "@/lib/utils";
import { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } from "discord.js"; import { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } from "discord.js";
import { configManager } from "@/lib/configManager"; import { configManager } from "@/lib/configManager";
import { config, reloadConfig } from "@/lib/config"; import { config, reloadConfig } from "@/lib/config";
import { KyokoClient } from "@/lib/BotClient"; // Import directly from lib, avoiding circular dep with index import { AuroraClient } from "@/lib/BotClient";
export const features = createCommand({ export const features = createCommand({
data: new SlashCommandBuilder() data: new SlashCommandBuilder()
@@ -31,7 +31,7 @@ export const features = createCommand({
const subcommand = interaction.options.getSubcommand(); const subcommand = interaction.options.getSubcommand();
if (subcommand === "list") { if (subcommand === "list") {
const activeCommands = KyokoClient.commands; const activeCommands = AuroraClient.commands;
const categories = new Map<string, string[]>(); const categories = new Map<string, string[]>();
// Group active commands // Group active commands
@@ -87,8 +87,8 @@ export const features = createCommand({
// Reload config from disk (which was updated by configManager) // Reload config from disk (which was updated by configManager)
reloadConfig(); reloadConfig();
await KyokoClient.loadCommands(true); await AuroraClient.loadCommands(true);
await KyokoClient.deployCommands(); await AuroraClient.deployCommands();
await interaction.editReply({ content: `✅ Command **${commandName}** has been ${enabled ? "enabled" : "disabled"}. Commands reloaded!` }); await interaction.editReply({ content: `✅ Command **${commandName}** has been ${enabled ? "enabled" : "disabled"}. Commands reloaded!` });
} }

View File

@@ -1,5 +1,5 @@
import { createCommand } from "@lib/utils"; import { createCommand } from "@lib/utils";
import { KyokoClient } from "@/lib/BotClient"; import { AuroraClient } from "@/lib/BotClient";
import { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits, MessageFlags } from "discord.js"; import { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits, MessageFlags } from "discord.js";
import { createErrorEmbed, createSuccessEmbed, createWarningEmbed } from "@lib/embeds"; import { createErrorEmbed, createSuccessEmbed, createWarningEmbed } from "@lib/embeds";
@@ -13,14 +13,14 @@ export const refresh = createCommand({
try { try {
const start = Date.now(); const start = Date.now();
await KyokoClient.loadCommands(true); await AuroraClient.loadCommands(true);
const duration = Date.now() - start; const duration = Date.now() - start;
// Deploy commands // Deploy commands
await KyokoClient.deployCommands(); await AuroraClient.deployCommands();
const embed = createSuccessEmbed( const embed = createSuccessEmbed(
`Successfully reloaded ${KyokoClient.commands.size} commands in ${duration}ms.`, `Successfully reloaded ${AuroraClient.commands.size} commands in ${duration}ms.`,
"System Refreshed" "System Refreshed"
); );

View File

@@ -1,5 +1,5 @@
import { Events, MessageFlags } from "discord.js"; import { Events, MessageFlags } from "discord.js";
import { KyokoClient } from "@/lib/BotClient"; import { AuroraClient } from "@/lib/BotClient";
import { userService } from "@/modules/user/user.service"; import { userService } from "@/modules/user/user.service";
import { createErrorEmbed } from "@lib/embeds"; import { createErrorEmbed } from "@lib/embeds";
import type { Event } from "@lib/types"; import type { Event } from "@lib/types";
@@ -32,7 +32,7 @@ const event: Event<Events.InteractionCreate> = {
} }
if (interaction.isAutocomplete()) { if (interaction.isAutocomplete()) {
const command = KyokoClient.commands.get(interaction.commandName); const command = AuroraClient.commands.get(interaction.commandName);
if (!command || !command.autocomplete) return; if (!command || !command.autocomplete) return;
try { try {
await command.autocomplete(interaction); await command.autocomplete(interaction);
@@ -44,7 +44,7 @@ const event: Event<Events.InteractionCreate> = {
if (!interaction.isChatInputCommand()) return; if (!interaction.isChatInputCommand()) return;
const command = KyokoClient.commands.get(interaction.commandName); const command = AuroraClient.commands.get(interaction.commandName);
if (!command) { if (!command) {
console.error(`No command matching ${interaction.commandName} was found.`); console.error(`No command matching ${interaction.commandName} was found.`);

View File

@@ -1,14 +1,14 @@
import { KyokoClient } from "@/lib/BotClient"; import { AuroraClient } from "@/lib/BotClient";
import { env } from "@lib/env"; import { env } from "@lib/env";
// Load commands & events // Load commands & events
await KyokoClient.loadCommands(); await AuroraClient.loadCommands();
await KyokoClient.loadEvents(); await AuroraClient.loadEvents();
await KyokoClient.deployCommands(); await AuroraClient.deployCommands();
// login with the token from .env // login with the token from .env
if (!env.DISCORD_BOT_TOKEN) { if (!env.DISCORD_BOT_TOKEN) {
throw new Error("❌ DISCORD_BOT_TOKEN is not set in environment variables."); throw new Error("❌ DISCORD_BOT_TOKEN is not set in environment variables.");
} }
KyokoClient.login(env.DISCORD_BOT_TOKEN); AuroraClient.login(env.DISCORD_BOT_TOKEN);

View File

@@ -185,4 +185,4 @@ class Client extends DiscordClient {
} }
} }
export const KyokoClient = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMembers] }); export const AuroraClient = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMembers] });

View File

@@ -1,6 +1,6 @@
import { readFileSync, writeFileSync } from 'fs'; import { readFileSync, writeFileSync } from 'fs';
import { join } from 'path'; import { join } from 'path';
import { KyokoClient } from '@/lib/BotClient'; import { AuroraClient } from '@/lib/BotClient';
const configPath = join(process.cwd(), 'src', 'config', 'config.json'); const configPath = join(process.cwd(), 'src', 'config', 'config.json');

View File

@@ -1,7 +1,7 @@
import { userTimers } from "@/db/schema"; import { userTimers } from "@/db/schema";
import { eq, and, lt } from "drizzle-orm"; import { eq, and, lt } from "drizzle-orm";
import { DrizzleClient } from "@/lib/DrizzleClient"; import { DrizzleClient } from "@/lib/DrizzleClient";
import { KyokoClient } from "@/lib/BotClient"; import { AuroraClient } from "@/lib/BotClient";
import { env } from "@/lib/env"; import { env } from "@/lib/env";
/** /**
@@ -51,7 +51,7 @@ export const schedulerService = {
if (guildId) { if (guildId) {
// We try to fetch, if bot is not in guild or lacks perms, it will catch // We try to fetch, if bot is not in guild or lacks perms, it will catch
const guild = await KyokoClient.guilds.fetch(guildId); const guild = await AuroraClient.guilds.fetch(guildId);
const member = await guild.members.fetch(userIdStr); const member = await guild.members.fetch(userIdStr);
await member.roles.remove(roleId); await member.roles.remove(roleId);
console.log(`👋 Removed temporary role ${roleId} from ${member.user.tag}`); console.log(`👋 Removed temporary role ${roleId} from ${member.user.tag}`);