[deploy] Fix stats duplication and polish help embed
All checks were successful
Deploy Discord Bot / deploy (push) Successful in 37s
All checks were successful
Deploy Discord Bot / deploy (push) Successful in 37s
This commit is contained in:
@@ -4,15 +4,19 @@ import { SlashCommand } from '../../utils/types';
|
|||||||
const command: SlashCommand = {
|
const command: SlashCommand = {
|
||||||
data: new SlashCommandBuilder().setName('help').setDescription('Zeigt Befehle und Module.'),
|
data: new SlashCommandBuilder().setName('help').setDescription('Zeigt Befehle und Module.'),
|
||||||
async execute(interaction: ChatInputCommandInteraction) {
|
async execute(interaction: ChatInputCommandInteraction) {
|
||||||
|
const avatar = interaction.client.user?.displayAvatarURL({ size: 256 }) ?? null;
|
||||||
const embed = new EmbedBuilder()
|
const embed = new EmbedBuilder()
|
||||||
.setTitle('Papo Hilfe')
|
.setTitle('✨ Papo Hilfe')
|
||||||
.setDescription('Multi-Guild ready | Admin, Tickets, Musik, Automod, Dashboard')
|
.setColor(0xf97316)
|
||||||
|
.setThumbnail(avatar)
|
||||||
|
.setDescription('Dein All-in-One Assistant: Tickets, Automod, Musik, Stats, Dashboard.')
|
||||||
.addFields(
|
.addFields(
|
||||||
{ name: 'Admin', value: '/ban /kick /mute /timeout /clear', inline: false },
|
{ name: '🛡️ Admin', value: '`/ban` `/kick` `/mute` `/timeout` `/clear`', inline: false },
|
||||||
{ name: 'Tickets', value: '/ticket /ticketpanel /ticketpriority /ticketstatus /transcript', inline: false },
|
{ name: '🎫 Tickets', value: '`/ticket` `/ticketpanel` `/ticketpriority` `/ticketstatus` `/transcript`', inline: false },
|
||||||
{ name: 'Musik', value: '/play /pause /resume /skip /stop /queue /loop', inline: false },
|
{ name: '🎵 Musik', value: '`/play` `/pause` `/resume` `/skip` `/stop` `/queue` `/loop`', inline: false },
|
||||||
{ name: 'Utility', value: '/ping /configure /serverinfo /rank', inline: false }
|
{ name: '📊 Server-Tools', value: '`/configure` `/serverinfo` `/rank`', inline: false }
|
||||||
);
|
)
|
||||||
|
.setFooter({ text: 'Tipp: Nutze /configure für Module & Dashboard-Link' });
|
||||||
await interaction.reply({ embeds: [embed], ephemeral: true });
|
await interaction.reply({ embeds: [embed], ephemeral: true });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ export class StatsService {
|
|||||||
private client: Client | null = null;
|
private client: Client | null = null;
|
||||||
private interval?: NodeJS.Timeout;
|
private interval?: NodeJS.Timeout;
|
||||||
private lastRun = new Map<string, number>();
|
private lastRun = new Map<string, number>();
|
||||||
|
private syncLocks = new Map<string, Promise<void>>();
|
||||||
|
|
||||||
public setClient(client: Client) {
|
public setClient(client: Client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
@@ -72,21 +73,25 @@ export class StatsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async saveConfig(guildId: string, config: Partial<ServerStatsConfig>) {
|
public async saveConfig(guildId: string, config: Partial<ServerStatsConfig>) {
|
||||||
const previous = await this.getConfig(guildId);
|
return this.withGuildLock(guildId, async () => {
|
||||||
const normalized = this.normalizeConfig({ ...previous, ...config });
|
const previous = await this.getConfig(guildId);
|
||||||
const synced = await this.syncGuild(guildId, normalized, previous);
|
const normalized = this.normalizeConfig({ ...previous, ...config });
|
||||||
await settingsStore.set(guildId, { serverStatsEnabled: synced.enabled, serverStatsConfig: synced } as any);
|
const synced = await this.syncGuild(guildId, normalized, previous);
|
||||||
this.lastRun.set(guildId, Date.now());
|
await settingsStore.set(guildId, { serverStatsEnabled: synced.enabled, serverStatsConfig: synced } as any);
|
||||||
return synced;
|
this.lastRun.set(guildId, Date.now());
|
||||||
|
return synced;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async refreshGuild(guildId: string) {
|
public async refreshGuild(guildId: string) {
|
||||||
const cfg = await this.getConfig(guildId);
|
return this.withGuildLock(guildId, async () => {
|
||||||
if (!cfg.enabled) return cfg;
|
const cfg = await this.getConfig(guildId);
|
||||||
const synced = await this.syncGuild(guildId, cfg, cfg);
|
if (!cfg.enabled) return cfg;
|
||||||
await settingsStore.set(guildId, { serverStatsEnabled: synced.enabled, serverStatsConfig: synced } as any);
|
const synced = await this.syncGuild(guildId, cfg, cfg);
|
||||||
this.lastRun.set(guildId, Date.now());
|
await settingsStore.set(guildId, { serverStatsEnabled: synced.enabled, serverStatsConfig: synced } as any);
|
||||||
return synced;
|
this.lastRun.set(guildId, Date.now());
|
||||||
|
return synced;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async disableGuild(guildId: string) {
|
public async disableGuild(guildId: string) {
|
||||||
@@ -248,4 +253,19 @@ export class StatsService {
|
|||||||
await this.refreshGuild(guildId).catch(() => undefined);
|
await this.refreshGuild(guildId).catch(() => undefined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async withGuildLock<T>(guildId: string, task: () => Promise<T>): Promise<T> {
|
||||||
|
const waitFor = this.syncLocks.get(guildId) || Promise.resolve();
|
||||||
|
const run = (async () => {
|
||||||
|
await waitFor.catch(() => undefined);
|
||||||
|
return task();
|
||||||
|
})();
|
||||||
|
this.syncLocks.set(guildId, run.then(() => undefined, () => undefined));
|
||||||
|
try {
|
||||||
|
return await run;
|
||||||
|
} finally {
|
||||||
|
const current = this.syncLocks.get(guildId);
|
||||||
|
if (current === run) this.syncLocks.delete(guildId);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user