Add new features for giveaways, tickets, self-roles, tags, starboard, suggestions, and birthdays

- Integrated new command modules for managing giveaways, tickets, self-roles, tags, starboard, suggestions, and birthdays, enhancing the bot's capabilities.
- Implemented job handling for giveaway endings, ticket management, and birthday role expirations, improving automation and user experience.
- Updated command definitions and interaction handling to support new features, ensuring smooth user interactions.
- Enhanced the job processing system with dedicated workers for managing various tasks, including auto-closing tickets and running birthday checks.
- Documented the new features and their setup processes in PHASE-TRACKING.md for clarity on implementation steps.
This commit is contained in:
smueller
2026-07-22 13:21:28 +02:00
parent 1ceb8c3574
commit 52b10c9536
11 changed files with 271 additions and 90 deletions

View File

@@ -12,13 +12,20 @@ import { completeVerification } from './modules/verification/handlers.js';
import { closePoll } from './modules/utility/poll.js';
import { sendReminder } from './modules/utility/reminders.js';
import { expireSelfRole } from './modules/selfroles/service.js';
import { endGiveaway } from './modules/giveaways/index.js';
import { closeInactiveTickets } from './modules/tickets/index.js';
import { expireBirthdayRole, runBirthdayCheck } from './modules/birthdays/index.js';
import {
automodQueue,
automodQueueName,
backupQueue,
backupQueueName,
birthdayQueue,
birthdayQueueName,
giveawayQueueName,
moderationQueueName,
reminderQueueName,
ticketQueue,
ticketQueueName,
verificationQueueName
} from './queues.js';
@@ -57,6 +64,16 @@ type SelfRoleExpireJob = {
roleId: string;
};
type GiveawayEndJob = {
giveawayId: string;
};
type BirthdayRoleExpireJob = {
guildId: string;
userId: string;
roleId: string;
};
export function startWorkers(context: BotContext): Worker[] {
const moderationWorker = new Worker<TempBanJob>(
moderationQueueName,
@@ -143,13 +160,17 @@ export function startWorkers(context: BotContext): Worker[] {
logger.error({ jobId: job?.id, error }, 'Reminder job failed');
});
const ticketWorker = new Worker<SelfRoleExpireJob>(
const ticketWorker = new Worker(
ticketQueueName,
async (job) => {
if (job.name !== 'selfRoleExpire') {
if (job.name === 'selfRoleExpire') {
const data = job.data as SelfRoleExpireJob;
await expireSelfRole(context, data.guildId, data.userId, data.roleId);
return;
}
await expireSelfRole(context, job.data.guildId, job.data.userId, job.data.roleId);
if (job.name === 'ticketAutoClose') {
await closeInactiveTickets(context);
}
},
{ connection: redis }
);
@@ -158,7 +179,50 @@ export function startWorkers(context: BotContext): Worker[] {
logger.error({ jobId: job?.id, error }, 'Ticket queue job failed');
});
return [moderationWorker, backupWorker, automodWorker, verificationWorker, reminderWorker, ticketWorker];
const giveawayWorker = new Worker<GiveawayEndJob>(
giveawayQueueName,
async (job) => {
if (job.name !== 'giveawayEnd') {
return;
}
await endGiveaway(context, job.data.giveawayId);
},
{ connection: redis }
);
giveawayWorker.on('failed', (job, error) => {
logger.error({ jobId: job?.id, error }, 'Giveaway job failed');
});
const birthdayWorker = new Worker(
birthdayQueueName,
async (job) => {
if (job.name === 'birthdayDailyCheck') {
await runBirthdayCheck(context);
return;
}
if (job.name === 'birthdayRoleExpire') {
const data = job.data as BirthdayRoleExpireJob;
await expireBirthdayRole(context, data.guildId, data.userId, data.roleId);
}
},
{ connection: redis }
);
birthdayWorker.on('failed', (job, error) => {
logger.error({ jobId: job?.id, error }, 'Birthday job failed');
});
return [
moderationWorker,
backupWorker,
automodWorker,
verificationWorker,
reminderWorker,
ticketWorker,
giveawayWorker,
birthdayWorker
];
}
export async function ensureRecurringJobs(): Promise<void> {
@@ -183,6 +247,26 @@ export async function ensureRecurringJobs(): Promise<void> {
);
await automodQueue.add('refreshPhishingList', {}, { removeOnComplete: 20, removeOnFail: 20 });
await ticketQueue.add(
'ticketAutoClose',
{},
{
repeat: { pattern: '0 * * * *' },
removeOnComplete: 20,
removeOnFail: 20
}
);
await birthdayQueue.add(
'birthdayDailyCheck',
{},
{
repeat: { pattern: '0 * * * *' },
removeOnComplete: 20,
removeOnFail: 20
}
);
}
async function runPgDumpBackup(): Promise<void> {