Compare commits
2 Commits
0435056271
...
5ee6959662
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ee6959662 | |||
| f17cde44c3 |
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
|
||||
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 '!',
|
||||
mod_log_channel TEXT,
|
||||
welcome_channel TEXT,
|
||||
welcome_message TEXT,
|
||||
goodbye_message TEXT,
|
||||
warn_threshold INTEGER DEFAULT 3,
|
||||
warn_action TEXT DEFAULT 'ban',
|
||||
warn_mute_duration INTEGER DEFAULT 1800
|
||||
|
||||
Reference in New Issue
Block a user