Version Estable
This commit is contained in:
41
src/core/api/discordAPI.ts
Normal file
41
src/core/api/discordAPI.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { REST } from "discord.js";
|
||||
// @ts-ignore
|
||||
import { Routes } from "discord-api-types/v10";
|
||||
import { commands } from "../loader";
|
||||
|
||||
export async function registeringCommands(): Promise<void> {
|
||||
const commandsToRegister: any[] = [];
|
||||
|
||||
// Recorremos la Collection que ya cargó loadCommands()
|
||||
for (const [name, cmd] of commands) {
|
||||
if (cmd.type === "slash") {
|
||||
commandsToRegister.push({
|
||||
name: cmd.name,
|
||||
description: cmd.description ?? "Sin descripción",
|
||||
type: 1, // CHAT_INPUT
|
||||
options: cmd.options ?? []
|
||||
});
|
||||
|
||||
console.log(`✅ Preparado para registrar: ${cmd.name}`);
|
||||
}
|
||||
}
|
||||
|
||||
const rest = new REST().setToken(process.env.TOKEN ?? "");
|
||||
|
||||
try {
|
||||
console.log(`🚀 Registrando ${commandsToRegister.length} comandos slash...`);
|
||||
|
||||
const data: any = await rest.put(
|
||||
Routes.applicationGuildCommands(
|
||||
process.env.CLIENT!,
|
||||
process.env.guildTest!
|
||||
),
|
||||
{ body: commandsToRegister }
|
||||
);
|
||||
|
||||
console.log(`✅ ${data.length} comandos registrados correctamente.`);
|
||||
} catch (error) {
|
||||
console.error("❌ Error registrando comandos:", error);
|
||||
}
|
||||
}
|
||||
|
||||
49
src/core/client.ts
Normal file
49
src/core/client.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// @ts-ignore
|
||||
import { Client, GatewayIntentBits } from 'discord.js';
|
||||
// 1. Importa PrismaClient
|
||||
// @ts-ignore
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
|
||||
process.loadEnvFile();
|
||||
|
||||
class Amayo extends Client {
|
||||
public key: string;
|
||||
// 2. Declara la propiedad prisma
|
||||
public prisma: PrismaClient;
|
||||
|
||||
constructor() {
|
||||
super({
|
||||
intents: [
|
||||
GatewayIntentBits.Guilds,
|
||||
GatewayIntentBits.GuildMembers,
|
||||
GatewayIntentBits.GuildMessages,
|
||||
GatewayIntentBits.MessageContent,
|
||||
GatewayIntentBits.GuildMessageTyping
|
||||
],
|
||||
rest: {
|
||||
retries: 10
|
||||
}
|
||||
});
|
||||
|
||||
this.key = process.env.TOKEN ?? '';
|
||||
// 3. Instancia PrismaClient en el constructor
|
||||
this.prisma = new PrismaClient();
|
||||
}
|
||||
|
||||
async play () {
|
||||
if(!this.key) {
|
||||
return console.error('No key provided');
|
||||
} else {
|
||||
// Ejemplo de cómo usarías prisma antes de iniciar sesión
|
||||
try {
|
||||
await this.prisma.$connect();
|
||||
console.log('Successfully connected to the database.');
|
||||
await this.login(this.key);
|
||||
} catch (error) {
|
||||
console.error('Failed to connect to the database:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Amayo;
|
||||
49
src/core/components.ts
Normal file
49
src/core/components.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
import { Collection } from "discord.js";
|
||||
|
||||
export const buttons: Collection<string, any> = new Collection<string, any>();
|
||||
export const modals = new Collection<string, any>();
|
||||
export const selectmenus = new Collection<string, any>();
|
||||
export const contextmenus = new Collection<string, any>();
|
||||
|
||||
export function loadComponents(dir: string = path.join(__dirname, "..", "components")) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(dir, file);
|
||||
const stat = fs.statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
loadComponents(fullPath); // recursivo
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.endsWith(".ts") && !file.endsWith(".js")) continue;
|
||||
|
||||
const imported = require(fullPath);
|
||||
const component = imported.default ?? imported;
|
||||
|
||||
if (!component?.customId) {
|
||||
console.warn(`⚠️ Archivo ignorado: ${file} (no tiene "customId")`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Detectamos el tipo según la carpeta en la que está
|
||||
if (fullPath.includes("buttons")) {
|
||||
buttons.set(component.customId, component);
|
||||
console.log(`🔘 Botón cargado: ${component.customId}`);
|
||||
} else if (fullPath.includes("modals")) {
|
||||
modals.set(component.customId, component);
|
||||
console.log(`📄 Modal cargado: ${component.customId}`);
|
||||
} else if (fullPath.includes("selectmenus")) {
|
||||
selectmenus.set(component.customId, component);
|
||||
console.log(`📜 SelectMenu cargado: ${component.customId}`);
|
||||
} else if (fullPath.includes("contextmenu")) {
|
||||
contextmenus.set(component.customId, component);
|
||||
console.log(`📑 ContextMenu cargado: ${component.customId}`);
|
||||
} else {
|
||||
console.log(`⚠️ Componente desconocido: ${component.customId}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/core/lib/vars.ts
Normal file
12
src/core/lib/vars.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import {Guild, User} from "discord.js";
|
||||
|
||||
export async function replaceVars(text: string, user: User | undefined, guild:
|
||||
Guild | undefined, stats: any) {
|
||||
if(!text) return;
|
||||
|
||||
return text
|
||||
.replace(/(user.name)/g, user!.username ?? '')
|
||||
.replace(/(user.id)/g, user!.id ?? '')
|
||||
.replace(/(user.mention)/g, `<@${user!.id}>`)
|
||||
.replace(/(user.avatar)/g, user!.displayAvatarURL({ forceStatic: false }))
|
||||
}
|
||||
43
src/core/loader.ts
Normal file
43
src/core/loader.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import * as fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { Collection } from "discord.js";
|
||||
|
||||
export const commands = new Collection<string, any>();
|
||||
|
||||
export function loadCommands(dir: string = path.join(__dirname, '..', 'commands')) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(dir, file);
|
||||
const stat = fs.statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
loadCommands(fullPath); // recursivo
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.endsWith('.ts')) continue;
|
||||
|
||||
const imported = require(fullPath);
|
||||
const command = imported.command ?? imported.default ?? imported;
|
||||
|
||||
if (!command?.data?.name && !command?.name) {
|
||||
console.warn(`⚠️ Archivo ignorado: ${file} (no es un comando válido)`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const name = command.data?.name ?? command.name;
|
||||
console.log(`📦 Loading command: ${name}`);
|
||||
|
||||
// @ts-ignore
|
||||
commands.set(name, command);
|
||||
|
||||
if (command.aliases?.length) {
|
||||
for (const alias of command.aliases) {
|
||||
commands.set(alias, command);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ Cargado comando: ${name}`);
|
||||
}
|
||||
}
|
||||
32
src/core/loaderEvents.ts
Normal file
32
src/core/loaderEvents.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { bot } from "../main";
|
||||
import path from "node:path";
|
||||
import * as fs from "node:fs";
|
||||
|
||||
export function loadEvents(dir: string = path.join(__dirname, "../events")) {
|
||||
const files = fs.readdirSync(dir);
|
||||
|
||||
for (const file of files) {
|
||||
const fullPath = path.join(dir, file);
|
||||
const stat = fs.statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
loadEvents(fullPath); // recursión para subcarpetas
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.endsWith(".ts") && !file.endsWith(".js")) continue;
|
||||
|
||||
const imported = require(fullPath);
|
||||
const event = imported.default ?? imported;
|
||||
|
||||
if (!event?.name || !event?.execute) continue;
|
||||
|
||||
if (event.once) {
|
||||
bot.once(event.name, (...args: any[]) => event.execute(...args));
|
||||
} else {
|
||||
bot.on(event.name, (...args: any[]) => event.execute(...args));
|
||||
}
|
||||
|
||||
console.log(`Evento cargado: ${event.name}`);
|
||||
}
|
||||
}
|
||||
13
src/core/redis.ts
Normal file
13
src/core/redis.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { createClient } from "redis";
|
||||
|
||||
export const redis = createClient({
|
||||
url: process.env.REDIS_URL,
|
||||
})
|
||||
|
||||
redis.on("error", (err: any) => console.error("Redis error:", err));
|
||||
redis.on("connect", () => console.log("✅ Conectado a Redis"));
|
||||
redis.on("reconnecting", () => console.warn("♻️ Reintentando conexión Redis"));
|
||||
|
||||
export async function redisConnect () {
|
||||
if (!redis.isOpen) await redis.connect();
|
||||
}
|
||||
19
src/core/types/commands.ts
Normal file
19
src/core/types/commands.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type {ChatInputCommandInteraction, Client, Message} from "discord.js";
|
||||
import Amayo from "../client";
|
||||
|
||||
export interface CommandMessage {
|
||||
name: string;
|
||||
type: 'message';
|
||||
aliases?: string[];
|
||||
cooldown?: number;
|
||||
run: (message: Message, args: string[], client: Amayo) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface CommandSlash {
|
||||
name: string;
|
||||
description: string;
|
||||
type: 'slash';
|
||||
options?: string[];
|
||||
cooldown?: number;
|
||||
run: (i: ChatInputCommandInteraction, client: Client) => Promise<void>;
|
||||
}
|
||||
7
src/core/types/components.ts
Normal file
7
src/core/types/components.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
import type {ButtonInteraction} from "discord.js";
|
||||
|
||||
|
||||
export interface button {
|
||||
customId: string;
|
||||
run: (interaction: ButtonInteraction) => Promise<void>;
|
||||
}
|
||||
Reference in New Issue
Block a user