// Geburtstags-Runde: einmal täglich ab 09:00 (Europe/Berlin) gratulieren // und die Tages-Rolle umhängen (gestern Geburtstag → Rolle wieder weg). import { getSetting, setSetting, birthdaysToday } from '../db.js'; import { birthdayChannelId, birthdayRoleId, discordGuildId, brandColor2 } from '../runtime-settings.js'; import { brandEmbed } from '../embeds.js'; import { moduleEnabled } from '../modules.js'; import { renderTemplate } from '../templates.js'; import { tuning, everyTuned } from '../tuning.js'; /** Aktuelles Datum/Stunde in Europe/Berlin */ function berlinNow() { const parts = new Intl.DateTimeFormat('de-DE', { timeZone: 'Europe/Berlin', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', hour12: false, }).formatToParts(new Date()); const get = (type) => Number(parts.find((p) => p.type === type)?.value); return { day: get('day'), month: get('month'), hour: get('hour'), dateKey: `${get('year')}-${get('month')}-${get('day')}` }; } export async function birthdayTick(client) { if (!moduleEnabled('birthdays')) return; const { day, month, hour, dateKey } = berlinNow(); if (hour < tuning('birthday_hour')) return; if (getSetting('last_birthday_run') === dateKey) return; // heute schon gelaufen setSetting('last_birthday_run', dateKey); const guildId = discordGuildId() ?? [...client.guilds.cache.keys()][0]; const guild = guildId ? await client.guilds.fetch(guildId).catch(() => null) : null; const kids = birthdaysToday(day, month); // Tages-Rolle: erst bei allen abräumen, dann den heutigen geben const roleId = birthdayRoleId(); if (guild && roleId) { const role = await guild.roles.fetch(roleId).catch(() => null); if (role) { for (const member of role.members.values()) { await member.roles.remove(roleId).catch(() => {}); } for (const b of kids) { const member = await guild.members.fetch(b.user_id).catch(() => null); await member?.roles.add(roleId).catch(() => {}); } } } if (kids.length === 0) return; const channelId = birthdayChannelId(); if (!channelId) return; const channel = await client.channels.fetch(channelId).catch(() => null); if (!channel?.isTextBased()) return; const mentions = kids.map((b) => `<@${b.user_id}>`).join(' '); const many = kids.length > 1; const vars = { mentions, count: kids.length }; await channel.send({ content: mentions, embeds: [ brandEmbed(client, 'GEBURTSTAG') .setColor(brandColor2()) .setTitle(renderTemplate(many ? 'birthday.title_multi' : 'birthday.title', vars)) .setDescription(renderTemplate(many ? 'birthday.text_multi' : 'birthday.text', vars)), ], allowedMentions: { users: kids.map((b) => b.user_id) }, }).catch(() => {}); console.log(`[birthday] ${kids.length} Gratulation(en) für den ${day}.${month}.`); } export function startBirthdays(client) { everyTuned('birthday_interval', 'minutes', () => birthdayTick(client), 'birthday'); birthdayTick(client).catch(() => {}); }