- Added a `cooldownSeconds` field to the `Tag` model, allowing for customizable cooldown periods between tag responses. - Updated tag command handling to incorporate cooldown logic, preventing spam and improving user experience. - Enhanced the WebUI to support cooldown configuration for tags, including input validation and localization for cooldown messages. - Refactored tag-related service functions to manage cooldowns effectively, ensuring accurate tracking and enforcement. - Improved localization for new cooldown-related messages in both English and German.
1002 lines
30 KiB
Plaintext
1002 lines
30 KiB
Plaintext
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?
|
|
verificationRecords VerificationRecord[]
|
|
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[]
|
|
componentMessageBindings ComponentMessageBinding[]
|
|
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)
|
|
/// Snipe/editsnipe storage and commands (SPEC: default off for privacy).
|
|
snipeEnabled Boolean @default(false)
|
|
/// Global command channel whitelist (empty = all channels unless denied).
|
|
commandAllowedChannelIds String[] @default([])
|
|
/// Global command channel blacklist.
|
|
commandDeniedChannelIds String[] @default([])
|
|
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([])
|
|
/// Days to keep Case / dashboard audit rows; 0 = keep forever.
|
|
retentionDays Int @default(90)
|
|
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?
|
|
welcomeComponents Json?
|
|
leaveType String @default("TEXT")
|
|
leaveContent String?
|
|
leaveEmbed Json?
|
|
leaveComponents 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")
|
|
/// MATH | RECAPTCHA_V2 | RECAPTCHA_V3 | HCAPTCHA | TURNSTILE
|
|
captchaProvider String @default("MATH")
|
|
minAccountAgeDays Int @default(0)
|
|
failAction String @default("KICK")
|
|
altDetectionEnabled Boolean @default(false)
|
|
altBlockOnMatch Boolean @default(true)
|
|
altIpWindowDays Int @default(30)
|
|
altInviteWindowHours Int @default(48)
|
|
altMaxAccountsPerInvite Int @default(3)
|
|
panelChannelId String?
|
|
panelMessageId String?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade)
|
|
}
|
|
|
|
/// One row per successful (or blocked-as-alt) verification attempt fingerprint.
|
|
model VerificationRecord {
|
|
id String @id @default(cuid())
|
|
guildId String
|
|
userId String
|
|
inviteCode String?
|
|
inviterId String?
|
|
ipHash String?
|
|
userAgentHash String?
|
|
captchaProvider String?
|
|
flaggedAsAlt Boolean @default(false)
|
|
matchedUserId String?
|
|
createdAt DateTime @default(now())
|
|
guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade)
|
|
|
|
@@unique([guildId, userId])
|
|
@@index([guildId, ipHash, createdAt])
|
|
@@index([guildId, inviteCode, createdAt])
|
|
}
|
|
|
|
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?
|
|
panelChannelId String?
|
|
panelMessageId 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?
|
|
components Json?
|
|
responseType String @default("TEXT")
|
|
triggerWord String?
|
|
cooldownSeconds Int @default(15)
|
|
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?
|
|
components 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 ComponentMessageBinding {
|
|
id String @id @default(cuid())
|
|
guildId String
|
|
channelId String
|
|
messageId String?
|
|
payload Json
|
|
createdById String
|
|
createdAt DateTime @default(now())
|
|
guild Guild @relation(fields: [guildId], references: [id], onDelete: Cascade)
|
|
|
|
@@index([guildId, createdAt])
|
|
@@index([messageId])
|
|
}
|
|
|
|
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("Watching")
|
|
activityText String @default("nexumi.de")
|
|
rotatingMessages Json?
|
|
maintenanceMode Boolean @default(false)
|
|
maintenanceMessage String?
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
/// Global `/about` message (Owner panel). Singleton row id = "singleton".
|
|
model BotAboutConfig {
|
|
id String @id @default("singleton")
|
|
enabled Boolean @default(true)
|
|
/// TEXT | EMBED | COMPONENTS_V2
|
|
messageType String @default("EMBED")
|
|
content String?
|
|
embed Json?
|
|
components Json?
|
|
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])
|
|
}
|
|
|
|
/// Per-tier limits and feature gates (FREE / PREMIUM). Seeded on first use.
|
|
model PremiumTierConfig {
|
|
tier String @id
|
|
maxTags Int
|
|
maxFeeds Int
|
|
maxBackups Int
|
|
/// JSON object of feature key → boolean (tags, feeds, guildbackup, …).
|
|
features Json
|
|
updatedAt DateTime @updatedAt
|
|
}
|
|
|
|
model GuildPremiumAssignment {
|
|
id String @id @default(cuid())
|
|
guildId String @unique
|
|
tier String
|
|
note String?
|
|
assignedById String
|
|
expiresAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([tier])
|
|
}
|
|
|
|
model UserPremiumAssignment {
|
|
id String @id @default(cuid())
|
|
userId String @unique
|
|
tier String
|
|
note String?
|
|
assignedById String
|
|
expiresAt DateTime?
|
|
createdAt DateTime @default(now())
|
|
updatedAt DateTime @updatedAt
|
|
|
|
@@index([tier])
|
|
}
|
|
|
|
model GdprDeletionLog {
|
|
id String @id @default(cuid())
|
|
userId String
|
|
guildId String?
|
|
summary Json?
|
|
createdAt DateTime @default(now())
|
|
|
|
@@index([userId, createdAt])
|
|
}
|
|
|