XP-Beträge, Wartezeiten, Prüf-Intervalle, Obergrenzen und Postzeiten
standen als Konstanten im Code. Wer den Server-Monitor seltener prüfen
lassen wollte oder das Level-System anders austarieren, musste die
Quelldateien anfassen.
src/tuning.js hält sie jetzt an einer Stelle, mit Standard, erlaubtem
Bereich und Erklärung. Der neue Config-Bereich „Werte" zeigt sie nach
Themen gruppiert; neben jedem Feld steht der erlaubte Bereich und der
Standard, angepasste Werte lassen sich einzeln zurücksetzen.
Die Grenzen sind nicht Kosmetik: ein Vertipper beim Prüf-Intervall würde
sonst den Bot in eine Schleife im Sekundentakt schicken. Gespeichert wird
ganz oder gar nicht — ein ungültiger Wert im Formular lässt auch die
gültigen daneben unverändert, statt die Hälfte zu schreiben.
Intervalle laufen nicht mehr über setInterval mit festem Abstand, sondern
über everyTuned: der Wert wird vor jeder Runde neu gelesen. Ein geändertes
Intervall greift damit ab dem nächsten Durchlauf, ohne Neustart. Ein
Fehler in einer Runde beendet die Schleife nicht.
Beim Testen aufgefallen und behoben: Number('') ist 0 und nicht NaN — ein
nie gesetzter Wert wäre dadurch auf sein Minimum gefallen statt auf den
Standard. Das Level-System hätte also 1 XP pro Nachricht vergeben und der
Monitor jede Minute geprüft.
Der Fetch-Wrapper im Frontend hat die Fehlermeldung des Servers verworfen;
jetzt steht im Panel „XP pro Nachricht: 1–500 XP" statt „fehlgeschlagen".
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
71 lines
3.1 KiB
JavaScript
71 lines
3.1 KiB
JavaScript
// 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(() => {});
|
|
}
|