add permission scanner, info panels, image QR scan, invite tracker, ticket templates

Five new features:
- /permissions scan: audits admin/ban roles, dangerous bot permissions,
  public channels, empty/duplicate/useless roles, too-many-admins warning.
- /panel create: fixed info panels (rules/support/bewerbung/partner/
  rollen/events/faq) with buttons wired into the existing ticket/
  register/partner flows, FAQ panels get a question dropdown.
- Image moderation: QR-code detection in message attachments via jimp+jsqr
  (pure JS, no native build deps) with a small scam-pattern check; opt-in
  toggle in dashboard settings since decoding costs per-message.
- Invite tracker extension: now resolves the inviter (not just the code),
  tracks suspicious joins per invite, and the dashboard growth page gets
  an invite breakdown + recent-joins table.
- Ticket categories: /ticketconfig lets each ticket topic get its own
  ping role and a modal question template shown before the channel is
  created; topics without config behave exactly as before.

Also fixes two rough edges found along the way: the welcome embed had
no way to attach an image despite the backend already supporting it
(added URL/file-upload fields + live preview), and Reaction Roles
required typing raw role IDs into a textarea (replaced with a proper
role picker). Incidentally repairs node_modules/.bin symlinks that were
committed as literal broken shell-script text instead of real symlinks.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-04 00:46:23 +02:00
parent 54376fdad7
commit 9943254aa4
49 changed files with 3992 additions and 339 deletions

View File

@@ -151,6 +151,8 @@ exports.Prisma.GuildSettingsScalarFieldEnum = {
brandingConfig: 'brandingConfig',
partnerConfig: 'partnerConfig',
galleryConfig: 'galleryConfig',
imageModerationConfig: 'imageModerationConfig',
ticketConfig: 'ticketConfig',
supportRoleId: 'supportRoleId',
updatedAt: 'updatedAt',
createdAt: 'createdAt'
@@ -469,6 +471,20 @@ exports.Prisma.GuildGrowthEventScalarFieldEnum = {
type: 'type',
userId: 'userId',
inviteCode: 'inviteCode',
inviterId: 'inviterId',
suspicious: 'suspicious',
createdAt: 'createdAt'
};
exports.Prisma.InfoPanelScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
type: 'type',
title: 'title',
description: 'description',
items: 'items',
createdAt: 'createdAt'
};
@@ -534,7 +550,8 @@ exports.Prisma.ModelName = {
PartnerRequest: 'PartnerRequest',
GalleryPost: 'GalleryPost',
GalleryVote: 'GalleryVote',
GuildGrowthEvent: 'GuildGrowthEvent'
GuildGrowthEvent: 'GuildGrowthEvent',
InfoPanel: 'InfoPanel'
};
/**