Refactor Amayo client initialization and enhance editor functionality

- Updated the Amayo client to use environment variables for configuration defaults.
- Improved cache and sweeper settings for message and user management.
- Added detailed error handling and logging during database connection and Discord login.
- Introduced a new interactive editor for creating and managing display components with modals.
- Implemented various editor actions including adding content, editing titles/descriptions, and managing components.
- Enhanced user feedback with ephemeral messages for actions taken in the editor.
This commit is contained in:
Shni
2025-10-14 11:12:52 -05:00
parent 6482fbc8ea
commit 0eb5aa0691
3 changed files with 2403 additions and 974 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,27 @@
import { Client, GatewayIntentBits, Options, Partials } from 'discord.js'; import {
import { prisma, ensurePrismaConnection } from './database/prisma'; Client,
import logger from './lib/logger'; GatewayIntentBits,
Options,
Partials,
ClientOptions,
} from "discord.js";
import { prisma, ensurePrismaConnection } from "./database/prisma";
import logger from "./lib/logger";
const DEFAULTS = {
CACHE_MESSAGES_LIMIT: 50,
CACHE_MEMBERS_LIMIT: 100,
SWEEP_MESSAGES_INTERVAL_SECONDS: 300,
SWEEP_MESSAGES_LIFETIME_SECONDS: 900,
USERS_SWEEP_INTERVAL_SECONDS: 60 * 30,
REST_RETRIES: 5,
} as const;
function intEnv(name: keyof typeof DEFAULTS, fallback?: number): number {
const raw = process.env[name];
const val = raw ? parseInt(raw, 10) : NaN;
return Number.isFinite(val) ? val : fallback ?? DEFAULTS[name];
}
class Amayo extends Client { class Amayo extends Client {
public key: string; public key: string;
@@ -8,57 +29,67 @@ class Amayo extends Client {
public mode: string; public mode: string;
constructor() { constructor() {
super({ // Build options here so `this` can be referenced in the users.sweep filter
const options: ClientOptions = {
intents: [ intents: [
GatewayIntentBits.Guilds, GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers, GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent GatewayIntentBits.MessageContent,
], ],
partials: [Partials.Channel, Partials.Message], partials: [Partials.Channel, Partials.Message],
makeCache: Options.cacheWithLimits({ makeCache: Options.cacheWithLimits({
MessageManager: parseInt(process.env.CACHE_MESSAGES_LIMIT || '50', 10), MessageManager: intEnv("CACHE_MESSAGES_LIMIT"),
GuildMemberManager: parseInt(process.env.CACHE_MEMBERS_LIMIT || '100', 10), GuildMemberManager: intEnv("CACHE_MEMBERS_LIMIT"),
ThreadManager: 10, ThreadManager: 10,
ReactionManager: 0, ReactionManager: 0,
GuildInviteManager: 0, GuildInviteManager: 0,
StageInstanceManager: 0, StageInstanceManager: 0,
PresenceManager: 0 PresenceManager: 0,
}), }),
sweepers: { sweepers: {
messages: { messages: {
interval: parseInt(process.env.SWEEP_MESSAGES_INTERVAL_SECONDS || '300', 10), interval: intEnv("SWEEP_MESSAGES_INTERVAL_SECONDS"),
lifetime: parseInt(process.env.SWEEP_MESSAGES_LIFETIME_SECONDS || '900', 10) lifetime: intEnv("SWEEP_MESSAGES_LIFETIME_SECONDS"),
}, },
users: { users: {
interval: 60 * 30, interval: DEFAULTS.USERS_SWEEP_INTERVAL_SECONDS,
filter: () => (user) => user.bot && user.id !== this.user?.id filter: () => (user) => user.bot && user.id !== this.user?.id,
} },
}, },
rest: { rest: {
retries: 5 retries: DEFAULTS.REST_RETRIES,
} },
}); };
this.key = process.env.TOKEN ?? ''; super(options);
this.mode = process.env.MODE ?? 'Normal';
this.key = process.env.TOKEN ?? "";
this.mode = process.env.MODE ?? "Normal";
} }
async play() { /**
* Inicia la conexión a la base de datos y al gateway de Discord.
* Lanza si falta la clave o si falla la conexión/login.
*/
public async play(): Promise<void> {
if (!this.key) { if (!this.key) {
logger.error('No key provided'); logger.error("No key provided");
throw new Error('Missing DISCORD TOKEN'); throw new Error("Missing DISCORD TOKEN");
} else { }
try { try {
await ensurePrismaConnection(); await ensurePrismaConnection();
logger.info('Successfully connected to the database (singleton).'); logger.info("Successfully connected to the database (singleton).");
await this.login(this.key); await this.login(this.key);
} catch (error) { } catch (error) {
logger.error({ err: error }, 'Failed to connect to DB or login to Discord'); logger.error(
{ err: error },
"Failed to connect to DB or login to Discord"
);
throw error; throw error;
} }
} }
}
} }
export default Amayo; export default Amayo;