Two feature batches plus a deploy fix: Moderation & engagement: persistent ModCase history (retrofits ban/kick/ mute/timeout/tempban to record cases), /warn, /watch watchlist with automatic alerts on deletions/tickets/automod hits, /case file lookup, achievement badges (/badges, /profile) with message/streak/ticket/ birthday/event/booster triggers, /weekplan RSVP boards, /poll with anonymous mode and scheduled auto-close, /suggest with vote/comment/ decide flow. Branding & growth: /branding (per-guild embed color/logo/footer/bot name/theme, applied across logging/ticket/register/embed-builder embeds and the dashboard sidebar/accent color at runtime), two new /setup server-type presets (Roleplay, Creator), /rules generate (template-based rule sets), /partner apply/list/config with invite validation and showcase posting, alt-account suspicion scoring on join (account age, avatar, name pattern, join bursts, ban-list similarity), /gallery submit with voting and weekly-winner scheduler, invite-attributed join/leave tracking with a new Wachstum dashboard page, and an expanded Admin dashboard (guild list, feature-usage counters). Also fixes production: the Docker container never ran `prisma migrate deploy`, so schema changes never reached the live database. The compose command now applies pending migrations on every start. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
28 lines
1.3 KiB
TypeScript
28 lines
1.3 KiB
TypeScript
import { SlashCommandBuilder, PermissionFlagsBits, ChatInputCommandInteraction } from 'discord.js';
|
|
import { SlashCommand } from '../../utils/types';
|
|
import { context } from '../../config/context';
|
|
|
|
const command: SlashCommand = {
|
|
guildOnly: true,
|
|
data: new SlashCommandBuilder()
|
|
.setName('warn')
|
|
.setDescription('Verwarnt einen Nutzer.')
|
|
.addUserOption((opt) => opt.setName('user').setDescription('Nutzer').setRequired(true))
|
|
.addStringOption((opt) => opt.setName('reason').setDescription('Grund').setRequired(true))
|
|
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers),
|
|
async execute(interaction: ChatInputCommandInteraction) {
|
|
if (!interaction.guild) return;
|
|
const user = interaction.options.getUser('user', true);
|
|
const reason = interaction.options.getString('reason', true);
|
|
|
|
await context.modCases.recordCase(interaction.guild.id, user.id, 'warn', reason, interaction.user.id, interaction.user.tag);
|
|
context.logging.logAction(user, 'Warn', reason, interaction.guild);
|
|
context.watchlist.notifyIfWatched(interaction.guild, user.id, 'Verwarnt', reason);
|
|
await user.send(`Du wurdest auf **${interaction.guild.name}** verwarnt. Grund: ${reason}`).catch(() => undefined);
|
|
|
|
await interaction.reply({ content: `${user.tag} wurde verwarnt. Grund: ${reason}` });
|
|
}
|
|
};
|
|
|
|
export default command;
|