Compare commits
4 Commits
1.0
...
5ee6959662
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ee6959662 | |||
| f17cde44c3 | |||
| 0435056271 | |||
| 1dcd1cad98 |
7
.gitattributes
vendored
Normal file
7
.gitattributes
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
* text=auto
|
||||||
|
*.ts text eol=lf
|
||||||
|
*.js text eol=lf
|
||||||
|
*.json text eol=lf
|
||||||
|
*.md text eol=lf
|
||||||
|
*.yml text eol=lf
|
||||||
|
*.yaml text eol=lf
|
||||||
@@ -293,7 +293,7 @@ const command: Command = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const reminders: any[] = DB.all(
|
const reminders: any[] = DB.all(
|
||||||
'SELECT r.*, c.name as channel_name FROM reminders r LEFT JOIN channels c ON r.channel_id = c.id WHERE r.guild_id = ? ORDER BY r.target_time ASC',
|
'SELECT * FROM reminders WHERE guild_id = ? ORDER BY target_time ASC',
|
||||||
guildId
|
guildId
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ const command: Command = {
|
|||||||
.setName('add')
|
.setName('add')
|
||||||
.setDescription('Kanal überwachen (Admin).')
|
.setDescription('Kanal überwachen (Admin).')
|
||||||
.addStringOption(option =>
|
.addStringOption(option =>
|
||||||
option.setName('channel')
|
option.setName('streamers')
|
||||||
.setDescription('Der Name des Twitch-Kanals')
|
.setDescription('Twitch-Kanäle (kommagetrennt, z.B. shroud, xQc, ninja)')
|
||||||
.setRequired(true))
|
.setRequired(true))
|
||||||
.addStringOption(option =>
|
.addStringOption(option =>
|
||||||
option.setName('message')
|
option.setName('message')
|
||||||
@@ -28,15 +28,19 @@ const command: Command = {
|
|||||||
.addSubcommand(subcommand =>
|
.addSubcommand(subcommand =>
|
||||||
subcommand
|
subcommand
|
||||||
.setName('remove')
|
.setName('remove')
|
||||||
.setDescription('Kanal aus Überwachung entfernen (Admin).')
|
.setDescription('Streamer aus Überwachung entfernen (Admin).')
|
||||||
.addStringOption(option =>
|
.addStringOption(option =>
|
||||||
option.setName('channel')
|
option.setName('streamers')
|
||||||
.setDescription('Der Name des Twitch-Kanals')
|
.setDescription('Twitch-Kanäle (kommagetrennt, z.B. shroud, xQc, ninja)')
|
||||||
.setRequired(true)))
|
.setRequired(true)))
|
||||||
.addSubcommand(subcommand =>
|
.addSubcommand(subcommand =>
|
||||||
subcommand
|
subcommand
|
||||||
.setName('list')
|
.setName('list')
|
||||||
.setDescription('Listet überwachte Kanäle.'))
|
.setDescription('Listet überwachte Kanäle.'))
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('listall')
|
||||||
|
.setDescription('Listet alle überwachten Kanäle des Servers (Admin).'))
|
||||||
.addSubcommand(subcommand =>
|
.addSubcommand(subcommand =>
|
||||||
subcommand
|
subcommand
|
||||||
.setName('help')
|
.setName('help')
|
||||||
@@ -55,10 +59,11 @@ const command: Command = {
|
|||||||
.setDescription('Überwache Twitch-Streams und bekomme Benachrichtigungen.')
|
.setDescription('Überwache Twitch-Streams und bekomme Benachrichtigungen.')
|
||||||
.addFields(
|
.addFields(
|
||||||
{ name: '`/twitch online <kanal>`', value: 'Prüft, ob ein Kanal gerade online ist.', inline: false },
|
{ name: '`/twitch online <kanal>`', value: 'Prüft, ob ein Kanal gerade online ist.', inline: false },
|
||||||
{ name: '`/twitch add <kanal> [nachricht]`', value: 'Überwacht einen Kanal in diesem Kanal (Mod).\nWenn der Streamer live geht, wird benachrichtigt.', inline: false },
|
{ name: '`/twitch add streamer1, streamer2, ...`', value: 'Überwacht Twitch-Kanäle in diesem Kanal (Mod).', inline: false },
|
||||||
{ name: '`/twitch remove <kanal>`', value: 'Entfernt einen Kanal aus der Überwachung (Mod).', inline: false },
|
{ name: '`/twitch remove streamer1, streamer2, ...`', value: 'Entfernt Twitch-Kanäle (Mod).', inline: false },
|
||||||
{ name: '`/twitch list`', value: 'Zeigt alle überwachten Kanäle in diesem Kanal an.', inline: false },
|
{ name: '`/twitch list`', value: 'Zeigt überwachte Kanäle in diesem Kanal.', inline: false },
|
||||||
{ name: 'Beispiel', value: '`/twitch add shroud Hallo! Shroud ist live!`', inline: false }
|
{ name: '`/twitch listall`', value: 'Zeigt alle überwachten Kanäle des Servers (Mod).', inline: false },
|
||||||
|
{ name: 'Beispiele', value: '`/twitch add shroud, ninja`\n`/twitch add #general shroud, ninja "Live!"`\n`/twitch remove shroud, ninja`', inline: false }
|
||||||
)
|
)
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
@@ -100,7 +105,7 @@ const command: Command = {
|
|||||||
if (subcommand === 'list') {
|
if (subcommand === 'list') {
|
||||||
const monitors: any[] = DB.all('SELECT * FROM twitch_monitors WHERE guild_id = ? AND discord_channel_id = ?', guildId, interaction.channelId);
|
const monitors: any[] = DB.all('SELECT * FROM twitch_monitors WHERE guild_id = ? AND discord_channel_id = ?', guildId, interaction.channelId);
|
||||||
if (monitors.length === 0) {
|
if (monitors.length === 0) {
|
||||||
await interaction.reply('Keine Twitch-Kanäle überwacht.');
|
await interaction.reply({ content: 'Keine Twitch-Kanäle überwacht.', flags: [MessageFlags.Ephemeral] });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,32 +115,143 @@ const command: Command = {
|
|||||||
.setColor(0x6441a5)
|
.setColor(0x6441a5)
|
||||||
.setDescription(list);
|
.setDescription(list);
|
||||||
|
|
||||||
await interaction.reply({ embeds: [embed] });
|
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Admin only
|
if (subcommand === 'listall') {
|
||||||
|
if (!isAdmin) {
|
||||||
|
await interaction.reply({ content: '❌ Keine Berechtigung.', flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const monitors: any[] = DB.all('SELECT * FROM twitch_monitors WHERE guild_id = ? ORDER BY channel_name ASC', guildId);
|
||||||
|
if (monitors.length === 0) {
|
||||||
|
await interaction.reply({ content: 'Keine Twitch-Kanäle überwacht.', flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle('📺 Alle überwachten Twitch-Kanäle')
|
||||||
|
.setColor(0x6441a5)
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
const chunks: string[] = [];
|
||||||
|
const chunkSize = 15;
|
||||||
|
|
||||||
|
for (let i = 0; i < monitors.length; i += chunkSize) {
|
||||||
|
const chunk = monitors.slice(i, i + chunkSize).map((m: any) => {
|
||||||
|
const channel = interaction.guild.channels.cache.get(m.discord_channel_id);
|
||||||
|
const channelName = channel ? channel.name : m.discord_channel_id;
|
||||||
|
return `• **${m.channel_name}** → #${channelName}`;
|
||||||
|
}).join('\n');
|
||||||
|
chunks.push(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
embed.setDescription(chunks[0]);
|
||||||
|
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
|
||||||
|
|
||||||
|
for (let i = 1; i < chunks.length; i++) {
|
||||||
|
const nextEmbed = new EmbedBuilder()
|
||||||
|
.setColor(0x6441a5)
|
||||||
|
.setDescription(chunks[i]);
|
||||||
|
await interaction.followUp({ embeds: [nextEmbed], flags: [MessageFlags.Ephemeral] });
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Admin only for add/remove
|
||||||
if (!isAdmin) {
|
if (!isAdmin) {
|
||||||
await interaction.reply({ content: '❌ Keine Berechtigung.', flags: [MessageFlags.Ephemeral] });
|
await interaction.reply({ content: '❌ Keine Berechtigung.', flags: [MessageFlags.Ephemeral] });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subcommand === 'add') {
|
if (subcommand === 'add') {
|
||||||
const channelName = interaction.options.getString('channel')!.toLowerCase();
|
const discordChannel = interaction.options.getChannel('channel');
|
||||||
|
const streamersInput = interaction.options.getString('streamers')!;
|
||||||
const message = interaction.options.getString('message');
|
const message = interaction.options.getString('message');
|
||||||
const discordChannelId = interaction.channelId;
|
const discordChannelId = interaction.channelId;
|
||||||
|
|
||||||
DB.run(
|
// Parse comma-separated streamers
|
||||||
'INSERT INTO twitch_monitors (guild_id, channel_name, discord_channel_id, custom_message) VALUES (?, ?, ?, ?) ON CONFLICT(guild_id, channel_name) DO UPDATE SET discord_channel_id = ?, custom_message = ?',
|
const streamers = streamersInput
|
||||||
guildId, channelName, discordChannelId, message, discordChannelId, message
|
.split(',')
|
||||||
);
|
.map((s: string) => s.trim().toLowerCase())
|
||||||
await interaction.reply(`✅ Kanal **${channelName}** wird überwacht.`);
|
.filter((s: string) => s.length > 0);
|
||||||
|
|
||||||
|
if (streamers.length === 0) {
|
||||||
|
await interaction.reply({ content: '❌ Keine gültigen Streamer angegeben.', flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = { added: 0, updated: 0, errors: 0 };
|
||||||
|
const errors: string[] = [];
|
||||||
|
|
||||||
|
for (const streamer of streamers) {
|
||||||
|
try {
|
||||||
|
// Check if stream exists
|
||||||
|
const stream = await TwitchManager.fetchStreamData(streamer);
|
||||||
|
if (!stream) {
|
||||||
|
// Streamer might be valid but offline - still add them
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if already exists
|
||||||
|
const existing = DB.get('SELECT id FROM twitch_monitors WHERE guild_id = ? AND channel_name = ?', guildId, streamer);
|
||||||
|
|
||||||
|
DB.run(
|
||||||
|
'INSERT INTO twitch_monitors (guild_id, channel_name, discord_channel_id, custom_message) VALUES (?, ?, ?, ?) ON CONFLICT(guild_id, channel_name) DO UPDATE SET discord_channel_id = ?, custom_message = ?',
|
||||||
|
guildId, streamer, discordChannelId, message, discordChannelId, message
|
||||||
|
);
|
||||||
|
|
||||||
|
if (existing) {
|
||||||
|
results.updated++;
|
||||||
|
} else {
|
||||||
|
results.added++;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
errors.push(streamer);
|
||||||
|
results.errors++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let reply = `✅ **${streamers.length}** Twitch-Kanal/Kanäle für <#${discordChannelId}> konfiguriert.`;
|
||||||
|
if (results.added > 0) reply += `\n🆕 Neu: ${results.added}`;
|
||||||
|
if (results.updated > 0) reply += `\n🔄 Aktualisiert: ${results.updated}`;
|
||||||
|
if (results.errors > 0) reply += `\n❌ Fehler: ${results.errors} (${errors.join(', ')})`;
|
||||||
|
|
||||||
|
await interaction.reply({ content: reply, flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subcommand === 'remove') {
|
if (subcommand === 'remove') {
|
||||||
const channelName = interaction.options.getString('channel')!.toLowerCase();
|
const streamersInput = interaction.options.getString('streamers')!;
|
||||||
DB.run('DELETE FROM twitch_monitors WHERE guild_id = ? AND channel_name = ?', guildId, channelName);
|
const streamers = streamersInput
|
||||||
await interaction.reply(`✅ Kanal **${channelName}** entfernt.`);
|
.split(',')
|
||||||
|
.map((s: string) => s.trim().toLowerCase())
|
||||||
|
.filter((s: string) => s.length > 0);
|
||||||
|
|
||||||
|
if (streamers.length === 0) {
|
||||||
|
await interaction.reply({ content: '❌ Keine gültigen Streamer angegeben.', flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const results = { removed: 0, notFound: 0 };
|
||||||
|
const notFound: string[] = [];
|
||||||
|
|
||||||
|
for (const streamer of streamers) {
|
||||||
|
const result = DB.run('DELETE FROM twitch_monitors WHERE guild_id = ? AND channel_name = ?', guildId, streamer);
|
||||||
|
if (result.changes === 0) {
|
||||||
|
notFound.push(streamer);
|
||||||
|
results.notFound++;
|
||||||
|
} else {
|
||||||
|
results.removed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let reply = '';
|
||||||
|
if (results.removed > 0) reply += `✅ ${results.removed} Streamer entfernt.`;
|
||||||
|
if (results.notFound > 0) reply += `\n❌ Nicht gefunden: ${notFound.join(', ')}`;
|
||||||
|
|
||||||
|
await interaction.reply({ content: reply, flags: [MessageFlags.Ephemeral] });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
158
src/commands/utility/welcome.ts
Normal file
158
src/commands/utility/welcome.ts
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
import { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } from 'discord.js';
|
||||||
|
import { Command } from '../../structures/Command.js';
|
||||||
|
|
||||||
|
const command: Command = {
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName('welcome')
|
||||||
|
.setDescription('Willkommens- und Abschiedsnachrichten verwalten.')
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('setchannel')
|
||||||
|
.setDescription('Kanal für Willkommen/Abschied setzen (Mod).')
|
||||||
|
.addChannelOption(option =>
|
||||||
|
option.setName('channel')
|
||||||
|
.setDescription('Discord-Kanal')
|
||||||
|
.setRequired(true)))
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('add')
|
||||||
|
.setDescription('Nachricht setzen (Mod).')
|
||||||
|
.addStringOption(option =>
|
||||||
|
option.setName('type')
|
||||||
|
.setDescription('Art der Nachricht')
|
||||||
|
.setRequired(true)
|
||||||
|
.addChoices(
|
||||||
|
{ name: 'Willkommen', value: 'welcome' },
|
||||||
|
{ name: 'Abschied', value: 'goodbye' }
|
||||||
|
))
|
||||||
|
.addStringOption(option =>
|
||||||
|
option.setName('message')
|
||||||
|
.setDescription('Die Nachricht. Variablen: {user}, {username}, {server}, {membercount}')
|
||||||
|
.setRequired(true)))
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('remove')
|
||||||
|
.setDescription('Nachricht entfernen (Mod).')
|
||||||
|
.addStringOption(option =>
|
||||||
|
option.setName('type')
|
||||||
|
.setDescription('Art der Nachricht')
|
||||||
|
.setRequired(true)
|
||||||
|
.addChoices(
|
||||||
|
{ name: 'Willkommen', value: 'welcome' },
|
||||||
|
{ name: 'Abschied', value: 'goodbye' }
|
||||||
|
)))
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('list')
|
||||||
|
.setDescription('Aktuelle Einstellungen anzeigen.'))
|
||||||
|
.addSubcommand(subcommand =>
|
||||||
|
subcommand
|
||||||
|
.setName('help')
|
||||||
|
.setDescription('Hilfe zu Welcome-Befehlen.')),
|
||||||
|
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('👋 Welcome Hilfe')
|
||||||
|
.setColor(0x2ecc71)
|
||||||
|
.setDescription('Begrüße neue Mitglieder oder verabschiede dich von ihnen.')
|
||||||
|
.addFields(
|
||||||
|
{ name: '`/welcome setchannel <#kanal>`', value: 'Setzt den Kanal für Willkommen/Abschied (Mod).\nStandard: Discord System-Channel.', inline: false },
|
||||||
|
{ name: '`/welcome add welcome <nachricht>`', value: 'Setzt die Willkommensnachricht (Mod).', inline: false },
|
||||||
|
{ name: '`/welcome add goodbye <nachricht>`', value: 'Setzt die Abschiedsnachricht (Mod).', inline: false },
|
||||||
|
{ name: '`/welcome remove welcome|goodbye`', value: 'Entfernt eine Nachricht (Mod).', inline: false },
|
||||||
|
{ name: '`/welcome list`', value: 'Zeigt aktuelle Einstellungen.', inline: false },
|
||||||
|
{ name: 'Variablen', value: '`{user}` - Nutzer erwähnen\n`{username}` - Nutzername\n`{server}` - Servername\n`{membercount}` - Mitgliederanzahl', inline: false },
|
||||||
|
{ name: 'Beispiel', value: '`/welcome add welcome Willkommen {user} auf {server}! Du bist der {membercount}. Nutzer.`', inline: false }
|
||||||
|
)
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subcommand === 'list') {
|
||||||
|
const settings: any = DB.get('SELECT * FROM guild_settings WHERE guild_id = ?', guildId);
|
||||||
|
|
||||||
|
const channel = settings?.welcome_channel
|
||||||
|
? `<#${settings.welcome_channel}>`
|
||||||
|
: 'Nicht gesetzt';
|
||||||
|
|
||||||
|
const welcomeMsg = settings?.welcome_message || 'Nicht gesetzt';
|
||||||
|
const goodbyeMsg = settings?.goodbye_message || 'Nicht gesetzt';
|
||||||
|
|
||||||
|
const embed = new EmbedBuilder()
|
||||||
|
.setTitle('👋 Welcome Einstellungen')
|
||||||
|
.setColor(0x2ecc71)
|
||||||
|
.setDescription(`Server: **${interaction.guild.name}**`)
|
||||||
|
.addFields(
|
||||||
|
{ name: 'Kanal', value: channel, inline: true },
|
||||||
|
{ name: '👋 Willkommen', value: welcomeMsg, inline: false },
|
||||||
|
{ name: '👋 Abschied', value: goodbyeMsg, inline: false }
|
||||||
|
)
|
||||||
|
.setTimestamp();
|
||||||
|
|
||||||
|
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Admin only for modify 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 welcome_channel = ? WHERE guild_id = ?',
|
||||||
|
channel.id,
|
||||||
|
guildId
|
||||||
|
);
|
||||||
|
|
||||||
|
await interaction.reply({ content: `✅ Kanal für Willkommen/Abschied auf ${channel} gesetzt.`, flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subcommand === 'add') {
|
||||||
|
const type = interaction.options.getString('type') as 'welcome' | 'goodbye';
|
||||||
|
const message = interaction.options.getString('message')!;
|
||||||
|
|
||||||
|
const column = type === 'welcome' ? 'welcome_message' : 'goodbye_message';
|
||||||
|
|
||||||
|
DB.run(
|
||||||
|
`UPDATE guild_settings SET ${column} = ? WHERE guild_id = ?`,
|
||||||
|
message,
|
||||||
|
guildId
|
||||||
|
);
|
||||||
|
|
||||||
|
const label = type === 'welcome' ? 'Willkommensnachricht' : 'Abschiedsnachricht';
|
||||||
|
await interaction.reply({ content: `✅ ${label} gesetzt:\n\`\`\`\n${message}\n\`\`\``, flags: [MessageFlags.Ephemeral] });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (subcommand === 'remove') {
|
||||||
|
const type = interaction.options.getString('type') as 'welcome' | 'goodbye';
|
||||||
|
const column = type === 'welcome' ? 'welcome_message' : 'goodbye_message';
|
||||||
|
|
||||||
|
DB.run(
|
||||||
|
`UPDATE guild_settings SET ${column} = NULL WHERE guild_id = ?`,
|
||||||
|
guildId
|
||||||
|
);
|
||||||
|
|
||||||
|
const label = type === 'welcome' ? 'Willkommensnachricht' : 'Abschiedsnachricht';
|
||||||
|
await interaction.reply({ content: `✅ ${label} entfernt.`, flags: [MessageFlags.Ephemeral] });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default command;
|
||||||
34
src/events/guildMemberAdd.ts
Normal file
34
src/events/guildMemberAdd.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { Events, GuildMember, TextChannel, EmbedBuilder } from 'discord.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: Events.GuildMemberAdd,
|
||||||
|
async execute(member: GuildMember) {
|
||||||
|
const DB = (member.client as any).DB;
|
||||||
|
const guildId = member.guild.id;
|
||||||
|
|
||||||
|
const settings: any = DB.get('SELECT * FROM guild_settings WHERE guild_id = ?', guildId);
|
||||||
|
|
||||||
|
// Use custom channel or fall back to Discord's system channel
|
||||||
|
const channelId = settings?.welcome_channel || member.guild.systemChannelId;
|
||||||
|
if (!channelId || !settings?.welcome_message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = member.guild.channels.cache.get(channelId);
|
||||||
|
if (!channel || !channel.isTextBased()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = settings.welcome_message
|
||||||
|
.replace(/{user}/g, `<@${member.id}>`)
|
||||||
|
.replace(/{username}/g, member.user.username)
|
||||||
|
.replace(/{server}/g, member.guild.name)
|
||||||
|
.replace(/{membercount}/g, member.guild.memberCount.toString());
|
||||||
|
|
||||||
|
try {
|
||||||
|
await (channel as TextChannel).send(message);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[WELCOME] Error sending welcome message:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
34
src/events/guildMemberRemove.ts
Normal file
34
src/events/guildMemberRemove.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { Events, GuildMember, TextChannel, EmbedBuilder } from 'discord.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: Events.GuildMemberRemove,
|
||||||
|
async execute(member: GuildMember) {
|
||||||
|
const DB = (member.client as any).DB;
|
||||||
|
const guildId = member.guild.id;
|
||||||
|
|
||||||
|
const settings: any = DB.get('SELECT * FROM guild_settings WHERE guild_id = ?', guildId);
|
||||||
|
|
||||||
|
// Use custom channel or fall back to Discord's system channel
|
||||||
|
const channelId = settings?.welcome_channel || member.guild.systemChannelId;
|
||||||
|
if (!channelId || !settings?.goodbye_message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const channel = member.guild.channels.cache.get(channelId);
|
||||||
|
if (!channel || !channel.isTextBased()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const message = settings.goodbye_message
|
||||||
|
.replace(/{user}/g, `<@${member.id}>`)
|
||||||
|
.replace(/{username}/g, member.user.username)
|
||||||
|
.replace(/{server}/g, member.guild.name)
|
||||||
|
.replace(/{membercount}/g, member.guild.memberCount.toString());
|
||||||
|
|
||||||
|
try {
|
||||||
|
await (channel as TextChannel).send(message);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[WELCOME] Error sending goodbye message:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -25,6 +25,8 @@ export class DB {
|
|||||||
prefix TEXT DEFAULT '!',
|
prefix TEXT DEFAULT '!',
|
||||||
mod_log_channel TEXT,
|
mod_log_channel TEXT,
|
||||||
welcome_channel TEXT,
|
welcome_channel TEXT,
|
||||||
|
welcome_message TEXT,
|
||||||
|
goodbye_message TEXT,
|
||||||
warn_threshold INTEGER DEFAULT 3,
|
warn_threshold INTEGER DEFAULT 3,
|
||||||
warn_action TEXT DEFAULT 'ban',
|
warn_action TEXT DEFAULT 'ban',
|
||||||
warn_mute_duration INTEGER DEFAULT 1800
|
warn_mute_duration INTEGER DEFAULT 1800
|
||||||
|
|||||||
Reference in New Issue
Block a user