add badges, weekly plans, polls, suggestions, mod-case system, branding, partner system, alt-account detection, gallery, growth tracking
Some checks failed
Deploy Discord Bot / deploy (push) Failing after -1m12s
SonarQube / sonar (push) Successful in 4s

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>
This commit is contained in:
2026-07-03 23:15:35 +02:00
parent 2ff54970e2
commit aa246cd7ea
69 changed files with 21111 additions and 66 deletions

165
node_modules/.prisma/client/edge.js generated vendored

File diff suppressed because one or more lines are too long

View File

@@ -147,6 +147,10 @@ exports.Prisma.GuildSettingsScalarFieldEnum = {
serverStatsConfig: 'serverStatsConfig',
lockdownConfig: 'lockdownConfig',
tasksEnabled: 'tasksEnabled',
badgesEnabled: 'badgesEnabled',
brandingConfig: 'brandingConfig',
partnerConfig: 'partnerConfig',
galleryConfig: 'galleryConfig',
supportRoleId: 'supportRoleId',
updatedAt: 'updatedAt',
createdAt: 'createdAt'
@@ -329,6 +333,145 @@ exports.Prisma.StaffTaskScalarFieldEnum = {
updatedAt: 'updatedAt'
};
exports.Prisma.ModCaseScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
type: 'type',
reason: 'reason',
moderatorId: 'moderatorId',
moderatorTag: 'moderatorTag',
createdAt: 'createdAt'
};
exports.Prisma.WatchlistScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
reason: 'reason',
addedBy: 'addedBy',
addedAt: 'addedAt',
active: 'active'
};
exports.Prisma.UserBadgeScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
badgeKey: 'badgeKey',
awardedAt: 'awardedAt'
};
exports.Prisma.UserActivityScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
messageCount: 'messageCount',
activeDays: 'activeDays',
lastActiveDay: 'lastActiveDay'
};
exports.Prisma.WeeklyPlanScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
title: 'title',
entries: 'entries',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.WeeklyPlanRsvpScalarFieldEnum = {
id: 'id',
planId: 'planId',
entryId: 'entryId',
userId: 'userId',
createdAt: 'createdAt'
};
exports.Prisma.PollScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
question: 'question',
options: 'options',
anonymous: 'anonymous',
closesAt: 'closesAt',
closed: 'closed',
createdBy: 'createdBy',
createdAt: 'createdAt'
};
exports.Prisma.PollVoteScalarFieldEnum = {
id: 'id',
pollId: 'pollId',
userId: 'userId',
optionId: 'optionId',
createdAt: 'createdAt'
};
exports.Prisma.SuggestionScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
userId: 'userId',
userTag: 'userTag',
content: 'content',
status: 'status',
createdAt: 'createdAt'
};
exports.Prisma.SuggestionVoteScalarFieldEnum = {
id: 'id',
suggestionId: 'suggestionId',
userId: 'userId',
value: 'value'
};
exports.Prisma.PartnerRequestScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
userTag: 'userTag',
serverName: 'serverName',
inviteCode: 'inviteCode',
memberCount: 'memberCount',
description: 'description',
status: 'status',
reviewedBy: 'reviewedBy',
createdAt: 'createdAt'
};
exports.Prisma.GalleryPostScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
userId: 'userId',
userTag: 'userTag',
imageUrl: 'imageUrl',
caption: 'caption',
createdAt: 'createdAt'
};
exports.Prisma.GalleryVoteScalarFieldEnum = {
id: 'id',
postId: 'postId',
userId: 'userId'
};
exports.Prisma.GuildGrowthEventScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
type: 'type',
userId: 'userId',
inviteCode: 'inviteCode',
createdAt: 'createdAt'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
@@ -377,7 +520,21 @@ exports.Prisma.ModelName = {
RegisterApplicationAnswer: 'RegisterApplicationAnswer',
RegisterApplicationNote: 'RegisterApplicationNote',
AutomodStrike: 'AutomodStrike',
StaffTask: 'StaffTask'
StaffTask: 'StaffTask',
ModCase: 'ModCase',
Watchlist: 'Watchlist',
UserBadge: 'UserBadge',
UserActivity: 'UserActivity',
WeeklyPlan: 'WeeklyPlan',
WeeklyPlanRsvp: 'WeeklyPlanRsvp',
Poll: 'Poll',
PollVote: 'PollVote',
Suggestion: 'Suggestion',
SuggestionVote: 'SuggestionVote',
PartnerRequest: 'PartnerRequest',
GalleryPost: 'GalleryPost',
GalleryVote: 'GalleryVote',
GuildGrowthEvent: 'GuildGrowthEvent'
};
/**

17714
node_modules/.prisma/client/index.d.ts generated vendored

File diff suppressed because it is too large Load Diff

165
node_modules/.prisma/client/index.js generated vendored

File diff suppressed because one or more lines are too long

159
node_modules/.prisma/client/wasm.js generated vendored
View File

@@ -147,6 +147,10 @@ exports.Prisma.GuildSettingsScalarFieldEnum = {
serverStatsConfig: 'serverStatsConfig',
lockdownConfig: 'lockdownConfig',
tasksEnabled: 'tasksEnabled',
badgesEnabled: 'badgesEnabled',
brandingConfig: 'brandingConfig',
partnerConfig: 'partnerConfig',
galleryConfig: 'galleryConfig',
supportRoleId: 'supportRoleId',
updatedAt: 'updatedAt',
createdAt: 'createdAt'
@@ -329,6 +333,145 @@ exports.Prisma.StaffTaskScalarFieldEnum = {
updatedAt: 'updatedAt'
};
exports.Prisma.ModCaseScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
type: 'type',
reason: 'reason',
moderatorId: 'moderatorId',
moderatorTag: 'moderatorTag',
createdAt: 'createdAt'
};
exports.Prisma.WatchlistScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
reason: 'reason',
addedBy: 'addedBy',
addedAt: 'addedAt',
active: 'active'
};
exports.Prisma.UserBadgeScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
badgeKey: 'badgeKey',
awardedAt: 'awardedAt'
};
exports.Prisma.UserActivityScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
messageCount: 'messageCount',
activeDays: 'activeDays',
lastActiveDay: 'lastActiveDay'
};
exports.Prisma.WeeklyPlanScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
title: 'title',
entries: 'entries',
createdAt: 'createdAt',
updatedAt: 'updatedAt'
};
exports.Prisma.WeeklyPlanRsvpScalarFieldEnum = {
id: 'id',
planId: 'planId',
entryId: 'entryId',
userId: 'userId',
createdAt: 'createdAt'
};
exports.Prisma.PollScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
question: 'question',
options: 'options',
anonymous: 'anonymous',
closesAt: 'closesAt',
closed: 'closed',
createdBy: 'createdBy',
createdAt: 'createdAt'
};
exports.Prisma.PollVoteScalarFieldEnum = {
id: 'id',
pollId: 'pollId',
userId: 'userId',
optionId: 'optionId',
createdAt: 'createdAt'
};
exports.Prisma.SuggestionScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
userId: 'userId',
userTag: 'userTag',
content: 'content',
status: 'status',
createdAt: 'createdAt'
};
exports.Prisma.SuggestionVoteScalarFieldEnum = {
id: 'id',
suggestionId: 'suggestionId',
userId: 'userId',
value: 'value'
};
exports.Prisma.PartnerRequestScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
userId: 'userId',
userTag: 'userTag',
serverName: 'serverName',
inviteCode: 'inviteCode',
memberCount: 'memberCount',
description: 'description',
status: 'status',
reviewedBy: 'reviewedBy',
createdAt: 'createdAt'
};
exports.Prisma.GalleryPostScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
channelId: 'channelId',
messageId: 'messageId',
userId: 'userId',
userTag: 'userTag',
imageUrl: 'imageUrl',
caption: 'caption',
createdAt: 'createdAt'
};
exports.Prisma.GalleryVoteScalarFieldEnum = {
id: 'id',
postId: 'postId',
userId: 'userId'
};
exports.Prisma.GuildGrowthEventScalarFieldEnum = {
id: 'id',
guildId: 'guildId',
type: 'type',
userId: 'userId',
inviteCode: 'inviteCode',
createdAt: 'createdAt'
};
exports.Prisma.SortOrder = {
asc: 'asc',
desc: 'desc'
@@ -377,7 +520,21 @@ exports.Prisma.ModelName = {
RegisterApplicationAnswer: 'RegisterApplicationAnswer',
RegisterApplicationNote: 'RegisterApplicationNote',
AutomodStrike: 'AutomodStrike',
StaffTask: 'StaffTask'
StaffTask: 'StaffTask',
ModCase: 'ModCase',
Watchlist: 'Watchlist',
UserBadge: 'UserBadge',
UserActivity: 'UserActivity',
WeeklyPlan: 'WeeklyPlan',
WeeklyPlanRsvp: 'WeeklyPlanRsvp',
Poll: 'Poll',
PollVote: 'PollVote',
Suggestion: 'Suggestion',
SuggestionVote: 'SuggestionVote',
PartnerRequest: 'PartnerRequest',
GalleryPost: 'GalleryPost',
GalleryVote: 'GalleryVote',
GuildGrowthEvent: 'GuildGrowthEvent'
};
/**