generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model Guild { id String @id createdAt DateTime @default(now()) updatedAt DateTime @updatedAt settings GuildSettings? cases Case[] escalationRules EscalationRule[] autoModConfig AutoModConfig? autoModRules AutoModRule[] loggingConfig LoggingConfig? logChannels LogChannel[] welcomeConfig WelcomeConfig? verificationConfig VerificationConfig? levelingConfig LevelingConfig? memberLevels MemberLevel[] levelRewards LevelReward[] economyConfig EconomyConfig? memberEconomies MemberEconomy[] shopItems ShopItem[] inventoryItems InventoryItem[] polls Poll[] reminders Reminder[] afkStatuses AfkStatus[] giveaways Giveaway[] ticketConfig TicketConfig? ticketCategories TicketCategory[] tickets Ticket[] selfRolePanels SelfRolePanel[] tags Tag[] starboardConfig StarboardConfig? starboardEntries StarboardEntry[] suggestionConfig SuggestionConfig? suggestions Suggestion[] birthdays Birthday[] birthdayConfig BirthdayConfig? tempVoiceConfig TempVoiceConfig? tempVoiceChannels TempVoiceChannel[] statsConfig StatsConfig? inviteStats InviteStat[] inviteJoins InviteJoin[] activityStats ActivityStat[] socialFeeds SocialFeed[] scheduledMessages ScheduledMessage[] guildBackups GuildBackup[] dashboardAccessRules DashboardAccessRule[] dashboardAuditLogs DashboardAuditLog[] commandOverrides CommandOverride[] } model GuildSettings { id String @id @default(cuid()) guildId String @unique locale String @default("de") timezone String @default("Europe/Berlin") moderationEnabled Boolean @default(true) guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model DashboardAccessRule { id String @id @default(cuid()) guildId String roleId String modules Json createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, roleId]) @@index([guildId]) } model DashboardAuditLog { id String @id @default(cuid()) guildId String? actorUserId String action String path String? before Json? after Json? createdAt DateTime @default(now()) guild Guild? @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId, createdAt]) @@index([actorUserId, createdAt]) } model User { id String @id createdAt DateTime @default(now()) warnings Warning[] notes ModNote[] } model Case { id String @id @default(cuid()) caseNumber Int guildId String targetUserId String moderatorId String action String reason String? metadata Json? deletedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) warnings Warning[] moderationNote ModNote[] @@unique([guildId, caseNumber]) @@index([guildId, targetUserId]) } model Warning { id String @id @default(cuid()) guildId String userId String moderatorId String reason String? caseId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) case Case? @relation(fields: [caseId], references: [id], onDelete: SetNull) @@index([guildId, userId]) } model ModNote { id String @id @default(cuid()) guildId String userId String moderatorId String note String caseId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt user User @relation(fields: [userId], references: [id], onDelete: Cascade) case Case? @relation(fields: [caseId], references: [id], onDelete: SetNull) @@index([guildId, userId]) } model EscalationRule { id String @id @default(cuid()) guildId String warnCount Int action String durationMs Int? reason String? enabled Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, warnCount]) @@index([guildId, enabled]) } model AutoModConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(true) antiRaidEnabled Boolean @default(false) antiRaidJoinThreshold Int @default(10) antiRaidWindowSeconds Int @default(10) antiRaidAction String @default("LOCKDOWN") antiNukeEnabled Boolean @default(false) antiNukeBanThreshold Int @default(5) antiNukeChannelThreshold Int @default(3) antiNukeWindowSeconds Int @default(60) lockdownActive Boolean @default(false) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model AutoModRule { id String @id @default(cuid()) guildId String ruleType String enabled Boolean @default(true) action String @default("DELETE") threshold Json? exceptions Json? wordList Json? durationMs Int? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, ruleType]) @@index([guildId, enabled]) } model LoggingConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(true) ignoreBots Boolean @default(true) ignoredChannelIds String[] @default([]) ignoredRoleIds String[] @default([]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model LogChannel { id String @id @default(cuid()) guildId String eventType String channelId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, eventType]) @@index([guildId]) } model WelcomeConfig { id String @id @default(cuid()) guildId String @unique welcomeEnabled Boolean @default(false) leaveEnabled Boolean @default(false) welcomeChannelId String? leaveChannelId String? welcomeType String @default("TEXT") welcomeContent String? welcomeEmbed Json? leaveContent String? leaveEmbed Json? welcomeDmEnabled Boolean @default(false) welcomeDmContent String? userAutoroleIds String[] @default([]) botAutoroleIds String[] @default([]) imageTitle String? imageSubtitle String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model VerificationConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(false) channelId String? verifiedRoleId String? unverifiedRoleId String? mode String @default("BUTTON") minAccountAgeDays Int @default(0) failAction String @default("KICK") panelChannelId String? panelMessageId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model LevelingConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(true) textXpMin Int @default(15) textXpMax Int @default(25) textCooldownSeconds Int @default(60) voiceXpPerMinute Int @default(10) noXpChannelIds String[] @default([]) noXpRoleIds String[] @default([]) roleMultipliers Json? channelMultipliers Json? levelUpMode String @default("CHANNEL") levelUpChannelId String? levelUpMessage String? stackRewards Boolean @default(true) cardAccentColor String @default("#6366F1") cardBackgroundColor String @default("#111827") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model MemberLevel { id String @id @default(cuid()) guildId String userId String xp Int @default(0) level Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, userId]) @@index([guildId, xp]) } model LevelReward { id String @id @default(cuid()) guildId String level Int roleId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, level]) @@index([guildId]) } model EconomyConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(true) currencyName String @default("Coins") currencySymbol String @default("🪙") dailyAmount Int @default(200) weeklyAmount Int @default(1000) workMin Int @default(50) workMax Int @default(150) workCooldownSeconds Int @default(3600) startingBalance Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model MemberEconomy { id String @id @default(cuid()) guildId String userId String balance Int @default(0) lastDailyAt DateTime? lastWeeklyAt DateTime? lastWorkAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, userId]) @@index([guildId, balance]) } model ShopItem { id String @id @default(cuid()) guildId String name String description String? price Int roleId String? stock Int? enabled Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) inventory InventoryItem[] @@index([guildId, enabled]) } model InventoryItem { id String @id @default(cuid()) guildId String userId String itemId String quantity Int @default(1) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) item ShopItem @relation(fields: [itemId], references: [id], onDelete: Cascade) @@unique([guildId, userId, itemId]) @@index([guildId, userId]) } model Poll { id String @id @default(cuid()) guildId String channelId String messageId String? creatorId String question String options Json multiSelect Boolean @default(false) anonymous Boolean @default(false) endsAt DateTime? closedAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) votes PollVote[] @@index([guildId]) } model PollVote { id String @id @default(cuid()) pollId String userId String optionIndex Int createdAt DateTime @default(now()) poll Poll @relation(fields: [pollId], references: [id], onDelete: Cascade) @@unique([pollId, userId, optionIndex]) @@index([pollId]) } model Reminder { id String @id @default(cuid()) guildId String? userId String channelId String content String remindAt DateTime recurringCron String? jobId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild? @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([userId]) @@index([remindAt]) } model AfkStatus { id String @id @default(cuid()) guildId String userId String reason String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, userId]) } model Giveaway { id String @id @default(cuid()) guildId String channelId String messageId String? prize String winnerCount Int @default(1) endsAt DateTime requiredRoleId String? requiredLevel Int? requiredMemberDays Int? paused Boolean @default(false) endedAt DateTime? winners String[] @default([]) entrants String[] @default([]) hostId String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId, endsAt]) } model TicketConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(true) mode String @default("CHANNEL") categoryId String? logChannelId String? transcriptDm Boolean @default(false) inactivityHours Int @default(72) ratingEnabled Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model TicketCategory { id String @id @default(cuid()) guildId String name String description String? emoji String? supportRoleIds String[] @default([]) formFields Json? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) tickets Ticket[] @@unique([guildId, name]) @@index([guildId]) } model Ticket { id String @id @default(cuid()) guildId String categoryId String? openerId String claimedById String? channelId String? threadId String? status String @default("OPEN") priority String @default("NORMAL") subject String? formAnswers Json? transcriptHtml String? rating Int? closedAt DateTime? lastActivityAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) category TicketCategory? @relation(fields: [categoryId], references: [id], onDelete: SetNull) @@index([guildId, status]) @@index([channelId]) } model SelfRolePanel { id String @id @default(cuid()) guildId String channelId String messageId String? title String description String? mode String @default("BUTTONS") behavior String @default("NORMAL") roles Json expiresAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId]) } model Tag { id String @id @default(cuid()) guildId String name String content String? embed Json? responseType String @default("TEXT") triggerWord String? allowedRoleIds String[] @default([]) allowedChannelIds String[] @default([]) createdById String useCount Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, name]) @@index([guildId]) } model StarboardConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(false) channelId String? emoji String @default("⭐") threshold Int @default(3) allowSelfStar Boolean @default(false) ignoredChannelIds String[] @default([]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model StarboardEntry { id String @id @default(cuid()) guildId String sourceChannelId String sourceMessageId String starboardMessageId String starCount Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, sourceMessageId]) @@index([guildId]) } model SuggestionConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(true) openChannelId String? approvedChannelId String? deniedChannelId String? createThread Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model Suggestion { id String @id @default(cuid()) guildId String authorId String content String status String @default("OPEN") messageId String? channelId String? threadId String? upvotes Int @default(0) downvotes Int @default(0) voterUpIds String[] @default([]) voterDownIds String[] @default([]) staffReason String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId, status]) } model BirthdayConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(true) channelId String? roleId String? message String? timezone String @default("Europe/Berlin") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model Birthday { id String @id @default(cuid()) guildId String userId String month Int day Int year Int? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, userId]) @@index([guildId, month, day]) } model TempVoiceConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(false) hubChannelId String? categoryId String? defaultName String @default("{user}'s Channel") defaultLimit Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model TempVoiceChannel { id String @id @default(cuid()) guildId String channelId String @unique ownerId String controlMessageId String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId, ownerId]) } model StatsConfig { id String @id @default(cuid()) guildId String @unique enabled Boolean @default(false) membersChannelId String? onlineChannelId String? boostsChannelId String? membersTemplate String @default("Members: {count}") onlineTemplate String @default("Online: {count}") boostsTemplate String @default("Boosts: {count}") createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) } model InviteStat { id String @id @default(cuid()) guildId String inviterId String code String? joins Int @default(0) leaves Int @default(0) fakes Int @default(0) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, inviterId]) @@index([guildId, joins]) } model InviteJoin { id String @id @default(cuid()) guildId String userId String inviterId String? code String? isFake Boolean @default(false) leftAt DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, userId]) @@index([guildId, inviterId]) } model ActivityStat { id String @id @default(cuid()) guildId String userId String channelId String? messageCount Int @default(0) voiceMinutes Int @default(0) day DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, userId, channelId, day]) @@index([guildId, day]) } model SocialFeed { id String @id @default(cuid()) guildId String type String sourceId String channelId String rolePingId String? template String? lastItemId String? enabled Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId, type]) @@index([enabled]) } model ScheduledMessage { id String @id @default(cuid()) guildId String channelId String creatorId String content String? embed Json? rolePingId String? cron String? runAt DateTime? jobId String? enabled Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId, enabled]) } model GuildBackup { id String @id @default(cuid()) guildId String name String createdById String payload Json createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@index([guildId, createdAt]) } model CommandOverride { id String @id @default(cuid()) guildId String commandName String enabled Boolean @default(true) allowedRoleIds String[] @default([]) deniedRoleIds String[] @default([]) allowedChannelIds String[] @default([]) deniedChannelIds String[] @default([]) cooldownSeconds Int? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade) @@unique([guildId, commandName]) @@index([guildId]) } model OwnerTeamMember { id String @id @default(cuid()) userId String @unique role String note String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model GlobalUserBlacklist { id String @id @default(cuid()) userId String @unique reason String? note String? createdById String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model GuildBlacklist { id String @id @default(cuid()) guildId String @unique reason String? createdById String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model FeatureFlag { id String @id @default(cuid()) key String @unique enabled Boolean @default(false) rolloutPercent Int @default(0) whitelistGuildIds String[] @default([]) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model BotPresenceConfig { id String @id @default("singleton") status String @default("online") activityType String @default("Playing") activityText String @default("nexumi.de") rotatingMessages Json? maintenanceMode Boolean @default(false) maintenanceMessage String? updatedAt DateTime @updatedAt } model ChangelogEntry { id String @id @default(cuid()) version String title String body String publishedAt DateTime @default(now()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model OwnerAuditLog { id String @id @default(cuid()) actorUserId String action String targetType String? targetId String? before Json? after Json? createdAt DateTime @default(now()) @@index([createdAt]) }