Added all the new config variables for v4.1.0!

This commit is contained in:
DJj123dj
2025-08-05 10:42:15 +02:00
parent adc2433216
commit 549c161830
18 changed files with 455 additions and 86 deletions
+84 -18
View File
@@ -76,10 +76,12 @@ export interface ODJsonConfig_DefaultStatusType {
enabled:boolean,
/**The type of status (e.g. playing, listening, custom, ...) */
type:Exclude<ODClientActivityType,false>,
/**The mode/status of the bot (e.g. online, invisible, idle, do not disturb) */
mode:ODClientActivityStatus
/**The text for the status. */
text:string,
/**The status of the bot (e.g. online, invisible, idle, do not disturb) */
status:ODClientActivityStatus
/**Additional text for the status. (visible below 'text') */
state:string,
}
/**## ODJsonConfig_DefaultMessageSettingsType `interface`
@@ -131,6 +133,30 @@ export interface ODJsonConfig_DefaultSystemLimits {
userMaximum:number
}
/**## ODJsonConfig_DefaultSystemChannelTopic `interface`
* All global channel topic settings.
*/
export interface ODJsonConfig_DefaultSystemChannelTopic {
/**Show the option name in the channel topic. */
showOptionName:boolean,
/**Show the option description in the channel topic. */
showOptionDescription:boolean,
/**Show the option topic text in the channel topic (configured in the options config). */
showOptionTopic:boolean,
/**Show the current close/reopen status in the channel topic (auto-updated). */
showClosed:boolean,
/**Show the current claim status in the channel topic (auto-updated). */
showClaimed:boolean,
/**Show the current pin status in the channel topic (auto-updated). */
showPinned:boolean,
/**Show the current priority in the channel topic (auto-updated). */
showPriority:boolean,
/**Show the creator of the ticket in the channel topic (auto-updated on transfer). */
showCreator:boolean,
/**Show the first 5 participants of the ticket in the channel topic (auto-updated). */
showParticipants:boolean
}
/**## ODJsonConfig_DefaultSystemPermissions `interface`
* Configure permissions for all Open Ticket commands & actions.
*/
@@ -153,7 +179,10 @@ export interface ODJsonConfig_DefaultSystemPermissions {
stats:ODJsonConfig_DefaultCmdPermissionSettingsType,
clear:ODJsonConfig_DefaultCmdPermissionSettingsType,
autoclose:ODJsonConfig_DefaultCmdPermissionSettingsType,
autodelete:ODJsonConfig_DefaultCmdPermissionSettingsType
autodelete:ODJsonConfig_DefaultCmdPermissionSettingsType,
transfer:ODJsonConfig_DefaultCmdPermissionSettingsType,
topic:ODJsonConfig_DefaultCmdPermissionSettingsType,
priority:ODJsonConfig_DefaultCmdPermissionSettingsType,
}
/**## ODJsonConfig_DefaultSystemMessages `interface`
@@ -171,35 +200,62 @@ export interface ODJsonConfig_DefaultSystemMessages {
renaming:ODJsonConfig_DefaultMessageSettingsType,
moving:ODJsonConfig_DefaultMessageSettingsType,
blacklisting:ODJsonConfig_DefaultMessageSettingsType,
roleAdding:ODJsonConfig_DefaultMessageSettingsType,
roleRemoving:ODJsonConfig_DefaultMessageSettingsType
transferring:ODJsonConfig_DefaultMessageSettingsType,
topicChange:ODJsonConfig_DefaultMessageSettingsType,
priorityChange:ODJsonConfig_DefaultMessageSettingsType,
reactionRole:ODJsonConfig_DefaultMessageSettingsType,
}
/**## ODJsonConfig_DefaultSystem `interface`
* All settings related to the ticket system.
*/
export interface ODJsonConfig_DefaultSystem {
/**Remove all participants (except admins) from the ticket when it's closed. */
removeParticipantsOnClose:boolean,
/**Reply with an ephemeral message when a ticket is created. */
replyOnTicketCreation:boolean,
/**Reply with an ephemeral message when reaction roles are changed. */
replyOnReactionRole:boolean,
/**Use a translated config checker in the console. */
useTranslatedConfigChecker:boolean,
/**Prefer slash-commands over text-commands when displaying them in menu's and messages. */
preferSlashOverText:boolean,
/**Reply with "unknown command" when the prefix is used without a valid command. */
sendErrorOnUnknownCommand:boolean,
/**Display the question fields (in a ticket message) in code blocks. */
questionFieldsInCodeBlock:boolean,
/**Display embed fields together with question fields (in a ticket message). */
displayFieldsWithQuestions:boolean,
/**Show global admins roles together with ticket admins in panel embeds. */
showGlobalAdminsInPanelRoles:boolean,
/**Disable the (✅❌) buttons and directly run the action. */
disableVerifyBars:boolean,
/**Display error embeds/messages with red instead of the default bot color. */
useRedErrorEmbeds:boolean,
/**Always show the reason field in embeds, even when there is no reason provided. */
alwaysShowReason:boolean,
/**The emoji style used in the bot. This will affect all embeds, titles & messages in the bot. */
emojiStyle:"before"|"after"|"double"|"disabled",
/**The emoji used when pinning tickets. This is '📌' by default. */
pinEmoji:string,
/**Reply with an ephemeral message when a ticket is created. */
replyOnTicketCreation:boolean,
/**Reply with an ephemeral message when reaction roles are changed. */
replyOnReactionRole:boolean,
/**Show a warning message before the ticket gets autoclosed. This will happen when only 1/4th of the autoclose time remains. */
showPreAutocloseWarning:boolean,
/**Ask for the priority of this ticket on ticket creation. This will happen in a dropdown in the ticket message. */
askPriorityOnTicketCreation:boolean,
/**Remove all participants (except admins) from the ticket when it's closed. */
removeParticipantsOnClose:boolean,
/**Disable autoclose for a ticket when it has been closed and re-opened. */
disableAutocloseAfterReopen:boolean,
/**Only allow autodelete when the ticket is already closed. */
autodeleteRequiresClosedTicket:boolean,
/**When enabled, only global admins are able to delete a ticket without transcript. */
adminOnlyDeleteWithoutTranscript:boolean,
/**Only allow ticket closing when at least 1 message has been sent by the creator. (admins are able to bypass) */
allowCloseBeforeMessage:boolean,
/**Only allow ticket closing when at least 1 message has been sent by a global or ticket admin. (admins are able to bypass) */
allowCloseBeforeAdminMessage:boolean,
/**Use a translated config checker in the console. */
useTranslatedConfigChecker:boolean,
/**Pin the (first) ticket message in the channel. This simulates old behaviour like Open Ticket v1, v2 & v3. */
pinFirstTicketMessage:boolean,
/**Enable/disable the ticket claim & unclaim button in the ticket message. */
enableTicketClaimButtons:boolean,
/**Enable/disable the ticket close & re-open button in the ticket message. */
@@ -219,6 +275,9 @@ export interface ODJsonConfig_DefaultSystem {
/**All settings related to global ticket limits. */
limits:ODJsonConfig_DefaultSystemLimits,
/**All global channel topic settings. */
channelTopic:ODJsonConfig_DefaultSystemChannelTopic,
/**Configure permissions for all Open Ticket commands & actions. */
permissions:ODJsonConfig_DefaultSystemPermissions,
@@ -366,8 +425,8 @@ export interface ODJsonConfig_DefaultOptionTicketChannelType {
/**The category to move the ticket to when claimed by this user. */
category:string
}[],
/**The channel description/topic shown at the top of the channel in discord. */
description:string
/**The channel topic shown at the top of the channel in discord. */
topic:string
}
/**## ODJsonConfig_DefaultOptionTicketType `interface`
@@ -428,14 +487,14 @@ export interface ODJsonConfig_DefaultOptionTicketType extends ODJsonConfig_Defau
/**Disable autodeleting when the ticket is claimed by someone. */
disableOnClaim:boolean
},
/**All settings related to the cooldown of this ticket type */
/**All settings related to the cooldown of this ticket type. */
cooldown:{
/**Enable cooldown (per user) */
enabled:boolean,
/**The amount of minutes a user needs to wait before being able to create a ticket again. */
cooldownMinutes:number
},
/**All settings related to the limits of this ticket type */
/**All settings related to the limits of this ticket type. */
limits:{
/**Enable option ticket limits. */
enabled:boolean,
@@ -443,6 +502,13 @@ export interface ODJsonConfig_DefaultOptionTicketType extends ODJsonConfig_Defau
globalMaximum:number,
/**The maximum amount of tickets of this type that a user is allowed to create at the same time. */
userMaximum:number
},
/**All settings related to the slow mode of this ticket type. */
slowMode:{
/**Enable channel slow mode. */
enabled:boolean,
/**The amount of seconds users need to wait between sending messages. */
slowModeSeconds:number
}
}
+4 -1
View File
@@ -156,7 +156,7 @@ export interface ODTicketOptionIds {
"opendiscord:channel-category-closed":ODOptionData<string>,
"opendiscord:channel-category-backup":ODOptionData<string>,
"opendiscord:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>,
"opendiscord:channel-description":ODOptionData<string>,
"opendiscord:channel-topic":ODOptionData<string>,
"opendiscord:dm-message-enabled":ODOptionData<boolean>,
"opendiscord:dm-message-text":ODOptionData<string>,
@@ -183,6 +183,9 @@ export interface ODTicketOptionIds {
"opendiscord:limits-enabled":ODOptionData<boolean>,
"opendiscord:limits-maximum-global":ODOptionData<number>,
"opendiscord:limits-maximum-user":ODOptionData<number>
"opendiscord:slowmode-enabled":ODOptionData<boolean>,
"opendiscord:slowmode-seconds":ODOptionData<number>,
}
/**## ODTicketOption `class`
+8
View File
@@ -158,6 +158,7 @@ export interface ODTicketIds {
"opendiscord:ticket-message":ODTicketData<string|null>,
"opendiscord:participants":ODTicketData<{type:"role"|"user",id:string}[]>,
"opendiscord:channel-suffix":ODTicketData<string>,
"opendiscord:previous-creators":ODTicketData<string[]>,
"opendiscord:open":ODTicketData<boolean>,
"opendiscord:opened-by":ODTicketData<string|null>,
@@ -165,6 +166,9 @@ export interface ODTicketIds {
"opendiscord:closed":ODTicketData<boolean>,
"opendiscord:closed-by":ODTicketData<string|null>,
"opendiscord:closed-on":ODTicketData<number|null>,
"opendiscord:reopened":ODTicketData<boolean>,
"opendiscord:reopened-by":ODTicketData<string|null>,
"opendiscord:reopened-on":ODTicketData<number|null>,
"opendiscord:claimed":ODTicketData<boolean>,
"opendiscord:claimed-by":ODTicketData<string|null>,
"opendiscord:claimed-on":ODTicketData<number|null>,
@@ -183,6 +187,10 @@ export interface ODTicketIds {
"opendiscord:autodelete-days":ODTicketData<number>,
"opendiscord:answers":ODTicketData<{id:string,name:string,type:"short"|"paragraph",value:string|null}[]>,
"opendiscord:priority":ODTicketData<number>,
"opendiscord:topic":ODTicketData<string>,
"opendiscord:message-sent":ODTicketData<boolean>,
"opendiscord:admin-message-sent":ODTicketData<boolean>,
}
/**## ODTicket `class`
+48 -14
View File
@@ -457,11 +457,11 @@ async function renderQuickSetupStatusType(backFn:() => api.ODPromiseVoid){
}).promise
if (answer.canceled) return await backFn()
else if (answer.selectedIndex == 0) quickSetupStorage.status = {enabled:false,status:"online",type:"custom",text:""}
else if (answer.selectedIndex == 1) quickSetupStorage.status = {enabled:true,status:"online",type:"custom",text:""}
else if (answer.selectedIndex == 2) quickSetupStorage.status = {enabled:true,status:"online",type:"listening",text:""}
else if (answer.selectedIndex == 3) quickSetupStorage.status = {enabled:true,status:"online",type:"watching",text:""}
else if (answer.selectedIndex == 4) quickSetupStorage.status = {enabled:true,status:"online",type:"playing",text:""}
else if (answer.selectedIndex == 0) quickSetupStorage.status = {enabled:false,mode:"online",type:"custom",text:"",state:""}
else if (answer.selectedIndex == 1) quickSetupStorage.status = {enabled:true,mode:"online",type:"custom",text:"",state:""}
else if (answer.selectedIndex == 2) quickSetupStorage.status = {enabled:true,mode:"online",type:"listening",text:"",state:""}
else if (answer.selectedIndex == 3) quickSetupStorage.status = {enabled:true,mode:"online",type:"watching",text:"",state:""}
else if (answer.selectedIndex == 4) quickSetupStorage.status = {enabled:true,mode:"online",type:"playing",text:"",state:""}
if (answer.selectedIndex == 0) return await renderQuickSetupLogs(async () => {await renderQuickSetupStatusType(backFn)})
else return await renderQuickSetupStatusText(async () => {await renderQuickSetupStatusType(backFn)})
@@ -1223,19 +1223,32 @@ async function saveQuickSetupConfig(){
slashCommands:quickSetupStorage.slashCommands ?? false,
textCommands:quickSetupStorage.textCommands ?? false,
status:quickSetupStorage.status ?? {enabled:false,status:"online",text:"",type:"custom"},
status:quickSetupStorage.status ?? {enabled:false,mode:"online",type:"custom",text:"",state:""},
system:{
removeParticipantsOnClose:quickSetupStorage.removeParticipantsOnClose ?? false,
replyOnTicketCreation:false,
replyOnReactionRole:true,
useTranslatedConfigChecker:true,
preferSlashOverText:quickSetupStorage.slashCommands ?? false,
sendErrorOnUnknownCommand:true,
questionFieldsInCodeBlock:true,
displayFieldsWithQuestions:false,
showGlobalAdminsInPanelRoles:false,
disableVerifyBars:false,
useRedErrorEmbeds:true,
alwaysShowReason:false,
emojiStyle:quickSetupStorage.emojiStyle ?? "before",
pinEmoji:"📌",
replyOnTicketCreation:false,
replyOnReactionRole:true,
showPreAutocloseWarning:false,
askPriorityOnTicketCreation:false,
removeParticipantsOnClose:quickSetupStorage.removeParticipantsOnClose ?? false,
disableAutocloseAfterReopen:true,
autodeleteRequiresClosedTicket:true,
adminOnlyDeleteWithoutTranscript:true,
allowCloseBeforeMessage:false,
allowCloseBeforeAdminMessage:true,
useTranslatedConfigChecker:true,
pinFirstTicketMessage:false,
enableTicketClaimButtons:true,
enableTicketCloseButtons:true,
@@ -1254,6 +1267,18 @@ async function saveQuickSetupConfig(){
globalMaximum:100,
userMaximum:quickSetupStorage.globalUserLimit ?? 3
},
channelTopic:{
showOptionName:true,
showOptionDescription:false,
showOptionTopic:true,
showClosed:true,
showClaimed:false,
showPinned:false,
showPriority:false,
showCreator:false,
showParticipants:false
},
permissions:{
help:"everyone",
@@ -1274,7 +1299,10 @@ async function saveQuickSetupConfig(){
stats:"everyone",
clear:"admin",
autoclose:"admin",
autodelete:"admin"
autodelete:"admin",
transfer:"admin",
topic:"admin",
priority:"admin",
},
messages:{
@@ -1289,8 +1317,10 @@ async function saveQuickSetupConfig(){
renaming:{dm:false,logs:true},
moving:{dm:true,logs:true},
blacklisting:{dm:true,logs:true},
roleAdding:{dm:false,logs:true},
roleRemoving:{dm:false,logs:true}
transferring:{dm:true,logs:true},
topicChange:{dm:false,logs:true},
priorityChange:{dm:false,logs:true},
reactionRole:{dm:false,logs:true}
}
}
}
@@ -1360,7 +1390,7 @@ async function saveQuickSetupConfig(){
closedCategory:"",
backupCategory:"",
claimedCategory:[],
description:ticket.description
topic:ticket.description
},
dmMessage:{
@@ -1418,6 +1448,10 @@ async function saveQuickSetupConfig(){
enabled:false,
globalMaximum:20,
userMaximum:3
},
slowMode:{
enabled:false,
slowModeSeconds:20
}
}
})
+4 -2
View File
@@ -147,7 +147,8 @@ export class ODVersionMigration {
try{
await this.#func()
return true
}catch{
}catch(err){
process.emit("uncaughtException",err)
return false
}
}
@@ -156,7 +157,8 @@ export class ODVersionMigration {
try{
await this.#afterInitFunc()
return true
}catch{
}catch(err){
process.emit("uncaughtException",err)
return false
}
}
+29
View File
@@ -1,4 +1,5 @@
import {opendiscord, api, utilities} from "../../index"
import fs from "fs"
/**Check if migration is required. Returns the last version used in the database. */
async function isMigrationRequired(): Promise<false|api.ODVersion> {
@@ -81,6 +82,22 @@ async function unloadMigrationContext(){
opendiscord.debug.debug("-- MIGRATION CONTEXT END --")
}
/**Create a backup of the (dev)config & database before migrating. */
function createMigrationBackup(){
if (fs.existsSync("./.backup/")) fs.rmSync("./.backup/",{force:true,recursive:true})
fs.mkdirSync("./.backup/")
const devconfigFlag = opendiscord.flags.get("opendiscord:dev-config")
const isDevConfig = devconfigFlag ? devconfigFlag.value : false
const devDatabaseFlag = opendiscord.flags.get("opendiscord:dev-database")
const isDevDatabase = devDatabaseFlag ? devDatabaseFlag.value : false
if (isDevConfig) fs.cpSync("./devconfig/","./.backup/devconfig/",{force:true,recursive:true})
else fs.cpSync("./config/","./.backup/config/",{force:true,recursive:true})
if (isDevDatabase) fs.cpSync("./devdatabase/","./.backup/devdatabase/",{force:true,recursive:true})
else fs.cpSync("./database/","./.backup/database/",{force:true,recursive:true})
}
/**Execute all version migration functions which are handled in the restricted migration context. */
async function loadAllVersionMigrations(lastVersion:api.ODVersion){
const migrations = (await import("./migration.js")).migrations
@@ -90,6 +107,11 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
else if (comparison == "higher") return 1
else return -1
})
if (migrations.length > 0){
//create backup of config & database
createMigrationBackup()
}
for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrate()
@@ -97,6 +119,7 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
{key:"success",value:success ? "true" : "false"},
{key:"afterInit",value:"false"}
])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
}
}
}
@@ -110,6 +133,11 @@ export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersio
else if (comparison == "higher") return 1
else return -1
})
if (migrations.length > 0){
//create backup of config & database
createMigrationBackup()
}
for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrateAfterInit()
@@ -117,6 +145,7 @@ export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersio
{key:"success",value:success ? "true" : "false"},
{key:"afterInit",value:"true"}
])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
}
}
}
+105 -1
View File
@@ -31,5 +31,109 @@ export const migrations = [
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),async () => {},async () => {}),
//MIGRATE TO v4.0.7
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),async () => {},async () => {})
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),async () => {},async () => {}),
//MIGRATE TO v4.1.0
new utilities.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.0"),async () => {},async () => {
//AFTER INIT MIGRATION
//migrate config
const generalConfig = opendiscord.configs.get("opendiscord:general")
const optionConfig = opendiscord.configs.get("opendiscord:options")
if (!generalConfig.data.status.state){
//only migrate config when it hasn't been done manually by the user.
if (!generalConfig.data._INFO) throw new api.ODSystemError("Couldn't find general.json '_INFO' category.")
generalConfig.data._INFO.version = "open-ticket-v4.1.0"
if (!generalConfig.data.status) throw new api.ODSystemError("Couldn't find general.json 'status' category.")
generalConfig.data.status.mode = generalConfig.data.status["status"] ?? "online"
generalConfig.data.status.state = ""
delete generalConfig.data.status["status"]
if (!generalConfig.data.system) throw new api.ODSystemError("Couldn't find general.json 'system' category.")
generalConfig.data.system.displayFieldsWithQuestions = false
generalConfig.data.system.showGlobalAdminsInPanelRoles = false
generalConfig.data.system.alwaysShowReason = false
generalConfig.data.system.pinEmoji = "📌"
generalConfig.data.system.showPreAutocloseWarning = false
generalConfig.data.system.askPriorityOnTicketCreation = false
generalConfig.data.system.disableAutocloseAfterReopen = true
generalConfig.data.system.autodeleteRequiresClosedTicket = true
generalConfig.data.system.adminOnlyDeleteWithoutTranscript = true
generalConfig.data.system.allowCloseBeforeMessage = false
generalConfig.data.system.allowCloseBeforeAdminMessage = true
generalConfig.data.system.pinFirstTicketMessage = false
generalConfig.data.system.channelTopic = {
showOptionName:true,
showOptionDescription:false,
showOptionTopic:true,
showClosed:true,
showClaimed:false,
showPinned:false,
showPriority:false,
showCreator:false,
showParticipants:false
}
if (!generalConfig.data.system.permissions) throw new api.ODSystemError("Couldn't find general.json 'system.permissions' category.")
generalConfig.data.system.permissions.transfer = "admin"
generalConfig.data.system.permissions.topic = "admin"
generalConfig.data.system.permissions.priority = "admin"
if (!generalConfig.data.system.messages) throw new api.ODSystemError("Couldn't find general.json 'system.messages' category.")
generalConfig.data.system.messages.transferring = {dm:false,logs:true}
generalConfig.data.system.messages.topicChange = {dm:false,logs:true}
generalConfig.data.system.messages.priorityChange = {dm:false,logs:true}
generalConfig.data.system.messages.reactionRole = generalConfig.data.system.messages["roleAdding"] ?? {dm:false,logs:true}
delete generalConfig.data.system.messages["roleAdding"]
delete generalConfig.data.system.messages["roleRemoving"]
for (const option of optionConfig.data){
if (option.type != "ticket") continue
option.channel.topic = option.channel["description"] ?? ""
delete option.channel["description"]
option.slowMode = {
enabled:false,
slowModeSeconds:20
}
}
await generalConfig.save()
await optionConfig.save()
}
//migrate database
const optionDatabase = opendiscord.databases.get("opendiscord:options")
const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
for (const option of (await optionDatabase.getCategory("opendiscord:used-option") ?? [])){
const optionData = option.value
const topicData = optionData.data.find((d) => d.id == "opendiscord:channel-description")
if (topicData) topicData.id = "opendiscord:channel-topic"
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-enabled")) optionData.data.push({id:"opendiscord:slowmode-enabled",value:false})
if (!optionData.data.find((d) => d.id == "opendiscord:slowmode-seconds")) optionData.data.push({id:"opendiscord:slowmode-seconds",value:20})
optionDatabase.set("opendiscord:used-option",option.key,optionData)
}
for (const ticket of (await ticketDatabase.getCategory("opendiscord:ticket") ?? [])){
const ticketData = ticket.value
if (!ticketData.data.find((d) => d.id == "opendiscord:previous-creators")) ticketData.data.push({id:"opendiscord:previous-creators",value:[]})
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened")) ticketData.data.push({id:"opendiscord:reopened",value:false})
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-by")) ticketData.data.push({id:"opendiscord:reopened-by",value:null})
if (!ticketData.data.find((d) => d.id == "opendiscord:reopened-on")) ticketData.data.push({id:"opendiscord:reopened-on",value:null})
if (!ticketData.data.find((d) => d.id == "opendiscord:priority")) ticketData.data.push({id:"opendiscord:priority",value:-1})
if (!ticketData.data.find((d) => d.id == "opendiscord:topic")) ticketData.data.push({id:"opendiscord:topic",value:""})
if (!ticketData.data.find((d) => d.id == "opendiscord:message-sent")) ticketData.data.push({id:"opendiscord:message-sent",value:true})
if (!ticketData.data.find((d) => d.id == "opendiscord:admin-message-sent")) ticketData.data.push({id:"opendiscord:admin-message-sent",value:true})
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
}
})
]