66 lines
2.2 KiB
TypeScript
66 lines
2.2 KiB
TypeScript
import { TextChannel, WebhookClient } from 'discord.js';
|
|
import { logger } from '../utils/logger';
|
|
|
|
|
|
|
|
export class WebhookService {
|
|
private static readonly MAX_WEBHOOKS = 10;
|
|
private static readonly WEBHOOK_NAME = 'Kord Mimic Webhook';
|
|
private static readonly WEBHOOK_CACHE_TTL_MS = 86400 * 1000;
|
|
private static readonly webhookCache = new Map<
|
|
string,
|
|
{ id: string; token: string; expiresAt: number }
|
|
>();
|
|
|
|
public static async getWebhookClient(channel: TextChannel): Promise<WebhookClient | null> {
|
|
try {
|
|
const now = Date.now();
|
|
const cached = this.webhookCache.get(channel.id);
|
|
if (cached && now < cached.expiresAt) {
|
|
return new WebhookClient({ id: cached.id, token: cached.token });
|
|
|
|
}
|
|
|
|
// 2. Fetch from Discord API
|
|
const webhooks = await channel.fetchWebhooks();
|
|
let kordWebhook = webhooks.find(wh => wh.name === this.WEBHOOK_NAME && wh.token !== null);
|
|
|
|
if (!kordWebhook) {
|
|
if (webhooks.size >= this.MAX_WEBHOOKS) {
|
|
// If we hit limits, delete the oldest webhook
|
|
const oldestWebhook = webhooks.last();
|
|
if (oldestWebhook) {
|
|
await oldestWebhook.delete('Hit max webhook limit for Kord');
|
|
logger.warn(`Deleted oldest webhook in channel ${channel.id}`);
|
|
} else {
|
|
logger.error(`Webhook limits reached in ${channel.id} but no webhook could be deleted.`);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
kordWebhook = await channel.createWebhook({
|
|
name: this.WEBHOOK_NAME,
|
|
avatar: channel.client.user?.displayAvatarURL(),
|
|
reason: 'Webhook needed for Kord Mimic & Prank feature',
|
|
});
|
|
logger.info(`Created new webhook for channel ${channel.id}`);
|
|
}
|
|
|
|
if (kordWebhook.token) {
|
|
this.webhookCache.set(channel.id, {
|
|
id: kordWebhook.id,
|
|
token: kordWebhook.token,
|
|
expiresAt: Date.now() + this.WEBHOOK_CACHE_TTL_MS,
|
|
|
|
});
|
|
return new WebhookClient({ id: kordWebhook.id, token: kordWebhook.token });
|
|
}
|
|
|
|
return null;
|
|
} catch (error) {
|
|
logger.error(`WebhookService Error on channel ${channel.id}:`, error);
|
|
return null;
|
|
}
|
|
}
|
|
}
|