init: initial commit
This commit is contained in:
8
app/src/lib/DrizzleClient.ts
Normal file
8
app/src/lib/DrizzleClient.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { drizzle } from "drizzle-orm/bun-sql";
|
||||
import { SQL } from "bun";
|
||||
import * as schema from "@db/schema";
|
||||
|
||||
const connectionString = process.env.DATABASE_URL || "postgres://kyoko:kyoko@localhost:5432/kyoko";
|
||||
const postgres = new SQL(connectionString);
|
||||
|
||||
export const DrizzleClient = drizzle(postgres, { schema });
|
||||
89
app/src/lib/KyokoClient.ts
Normal file
89
app/src/lib/KyokoClient.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import { Client as DiscordClient, Collection, GatewayIntentBits, REST, Routes, SlashCommandBuilder } from "discord.js";
|
||||
import { readdir } from "node:fs/promises";
|
||||
import { join } from "node:path";
|
||||
import type { Command } from "@lib/types";
|
||||
|
||||
class Client extends DiscordClient {
|
||||
|
||||
commands: Collection<string, Command>;
|
||||
|
||||
constructor({ intents }: { intents: number[] }) {
|
||||
super({ intents });
|
||||
this.commands = new Collection<string, Command>();
|
||||
}
|
||||
|
||||
async loadCommands() {
|
||||
const commandsPath = join(import.meta.dir, '../commands');
|
||||
await this.readCommandsRecursively(commandsPath);
|
||||
}
|
||||
|
||||
private async readCommandsRecursively(dir: string) {
|
||||
try {
|
||||
const files = await readdir(dir, { withFileTypes: true });
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = join(dir, file.name);
|
||||
|
||||
if (file.isDirectory()) {
|
||||
await this.readCommandsRecursively(filePath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.name.endsWith('.ts') && !file.name.endsWith('.js')) continue;
|
||||
|
||||
try {
|
||||
const commandModule = await import(filePath);
|
||||
const commands = Object.values(commandModule);
|
||||
|
||||
for (const command of commands) {
|
||||
if (this.isValidCommand(command)) {
|
||||
this.commands.set(command.data.name, command);
|
||||
console.log(`Loaded command: ${command.data.name}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to load command from ${filePath}:`, error);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error reading directory ${dir}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
private isValidCommand(command: any): command is Command {
|
||||
return command && typeof command === 'object' && 'data' in command && 'execute' in command;
|
||||
}
|
||||
|
||||
async deployCommands() {
|
||||
const rest = new REST().setToken(this.token!);
|
||||
const commandsData = this.commands.map(c => c.data.toJSON());
|
||||
const guildId = process.env.DISCORD_GUILD_ID;
|
||||
|
||||
try {
|
||||
console.log(`Started refreshing ${commandsData.length} application (/) commands.`);
|
||||
|
||||
let data;
|
||||
if (guildId) {
|
||||
console.log(`Registering commands to guild: ${guildId}`);
|
||||
data = await rest.put(
|
||||
Routes.applicationGuildCommands(this.user!.id, guildId),
|
||||
{ body: commandsData },
|
||||
);
|
||||
// Clear global commands to avoid duplicates
|
||||
await rest.put(Routes.applicationCommands(this.user!.id), { body: [] });
|
||||
} else {
|
||||
console.log('Registering commands globally');
|
||||
data = await rest.put(
|
||||
Routes.applicationCommands(this.user!.id),
|
||||
{ body: commandsData },
|
||||
);
|
||||
}
|
||||
|
||||
console.log(`Successfully reloaded ${(data as any).length} application (/) commands.`);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const KyokoClient = new Client({ intents: [GatewayIntentBits.Guilds, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages] });
|
||||
6
app/src/lib/types.ts
Normal file
6
app/src/lib/types.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import type { ChatInputCommandInteraction, SlashCommandBuilder, SlashCommandOptionsOnlyBuilder, SlashCommandSubcommandsOnlyBuilder } from "discord.js";
|
||||
|
||||
export interface Command {
|
||||
data: SlashCommandBuilder | SlashCommandOptionsOnlyBuilder | SlashCommandSubcommandsOnlyBuilder;
|
||||
execute: (interaction: ChatInputCommandInteraction) => Promise<void> | void;
|
||||
}
|
||||
Reference in New Issue
Block a user