Add: Logging module with moderation events
Commands: - /log setchannel, enable, disable, list, help Events logged: - messages: deleted/edited messages - roles: role changes - nicks: nickname changes - channels: channel create/delete - warns, mutes, kicks, bans: moderation actions Moderation logging integrated into admin.ts for all mod actions (warn, mute, kick, ban). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,27 @@
|
||||
import { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, GuildMember, MessageFlags } from 'discord.js';
|
||||
import { Command } from '../../structures/Command.js';
|
||||
|
||||
async function sendModerationLog(client: any, guildId: string, event: string, embed: EmbedBuilder) {
|
||||
const DB = client.DB;
|
||||
const settings: any = DB.get('SELECT log_events FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
if (!settings?.log_events) return;
|
||||
const activeEvents = settings.log_events.split(',').filter(Boolean);
|
||||
if (!activeEvents.includes(event)) return;
|
||||
|
||||
const logSettings: any = DB.get('SELECT log_channel FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
if (!logSettings?.log_channel) return;
|
||||
|
||||
const channel = client.guilds.cache.get(guildId)?.channels.cache.get(logSettings.log_channel);
|
||||
if (!channel || !channel.isTextBased()) return;
|
||||
|
||||
try {
|
||||
await (channel as any).send({ embeds: [embed] });
|
||||
} catch (error) {
|
||||
console.error(`[LOG] Error sending moderation log (${event}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
const command: Command = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('admin')
|
||||
@@ -174,6 +195,17 @@ const command: Command = {
|
||||
try {
|
||||
await target.kick(reason);
|
||||
await interaction.reply(`✅ Gekickt: ${target.user.tag}\nGrund: ${reason}`);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('👢 User gekickt')
|
||||
.setColor(0xf39c12)
|
||||
.addFields(
|
||||
{ name: 'Nutzer', value: `${target.user.tag} (<@${target.id}>)`, inline: true },
|
||||
{ name: 'Moderator', value: `${interaction.user.tag} (<@${interaction.user.id}>)`, inline: true },
|
||||
{ name: 'Grund', value: reason, inline: false }
|
||||
)
|
||||
.setTimestamp();
|
||||
await sendModerationLog(interaction.client, guildId, 'kicks', embed);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
await interaction.reply({ content: '❌ Fehler beim Kicken.', flags: [MessageFlags.Ephemeral] });
|
||||
@@ -236,6 +268,18 @@ const command: Command = {
|
||||
}
|
||||
|
||||
await interaction.reply({ content: message });
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('⚠️ User verwarnt')
|
||||
.setColor(0xf39c12)
|
||||
.addFields(
|
||||
{ name: 'Nutzer', value: `${target.user.tag} (<@${target.id}>)`, inline: true },
|
||||
{ name: 'Moderator', value: `${interaction.user.tag} (<@${interaction.user.id}>)`, inline: true },
|
||||
{ name: 'Grund', value: reason, inline: false },
|
||||
{ name: 'Warnungen', value: `${warnCount}/${warnThreshold}`, inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
await sendModerationLog(interaction.client, guildId, 'warns', embed);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -320,6 +364,18 @@ const command: Command = {
|
||||
try {
|
||||
await target.timeout(durationMs, reason);
|
||||
await interaction.reply(`✅ Gemuted: ${target.user.tag}\nDauer: ${durationText}\nGrund: ${reason}`);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('🔇 User gemutet')
|
||||
.setColor(0xf39c12)
|
||||
.addFields(
|
||||
{ name: 'Nutzer', value: `${target.user.tag} (<@${target.id}>)`, inline: true },
|
||||
{ name: 'Moderator', value: `${interaction.user.tag} (<@${interaction.user.id}>)`, inline: true },
|
||||
{ name: 'Dauer', value: durationText, inline: true },
|
||||
{ name: 'Grund', value: reason, inline: false }
|
||||
)
|
||||
.setTimestamp();
|
||||
await sendModerationLog(interaction.client, guildId, 'mutes', embed);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
await interaction.reply({ content: '❌ Fehler beim Muten.', flags: [MessageFlags.Ephemeral] });
|
||||
@@ -363,6 +419,18 @@ const command: Command = {
|
||||
try {
|
||||
await target.ban({ deleteMessageSeconds: deleteDays * 86400, reason });
|
||||
await interaction.reply(`✅ Gebannt: ${target.user.tag}\nGrund: ${reason}`);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('🔨 User gebannt')
|
||||
.setColor(0xe74c3c)
|
||||
.addFields(
|
||||
{ name: 'Nutzer', value: `${target.user.tag} (<@${target.id}>)`, inline: true },
|
||||
{ name: 'Moderator', value: `${interaction.user.tag} (<@${interaction.user.id}>)`, inline: true },
|
||||
{ name: 'Grund', value: reason, inline: false },
|
||||
{ name: 'Nachrichten gelöscht', value: `${deleteDays} Tage`, inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
await sendModerationLog(interaction.client, guildId, 'bans', embed);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
await interaction.reply({ content: '❌ Fehler beim Bannen.', flags: [MessageFlags.Ephemeral] });
|
||||
|
||||
175
src/commands/utility/log.ts
Normal file
175
src/commands/utility/log.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
import { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } from 'discord.js';
|
||||
import { Command } from '../../structures/Command.js';
|
||||
|
||||
const AVAILABLE_EVENTS = [
|
||||
{ value: 'messages', label: 'Nachrichten', desc: 'Gelöschte und edierte Nachrichten' },
|
||||
{ value: 'roles', label: 'Rollen', desc: 'Rollenänderungen' },
|
||||
{ value: 'nicks', label: 'Nicknames', desc: 'Nickname-Änderungen' },
|
||||
{ value: 'channels', label: 'Channels', desc: 'Channel erstellt/gelöscht' },
|
||||
{ value: 'warns', label: 'Verwarnungen', desc: 'User verwarnt' },
|
||||
{ value: 'mutes', label: 'Mutes', desc: 'User gemutet' },
|
||||
{ value: 'kicks', label: 'Kicks', desc: 'User gekickt' },
|
||||
{ value: 'bans', label: 'Bans', desc: 'User gebannt' },
|
||||
];
|
||||
|
||||
const command: Command = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('log')
|
||||
.setDescription('Log-Einstellungen verwalten (Mod).')
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('setchannel')
|
||||
.setDescription('Log-Kanal setzen (Mod).')
|
||||
.addChannelOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('Discord-Kanal für Logs')
|
||||
.setRequired(true)))
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('enable')
|
||||
.setDescription('Event-Logging aktivieren (Mod).')
|
||||
.addStringOption(option =>
|
||||
option.setName('event')
|
||||
.setDescription('Welches Event loggen?')
|
||||
.setRequired(true)
|
||||
.addChoices(...AVAILABLE_EVENTS.map(e => ({ name: `${e.label} - ${e.desc}`, value: e.value })))))
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('disable')
|
||||
.setDescription('Event-Logging deaktivieren (Mod).')
|
||||
.addStringOption(option =>
|
||||
option.setName('event')
|
||||
.setDescription('Welches Event nicht mehr loggen?')
|
||||
.setRequired(true)
|
||||
.addChoices(...AVAILABLE_EVENTS.map(e => ({ name: `${e.label} - ${e.desc}`, value: e.value })))))
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('list')
|
||||
.setDescription('Aktive Log-Events anzeigen (Mod).'))
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('help')
|
||||
.setDescription('Hilfe zu Log-Befehlen (Mod).')),
|
||||
category: 'Admin',
|
||||
async execute(interaction: any) {
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
const guildId = interaction.guildId;
|
||||
const isAdmin = interaction.memberPermissions?.has(PermissionFlagsBits.ModerateMembers);
|
||||
const DB = interaction.client.DB;
|
||||
|
||||
// Ensure guild settings exist
|
||||
DB.run('INSERT OR IGNORE INTO guild_settings (guild_id) VALUES (?)', guildId);
|
||||
|
||||
if (subcommand === 'help') {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('📋 Log Hilfe')
|
||||
.setColor(0x9b59b6)
|
||||
.setDescription('Loggt verschiedene Server-Events in einen Kanal.')
|
||||
.addFields(
|
||||
{ name: '`/log setchannel <#kanal>`', value: 'Setzt den Kanal für Logs (Mod).', inline: false },
|
||||
{ name: '`/log enable <event>`', value: 'Aktiviert ein Event zum Loggen (Mod).', inline: false },
|
||||
{ name: '`/log disable <event>`', value: 'Deaktiviert ein Event (Mod).', inline: false },
|
||||
{ name: '`/log list`', value: 'Zeigt aktive Log-Events (Mod).', inline: false },
|
||||
{ name: 'Events', value: AVAILABLE_EVENTS.map(e => `• **${e.value}**: ${e.desc}`).join('\n'), inline: false }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
|
||||
return;
|
||||
}
|
||||
|
||||
// Admin only for all commands
|
||||
if (!isAdmin) {
|
||||
await interaction.reply({ content: '❌ Keine Berechtigung. Moderatoren erforderlich.', flags: [MessageFlags.Ephemeral] });
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'setchannel') {
|
||||
const channel = interaction.options.getChannel('channel');
|
||||
|
||||
DB.run(
|
||||
'UPDATE guild_settings SET log_channel = ? WHERE guild_id = ?',
|
||||
channel.id,
|
||||
guildId
|
||||
);
|
||||
|
||||
await interaction.reply({ content: `✅ Log-Kanal auf ${channel} gesetzt.`, flags: [MessageFlags.Ephemeral] });
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'list') {
|
||||
const settings: any = DB.get('SELECT * FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
const channel = settings?.log_channel
|
||||
? `<#${settings.log_channel}>`
|
||||
: 'Nicht gesetzt';
|
||||
|
||||
const activeEvents = (settings?.log_events || '').split(',').filter(Boolean);
|
||||
const eventsList = activeEvents.length > 0
|
||||
? AVAILABLE_EVENTS.filter(e => activeEvents.includes(e.value))
|
||||
.map(e => `• **${e.label}**: ${e.desc}`)
|
||||
.join('\n')
|
||||
: 'Keine Events aktiv';
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('📋 Log Einstellungen')
|
||||
.setColor(0x9b59b6)
|
||||
.setDescription(`Server: **${interaction.guild.name}**`)
|
||||
.addFields(
|
||||
{ name: 'Log-Kanal', value: channel, inline: true },
|
||||
{ name: 'Aktive Events', value: eventsList, inline: false }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'enable') {
|
||||
const event = interaction.options.getString('event')!;
|
||||
const settings: any = DB.get('SELECT log_events FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
const currentEvents = (settings?.log_events || '').split(',').filter(Boolean);
|
||||
|
||||
if (currentEvents.includes(event)) {
|
||||
await interaction.reply({ content: `ℹ️ Event **${event}** ist bereits aktiviert.`, flags: [MessageFlags.Ephemeral] });
|
||||
return;
|
||||
}
|
||||
|
||||
currentEvents.push(event);
|
||||
|
||||
DB.run(
|
||||
'UPDATE guild_settings SET log_events = ? WHERE guild_id = ?',
|
||||
currentEvents.join(','),
|
||||
guildId
|
||||
);
|
||||
|
||||
await interaction.reply({ content: `✅ Event **${event}** aktiviert.`, flags: [MessageFlags.Ephemeral] });
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'disable') {
|
||||
const event = interaction.options.getString('event')!;
|
||||
const settings: any = DB.get('SELECT log_events FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
const currentEvents = (settings?.log_events || '').split(',').filter(Boolean);
|
||||
|
||||
if (!currentEvents.includes(event)) {
|
||||
await interaction.reply({ content: `ℹ️ Event **${event}** ist nicht aktiviert.`, flags: [MessageFlags.Ephemeral] });
|
||||
return;
|
||||
}
|
||||
|
||||
const newEvents = currentEvents.filter((e: string) => e !== event);
|
||||
|
||||
DB.run(
|
||||
'UPDATE guild_settings SET log_events = ? WHERE guild_id = ?',
|
||||
newEvents.join(','),
|
||||
guildId
|
||||
);
|
||||
|
||||
await interaction.reply({ content: `✅ Event **${event}** deaktiviert.`, flags: [MessageFlags.Ephemeral] });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default command;
|
||||
56
src/events/channelEvent.ts
Normal file
56
src/events/channelEvent.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { Events, GuildChannel, EmbedBuilder } from 'discord.js';
|
||||
|
||||
async function sendLog(client: any, guildId: string, event: string, embed: EmbedBuilder) {
|
||||
const DB = client.DB;
|
||||
const settings: any = DB.get('SELECT log_events FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
if (!settings?.log_events) return;
|
||||
const activeEvents = settings.log_events.split(',').filter(Boolean);
|
||||
if (!activeEvents.includes(event)) return;
|
||||
|
||||
const logSettings: any = DB.get('SELECT log_channel FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
if (!logSettings?.log_channel) return;
|
||||
|
||||
const channel = client.guilds.cache.get(guildId)?.channels.cache.get(logSettings.log_channel);
|
||||
if (!channel || !channel.isTextBased()) return;
|
||||
|
||||
try {
|
||||
await (channel as any).send({ embeds: [embed] });
|
||||
} catch (error) {
|
||||
console.error(`[LOG] Error sending log (${event}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Channel Create
|
||||
export const channelCreateEvent = {
|
||||
name: Events.ChannelCreate,
|
||||
async execute(channel: GuildChannel) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('📁 Channel erstellt')
|
||||
.setColor(0x27ae60)
|
||||
.addFields(
|
||||
{ name: 'Name', value: channel.name, inline: true },
|
||||
{ name: 'Typ', value: channel.type.toString(), inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(channel.client, channel.guild!.id, 'channels', embed);
|
||||
},
|
||||
};
|
||||
|
||||
// Channel Delete
|
||||
export const channelDeleteEvent = {
|
||||
name: Events.ChannelDelete,
|
||||
async execute(channel: GuildChannel) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('📁 Channel gelöscht')
|
||||
.setColor(0xe74c3c)
|
||||
.addFields(
|
||||
{ name: 'Name', value: channel.name, inline: true },
|
||||
{ name: 'Typ', value: channel.type.toString(), inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(channel.client, channel.guild!.id, 'channels', embed);
|
||||
},
|
||||
};
|
||||
80
src/events/guildMemberUpdate.ts
Normal file
80
src/events/guildMemberUpdate.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { Events, GuildMember, EmbedBuilder } from 'discord.js';
|
||||
|
||||
async function sendLog(client: any, guildId: string, event: string, embed: EmbedBuilder) {
|
||||
const DB = client.DB;
|
||||
const settings: any = DB.get('SELECT log_events FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
if (!settings?.log_events) return;
|
||||
const activeEvents = settings.log_events.split(',').filter(Boolean);
|
||||
if (!activeEvents.includes(event)) return;
|
||||
|
||||
const logSettings: any = DB.get('SELECT log_channel FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
if (!logSettings?.log_channel) return;
|
||||
|
||||
const channel = client.guilds.cache.get(guildId)?.channels.cache.get(logSettings.log_channel);
|
||||
if (!channel || !channel.isTextBased()) return;
|
||||
|
||||
try {
|
||||
await (channel as any).send({ embeds: [embed] });
|
||||
} catch (error) {
|
||||
console.error(`[LOG] Error sending log (${event}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Guild Member Update (nickname + roles)
|
||||
export default {
|
||||
name: Events.GuildMemberUpdate,
|
||||
async execute(oldMember: GuildMember, newMember: GuildMember) {
|
||||
const guildId = newMember.guild.id;
|
||||
|
||||
// Nickname change
|
||||
if (oldMember.nickname !== newMember.nickname) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('📝 Nickname geändert')
|
||||
.setColor(0x3498db)
|
||||
.addFields(
|
||||
{ name: 'Nutzer', value: `${newMember.user.tag} (<@${newMember.id}>)`, inline: true }
|
||||
)
|
||||
.addFields(
|
||||
{ name: 'Vorher', value: oldMember.nickname || newMember.user.username, inline: true },
|
||||
{ name: 'Nachher', value: newMember.nickname || newMember.user.username, inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(newMember.client, guildId, 'nicks', embed);
|
||||
}
|
||||
|
||||
// Role changes
|
||||
const oldRoles = oldMember.roles.cache;
|
||||
const newRoles = newMember.roles.cache;
|
||||
|
||||
const addedRoles = newRoles.filter(r => !oldRoles.has(r.id));
|
||||
const removedRoles = oldRoles.filter(r => !newRoles.has(r.id));
|
||||
|
||||
for (const role of addedRoles) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('🎭 Rolle hinzugefügt')
|
||||
.setColor(0x27ae60)
|
||||
.addFields(
|
||||
{ name: 'Nutzer', value: `${newMember.user.tag} (<@${newMember.id}>)`, inline: true },
|
||||
{ name: 'Rolle', value: `${role[1].name} (<@&${role[1].id}>)`, inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(newMember.client, guildId, 'roles', embed);
|
||||
}
|
||||
|
||||
for (const role of removedRoles) {
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('🎭 Rolle entfernt')
|
||||
.setColor(0xe74c3c)
|
||||
.addFields(
|
||||
{ name: 'Nutzer', value: `${newMember.user.tag} (<@${newMember.id}>)`, inline: true },
|
||||
{ name: 'Rolle', value: `${role[1].name} (<@&${role[1].id}>)`, inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(newMember.client, guildId, 'roles', embed);
|
||||
}
|
||||
},
|
||||
};
|
||||
73
src/events/messageDelete.ts
Normal file
73
src/events/messageDelete.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { Events, Message, TextChannel, GuildChannel, AuditLogEvent, EmbedBuilder } from 'discord.js';
|
||||
|
||||
function getLogChannel(client: any, guildId: string): TextChannel | null {
|
||||
const DB = client.DB;
|
||||
const settings: any = DB.get('SELECT * FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
if (!settings?.log_channel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const channel = client.guilds.cache.get(guildId)?.channels.cache.get(settings.log_channel);
|
||||
if (!channel || !channel.isTextBased()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return channel as TextChannel;
|
||||
}
|
||||
|
||||
function isEventEnabled(client: any, guildId: string, event: string): boolean {
|
||||
const DB = client.DB;
|
||||
const settings: any = DB.get('SELECT log_events FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
if (!settings?.log_events) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const activeEvents = settings.log_events.split(',').filter(Boolean);
|
||||
return activeEvents.includes(event);
|
||||
}
|
||||
|
||||
async function sendLog(client: any, guildId: string, event: string, embed: EmbedBuilder) {
|
||||
if (!isEventEnabled(client, guildId, event)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = getLogChannel(client, guildId);
|
||||
if (!channel) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await channel.send({ embeds: [embed] });
|
||||
} catch (error) {
|
||||
console.error(`[LOG] Error sending log (${event}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Message Delete
|
||||
export default {
|
||||
name: Events.MessageDelete,
|
||||
async execute(message: Message) {
|
||||
if (!message.guild || message.author.bot) return;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('🗑️ Nachricht gelöscht')
|
||||
.setColor(0xe74c3c)
|
||||
.addFields(
|
||||
{ name: 'Autor', value: `${message.author.tag} (<@${message.author.id}>)`, inline: true },
|
||||
{ name: 'Kanal', value: `<#${message.channelId}>`, inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
if (message.content) {
|
||||
embed.addFields({ name: 'Inhalt', value: message.content.substring(0, 1024), inline: false });
|
||||
}
|
||||
|
||||
if (message.attachments.size > 0) {
|
||||
embed.addFields({ name: 'Anhänge', value: `${message.attachments.size} Datei(en)`, inline: true });
|
||||
}
|
||||
|
||||
await sendLog(message.client, message.guildId!, 'messages', embed);
|
||||
},
|
||||
};
|
||||
47
src/events/messageUpdate.ts
Normal file
47
src/events/messageUpdate.ts
Normal file
@@ -0,0 +1,47 @@
|
||||
import { Events, Message, EmbedBuilder } from 'discord.js';
|
||||
|
||||
async function sendLog(client: any, guildId: string, event: string, embed: EmbedBuilder) {
|
||||
const DB = client.DB;
|
||||
const settings: any = DB.get('SELECT log_events FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
|
||||
if (!settings?.log_events) return;
|
||||
const activeEvents = settings.log_events.split(',').filter(Boolean);
|
||||
if (!activeEvents.includes(event)) return;
|
||||
|
||||
const logSettings: any = DB.get('SELECT log_channel FROM guild_settings WHERE guild_id = ?', guildId);
|
||||
if (!logSettings?.log_channel) return;
|
||||
|
||||
const channel = client.guilds.cache.get(guildId)?.channels.cache.get(logSettings.log_channel);
|
||||
if (!channel || !channel.isTextBased()) return;
|
||||
|
||||
try {
|
||||
await (channel as any).send({ embeds: [embed] });
|
||||
} catch (error) {
|
||||
console.error(`[LOG] Error sending log (${event}):`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Message Update (Edit)
|
||||
export default {
|
||||
name: Events.MessageUpdate,
|
||||
async execute(oldMessage: Message, newMessage: Message) {
|
||||
if (!newMessage.guild || newMessage.author?.bot) return;
|
||||
if (!oldMessage.content || !newMessage.content) return;
|
||||
if (oldMessage.content === newMessage.content) return;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('✏️ Nachricht editiert')
|
||||
.setColor(0xf39c12)
|
||||
.addFields(
|
||||
{ name: 'Autor', value: `${newMessage.author.tag} (<@${newMessage.author.id}>)`, inline: true },
|
||||
{ name: 'Kanal', value: `<#${newMessage.channelId}>`, inline: true }
|
||||
)
|
||||
.addFields(
|
||||
{ name: 'Vorher', value: oldMessage.content.substring(0, 1024), inline: false },
|
||||
{ name: 'Nachher', value: newMessage.content.substring(0, 1024), inline: false }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await sendLog(newMessage.client, newMessage.guildId!, 'messages', embed);
|
||||
},
|
||||
};
|
||||
@@ -27,6 +27,8 @@ export class DB {
|
||||
welcome_channel TEXT,
|
||||
welcome_message TEXT,
|
||||
goodbye_message TEXT,
|
||||
log_channel TEXT,
|
||||
log_events TEXT DEFAULT 'messages,roles,nicks,channels,moderation',
|
||||
warn_threshold INTEGER DEFAULT 3,
|
||||
warn_action TEXT DEFAULT 'ban',
|
||||
warn_mute_duration INTEGER DEFAULT 1800
|
||||
|
||||
Reference in New Issue
Block a user