Open Ticket v4.2: Config Update (JSONC)

This commit is contained in:
DJj123dj
2026-05-17 22:28:23 +02:00
parent afd7f80b8d
commit dd8d5a12d6
106 changed files with 2199 additions and 1198 deletions
+2 -2
View File
@@ -49,14 +49,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.adding.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.adding.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"add",reason,additionalData:data}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.adding.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"add",reason,additionalData:data}))
if (creator && generalConfig.data.logs.logMessages.adding.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"add",reason,additionalData:data}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params
+5 -3
View File
@@ -46,8 +46,9 @@ export async function registerActions(){
const {guild,user,channel,option,ticket,currentCategoryId} = params
if (!ticket) return
if (!ticket.get("opendiscord:closed").value) return
if (!generalConfig.data.ticketSystem.closedCategory.enabled) return
const closeCategoryId = option.get("opendiscord:channel-category-closed").value
const closeCategoryId = generalConfig.data.ticketSystem.closedCategory.categoryId
if (!closeCategoryId) return
const closeCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,closeCategoryId)
if (closeCategory){
@@ -74,7 +75,7 @@ export async function registerActions(){
if (!ticket) return
if (!ticket.get("opendiscord:claimed").value) return
const claimedCategoryIds = option.get("opendiscord:channel-categories-claimed").value
const claimedCategoryIds = generalConfig.data.ticketSystem.claimedCategories
const claimCategoryId = claimedCategoryIds.find((c) => c.user == user.id)?.category
if (!claimCategoryId) return
const claimCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,claimCategoryId)
@@ -101,8 +102,9 @@ export async function registerActions(){
const {guild,user,channel,option,ticket,currentCategoryId} = params
if (!instance.newCategory || !instance.newCategoryId || !instance.shouldChangeCategory) return
if (instance.newCategory.children.cache.size < 50) return
if (!generalConfig.data.ticketSystem.backupCategory.enabled) return
const backupCategoryId = option.get("opendiscord:channel-category-backup").value
const backupCategoryId = generalConfig.data.ticketSystem.backupCategory.categoryId
if (!backupCategoryId) return
const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,backupCategoryId)
if (backupCategory){
+1 -1
View File
@@ -19,7 +19,7 @@ export async function registerActions(){
const baseChannelName = (channelRenamed) ? channelRenamed : channelPrefix+channelSuffix
//calculate status emojis
const pinEmoji = (ticket && ticket.get("opendiscord:pinned").value) ? generalConfig.data.system.pinEmoji : ""
const pinEmoji = (ticket && ticket.get("opendiscord:pinned").value) ? generalConfig.data.ticketSystem.pinEmoji : ""
const priorityEmoji = (ticket) ? (opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? "") : ""
instance.newChannelName = pinEmoji+priorityEmoji+baseChannelName
+2 -2
View File
@@ -73,14 +73,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.claiming.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null}))
if (creator && generalConfig.data.logs.logMessages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+1 -1
View File
@@ -47,7 +47,7 @@ export async function registerActions(){
const {guild,channel,user,filter,list} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.deleting.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:clear-logs").build(origin,{guild,channel,user,filter,list:instance.list ?? []}))
}
+3 -3
View File
@@ -99,7 +99,7 @@ export async function registerActions(){
ticket.get("opendiscord:participants").value.forEach((participant) => {
//all participants that aren't roles/admins => readonly (OR non-viewable when enabled)
if (participant.type == "user"){
if (generalConfig.data.system.removeParticipantsOnClose) permissions.push({
if (generalConfig.data.ticketSystem.removeParticipantsOnClose) permissions.push({
type:discord.OverwriteType.Member,
id:participant.id,
allow:[],
@@ -138,14 +138,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.closing.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.closing.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"close",reason,additionalData:null}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.closing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"close",reason,additionalData:null}))
if (creator && generalConfig.data.logs.logMessages.closing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"close",reason,additionalData:null}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+12 -12
View File
@@ -91,15 +91,15 @@ export async function registerActions(){
//handle channel topic
const channelTopics: string[] = []
if (generalConfig.data.system.channelTopic.showOptionName) channelTopics.push(option.get("opendiscord:name").value)
if (generalConfig.data.system.channelTopic.showOptionDescription) channelTopics.push(option.get("opendiscord:description").value)
if (generalConfig.data.system.channelTopic.showOptionTopic) channelTopics.push(channelTopicText)
if (generalConfig.data.system.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.get("opendiscord:none").renderDisplayName())
if (generalConfig.data.system.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+lang.getTranslation("params.uppercase.open"))
if (generalConfig.data.system.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+lang.getTranslation("params.uppercase.noone"))
if (generalConfig.data.system.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+lang.getTranslation("params.uppercase.no"))
if (generalConfig.data.system.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(user.id))
if (generalConfig.data.system.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+participants.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", "))
if (generalConfig.data.ticketSystem.channelTopic.showOptionName) channelTopics.push(option.get("opendiscord:name").value)
if (generalConfig.data.ticketSystem.channelTopic.showOptionDescription) channelTopics.push(option.get("opendiscord:description").value)
if (generalConfig.data.ticketSystem.channelTopic.showOptionTopic) channelTopics.push(channelTopicText)
if (generalConfig.data.ticketSystem.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.get("opendiscord:none").renderDisplayName())
if (generalConfig.data.ticketSystem.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+lang.getTranslation("params.uppercase.open"))
if (generalConfig.data.ticketSystem.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+lang.getTranslation("params.uppercase.noone"))
if (generalConfig.data.ticketSystem.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+lang.getTranslation("params.uppercase.no"))
if (generalConfig.data.ticketSystem.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(user.id))
if (generalConfig.data.ticketSystem.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+participants.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", "))
//create channel
const channel = await guild.channels.create({
@@ -192,7 +192,7 @@ export async function registerActions(){
ticket.get("opendiscord:ticket-message").value = ticketMsg.id
//pin ticket message (if required)
if (generalConfig.data.system.pinFirstTicketMessage && ticketMsg.pinnable) await ticketMsg.pin("Ticket Message")
if (generalConfig.data.ticketSystem.pinFirstTicketMessage && ticketMsg.pinnable) await ticketMsg.pin("Ticket Message")
//manage stats
await opendiscord.statistics.get("opendiscord:ticket").setStat("opendiscord:messages-sent",ticket.id.value,1,"increase")
@@ -212,13 +212,13 @@ export async function registerActions(){
if (!ticket || !channel) return opendiscord.log("Ticket Creation Error: Unable to send ticket message. Previous worker failed!","error")
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.creation.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.creation.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-logs").build(origin,{guild,channel,user,ticket}))
}
//to dm
if (generalConfig.data.system.messages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-dm").build(origin,{guild,channel,user,ticket}))
if (generalConfig.data.logs.logMessages.creation.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:ticket-created-dm").build(origin,{guild,channel,user,ticket}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
+3 -3
View File
@@ -38,14 +38,14 @@ export async function registerActions(){
}),
new api.ODWorker("opendiscord:check-global-limits",2,(instance,params,origin,cancel) => {
const generalConfig = opendiscord.configs.get("opendiscord:general")
if (!generalConfig.data.system.limits.enabled) return
if (!generalConfig.data.ticketSystem.limits.enabled) return
const allTickets = opendiscord.tickets.getAll()
const globalTicketCount = allTickets.length
const userTickets = opendiscord.tickets.getFiltered((ticket) => ticket.exists("opendiscord:opened-by") && (ticket.get("opendiscord:opened-by").value == params.user.id))
const userTicketCount = userTickets.length
if (globalTicketCount >= generalConfig.data.system.limits.globalMaximum){
if (globalTicketCount >= generalConfig.data.ticketSystem.limits.globalMaximum){
instance.valid = false
instance.reason = "global-limit"
opendiscord.log(params.user.displayName+" tried to create a ticket but reached the limit!","info",[
@@ -55,7 +55,7 @@ export async function registerActions(){
{key:"limit",value:"global"}
])
return cancel()
}else if (userTicketCount >= generalConfig.data.system.limits.userMaximum){
}else if (userTicketCount >= generalConfig.data.ticketSystem.limits.userMaximum){
instance.valid = false
instance.reason = "global-user-limit"
opendiscord.log(params.user.displayName+" tried to create a ticket, but reached the limit!","info",[
+2 -2
View File
@@ -60,14 +60,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.deleting.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.deleting.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.deleting.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null}))
if (creator && generalConfig.data.logs.logMessages.deleting.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null}))
}),
new api.ODWorker("opendiscord:delete-channel",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
+2 -2
View File
@@ -140,14 +140,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.moving.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.moving.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"move",reason,additionalData:data}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.moving.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"move",reason,additionalData:data}))
if (creator && generalConfig.data.logs.logMessages.moving.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"move",reason,additionalData:data}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -73,14 +73,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.pinning.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null}))
if (creator && generalConfig.data.logs.logMessages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -88,13 +88,13 @@ export async function registerActions(){
if (!instance.role || !instance.result) return
//to logs
if (generalConfig.data.system.logs.enabled && (generalConfig.data.system.messages.reactionRole.logs)){
if (generalConfig.data.logs.enabled && (generalConfig.data.logs.logMessages.reactionRole.logs)){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-logs").build(origin,{guild,user,role:instance.role,result:instance.result}))
}
//to dm
if (generalConfig.data.system.messages.reactionRole.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-dm").build(origin,{guild,user,role:instance.role,result:instance.result}))
if (generalConfig.data.logs.logMessages.reactionRole.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:reaction-role-dm").build(origin,{guild,user,role:instance.role,result:instance.result}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,option} = params
+2 -2
View File
@@ -44,14 +44,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.removing.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.removing.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.removing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data}))
if (creator && generalConfig.data.logs.logMessages.removing.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params
+2 -2
View File
@@ -52,14 +52,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason,data} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.renaming.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.renaming.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.renaming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data}))
if (creator && generalConfig.data.logs.logMessages.renaming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+3 -3
View File
@@ -29,7 +29,7 @@ export async function registerActions(){
ticket.get("opendiscord:open").value = true
ticket.get("opendiscord:busy").value = true
if (generalConfig.data.system.disableAutocloseAfterReopen){
if (generalConfig.data.ticketSystem.disableAutocloseAfterReopen){
//disable autoclose after reopen
ticket.get("opendiscord:autoclose-enabled").value = false
ticket.get("opendiscord:autoclose-hours").value = 0
@@ -136,14 +136,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.reopening.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.reopening.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.reopening.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null}))
if (creator && generalConfig.data.logs.logMessages.reopening.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -69,14 +69,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.claiming.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.claiming.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null}))
if (creator && generalConfig.data.logs.logMessages.claiming.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+2 -2
View File
@@ -64,14 +64,14 @@ export async function registerActions(){
const {guild,channel,user,ticket,reason} = params
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.pinning.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.pinning.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-logs").build(origin,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null}))
}
//to dm
const creator = await opendiscord.tickets.getTicketUser(ticket,"creator")
if (creator && generalConfig.data.system.messages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null}))
if (creator && generalConfig.data.logs.logMessages.pinning.dm) await opendiscord.client.sendUserDm(creator,await opendiscord.builders.messages.getSafe("opendiscord:ticket-action-dm").build(origin,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null}))
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
+9 -9
View File
@@ -29,15 +29,15 @@ export async function registerActions(){
//handle channel topic
const channelTopics: string[] = []
if (generalConfig.data.system.channelTopic.showOptionName) channelTopics.push(ticket.option.get("opendiscord:name").value)
if (generalConfig.data.system.channelTopic.showOptionDescription) channelTopics.push(ticket.option.get("opendiscord:description").value)
if (generalConfig.data.system.channelTopic.showOptionTopic) channelTopics.push(ticket.get("opendiscord:topic").value)
if (generalConfig.data.system.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).renderDisplayName())
if (generalConfig.data.system.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+(closed ? lang.getTranslation("params.uppercase.closed") : lang.getTranslation("params.uppercase.open")))
if (generalConfig.data.system.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+(claimedBy ? discord.userMention(claimedBy) : lang.getTranslation("params.uppercase.noone")))
if (generalConfig.data.system.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+(pinned ? lang.getTranslation("params.uppercase.yes") : lang.getTranslation("params.uppercase.no")))
if (generalConfig.data.system.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(creator))
if (generalConfig.data.system.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+ticket.get("opendiscord:participants").value.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", "))
if (generalConfig.data.ticketSystem.channelTopic.showOptionName) channelTopics.push(ticket.option.get("opendiscord:name").value)
if (generalConfig.data.ticketSystem.channelTopic.showOptionDescription) channelTopics.push(ticket.option.get("opendiscord:description").value)
if (generalConfig.data.ticketSystem.channelTopic.showOptionTopic) channelTopics.push(ticket.get("opendiscord:topic").value)
if (generalConfig.data.ticketSystem.channelTopic.showPriority) channelTopics.push("**"+lang.getTranslation("params.uppercase.priority")+":** "+opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).renderDisplayName())
if (generalConfig.data.ticketSystem.channelTopic.showClosed) channelTopics.push("**"+lang.getTranslation("params.uppercase.status")+":** "+(closed ? lang.getTranslation("params.uppercase.closed") : lang.getTranslation("params.uppercase.open")))
if (generalConfig.data.ticketSystem.channelTopic.showClaimed) channelTopics.push("**"+lang.getTranslation("stats.properties.claimedBy")+":** "+(claimedBy ? discord.userMention(claimedBy) : lang.getTranslation("params.uppercase.noone")))
if (generalConfig.data.ticketSystem.channelTopic.showPinned) channelTopics.push("**"+lang.getTranslation("params.uppercase.pinned")+":** "+(pinned ? lang.getTranslation("params.uppercase.yes") : lang.getTranslation("params.uppercase.no")))
if (generalConfig.data.ticketSystem.channelTopic.showCreator) channelTopics.push("**"+lang.getTranslation("params.uppercase.creator")+":** "+discord.userMention(creator))
if (generalConfig.data.ticketSystem.channelTopic.showParticipants) channelTopics.push("**"+lang.getTranslation("params.uppercase.participants")+":** "+ticket.get("opendiscord:participants").value.map((p) => (p.type == "user") ? discord.userMention(p.id) : discord.roleMention(p.id)).join(", "))
//update channel
channel.setTopic(channelTopics.join(" • "),"Topic Changed")
+5 -5
View File
@@ -29,7 +29,7 @@ export async function replyHasPermissions(instance:api.ODButtonResponderInstance
//check permissions
const {user,member,channel,guild} = instance
const generalConfig = opendiscord.configs.get("opendiscord:general")
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions[commandName],"support",user,member,channel,guild,settings)
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.permissions[commandName],"support",user,member,channel,guild,settings)
if (!permsResult.hasPerms){
if (permsResult.reason == "not-in-server" && channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
@@ -139,18 +139,18 @@ export async function replyMessageMustBeSentBeforeClose(instance:api.ODButtonRes
const {user,member,channel,guild} = instance
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions[commandName],"support",user,member,channel,guild)
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.permissions[commandName],"support",user,member,channel,guild)
if (!permsResult.hasPerms) throw new api.ODSystemError("Please check permissions before using replyMessageMustBeSentBeforeClose()")
if (!guild || channel.isDMBased()) throw new api.ODSystemError("replyMessageMustBeSentBeforeClose() must be used in a guild and not a DM channel.")
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
if (!permsResult.isAdmin && (!generalConfig.data.ticketSystem.allowCloseBeforeMessage || !generalConfig.data.ticketSystem.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
if (analysis && !generalConfig.data.ticketSystem.allowCloseBeforeMessage && analysis.totalMessages < 1){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return false
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
if (analysis && !generalConfig.data.ticketSystem.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return false
}
+2 -2
View File
@@ -255,7 +255,7 @@ const ticketButtons = () => {
instance.setMode("button")
instance.setCustomId("od:pin-ticket")
instance.setColor("gray")
instance.setEmoji(generalConfig.data.system.pinEmoji)
instance.setEmoji(generalConfig.data.ticketSystem.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.pin"))
})
)
@@ -269,7 +269,7 @@ const ticketButtons = () => {
instance.setMode("button")
instance.setCustomId("od:unpin-ticket")
instance.setColor("gray")
instance.setEmoji(generalConfig.data.system.pinEmoji)
instance.setEmoji(generalConfig.data.ticketSystem.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.unpin"))
})
)
+53 -53
View File
@@ -42,7 +42,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",customTitle ?? lang.getTranslation("errors.titles.internalError")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method]) + (layout == "simple") ? "\n"+error : "")
@@ -75,7 +75,7 @@ const errorEmbeds = () => {
})
const commandSyntax = "**"+error.prefix+error.name+" "+optionSyntax.join(" ")+"**"
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionMissing")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.optionMissing"))
@@ -130,7 +130,7 @@ const errorEmbeds = () => {
else if (error.reason == "channel_type" && error.option.type == "channel") reasonValue = lang.getTranslation("errors.optionInvalidReasons.channelType")
else if (error.reason == "not_in_guild") reasonValue = lang.getTranslation("errors.optionInvalidReasons.notInGuild")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.optionInvalid")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.optionInvalid")+"\n"+reasonTitle+": `"+reasonValue+"`")
@@ -144,7 +144,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-unknown-command",0,async (instance,params) => {
const {user} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownCommand")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.unknownCommand"))
@@ -169,7 +169,7 @@ const errorEmbeds = () => {
else if (perm == "discord-administrator") return "- "+lang.getTranslation("errors.permissions.discord-administrator")
}).join("\n")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissions",[method]))
@@ -185,7 +185,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsCooldown",[method]))
@@ -201,7 +201,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.noPermissionsBlacklist",[method]))
@@ -214,7 +214,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,origin) => {
const {user,limit} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.noPermissions")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
if (limit == "global") instance.setDescription(lang.getTranslation("errors.descriptions.noPermissionsLimitGlobal"))
@@ -232,7 +232,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.internalError")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.internalError",[method]))
@@ -247,7 +247,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,origin) => {
const {user} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.unknownTicket"))
@@ -261,7 +261,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,origin) => {
const {user} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.deprecatedTicket")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.deprecatedTicket"))
@@ -281,7 +281,7 @@ const errorEmbeds = () => {
}else return "- `"+option.id.value+"`"
}).join("\n")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownOption")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo"))
@@ -301,7 +301,7 @@ const errorEmbeds = () => {
}else return "- `"+panel.id.value+"`"
}).join("\n")
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownPanel")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.addFields({name:lang.getTranslation("params.uppercase.validPanels")+":",value:renderedPanels})
@@ -317,7 +317,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.notInGuild")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.notInGuild",[method]))
@@ -332,7 +332,7 @@ const errorEmbeds = () => {
const method = (origin == "ticket-move" || origin == "ticket-pin" || origin == "ticket-rename" || origin == "ticket-unpin" || origin == "ticket-priority" || origin == "ticket-transfer") ? origin : getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.channelRename")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslation("errors.descriptions.channelRename"))
@@ -352,7 +352,7 @@ const errorEmbeds = () => {
const method = (origin == "ticket-create" || origin == "ticket-close" || origin == "ticket-reopen" || origin == "ticket-claim" || origin == "ticket-unclaim" || origin == "ticket-move") ? origin : getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
//TODO TRANSLATION!!!
instance.setTitle(utilities.emojiTitle("❌","Unable To Change Category"))
instance.setAuthor(user.displayName,user.displayAvatarURL())
@@ -376,7 +376,7 @@ const errorEmbeds = () => {
const method = getMethodFromOrigin(origin)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.busy")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("errors.descriptions.busy",[method]))
@@ -501,7 +501,7 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-ticket-unknown",0,async (instance,params) => {
const {user,id} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.unknownTicket")))
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.statsError",[discord.channelMention(id)]))
@@ -534,8 +534,8 @@ const panelEmbeds = () => {
instance.setDescription(embedOptions.description)
}
if (panel.get("opendiscord:enable-max-tickets-warning-embed").value && generalConfig.data.system.limits.enabled){
instance.setDescription(instance.data.description+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*")
if (panel.get("opendiscord:enable-max-tickets-warning-embed").value && generalConfig.data.ticketSystem.limits.enabled){
instance.setDescription(instance.data.description+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.ticketSystem.limits.userMaximum.toString()])+"*")
}
if (panel.get("opendiscord:describe-options-in-embed-fields").value){
@@ -623,12 +623,12 @@ const ticketEmbeds = () => {
if (ticket.option.get("opendiscord:questions").value.length > 0){
//show config fields if mixing is allowed
if (generalConfig.data.system.displayFieldsWithQuestions) instance.addFields(...embedOptions.fields)
if (generalConfig.data.ticketSystem.displayFieldsWithQuestions) instance.addFields(...embedOptions.fields)
const answers = ticket.get("opendiscord:answers").value
answers.forEach((answer) => {
if (!answer.value || answer.value.length == 0) return
if (generalConfig.data.system.questionFieldsInCodeBlock) instance.addFields({name:answer.name,value:"```"+answer.value.slice(0,1024-6)+"```",inline:false})
if (generalConfig.data.ticketSystem.questionFieldsInCodeBlock) instance.addFields({name:answer.name,value:"```"+answer.value.slice(0,1024-6)+"```",inline:false})
else instance.addFields({name:answer.name,value:answer.value,inline:false})
})
}else if (embedOptions.fields){
@@ -656,7 +656,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close")))
instance.setDescription(lang.getTranslation("actions.descriptions.close"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -670,7 +670,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔓",lang.getTranslation("actions.titles.reopen")))
instance.setDescription(lang.getTranslation("actions.descriptions.reopen"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -684,7 +684,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.delete")))
instance.setDescription(lang.getTranslation("actions.descriptions.delete"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -698,7 +698,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👋",lang.getTranslation("actions.titles.claim")))
instance.setDescription(lang.getTranslation("actions.descriptions.claim"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -712,7 +712,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslation("actions.descriptions.unclaim"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -724,9 +724,9 @@ const ticketEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslation("actions.descriptions.pin"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -738,9 +738,9 @@ const ticketEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setDescription(lang.getTranslation("actions.descriptions.unpin"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -754,7 +754,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.rename",["`#"+data+"`"]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -768,7 +768,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.move",["`"+data.get("opendiscord:name").value+"`"]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -782,7 +782,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.add",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -796,7 +796,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.remove")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.remove",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -828,10 +828,10 @@ const ticketEmbeds = () => {
instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslation("actions.logs.unclaimDm"))
}else if (mode == "pin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslation("actions.logs.pinDm"))
}else if (mode == "unpin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setDescription(lang.getTranslation("actions.logs.unpinDm"))
}else if (mode == "rename"){
instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename")))
@@ -864,7 +864,7 @@ const ticketEmbeds = () => {
{name:lang.getTranslation("params.uppercase.ticket")+":",value:"```#"+(channel ? channel.name : "<unknown>")+"```",inline:false},
{name:lang.getTranslation("params.uppercase.option")+":",value:"```"+(ticket.option.get("opendiscord:name").value)+"```",inline:false},
)
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```",inline:false})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```",inline:false})
if (mode == "close"){
instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close")))
@@ -882,10 +882,10 @@ const ticketEmbeds = () => {
instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslationWithParams("actions.logs.unclaimLog",[discord.userMention(user.id)]))
}else if (mode == "pin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslationWithParams("actions.logs.pinLog",[discord.userMention(user.id)]))
}else if (mode == "unpin"){
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.ticketSystem.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setDescription(lang.getTranslationWithParams("actions.logs.unpinLog",[discord.userMention(user.id)]))
}else if (mode == "rename"){
instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename")))
@@ -938,7 +938,7 @@ const blacklistEmbeds = () => {
if (blacklist){
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistGetSuccess",[discord.userMention(data.id)]))
if (blacklist.reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(blacklist.reason ?? "/")+"```"})
if (blacklist.reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(blacklist.reason ?? "/")+"```"})
}else instance.setDescription("*"+lang.getTranslationWithParams("actions.descriptions.blacklistGetEmpty",[discord.userMention(data.id)])+"*")
})
@@ -954,7 +954,7 @@ const blacklistEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🚫",lang.getTranslation("actions.titles.blacklistAdd")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistAdd",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -968,7 +968,7 @@ const blacklistEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🆓",lang.getTranslation("actions.titles.blacklistRemove")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistRemove",[discord.userMention(data.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -985,7 +985,7 @@ const blacklistEmbeds = () => {
instance.setTitle(utilities.emojiTitle((mode == "add") ? "🚫" : "🆓",title))
instance.setTimestamp(new Date())
instance.setDescription(text)
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1004,7 +1004,7 @@ const blacklistEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setTimestamp(new Date())
instance.setDescription(text)
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
@@ -1103,12 +1103,12 @@ const transcriptEmbeds = () => {
new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,reason} = params
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setColor(generalConfig.data.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("transcripts.errors.title")))
instance.setTimestamp(new Date())
instance.setDescription(lang.getTranslation("transcripts.errors.error"))
instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
@@ -1289,7 +1289,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseEnabled")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autocloseEnabled",[time.toString()]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1303,7 +1303,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteEnabled")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autodeleteEnabled",[time.toString()]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1317,7 +1317,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseDisabled")))
instance.setDescription(lang.getTranslation("actions.descriptions.autocloseDisabled"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1331,7 +1331,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteDisabled")))
instance.setDescription(lang.getTranslation("actions.descriptions.autodeleteDisabled"))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
@@ -1361,7 +1361,7 @@ const extraEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🚨",lang.getTranslation("actions.titles.prioritySet")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.prioritySet",["**"+priority.renderDisplayName()+"**",discord.userMention(user.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1388,7 +1388,7 @@ const extraEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.transfer")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.transfer",[discord.userMention(oldCreator.id),discord.userMention(newCreator.id),discord.userMention(user.id)]))
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
if (reason || generalConfig.data.ticketSystem.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
+16 -16
View File
@@ -286,8 +286,8 @@ const panelMessages = () => {
instance.setContent(text)
}
if (panel.get("opendiscord:enable-max-tickets-warning-text").value && generalConfig.data.system.limits.enabled){
instance.setContent(instance.data.content+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.system.limits.userMaximum.toString()])+"*")
if (panel.get("opendiscord:enable-max-tickets-warning-text").value && generalConfig.data.ticketSystem.limits.enabled){
instance.setContent(instance.data.content+"\n\n*"+lang.getTranslationWithParams("actions.descriptions.ticketMessageLimit",[generalConfig.data.ticketSystem.limits.userMaximum.toString()])+"*")
}
//add embed
@@ -399,7 +399,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:ticket-message-components",1,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
//add components
if (generalConfig.data.system.enableTicketClaimButtons && !ticket.get("opendiscord:closed").value){
if (generalConfig.data.ticketSystem.enableTicketClaimButtons && !ticket.get("opendiscord:closed").value){
//enable ticket claiming
if (ticket.get("opendiscord:claimed").value){
instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -407,7 +407,7 @@ const ticketMessages = () => {
instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("ticket-message",{guild,channel,user,ticket}))
}
}
if (generalConfig.data.system.enableTicketPinButtons && !ticket.get("opendiscord:closed").value){
if (generalConfig.data.ticketSystem.enableTicketPinButtons && !ticket.get("opendiscord:closed").value){
//enable ticket pinning
if (ticket.get("opendiscord:pinned").value){
instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -415,7 +415,7 @@ const ticketMessages = () => {
instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("ticket-message",{guild,channel,user,ticket}))
}
}
if (generalConfig.data.system.enableTicketCloseButtons){
if (generalConfig.data.ticketSystem.enableTicketCloseButtons){
//enable ticket closing
if (ticket.get("opendiscord:closed").value){
instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("ticket-message",{guild,channel,user,ticket}))
@@ -424,7 +424,7 @@ const ticketMessages = () => {
}
}
//enable ticket deletion
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("ticket-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("ticket-message",{guild,channel,user,ticket}))
}),
new api.ODWorker("opendiscord:ticket-message-disable-components",2,async (instance,params,origin) => {
const {ticket} = params
@@ -445,8 +445,8 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:close-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("close-message",{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("close-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("close-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("close-message",{guild,channel,user,ticket}))
})
)
@@ -456,8 +456,8 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:close-ticket").build("reopen-message",{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("reopen-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:close-ticket").build("reopen-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("reopen-message",{guild,channel,user,ticket}))
})
)
@@ -476,7 +476,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:claim-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("claim-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:unclaim-ticket").build("claim-message",{guild,channel,user,ticket}))
})
)
@@ -486,7 +486,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("unclaim-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketClaimButtons) instance.addComponent(await buttons.getSafe("opendiscord:claim-ticket").build("unclaim-message",{guild,channel,user,ticket}))
})
)
@@ -496,7 +496,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:pin-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("pin-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:unpin-ticket").build("pin-message",{guild,channel,user,ticket}))
})
)
@@ -506,7 +506,7 @@ const ticketMessages = () => {
new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason}))
if (generalConfig.data.system.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("unpin-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketPinButtons) instance.addComponent(await buttons.getSafe("opendiscord:pin-ticket").build("unpin-message",{guild,channel,user,ticket}))
})
)
@@ -732,8 +732,8 @@ const autoMessages = () => {
new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,origin) => {
const {guild,channel,user,ticket} = params
instance.addEmbed(await embeds.getSafe("opendiscord:autoclose-message").build(origin,{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("autoclose-message",{guild,channel,user,ticket}))
if (generalConfig.data.system.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("autoclose-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketCloseButtons) instance.addComponent(await buttons.getSafe("opendiscord:reopen-ticket").build("autoclose-message",{guild,channel,user,ticket}))
if (generalConfig.data.ticketSystem.enableTicketDeleteButtons) instance.addComponent(await buttons.getSafe("opendiscord:delete-ticket").build("autoclose-message",{guild,channel,user,ticket}))
})
)
+3 -3
View File
@@ -14,7 +14,7 @@ export async function registerCommandResponders(){
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.blacklist,"support",user,member,channel,guild)
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.permissions.blacklist,"support",user,member,channel,guild)
if (!permsResult.hasPerms){
if (permsResult.reason == "not-in-server") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild,channel,user,permissions:["support"]}))
@@ -83,13 +83,13 @@ export async function registerCommandResponders(){
const reason = instance.options.getString("reason",false)
//to logs
if (generalConfig.data.system.logs.enabled && generalConfig.data.system.messages.blacklisting.logs){
if (generalConfig.data.logs.enabled && generalConfig.data.logs.logMessages.blacklisting.logs){
const logChannel = opendiscord.posts.get("opendiscord:logs")
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-logs").build(origin,{guild,channel,user,mode:scope,data,reason}))
}
//to dm
if (generalConfig.data.system.messages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:blacklist-dm").build(origin,{guild,channel,user,mode:scope,data,reason}))
if (generalConfig.data.logs.logMessages.blacklisting.dm) await opendiscord.client.sendUserDm(user,await opendiscord.builders.messages.getSafe("opendiscord:blacklist-dm").build(origin,{guild,channel,user,mode:scope,data,reason}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
+1 -1
View File
@@ -90,7 +90,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.system.disableVerifyBars){
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -95,7 +95,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.system.disableVerifyBars){
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
+3 -3
View File
@@ -36,7 +36,7 @@ export async function registerCommandResponders(){
//don't allow deleteWithoutTranscript to non-global-admins when enabled
const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false
if (withoutTranscript && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
if (withoutTranscript && generalConfig.data.ticketSystem.adminOnlyDeleteWithoutTranscript){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelRoleScope:false,allowChannelUserScope:false,allowGlobalRoleScope:true,allowGlobalUserScope:true}))){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
return cancel()
@@ -93,7 +93,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.system.disableVerifyBars){
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
@@ -146,7 +146,7 @@ export async function registerVerifyBars(){
//don't allow deleteWithoutTranscript to non-global-admins when enabled
const withoutTranscript = (params.selectedButtonId == "accept-without-transcript")
if (withoutTranscript && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
if (withoutTranscript && generalConfig.data.ticketSystem.adminOnlyDeleteWithoutTranscript){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild,{allowChannelRoleScope:false,allowChannelUserScope:false,allowGlobalRoleScope:true,allowGlobalUserScope:true}))){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
return cancel()
+1 -1
View File
@@ -19,7 +19,7 @@ export async function registerCommandResponders(){
//calculate slash/text mode for help menu
let mode: "slash"|"text"
if (generalConfig.data.slashCommands && generalConfig.data.textCommands) mode = (generalConfig.data.system.preferSlashOverText) ? "slash" : "text"
if (generalConfig.data.slashCommands && generalConfig.data.textCommands) mode = (generalConfig.data.ticketSystem.preferSlashOverText) ? "slash" : "text"
else if (!generalConfig.data.slashCommands) mode = "text"
else mode = "slash"
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.system.disableVerifyBars){
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.system.disableVerifyBars){
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -34,7 +34,7 @@ export async function registerButtonResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"}))
return cancel()
}
if (generalConfig.data.system.replyOnReactionRole) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result}))
if (generalConfig.data.ticketSystem.replyOnReactionRole) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reaction-role").build("panel-button",{guild,user,role:res.role,result:res.result}))
})
)
}
+6 -6
View File
@@ -105,7 +105,7 @@ export async function registerButtonResponders(){
if (!(await checkTicketCreationPerms(instance,"panel-button",guild,user,option))) return cancel()
//CREATE TICKET
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-button",{guild,user,answers:[],option})
if (!res.channel || !res.ticket){
@@ -113,7 +113,7 @@ export async function registerButtonResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"}))
return cancel()
}
if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket}))
if (generalConfig.data.ticketSystem.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-button",{guild,channel:res.channel,user,ticket:res.ticket}))
}
})
)
@@ -147,7 +147,7 @@ export async function registerDropdownResponders(){
if (!(await checkTicketCreationPerms(instance,"panel-dropdown",guild,user,option))) return cancel()
//CREATE TICKET
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
const res = await opendiscord.actions.get("opendiscord:create-ticket").run("panel-dropdown",{guild,user,answers:[],option})
if (!res.channel || !res.ticket){
@@ -155,7 +155,7 @@ export async function registerDropdownResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"}))
return cancel()
}
if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket}))
if (generalConfig.data.ticketSystem.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build("panel-dropdown",{guild,channel:res.channel,user,ticket:res.ticket}))
}
//update panel after dropdown usage (reset panel choice)
@@ -214,7 +214,7 @@ export async function registerModalResponders(){
}
})
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
//CREATE TICKET
const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalOrigin,{guild,user,answers,option})
@@ -223,7 +223,7 @@ export async function registerModalResponders(){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"}))
return cancel()
}
if (generalConfig.data.system.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(originalOrigin,{guild,channel:res.channel,user,ticket:res.ticket}))
if (generalConfig.data.ticketSystem.replyOnTicketCreation) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(originalOrigin,{guild,channel:res.channel,user,ticket:res.ticket}))
})
])
}
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.system.disableVerifyBars){
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
+1 -1
View File
@@ -89,7 +89,7 @@ export async function registerButtonResponders(){
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.system.disableVerifyBars){
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
+8 -8
View File
@@ -42,7 +42,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or close with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.close"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//REOPEN TICKET VERIFYBAR
@@ -57,7 +57,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or reopen with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.reopen"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//DELETE TICKET VERIFYBAR
@@ -72,8 +72,8 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or delete with reason or without transcript
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.delete"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.system.enableDeleteWithoutTranscript) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithoutTranscript,lang.getTranslation("actions.buttons.withoutTranscript"),"red","📄")
if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.ticketSystem.enableDeleteWithoutTranscript) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithoutTranscript,lang.getTranslation("actions.buttons.withoutTranscript"),"red","📄")
}))
//CLAIM TICKET VERIFYBAR
@@ -88,7 +88,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or claim with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.claim"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//UNCLAIM TICKET VERIFYBAR
@@ -103,7 +103,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or unclaim with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unclaim"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//PIN TICKET VERIFYBAR
@@ -118,7 +118,7 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or pin with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.pin"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//UNPIN TICKET VERIFYBAR
@@ -133,6 +133,6 @@ export async function registerAllVerifyBarModifiers(){
//cancel, accept or unpin with reason
await addVerifyButton(instance,params,"❌",true,api.ODVerifyButtonId.Cancel)
await addVerifyButton(instance,params,"✅",true,api.ODVerifyButtonId.Accept,lang.getTranslation("actions.buttons.unpin"))
if (generalConfig.data.system.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
if (generalConfig.data.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
}
-3
View File
@@ -32,9 +32,6 @@ export interface ODTicketOptionIdMappings extends ODOptionIdConstraint {
"opendiscord:channel-prefix":ODOptionData<string>,
"opendiscord:channel-suffix":ODOptionData<"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed">,
"opendiscord:channel-category":ODOptionData<string>,
"opendiscord:channel-category-closed":ODOptionData<string>,
"opendiscord:channel-category-backup":ODOptionData<string>,
"opendiscord:channel-categories-claimed":ODOptionData<{user:string,category:string}[]>,
"opendiscord:channel-topic":ODOptionData<string>,
"opendiscord:dm-message-enabled":ODOptionData<boolean>,
+124 -65
View File
@@ -31,7 +31,7 @@ interface ODQuickSetupVariables {
globalUserLimit?:number|null,
removeParticipantsOnClose?:boolean,
ticketMessageLayout?:"embed"|"text"|null,
emojiStyle?:api.ODGeneralJsonConfig_System["emojiStyle"],
emojiStyle?:api.ODGeneralJsonConfig_TicketSystem["emojiStyle"],
panelName?:string,
panelDescription?:string,
panelDropdown?:boolean,
@@ -234,7 +234,7 @@ async function renderQuickSetupBotToken(backFn:() => api.ODPromiseVoid){
cli.renderHeader(headerOpts,"⏱️ Open Ticket Quick Setup: Bot Token")
terminal.bold.blue(stepCount(2)+"Please insert the token of your discord bot.\n")
terminal.gray("This is used to configure the bot and is then stored securely in the './config/general.json' file.\n\n> ")
terminal.gray("This is used to configure the bot and is then stored securely in the './config/general.jsonc' file.\n\n> ")
const answer = await terminal.inputField({
style:terminal.white,
@@ -1203,11 +1203,7 @@ async function saveQuickSetupConfig(){
//GENERAL CONFIG
const generalConfig = opendiscord.configs.get("opendiscord:general")
const generalConfigData: api.ODGeneralJsonConfig_GeneralData = {
_INFO:{
support:"https://otdocs.dj-dj.be",
discord:"https://discord.dj-dj.be",
version:"open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()
},
_CONFIG_VERSION:"open-ticket-"+opendiscord.versions.get("opendiscord:version").toString(),
token:quickSetupStorage.client?.token ?? "<unknown-token>",
tokenFromENV:false,
@@ -1222,8 +1218,29 @@ async function saveQuickSetupConfig(){
textCommands:quickSetupStorage.textCommands ?? false,
status:quickSetupStorage.status ?? {enabled:false,mode:"online",type:"custom",text:"",state:""},
logs:{
enabled:(typeof quickSetupStorage.logChannel == "string"),
channel:quickSetupStorage.logChannel ?? "",
logMessages:{
creation:{dm:true,logs:true},
closing:{dm:true,logs:true},
deleting:{dm:true,logs:true},
reopening:{dm:false,logs:true},
claiming:{dm:false,logs:true},
pinning:{dm:false,logs:true},
adding:{dm:false,logs:true},
removing:{dm:false,logs:true},
renaming:{dm:false,logs:true},
moving:{dm:true,logs:true},
blacklisting:{dm:true,logs:true},
transferring:{dm:true,logs:true},
topicChange:{dm:false,logs:true},
priorityChange:{dm:false,logs:true},
reactionRole:{dm:false,logs:true}
}
},
system:{
ticketSystem:{
preferSlashOverText:quickSetupStorage.slashCommands ?? false,
sendErrorOnUnknownCommand:true,
questionFieldsInCodeBlock:true,
@@ -1234,10 +1251,11 @@ async function saveQuickSetupConfig(){
alwaysShowReason:false,
emojiStyle:quickSetupStorage.emojiStyle ?? "before",
pinEmoji:"📌",
closeEmoji:"🔒",
replyOnTicketCreation:false,
replyOnTicketCreation:true,
replyOnReactionRole:true,
askPriorityOnTicketCreation:false,
askPriorityOnTicketCreation:true,
removeParticipantsOnClose:quickSetupStorage.removeParticipantsOnClose ?? false,
disableAutocloseAfterReopen:true,
autodeleteRequiresClosedTicket:true,
@@ -1245,7 +1263,7 @@ async function saveQuickSetupConfig(){
allowCloseBeforeMessage:false,
allowCloseBeforeAdminMessage:true,
useTranslatedConfigChecker:true,
pinFirstTicketMessage:false,
pinFirstTicketMessage:true,
enableTicketClaimButtons:true,
enableTicketCloseButtons:true,
@@ -1253,11 +1271,7 @@ async function saveQuickSetupConfig(){
enableTicketDeleteButtons:true,
enableTicketActionWithReason:true,
enableDeleteWithoutTranscript:true,
logs:{
enabled:(typeof quickSetupStorage.logChannel == "string"),
channel:quickSetupStorage.logChannel ?? ""
},
enableCreateTicketForOtherUser:true,
limits:{
enabled:(typeof quickSetupStorage.globalUserLimit == "number"),
@@ -1276,49 +1290,41 @@ async function saveQuickSetupConfig(){
showCreator:false,
showParticipants:false
},
permissions:{
help:"everyone",
panel:"admin",
ticket:"everyone",
close:"admin",
delete:"admin",
reopen:"admin",
claim:"admin",
unclaim:"admin",
pin:"admin",
unpin:"admin",
move:"admin",
rename:"admin",
add:"admin",
remove:"admin",
blacklist:"admin",
stats:"everyone",
clear:"admin",
autoclose:"admin",
autodelete:"admin",
transfer:"admin",
topic:"admin",
priority:"admin",
closedCategory:{
enabled:false,
categoryId:""
},
messages:{
creation:{dm:true,logs:true},
closing:{dm:true,logs:true},
deleting:{dm:true,logs:true},
reopening:{dm:false,logs:true},
claiming:{dm:false,logs:true},
pinning:{dm:false,logs:true},
adding:{dm:false,logs:true},
removing:{dm:false,logs:true},
renaming:{dm:false,logs:true},
moving:{dm:true,logs:true},
blacklisting:{dm:true,logs:true},
transferring:{dm:true,logs:true},
topicChange:{dm:false,logs:true},
priorityChange:{dm:false,logs:true},
reactionRole:{dm:false,logs:true}
}
backupCategory:{
enabled:false,
categoryId:""
},
claimedCategories:[],
},
permissions:{
help:"everyone",
panel:"admin",
ticket:"everyone",
close:"admin",
delete:"admin",
reopen:"admin",
claim:"admin",
unclaim:"admin",
pin:"admin",
unpin:"admin",
move:"admin",
rename:"admin",
add:"admin",
remove:"admin",
blacklist:"admin",
stats:"everyone",
clear:"admin",
autoclose:"admin",
autodelete:"admin",
transfer:"admin",
topic:"admin",
priority:"admin",
transcripts:"admin"
}
}
generalConfig.data = generalConfigData
@@ -1330,10 +1336,11 @@ async function saveQuickSetupConfig(){
{
id:"example-question-1",
name:"Example Question 1",
description:"This is a short text input question.",
type:"short",
required:true,
placeholder:"Insert your short answer here!",
placeholder:"Insert answer...",
length:{
enabled:false,
min:0,
@@ -1343,15 +1350,69 @@ async function saveQuickSetupConfig(){
{
id:"example-question-2",
name:"Example Question 2",
description:"This is a paragraph text input question.",
type:"paragraph",
required:false,
placeholder:"Insert your long answer here!",
placeholder:"Insert answer...",
length:{
enabled:false,
min:0,
max:1000
}
},
{
id:"example-question-3",
name:"Example Question 3",
description:"This is a dropdown question.",
type:"dropdown",
required:false,
placeholder:"Choose your answer...",
choices:[
{title:"Choice A",description:"Apple",emoji:"🍎"},
{title:"Choice B",description:"Banana",emoji:"🍌"},
{title:"Choice C",description:"Orange",emoji:"🍊"},
{title:"Choice D",description:"Kiwi",emoji:"🥝"}
]
},
{
id:"example-question-4",
name:"Example Question 4",
description:"This is a radio select question.",
type:"radio-select",
required:true,
choices:[
{title:"Choice A",description:"Up",selectedByDefault:false},
{title:"Choice B",description:"Down",selectedByDefault:false},
{title:"Choice C",description:"Left",selectedByDefault:false},
{title:"Choice D",description:"Right",selectedByDefault:false}
]
},
{
id:"example-question-5",
name:"Example Question 5",
description:"This is a checkbox select question.",
type:"checkbox-select",
required:true,
limits:{
enabled:false,
min:0,
max:10
},
choices:[
{title:"Choice A",description:"Happiness",selectedByDefault:false},
{title:"Choice B",description:"Anger",selectedByDefault:false},
{title:"Choice C",description:"Sadness",selectedByDefault:false},
{title:"Choice D",description:"Fear",selectedByDefault:false}
]
},
{
id:"example-text-display",
type:"text-display",
textContents:"This is a text display. It isn't a question, but allows you to display a text, explaination or details."
}
]
questionsConfig.data = questionsConfigData
@@ -1384,9 +1445,6 @@ async function saveQuickSetupConfig(){
prefix:ticket.channelPrefix,
suffix:ticket.channelSuffix,
category:quickSetupStorage.ticketCategory ?? "",
closedCategory:"",
backupCategory:"",
claimedCategory:[],
topic:ticket.description
},
@@ -1482,6 +1540,7 @@ async function saveQuickSetupConfig(){
},
settings:{
dropdownPlaceholder:"Open a ticket",
maximumButtonsPerRow:5,
enableMaxTicketsWarningInText:(quickSetupStorage.panelLayout == "text" && (quickSetupStorage.panelMaxTicketsWarning ?? false)),
enableMaxTicketsWarningInEmbed:(quickSetupStorage.panelLayout == "embed" && (quickSetupStorage.panelMaxTicketsWarning ?? false)),
+2 -2
View File
@@ -58,7 +58,7 @@ export class ODOpenTicketMain extends api.ODMain {
priorities: api.ODMappedPriorityManager
constructor(){
const version = api.ODVersion.fromString("opendiscord:version","v4.1.3")
const version = api.ODVersion.fromString("opendiscord:version","v4.2.0")
const debugfile = new api.ODDebugFileManager("./","otdebug.txt",5000,version)
const console = new api.ODConsoleManager(100,debugfile)
const debug = new api.ODDebugger(console)
@@ -108,7 +108,7 @@ export class ODOpenTicketMain extends api.ODMain {
},"openticket")
this.livestatus.useMain(this)
this.versions.add(api.ODVersion.fromString("opendiscord:version","v4.1.3"))
this.versions.add(api.ODVersion.fromString("opendiscord:version","v4.2.0"))
this.versions.add(api.ODVersion.fromString("opendiscord:transcripts","v2.1.0"))
//OPEN TICKET
+196 -95
View File
@@ -10,20 +10,20 @@ import { ODRoleUpdateMode } from "../api/role.js"
* It's used to generate typescript declarations for this class.
*/
export interface ODConfigManagerIdMappings extends api.ODConfigManagerIdConstraint {
"opendiscord:general":ODGeneralJsonConfig,
"opendiscord:questions":ODQuestionsJsonConfig,
"opendiscord:options":ODOptionsJsonConfig,
"opendiscord:panels":ODPanelsJsonConfig,
"opendiscord:transcripts":ODTranscriptsJsonConfig
"opendiscord:general":ODGeneralJsonCommentsConfig,
"opendiscord:questions":ODQuestionsJsonCommentsConfig,
"opendiscord:options":ODOptionsJsonCommentsConfig,
"opendiscord:panels":ODPanelsJsonCommentsConfig,
"opendiscord:transcripts":ODTranscriptsJsonCommentsConfig
}
///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES
// --> general.json
// --> general.jsonc
///////////////////////////////////////
/**## ODGeneralJsonConfig_Status `interface`
* This interface is an object which has all properties for the status object in the `general.json` config!
* This interface is an object which has all properties for the status object in the `general.jsonc` config!
*/
export interface ODGeneralJsonConfig_Status {
/**Is the status enabled? */
@@ -39,7 +39,7 @@ export interface ODGeneralJsonConfig_Status {
}
/**## ODGeneralJsonConfig_MessageSettings `interface`
* This interface is an object which has all properties for the "system"."messages".... object in the `general.json` config!
* This interface is an object which has all properties for the "system"."messages".... object in the `general.jsonc` config!
*/
export interface ODGeneralJsonConfig_MessageSettings {
/**Enable sending DM logs to the ticket creator for this action. */
@@ -49,22 +49,10 @@ export interface ODGeneralJsonConfig_MessageSettings {
}
/**## ODGeneralJsonConfig_CmdPermissionSettingsType `type`
* This type is a collection of command permission settings for the "system"."permissions".... object in the `general.json` config!
* This type is a collection of command permission settings for the "system"."permissions".... object in the `general.jsonc` config!
*/
export type ODGeneralJsonConfig_CmdPermissionSettingsType = "admin"|"everyone"|"none"|string
/**## ODGeneralJsonConfig_Info `interface`
* This object contains a few URLs and metadata for the config.
*/
export interface ODGeneralJsonConfig_Info {
/**A link to the Open Ticket documentation. */
support:string,
/**A link to the DJdj Development discord server. */
discord:string,
/**The version of Open Ticket this config is compatible with. */
version:string
}
/**## ODGeneralJsonConfig_SystemLogs `interface`
* All settings related to the log channel.
*/
@@ -72,7 +60,9 @@ export interface ODGeneralJsonConfig_SystemLogs {
/**Enable logging. Individual actions should still be added via the `"system"."messages"..."logs"` */
enabled:boolean,
/**The channel to send logs to. */
channel:string
channel:string,
/**Configure dm & log messages for all Open Ticket commands & actions. */
logMessages:ODGeneralJsonConfig_LogMessages
}
/**## ODGeneralJsonConfig_SystemLimits `interface`
@@ -137,12 +127,13 @@ export interface ODGeneralJsonConfig_SystemPermissions {
transfer:ODGeneralJsonConfig_CmdPermissionSettingsType,
topic:ODGeneralJsonConfig_CmdPermissionSettingsType,
priority:ODGeneralJsonConfig_CmdPermissionSettingsType,
transcripts:ODGeneralJsonConfig_CmdPermissionSettingsType,
}
/**## ODGeneralJsonConfig_SystemMessages `interface`
/**## ODGeneralJsonConfig_LogMessages `interface`
* Configure dm & log messages for all Open Ticket commands & actions.
*/
export interface ODGeneralJsonConfig_SystemMessages {
export interface ODGeneralJsonConfig_LogMessages {
creation:ODGeneralJsonConfig_MessageSettings,
closing:ODGeneralJsonConfig_MessageSettings,
deleting:ODGeneralJsonConfig_MessageSettings,
@@ -160,10 +151,10 @@ export interface ODGeneralJsonConfig_SystemMessages {
reactionRole:ODGeneralJsonConfig_MessageSettings,
}
/**## ODGeneralJsonConfig_System `interface`
/**## ODGeneralJsonConfig_TicketSystem `interface`
* All settings related to the ticket system.
*/
export interface ODGeneralJsonConfig_System {
export interface ODGeneralJsonConfig_TicketSystem {
/**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. */
@@ -184,6 +175,8 @@ export interface ODGeneralJsonConfig_System {
emojiStyle:"before"|"after"|"double"|"disabled",
/**The emoji used when pinning tickets. This is '📌' by default. */
pinEmoji:string,
/**The emoji used when closing tickets. This is '🔒' by default. */
closeEmoji:string,
/**Reply with an ephemeral message when a ticket is created. */
replyOnTicketCreation:boolean,
@@ -220,9 +213,8 @@ export interface ODGeneralJsonConfig_System {
enableTicketActionWithReason:boolean,
/**Enable/disable the delete without transcript feature (button & /delete command). */
enableDeleteWithoutTranscript:boolean,
/**All settings related to the log channel. */
logs:ODGeneralJsonConfig_SystemLogs,
/**Enable/disable creating tickets for other users with /ticket <user>. (ADMIN ONLY) */
enableCreateTicketForOtherUser:boolean,
/**All settings related to global ticket limits. */
limits:ODGeneralJsonConfig_SystemLimits,
@@ -230,19 +222,31 @@ export interface ODGeneralJsonConfig_System {
/**All global channel topic settings. */
channelTopic:ODGeneralJsonConfig_SystemChannelTopic,
/**Configure permissions for all Open Ticket commands & actions. */
permissions:ODGeneralJsonConfig_SystemPermissions,
/**Configure dm & log messages for all Open Ticket commands & actions. */
messages:ODGeneralJsonConfig_SystemMessages
/**Move closed tickets to this channel category. */
closedCategory:{
enabled:boolean
categoryId:string
},
/**Create tickets in this channel category when the original category is full (max 50 channels). */
backupCategory:{
enabled:boolean
categoryId:string
},
/**Move claimed tickets to the matching channel category of the user that claimed the ticket. */
claimedCategories:{
/**The user who claimed the ticket. */
user:string,
/**The category to move the ticket to. */
category:string
}[],
}
/**## ODGeneralJsonConfig_GeneralData `interface`
* All contents of the `general.json` config file.
* All contents of the `general.jsonc` config file.
*/
export interface ODGeneralJsonConfig_GeneralData {
/**This object contains a few URLs and metadata for the config. */
_INFO:ODGeneralJsonConfig_Info,
_CONFIG_VERSION:string,
/**The token of the bot. (Empty when using `tokenFromENV`) */
token:string,
@@ -267,18 +271,24 @@ export interface ODGeneralJsonConfig_GeneralData {
/**All settings related to the status of the bot. */
status:ODGeneralJsonConfig_Status,
/**All settings related to the ticket system. */
system:ODGeneralJsonConfig_System
ticketSystem:ODGeneralJsonConfig_TicketSystem,
/**Configure permissions for all Open Ticket commands & actions. */
permissions:ODGeneralJsonConfig_SystemPermissions,
/**All settings related to the log channel. */
logs:ODGeneralJsonConfig_SystemLogs,
}
///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES
// --> options.json
// --> options.jsonc
///////////////////////////////////////
/**## ODOptionsJsonConfig_BaseOption `interface`
* This interface is an object which has all basic properties for options in the `options.json` config!
* The basic properties for options in the `options.jsonc` config!
*/
export interface ODOptionsJsonConfig_BaseOption {
/**The id of this option. */
@@ -288,7 +298,7 @@ export interface ODOptionsJsonConfig_BaseOption {
/**The description of this option. */
description:string,
/**The type of this option. This type also determines the other option-specific variables. */
type:"ticket"|"website"|"role",
type:"ticket"|"website"|"role"|"sub-panel",
/**All settings related to the button for the 3 option types. */
button:{
/**The emoji of the button. (can also be empty) */
@@ -299,7 +309,7 @@ export interface ODOptionsJsonConfig_BaseOption {
}
/**## ODOptionsJsonConfig_OptionButtonSettings `interface`
* This interface is an object which has all button settings for ticket & reaction role options in the `options.json` config!
* The button settings for ticket, sub-panel & reaction role options in the `options.jsonc` config!
*/
export interface ODOptionsJsonConfig_OptionButtonSettings {
/**The emoji of the button. (can also be empty) */
@@ -311,7 +321,7 @@ export interface ODOptionsJsonConfig_OptionButtonSettings {
}
/**## ODOptionsJsonConfig_TicketOptionEmbedSettings `interface`
* This interface is an object which has all message embed settings for ticket options in the `options.json` config!
* The message embed settings for ticket options in the `options.jsonc` config!
*/
export interface ODOptionsJsonConfig_TicketOptionEmbedSettings {
/**Is this embed enabled? */
@@ -340,7 +350,7 @@ export interface ODOptionsJsonConfig_TicketOptionEmbedSettings {
}
/**## ODOptionsJsonConfig_TicketOptionPingSettings `interface`
* This interface is an object which has all message ping settings for ticket options in the `options.json` config!
* The message ping settings for ticket options in the `options.jsonc` config!
*/
export interface ODOptionsJsonConfig_TicketOptionPingSettings {
/**Ping `@here`. */
@@ -361,23 +371,12 @@ export interface ODOptionsJsonConfig_TicketOptionChannelSettings {
suffix:"user-name"|"user-nickname"|"user-id"|"random-number"|"random-hex"|"counter-dynamic"|"counter-fixed",
/**An optional discord category id to create this ticket in. */
category:string,
/**An optional discord category id to move this ticket to when closed. */
closedCategory:string,
/**An optional discord category id to create this ticket in when the primary one is full (max. 50 tickets). */
backupCategory:string,
/**A list of discord category ids to move this ticket to when claimed by a specific user. */
claimedCategory:{
/**The user which claimed the ticket. */
user:string,
/**The category to move the ticket to when claimed by this user. */
category:string
}[],
/**The channel topic shown at the top of the channel in discord. */
topic:string
}
/**## ODOptionsJsonConfig_TicketOption `interface`
* This interface is an object which has all ticket properties for options in the `options.json` config!
* All properties for ticket options in the `options.jsonc` config!
*/
export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_BaseOption {
type:"ticket",
@@ -388,7 +387,7 @@ export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_Ba
readonlyAdmins:string[],
/**When enabled, blacklisted users can still create this ticket type. (used for appeals, etc) */
allowCreationByBlacklistedUsers:boolean,
/**A list of valid question ids from the `questions.json` config. */
/**A list of valid question ids from the `questions.jsonc` config. */
questions:string[],
/**All settings related to the ticket channel itself. */
channel:ODOptionsJsonConfig_TicketOptionChannelSettings,
@@ -460,7 +459,7 @@ export interface ODOptionsJsonConfig_TicketOption extends ODOptionsJsonConfig_Ba
}
/**## ODOptionsJsonConfig_WebsiteOption `interface`
* This interface is an object which has all website properties for options in the `options.json` config!
* All properties for website options in the `options.jsonc` config!
*/
export interface ODOptionsJsonConfig_WebsiteOption extends ODOptionsJsonConfig_BaseOption {
type:"website",
@@ -469,7 +468,7 @@ export interface ODOptionsJsonConfig_WebsiteOption extends ODOptionsJsonConfig_B
}
/**## ODOptionsJsonConfig_RoleOption `interface`
* This interface is an object which has all reaction role properties for options in the `options.json` config!
* All properties for reaction-role options in the `options.jsonc` config!
*/
export interface ODOptionsJsonConfig_RoleOption extends ODOptionsJsonConfig_BaseOption {
type:"role",
@@ -484,18 +483,28 @@ export interface ODOptionsJsonConfig_RoleOption extends ODOptionsJsonConfig_Base
addOnMemberJoin:boolean
}
/**## ODOptionsJsonConfig_OptionsData `type`
* All contents of the `options.json` config file.
/**## ODOptionsJsonConfig_SubPanelOption `interface`
* All properties for sub-panel options in the `options.jsonc` config!
*/
export type ODOptionsJsonConfig_OptionsData = (ODOptionsJsonConfig_TicketOption|ODOptionsJsonConfig_WebsiteOption|ODOptionsJsonConfig_RoleOption)[]
export interface ODOptionsJsonConfig_SubPanelOption extends ODOptionsJsonConfig_BaseOption {
type:"sub-panel",
button:ODOptionsJsonConfig_OptionButtonSettings,
/**The panel ID of the sub-panel to show when the button is clicked. */
subPanelId:string
}
/**## ODOptionsJsonConfig_OptionsData `type`
* All contents of the `options.jsonc` config file.
*/
export type ODOptionsJsonConfig_OptionsData = (ODOptionsJsonConfig_TicketOption|ODOptionsJsonConfig_WebsiteOption|ODOptionsJsonConfig_RoleOption|ODOptionsJsonConfig_SubPanelOption)[]
///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES
// --> panels.json
// --> panels.jsonc
///////////////////////////////////////
/**## ODPanelsJsonConfig_PanelEmbedSettings `interface`
* This interface is an object which has all message embed settings for panels in the `panels.json` config!
* This interface is an object which has all message embed settings for panels in the `panels.jsonc` config!
*/
export interface ODPanelsJsonConfig_PanelEmbedSettings {
/**Is this embed enabled? */
@@ -535,6 +544,8 @@ export interface ODPanelsJsonConfig_PanelEmbedSettings {
export interface ODPanelsJsonConfig_PanelSettings {
/**The placeholder used in the dropdown when enabled. */
dropdownPlaceholder:string,
/**The maximum amount of option buttons before starting a new row. */
maximumButtonsPerRow:number
/**Enable a max tickets warning in the text contents. */
enableMaxTicketsWarningInText:boolean,
@@ -554,7 +565,7 @@ export interface ODPanelsJsonConfig_PanelSettings {
}
/**## ODPanelsJsonConfig_Panel `interface`
* This interface is an object which has all properties for panels in the `panels.json` config!
* This interface is an object which has all properties for panels in the `panels.jsonc` config!
*/
export interface ODPanelsJsonConfig_Panel {
/**The id of this panel. */
@@ -563,7 +574,7 @@ export interface ODPanelsJsonConfig_Panel {
name:string,
/**When enabled, the panel uses a dropdown instead of buttons. */
dropdown:boolean,
/**A list of valid options ids from the `options.json` config. */
/**A list of valid options ids from the `options.jsonc` config. */
options:string[],
/**The raw text contents of this panel. (empty for embed only) */
@@ -575,19 +586,19 @@ export interface ODPanelsJsonConfig_Panel {
}
/**## ODPanelsJsonConfig_PanelsData `type`
* All contents of the `panels.json` config file.
* All contents of the `panels.jsonc` config file.
*/
export type ODPanelsJsonConfig_PanelsData = ODPanelsJsonConfig_Panel[]
///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES
// --> questions.json
// --> questions.jsonc
///////////////////////////////////////
/**## ODQuestionsJsonConfig_QuestionLengthSettings `interface`
/**## ODQuestionsJsonConfig_TextLengthLimits `interface`
* This interface is a collection of settings related to length validation in a question.
*/
export interface ODQuestionsJsonConfig_QuestionLengthSettings {
export interface ODQuestionsJsonConfig_TextLengthLimits {
/**Enable text length verification. */
enabled:boolean,
/**The minimum text input length. */
@@ -596,48 +607,138 @@ export interface ODQuestionsJsonConfig_QuestionLengthSettings {
max:number
}
/**## ODQuestionsJsonConfig_CheckboxLimits `interface`
* The required amount of checkboxes validation in a question.
*/
export interface ODQuestionsJsonConfig_CheckboxLimits {
/**Enable checkbox limits. */
enabled:boolean,
/**The minimum amount of selected checkboxes. */
min:number,
/**The maximum amount of selected checkboxes. */
max:number
}
/**## ODQuestionsJsonConfig_DropdownChoice `interface`
* A dropdown choice used in `ODQuestionsJsonConfig_DropdownQuestion`
*/
export interface ODQuestionsJsonConfig_DropdownChoice {
/**The title of the choice. */
title:string,
/**The optional description of the choice. (Leave empty for none) */
description:string,
/**The optional emoji of the choice. (Leave empty for none) */
emoji:string
}
/**## ODQuestionsJsonConfig_RadioCheckboxChoice `interface`
* A radio/checkbox choice used in `ODQuestionsJsonConfig_RadioSelectQuestion` & `ODQuestionsJsonConfig_CheckboxSelectQuestion`
*/
export interface ODQuestionsJsonConfig_RadioCheckboxChoice {
/**The title of the choice. */
title:string,
/**The optional description of the choice. (Leave empty for none) */
description:string,
/**Is this choice selected by default? */
selectedByDefault:boolean
}
/**## ODQuestionsJsonConfig_BaseQuestion `interface`
* This interface is an object which has all universal properties for questions in the `questions.json` config!
* This interface is an object which has all universal properties for questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_BaseQuestion {
/**The id of this question. */
id:string,
/**The name of this question. */
name:string,
/**The description of this question. (Leave empty for none) */
description:string,
/**The type of this question. */
type:"short"|"paragraph",
type:"short"|"paragraph"|"text-display"|"dropdown"|"radio-select"|"checkbox-select",
/**Is this question required? */
required:boolean,
}
/**## ODQuestionsJsonConfig_TextDisplayQuestion `interface`
* All properties for a text-display in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_TextDisplayQuestion {
/**The id of this text-display. */
id:string,
/**The type of this question. */
type:"text-display",
/**The text contents to show in the modal. */
textContents:string
}
/**## ODQuestionsJsonConfig_ShortQuestion `interface`
* This interface is an object which has all properties for short questions in the `questions.json` config!
* All properties for short questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_ShortQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"short",
/**A placeholder for the question. */
placeholder:string,
/**A collection of settings related to length validation in a question. */
length:ODQuestionsJsonConfig_QuestionLengthSettings
length:ODQuestionsJsonConfig_TextLengthLimits
}
/**## ODQuestionsJsonConfig_ParagraphQuestion `interface`
* This interface is an object which has all properties for paragraph questions in the `questions.json` config!
* All properties for paragraph questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_ParagraphQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"paragraph",
/**A placeholder for the question. */
placeholder:string,
/**A collection of settings related to length validation in a question. */
length:ODQuestionsJsonConfig_QuestionLengthSettings
length:ODQuestionsJsonConfig_TextLengthLimits
}
/**## ODQuestionsJsonConfig_DropdownQuestion `interface`
* All properties for dropdown questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_DropdownQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"dropdown",
/**A placeholder for the dropdown. */
placeholder:string,
/**A list of maximum 25 dropdown choices. */
choices:ODQuestionsJsonConfig_DropdownChoice[]
}
/**## ODQuestionsJsonConfig_RadioSelectQuestion `interface`
* All properties for radio select questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_RadioSelectQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"radio-select",
/**A list of minimum 2, maximum 10 radio choices. */
choices:ODQuestionsJsonConfig_RadioCheckboxChoice[]
}
/**## ODQuestionsJsonConfig_CheckboxSelectQuestion `interface`
* All properties for checkbox select questions in the `questions.jsonc` config!
*/
export interface ODQuestionsJsonConfig_CheckboxSelectQuestion extends ODQuestionsJsonConfig_BaseQuestion {
type:"checkbox-select",
/**Verify the checked amount of checkboxes with a minimum & maximum. */
limits:ODQuestionsJsonConfig_CheckboxLimits
/**A list of minimum 1, maximum 10 checkbox choices. */
choices:ODQuestionsJsonConfig_RadioCheckboxChoice[]
}
/**## ODQuestionsJsonConfig_QuestionsData `type`
* All contents of the `questions.json` config file.
* All contents of the `questions.jsonc` config file.
*/
export type ODQuestionsJsonConfig_QuestionsData = (ODQuestionsJsonConfig_ShortQuestion|ODQuestionsJsonConfig_ParagraphQuestion)[]
export type ODQuestionsJsonConfig_QuestionsData = (
ODQuestionsJsonConfig_ShortQuestion|
ODQuestionsJsonConfig_ParagraphQuestion|
ODQuestionsJsonConfig_TextDisplayQuestion|
ODQuestionsJsonConfig_DropdownQuestion|
ODQuestionsJsonConfig_RadioSelectQuestion|
ODQuestionsJsonConfig_CheckboxSelectQuestion
)[]
///////////////////////////////////////
// CONFIG STRUCTURES, VALUES & TYPES
// --> transcripts.json
// --> transcripts.jsonc
///////////////////////////////////////
/**## ODTranscriptsJsonConfig_TranscriptsTextLayout `interface`
@@ -712,7 +813,7 @@ export interface ODTranscriptsJsonConfig_TranscriptsHtmlLayout {
}
/**## ODTranscriptsJsonConfig_TranscriptsData `interface`
* All contents of the `transcripts.json` config file.
* All contents of the `transcripts.jsonc` config file.
*/
export interface ODTranscriptsJsonConfig_TranscriptsData {
/**All general settings related to transcripts. */
@@ -760,27 +861,27 @@ export interface ODTranscriptsJsonConfig_TranscriptsData {
*/
export class ODMappedConfigManager extends api.ODConfigManager<ODConfigManagerIdMappings> {}
/**## ODGeneralJsonConfig `class
* A special class with types for the Open Ticket `config/general.json` config file
/**## ODGeneralJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/general.jsonc` config file
*/
export class ODGeneralJsonConfig extends api.ODJsonConfig<ODGeneralJsonConfig_GeneralData> {}
export class ODGeneralJsonCommentsConfig extends api.ODJsonCommentsConfig<ODGeneralJsonConfig_GeneralData> {}
/**## ODQuestionsJsonConfig `class
* A special class with types for the Open Ticket `config/questions.json` config file
/**## ODQuestionsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/questions.jsonc` config file
*/
export class ODQuestionsJsonConfig extends api.ODJsonConfig<ODQuestionsJsonConfig_QuestionsData> {}
export class ODQuestionsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODQuestionsJsonConfig_QuestionsData> {}
/**## ODOptionsJsonConfig `class
* A special class with types for the Open Ticket `config/options.json` config file
/**## ODOptionsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/options.jsonc` config file
*/
export class ODOptionsJsonConfig extends api.ODJsonConfig<ODOptionsJsonConfig_OptionsData> {}
export class ODOptionsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODOptionsJsonConfig_OptionsData> {}
/**## ODPanelsJsonConfig `class
* A special class with types for the Open Ticket `config/panels.json` config file
/**## ODPanelsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/panels.jsonc` config file
*/
export class ODPanelsJsonConfig extends api.ODJsonConfig<ODPanelsJsonConfig_PanelsData> {}
export class ODPanelsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODPanelsJsonConfig_PanelsData> {}
/**## ODTranscriptsJsonConfig `class
* A special class with types for the Open Ticket `config/transcripts.json` config file
/**## ODTranscriptsJsonCommentsConfig `class
* A special class with types for the Open Ticket `config/transcripts.jsonc` config file
*/
export class ODTranscriptsJsonConfig extends api.ODJsonConfig<ODTranscriptsJsonConfig_TranscriptsData> {}
export class ODTranscriptsJsonCommentsConfig extends api.ODJsonCommentsConfig<ODTranscriptsJsonConfig_TranscriptsData> {}
+5 -5
View File
@@ -6,21 +6,21 @@ import * as api from "@open-discord-bots/framework/api"
export interface ODOpenTicketFuseList {
/**Load the default Open Ticket ticket priority levels. */
priorityLoading:boolean,
/**Load the default Open Ticket questions (from `config/questions.json`) */
/**Load the default Open Ticket questions (from `config/questions.jsonc`) */
questionLoading:boolean,
/**Load the default Open Ticket options (from `config/options.json`) */
/**Load the default Open Ticket options (from `config/options.jsonc`) */
optionLoading:boolean,
/**Load the default Open Ticket panels (from `config/panels.json`) */
/**Load the default Open Ticket panels (from `config/panels.jsonc`) */
panelLoading:boolean,
/**Load the default Open Ticket tickets (from `database/tickets.json`) */
ticketLoading:boolean,
/**Load the default Open Ticket reaction roles (from `config/options.json`) */
/**Load the default Open Ticket reaction roles (from `config/options.jsonc`) */
roleLoading:boolean,
/**Load the default Open Ticket blacklist (from `database/users.json`) */
blacklistLoading:boolean,
/**Load the default Open Ticket transcript compilers. */
transcriptCompilerLoading:boolean,
/**Load the default Open Ticket transcript history (from `database/transcripts.json`) */
/**Load the default Open Ticket transcript history (from `database/transcripts.jsonc`) */
transcriptHistoryLoading:boolean,
/**The interval in milliseconds that are between autoclose timeout checkers. */
autocloseCheckInterval:number,
+95 -49
View File
@@ -1,9 +1,24 @@
import {opendiscord, api, utilities} from "../../index.js"
import fs from "fs"
import path from "path"
/**Check if the no-migration flag is active. */
function isMigrationAllowedFromFlag(){
return (!process.argv.includes("--no-migration") && !process.argv.includes("-nm"))
}
/**Read the global.json database raw to detect the last version of the bot. */
function getRawLastVersion(){
const isDevDatabase = process.argv.includes("--dev-database") || process.argv.includes("-dd")
const globalDatabaseLocation = path.join(process.cwd(),(isDevDatabase) ? "./devdatabase/global.json" : "./database/global.json")
const rawData: api.ODJsonDatabaseStructure = JSON.parse(fs.readFileSync(globalDatabaseLocation).toString())
const lastVersion = rawData.find((d) => d.category == "opendiscord:last-version" && d.key == "opendiscord:version")?.value ?? null
return lastVersion as string|null
}
/**Check if migration is required. Returns the last version used in the database. */
async function isMigrationRequired(): Promise<false|api.ODVersion> {
const rawVersion = await opendiscord.databases.get("opendiscord:global").get("opendiscord:last-version","opendiscord:version")
const rawVersion = getRawLastVersion()
if (!rawVersion) return false
const version = api.ODVersion.fromString("opendiscord:last-version",rawVersion)
if (opendiscord.versions.get("opendiscord:version").compare(version) == "higher"){
@@ -20,47 +35,6 @@ async function saveAllVersionsToDatabase(){
})
}
export async function loadVersionMigrationSystem(){
//ENTER MIGRATION CONTEXT
await preloadMigrationContext()
const lastVersion = await isMigrationRequired()
//save last version to database (OR set to current version if no migration is required)
opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("opendiscord:last-version",opendiscord.versions.get("opendiscord:version").toString()))
if (lastVersion && !opendiscord.flags.get("opendiscord:no-migration").value){
//MIGRATION IS REQUIRED
opendiscord.log("Detected old data!","info")
opendiscord.log("Starting closed API context...","debug")
await utilities.timer(600)
opendiscord.log("Migrating data to new version...","debug")
await loadAllVersionMigrations(lastVersion)
opendiscord.log("Stopping closed API context...","debug")
await utilities.timer(400)
opendiscord.log("All data is now up to date!","info")
await utilities.timer(200)
console.log("---------------------------------------------------------------------")
}
saveAllVersionsToDatabase()
//DEFAULT FLAGS
if (opendiscord.flags.exists("opendiscord:no-plugins") && opendiscord.flags.get("opendiscord:no-plugins").value) opendiscord.sharedFuses.setFuse("pluginLoading",false)
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.sharedFuses.setFuse("softPluginLoading",true)
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.sharedFuses.setFuse("crashOnError",true)
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value){
opendiscord.sharedFuses.setFuse("forceSlashCommandRegistration",true)
opendiscord.sharedFuses.setFuse("forceContextMenuRegistration",true)
}
if (opendiscord.flags.exists("opendiscord:silent") && opendiscord.flags.get("opendiscord:silent").value) opendiscord.console.silent = true
//LEAVE MIGRATION CONTEXT
await unloadMigrationContext()
return lastVersion
}
/**Initialize the migration context by loading the built-in flags, configs & databases. */
async function preloadMigrationContext(){
opendiscord.debug.debug("-- MIGRATION CONTEXT START --")
@@ -73,6 +47,52 @@ async function preloadMigrationContext(){
opendiscord.debug.visible = true
}
export async function loadVersionMigrationSystem(){
const lastVersion = await isMigrationRequired()
//save last version in version manager (OR set to current version if no migration is required)
opendiscord.versions.add(lastVersion ? lastVersion : api.ODVersion.fromString("opendiscord:last-version",opendiscord.versions.get("opendiscord:version").toString()))
//MIGRATION IS REQUIRED
if (lastVersion && isMigrationAllowedFromFlag()){
//BEFORE STARTUP MIGRATION
opendiscord.log("Detected old data!","info")
await loadBeforeStartupMigrations(lastVersion)
}
//ENTER MIGRATION CONTEXT (must be separate for flags to work)
await preloadMigrationContext()
if (lastVersion && isMigrationAllowedFromFlag()){
//CONTEXT MIGRATION
opendiscord.log("Starting restricted API context...","debug")
await utilities.timer(600)
opendiscord.log("Migrating data to new version...","debug")
await loadContextMigrations(lastVersion)
opendiscord.log("Stopping restricted API context...","debug")
await utilities.timer(400)
opendiscord.log("All data is now up to date!","info")
await utilities.timer(200)
console.log("---------------------------------------------------------------------")
}
saveAllVersionsToDatabase()
//SET FUSES & PROPERTIES OF SPECIAL FLAGS
if (opendiscord.flags.exists("opendiscord:no-plugins") && opendiscord.flags.get("opendiscord:no-plugins").value) opendiscord.sharedFuses.setFuse("pluginLoading",false)
if (opendiscord.flags.exists("opendiscord:soft-plugins") && opendiscord.flags.get("opendiscord:soft-plugins").value) opendiscord.sharedFuses.setFuse("softPluginLoading",true)
if (opendiscord.flags.exists("opendiscord:crash") && opendiscord.flags.get("opendiscord:crash").value) opendiscord.sharedFuses.setFuse("crashOnError",true)
if (opendiscord.flags.exists("opendiscord:force-slash-update") && opendiscord.flags.get("opendiscord:force-slash-update").value){
opendiscord.sharedFuses.setFuse("forceSlashCommandRegistration",true)
opendiscord.sharedFuses.setFuse("forceContextMenuRegistration",true)
}
if (opendiscord.flags.exists("opendiscord:silent") && opendiscord.flags.get("opendiscord:silent").value) opendiscord.console.silent = true
//LEAVE MIGRATION CONTEXT
await unloadMigrationContext()
return lastVersion
}
/**Unload the migration context to start the bot normally. */
async function unloadMigrationContext(){
opendiscord.debug.visible = false
@@ -98,8 +118,8 @@ function createMigrationBackup(){
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){
/**Execute all version migration functions which are handled before any flags, configs or databases are loaded. */
async function loadBeforeStartupMigrations(lastVersion:api.ODVersion){
const migrations = (await import("./migration.js")).migrations
migrations.sort((a,b) => {
const comparison = a.version.compare(b.version)
@@ -114,10 +134,36 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrate()
const success = await migration.migrateBeforeStartup()
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
{key:"success",value:success ? "true" : "false"},
{key:"afterInit",value:"false"}
{key:"type",value:"before-startup"}
])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
}
}
}
/**Execute all version migration functions which are handled in the restricted migration context. */
async function loadContextMigrations(lastVersion:api.ODVersion){
const migrations = (await import("./migration.js")).migrations
migrations.sort((a,b) => {
const comparison = a.version.compare(b.version)
if (comparison == "equal") return 0
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.migrateInContext()
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
{key:"success",value:success ? "true" : "false"},
{key:"type",value:"restricted-context"}
])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
}
@@ -125,7 +171,7 @@ async function loadAllVersionMigrations(lastVersion:api.ODVersion){
}
/**Execute all version migration functions which are handled in the normal startup sequence. */
export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersion){
export async function loadAfterStartupMigrations(lastVersion:api.ODVersion){
const migrations = (await import("./migration.js")).migrations
migrations.sort((a,b) => {
const comparison = a.version.compare(b.version)
@@ -140,10 +186,10 @@ export async function loadAllAfterInitVersionMigrations(lastVersion:api.ODVersio
for (const migration of migrations){
if (migration.version.compare(lastVersion) == "higher"){
const success = await migration.migrateAfterInit()
const success = await migration.migrateAfterStartup()
if (success) opendiscord.log("Migrated data to "+migration.version.toString()+"!","debug",[
{key:"success",value:success ? "true" : "false"},
{key:"afterInit",value:"true"}
{key:"type",value:"after-startup"}
])
else throw new api.ODSystemError("Migration Error: Unable to migrate database & config to the new version of the bot.")
}
+308 -104
View File
@@ -1,147 +1,351 @@
import { opendiscord, api, utilities } from "../../index.js"
import fs from "fs"
import path from "path"
export const migrations = [
//MIGRATE TO v4.0.0
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.0"),{}),
//MIGRATE TO v4.0.1
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.1"),async () => {},async () => {
//AFTER INIT MIGRATION
//add opendiscord:panel-message properties for all existing panels.
const globalDatabase = opendiscord.databases.get("opendiscord:global")
for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){
globalDatabase.set("opendiscord:panel-message",panel.key,panel.value)
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.1"),{
afterStartupMigrate:async () => {
//add opendiscord:panel-message properties for all existing panels.
const globalDatabase = opendiscord.databases.get("opendiscord:global")
for (const panel of (await globalDatabase.getCategory("opendiscord:panel-update") ?? [])){
globalDatabase.set("opendiscord:panel-message",panel.key,panel.value)
}
}
}),
//MIGRATE TO v4.0.2
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.2"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.2"),{}),
//MIGRATE TO v4.0.3
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.3"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.3"),{}),
//MIGRATE TO v4.0.4
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.4"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.4"),{}),
//MIGRATE TO v4.0.5
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.5"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.5"),{}),
//MIGRATE TO v4.0.6
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.6"),{}),
//MIGRATE TO v4.0.7
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.0.7"),{}),
//MIGRATE TO v4.1.0
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.0"),async () => {},async () => {
//AFTER INIT MIGRATION
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.0"),{
afterStartupMigrate:async () => {
//migrate config
const generalConfig = opendiscord.configs.get("opendiscord:general")
const optionConfig = opendiscord.configs.get("opendiscord:options")
//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.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._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.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"].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
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.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,
showPriority:false,
showClosed:true,
showClaimed:false,
showPinned: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
generalConfig.data["system"].channelTopic = {
showOptionName:true,
showOptionDescription:false,
showOptionTopic:true,
showPriority:false,
showClosed:true,
showClaimed:false,
showPinned: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()
}
await generalConfig.save()
await optionConfig.save()
}
//migrate database
const optionDatabase = opendiscord.databases.get("opendiscord:options")
const ticketDatabase = opendiscord.databases.get("opendiscord:tickets")
//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})
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)
}
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})
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)
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
}
}
}),
//MIGRATE TO v4.1.1
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.1"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.1"),{}),
//MIGRATE TO v4.1.2
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.2"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.2"),{}),
//MIGRATE TO v4.1.3
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.3"),async () => {},async () => {}),
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.1.3"),{}),
//MIGRATE TO v4.2.0
new api.ODVersionMigration(api.ODVersion.fromString("opendiscord:version","v4.2.0"),{
beforeStartupMigrate:async () => {
const isDevconfig = (process.argv.includes("--dev-config") || process.argv.includes("-dc"))
//transfer config files to .jsonc
const configDir = path.join(process.cwd(),(isDevconfig) ? "./devconfig/" : "./config/")
for (const file of fs.readdirSync(configDir).filter((f) => f.endsWith(".json"))){
try{
fs.copyFileSync(path.join(configDir,file),path.join(configDir,file.replace(".json",".jsonc")))
fs.rmSync(path.join(configDir,file))
}catch(err){
process.emit("uncaughtException",err)
}
}
},
afterStartupMigrate:async () => {
//migrate config
const generalConfig = opendiscord.configs.get("opendiscord:general")
const questionConfig = opendiscord.configs.get("opendiscord:questions")
const optionConfig = opendiscord.configs.get("opendiscord:options")
const panelConfig = opendiscord.configs.get("opendiscord:panels")
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
if (!generalConfig.data.ticketSystem){
//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.jsonc '_INFO' category.")
delete generalConfig.data["_INFO"]
generalConfig.data._CONFIG_VERSION = "open-ticket-v4.2.0"
if (!generalConfig.data["system"]) throw new api.ODSystemError("Couldn't find general.jsonc 'system' category.")
generalConfig.data.ticketSystem = generalConfig.data["system"]
generalConfig.data.ticketSystem.closeEmoji = "🔒"
generalConfig.data.ticketSystem.askPriorityOnTicketCreation = true
generalConfig.data.ticketSystem.enableCreateTicketForOtherUser = true
delete generalConfig.data["system"]
generalConfig.data.logs = generalConfig.data.ticketSystem["logs"]
delete generalConfig.data.ticketSystem["logs"]
generalConfig.data.logs.logMessages = generalConfig.data.ticketSystem["messages"]
delete generalConfig.data.ticketSystem["messages"]
generalConfig.data.permissions = generalConfig.data.ticketSystem["permissions"]
delete generalConfig.data.ticketSystem["permissions"]
generalConfig.data.permissions.transcripts = "admin"
//closed category
const closedCategory = {enabled:false,categoryId:"DISCORD_CATEGORY_ID"}
for (const option of optionConfig.data){
if (option.type != "ticket") continue
if (option.channel["closedCategory"] && /^\d+$/.test(option.channel["closedCategory"])){
closedCategory.enabled = true
closedCategory.categoryId = option.channel["closedCategory"]
}
}
generalConfig.data.ticketSystem.closedCategory = closedCategory
//backup category
const backupCategory = {enabled:false,categoryId:"DISCORD_CATEGORY_ID"}
for (const option of optionConfig.data){
if (option.type != "ticket") continue
if (option.channel["backupCategory"] && /^\d+$/.test(option.channel["backupCategory"])){
backupCategory.enabled = true
backupCategory.categoryId = option.channel["backupCategory"]
}
}
generalConfig.data.ticketSystem.backupCategory = backupCategory
//claimed categories
const claimedCategories: {user:string,category:string}[] = []
for (const option of optionConfig.data){
if (option.type != "ticket" || !Array.isArray(option.channel["claimedCategory"])) continue
for (const {user,category} of option.channel["claimedCategory"]){
if (typeof user == "string" && typeof category == "string" && /^\d+$/.test(user) && /^\d+$/.test(category) && !claimedCategories.find((c) => c.user == user)){
claimedCategories.push({user,category})
}
}
}
generalConfig.data.ticketSystem.claimedCategories = claimedCategories
//delete properties from options.jsonc
for (const option of optionConfig.data){
if (option.type != "ticket") continue
delete option.channel["closedCategory"]
delete option.channel["backupCategory"]
delete option.channel["claimedCategory"]
}
//update panels config:
for (const panel of panelConfig.data){
panel.settings.maximumButtonsPerRow = 5
}
//update questions config:
for (const question of questionConfig.data){
if (question.type !== "paragraph" && question.type !== "short") continue
question.description = ""
}
//add new sub-panel option example (for users to try)
optionConfig.data.push({
id:"example-sub-panel",
name:"Example Sub-Panel",
description:"This is an example of how to implement a sub-panel in Open Ticket.",
type:"sub-panel",
button:{
color:"gray",
label:"Sub-Panel Example",
emoji:"📋"
},
subPanelId:panelConfig.data[0]?.id ?? "example-panel"
})
//add new question examples (for users to try)
questionConfig.data.push(
{
id:"example-dropdown-question",
name:"Example Dropdown Question",
description:"This is a dropdown question.",
type:"dropdown",
required:false,
placeholder:"Choose your answer...",
choices:[
{title:"Choice A",description:"Apple",emoji:"🍎"},
{title:"Choice B",description:"Banana",emoji:"🍌"},
{title:"Choice C",description:"Orange",emoji:"🍊"},
{title:"Choice D",description:"Kiwi",emoji:"🥝"}
]
},
{
id:"example-radio-question",
name:"Example Radio Question",
description:"This is a radio select question.",
type:"radio-select",
required:true,
choices:[
{title:"Choice A",description:"Up",selectedByDefault:false},
{title:"Choice B",description:"Down",selectedByDefault:false},
{title:"Choice C",description:"Left",selectedByDefault:false},
{title:"Choice D",description:"Right",selectedByDefault:false}
]
},
{
id:"example-checkbox-question",
name:"Example Checkbox Question",
description:"This is a checkbox select question.",
type:"checkbox-select",
required:true,
limits:{
enabled:false,
min:0,
max:10
},
choices:[
{title:"Choice A",description:"Happiness",selectedByDefault:false},
{title:"Choice B",description:"Anger",selectedByDefault:false},
{title:"Choice C",description:"Sadness",selectedByDefault:false},
{title:"Choice D",description:"Fear",selectedByDefault:false}
]
},
{
id:"example-text-display-question",
type:"text-display",
textContents:"This is a text display. It isn't a question, but allows you to display a text, explaination or details."
}
)
await generalConfig.save()
await questionConfig.save()
await optionConfig.save()
await panelConfig.save()
await transcriptConfig.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
optionData.data = optionData.data.filter((data) => (
data.id !== "opendiscord:channel-category-closed" &&
data.id !== "pendiscord:channel-category-backup" &&
data.id !== "opendiscord:channel-categories-claimed"
))
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:channel-renamed")) ticketData.data.push({id:"opendiscord:channel-renamed",value:null})
ticketDatabase.set("opendiscord:ticket",ticket.key,ticketData)
}
}
}),
]
+250 -103
View File
@@ -17,7 +17,7 @@ export async function loadAllConfigCheckerFunctions(){
}
export async function loadAllConfigCheckerTranslations(){
if ((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false){
if ((generalConfig && generalConfig.data.ticketSystem && generalConfig.data.ticketSystem.useTranslatedConfigChecker) ? generalConfig.data.ticketSystem.useTranslatedConfigChecker : false){
registerDefaultCheckerSystemTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker system text
registerDefaultCheckerMessageTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate checker messages
registerDefaultCheckerCustomTranslations(opendiscord.checkers.translation,opendiscord.languages) //translate custom checker messages
@@ -25,7 +25,7 @@ export async function loadAllConfigCheckerTranslations(){
}
//GLOBAL FUNCTIONS
export const registerDefaultCheckerSystemTranslations = (tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager) => {
export function registerDefaultCheckerSystemTranslations(tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager){
//SYSTEM
tm.quickTranslate(lm,"checker.system.headerOpenTicket","other","opendiscord:header-projectname") //OPEN TICKET
tm.quickTranslate(lm,"checker.system.typeError","other","opendiscord:type-error") // [ERROR] (ignore)
@@ -42,7 +42,7 @@ export const registerDefaultCheckerSystemTranslations = (tm:api.ODMappedCheckerT
tm.quickTranslate(lm,"checker.system.dataMessages","other","opendiscord:data-message") // message
}
export const registerDefaultCheckerMessageTranslations = (tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager) => {
export function registerDefaultCheckerMessageTranslations(tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager){
//STRUCTURES
tm.quickTranslate(lm,"checker.messages.invalidType","message","opendiscord:invalid-type") // This property needs to be the type: {0}!
tm.quickTranslate(lm,"checker.messages.propertyMissing","message","opendiscord:property-missing") // The property {0} is missing from this object!
@@ -117,7 +117,7 @@ export const registerDefaultCheckerMessageTranslations = (tm:api.ODMappedChecker
tm.quickTranslate(lm,"checker.messages.idNonExistent","message","opendiscord:id-non-existent") // The id {0} doesn't exist!
}
export const registerDefaultCheckerCustomTranslations = (tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager) => {
export function registerDefaultCheckerCustomTranslations(tm:api.ODMappedCheckerTranslationRegister,lm:api.ODMappedLanguageManager){
//CUSTOM
tm.quickTranslate(lm,"checker.messages.invalidLanguage","message","opendiscord:invalid-language") // This is an invalid language!
tm.quickTranslate(lm,"checker.messages.invalidButton","message","opendiscord:invalid-button") // This button needs to have at least an {0} or {1}!
@@ -128,13 +128,30 @@ export const registerDefaultCheckerCustomTranslations = (tm:api.ODMappedCheckerT
}
//UTILITY FUNCTIONS
const createMsgStructure = (id:api.ODValidId,displayName:string) => {
/**Get the panel ids from `panels.jsonc` before it has been checked by the config checker. */
function getUnsafePanelIds(): string[] {
const panelsConfig = opendiscord.configs.get("opendiscord:panels")
if (!Array.isArray(panelsConfig.data)) return []
const panelIds: string[] = []
for (const unsafePanel of panelsConfig.data){
if (unsafePanel["id"]) panelIds.push(unsafePanel["id"])
}
return panelIds
}
function createMsgStructure(id:api.ODValidId,displayName:string){
return new api.ODCheckerObjectStructure(id,{children:[
{key:"dm",checker:new api.ODCheckerBooleanStructure("opendiscord:msg-dm",{cliInitDefaultValue:false,cliDisplayName:"DM Enabled",cliDisplayDescription:"Will this action be sent in DM to the creator of the ticket?"})},
{key:"logs",checker:new api.ODCheckerBooleanStructure("opendiscord:msg-logs",{cliInitDefaultValue:true,cliDisplayName:"Logs Enabled",cliDisplayDescription:"Will this action be sent in the Discord log channel?"})},
],cliDisplayName:displayName,cliDisplayDescription:"Configure which places this action gets logged/sent to."})
}
const createTicketEmbedStructure = (id:api.ODValidId) => {
function createPermissionStructure(id:api.ODValidId,displayName:string){
return new api.ODCheckerCustomStructure_DiscordId(id,"role",false,["admin","everyone","none"],{cliDisplayName:displayName,cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})
}
function createTicketEmbedStructure(id:api.ODValidId){
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this message."})},
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:ticket-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})},
@@ -151,14 +168,16 @@ const createTicketEmbedStructure = (id:api.ODValidId) => {
{key:"timestamp",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-embed-timestamp",{cliDisplayName:"Timestamp",cliDisplayDescription:"Add a timestamp to the embed."})}
],cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."}),cliInitDefaultValue:{enabled:false,title:"",description:"",customColor:"",image:"",thumbnail:"",fields:[],timestamp:false},cliDisplayName:"Message Embed",cliDisplayDescription:"Configure the embed of this message."})
}
const createTicketPingStructure = (id:api.ODValidId) => {
function createTicketPingStructure(id:api.ODValidId){
return new api.ODCheckerObjectStructure(id,{children:[
{key:"@here",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-here",{cliDisplayName:"@here Ping",cliDisplayDescription:"Enable/disable an '@here' ping."})},
{key:"@everyone",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-ping-everyone",{cliDisplayName:"@everyone Ping",cliDisplayDescription:"Enable/disable an '@everyone' ping."})},
{key:"custom",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ping-custom","role",[],{allowDoubles:false,cliDisplayPropertyName:"custom role id",cliDisplayName:"Custom Role Ping",cliDisplayDescription:"Choose your own roles to ping in this message."},{cliDisplayName:"Custom Role",cliDisplayDescription:"The discord role ID of a custom mention/ping."})},
],cliInitDefaultValue:{"@here":true,"@everyone":false,custom:[],cliDisplayName:"Message Pings",cliDisplayDescription:"Configure the pings/mentions of this message."}})
}
const createPanelEmbedStructure = (id:api.ODValidId) => {
function createPanelEmbedStructure(id:api.ODValidId){
return new api.ODCheckerEnabledObjectStructure(id,{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure(id,{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-embed-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the embed of this panel."})},
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:panel-embed-text",{maxLength:256,cliDisplayName:"Title",cliDisplayDescription:"The title of this embed."})},
@@ -188,23 +207,19 @@ function loadFromEnv(){
//STRUCTURES
export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendiscord:general",{children:[
//INFO
{key:"_INFO",cliHideInEditMode:true,checker:new api.ODCheckerObjectStructure("opendiscord:info",{children:[
{key:"support",checker:new api.ODCheckerStringStructure("opendiscord:info-support",{choices:["https://otdocs.dj-dj.be"]})},
{key:"discord",checker:new api.ODCheckerStringStructure("opendiscord:info-discord",{choices:["https://discord.dj-dj.be"]})},
{key:"version",checker:new api.ODCheckerStringStructure("opendiscord:info-version",{custom(checker,value,locationTrace,locationId,locationDocs) {
const lt = checker.locationTraceDeref(locationTrace)
if (typeof value != "string") return false
else if (value != "open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()){
checker.createMessage("opendiscord:invalid-version","warning","The version specified in your config does not match! Make sure you have updated the config to the latest version!",lt,null,[],locationId,locationDocs)
return false
}else return true
},})},
]})},
{key:"_CONFIG_VERSION",cliHideInEditMode:true,checker:new api.ODCheckerStringStructure("opendiscord:config-version",{custom(checker,value,locationTrace,locationId,locationDocs) {
const lt = checker.locationTraceDeref(locationTrace)
if (typeof value != "string") return false
else if (value != "open-ticket-"+opendiscord.versions.get("opendiscord:version").toString()){
checker.createMessage("opendiscord:invalid-version","warning","The version specified in your config does not match! Make sure you have updated the config to the latest version!",lt,null,[],locationId,locationDocs)
return false
}else return true
},})},
//BASIC
{key:"token",checker:(loadFromEnv()) ? new api.ODCheckerStringStructure("opendiscord:token-disabled",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."}) : new api.ODCheckerCustomStructure_DiscordToken("opendiscord:token",{cliDisplayName:"Token",cliDisplayDescription:"The token of your discord bot."})},
{key:"tokenFromENV",checker:new api.ODCheckerBooleanStructure("opendiscord:token-env",{cliDisplayName:"Token From ENV",cliDisplayDescription:"Use the token from the .env file instead of general.json."})},
{key:"tokenFromENV",checker:new api.ODCheckerBooleanStructure("opendiscord:token-env",{cliDisplayName:"Token From ENV",cliDisplayDescription:"Use the token from the .env file instead of general.jsonc."})},
{key:"mainColor",checker:new api.ODCheckerCustomStructure_HexColor("opendiscord:main-color",true,false,{cliDisplayName:"Main Color",cliDisplayDescription:"The main color of your bot, used in almost all embeds."})},
{key:"language",checker:new api.ODCheckerStringStructure("opendiscord:language",{
custom:(checker,value,locationTrace,locationId,locationDocs) => {
@@ -230,6 +245,7 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"status",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:status",{
property:"enabled",
enabledValue:true,
ignoreCheckIfDisabled:true,
checker:new api.ODCheckerObjectStructure("opendiscord:status",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:status-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable the status. When disabled, the bot will be online without any status."})},
{key:"type",checker:new api.ODCheckerStringStructure("opendiscord:status-type",{choices:["listening","watching","playing","custom"],cliDisplayName:"Type",cliDisplayDescription:"The type of status: Listening, Watching, Playing or Custom."})},
@@ -241,8 +257,8 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
cliDisplayDescription:"Manage the status of the bot."
})},
//SYSTEM
{key:"system",checker:new api.ODCheckerObjectStructure("opendiscord:system",{children:[
//TICKET SYSTEM
{key:"ticketSystem",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-system",{children:[
{key:"preferSlashOverText",checker:new api.ODCheckerBooleanStructure("opendiscord:prefer-slash-over-text",{cliDisplayName:"Prefer Slash Over Text",cliDisplayDescription:"Prefer displaying slash commands over text commands in help menus."})},
{key:"sendErrorOnUnknownCommand",checker:new api.ODCheckerBooleanStructure("opendiscord:send-error-on-unknown-command",{cliDisplayName:"Send Error On Unknown Command",cliDisplayDescription:"Send an error when using the text-command prefix without a valid command."})},
{key:"questionFieldsInCodeBlock",checker:new api.ODCheckerBooleanStructure("opendiscord:question-fields-in-code-block",{cliDisplayName:"Questions Fields In Code Blocks",cliDisplayDescription:"Display question fields in code blocks instead of plain text."})},
@@ -252,7 +268,8 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"useRedErrorEmbeds",checker:new api.ODCheckerBooleanStructure("opendiscord:use-red-error-embeds",{cliDisplayName:"Use Red Error Embeds",cliDisplayDescription:"Display all error messages with a red border instead of the default color of the bot."})},
{key:"alwaysShowReason",checker:new api.ODCheckerBooleanStructure("opendiscord:always-show-reason",{cliDisplayName:"Always Show Reason",cliDisplayDescription:"Always show the reason field in embeds, even when there is no reason provided."})},
{key:"emojiStyle",checker:new api.ODCheckerStringStructure("opendiscord:emoji-style",{choices:["before","after","double","disabled"],cliDisplayName:"Emoji Style",cliDisplayDescription:"Choose how the bot will display emojis in message titles. (Visit docs for more info)"})},
{key:"pinEmoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:pin-emoji",1,1,false,{cliDisplayName:"Pin Emoji",cliDisplayDescription:"The emoji used when pinning tickets. This is '📌' by default."})},
{key:"pinEmoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:pin-emoji",0,1,false,{cliDisplayName:"Pin Emoji",cliDisplayDescription:"The emoji used when pinning tickets. This is '📌' by default. Leave empty to disable."})},
{key:"closeEmoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:close-emoji",0,1,false,{cliDisplayName:"Pin Emoji",cliDisplayDescription:"The emoji used when closing tickets. This is '🔒' by default. Leave empty to disable."})},
{key:"replyOnTicketCreation",checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-ticket-creation",{cliDisplayName:"Reply On Ticket Creation",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when creating a ticket."})},
{key:"replyOnReactionRole",checker:new api.ODCheckerBooleanStructure("opendiscord:reply-on-reaction-role",{cliDisplayName:"Reply On Reaction Role",cliDisplayDescription:"When enabled, the bot will send an ephemeral reply in the channel of the panel when using a role button."})},
@@ -272,11 +289,7 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"enableTicketDeleteButtons",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-delete-buttons",{cliDisplayName:"Enable Ticket Delete Buttons",cliDisplayDescription:"Enable/disable buttons for deleting a ticket. Be aware that this doesn't disable the command!"})},
{key:"enableTicketActionWithReason",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-ticket-action-with-reason",{cliDisplayName:"Enable Ticket Action With Reason",cliDisplayDescription:"Enable/disable buttons to write an additional reason for all ticket actions."})},
{key:"enableDeleteWithoutTranscript",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-delete-without-transcript",{cliDisplayName:"Enable Delete Without Transcript",cliDisplayDescription:"Enable/disable the ability to delete tickets without a transcript."})},
{key:"logs",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:system-logs",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:system-logs",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:logs-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable discord logs in a discord channel."})},
{key:"channel",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:logs-channel","channel",false,[],{cliDisplayName:"Log Channel",cliDisplayDescription:"The ID of the discord channel to log messages to. You can configure the messages somewhere else."})},
],cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage everything related to logs in a discord channel."}),cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage everything related to logs in a discord channel."})},
{key:"enableCreateTicketForOtherUser",checker:new api.ODCheckerBooleanStructure("opendiscord:enable-create-for-other-user",{cliDisplayName:"Enable Create ticket for other user",cliDisplayDescription:"Enable/disable the ability for admins to create a ticket for another user."})},
{key:"limits",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:limits",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:limits",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:limits-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable global limits."})},
@@ -287,42 +300,66 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"channelTopic",checker:new api.ODCheckerObjectStructure("opendiscord:channel-topic",{children:[
{key:"showOptionName",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-name",{cliDisplayName:"Show Option Name",cliDisplayDescription:"Show the option name in the channel topic."})},
{key:"showOptionDescription",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-description",{cliDisplayName:"Show Option Description",cliDisplayDescription:"Show the option description in the channel topic."})},
{key:"showOptionTopic",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-topic",{cliDisplayName:"Show Option Topic",cliDisplayDescription:"Show the option topic text in the channel topic (configured in the options.json config)."})},
{key:"showOptionTopic",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-option-topic",{cliDisplayName:"Show Option Topic",cliDisplayDescription:"Show the option topic text in the channel topic (configured in the options.jsonc config)."})},
{key:"showPriority",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-priority",{cliDisplayName:"Show Priority",cliDisplayDescription:"Show the current priority in the channel topic (auto-updated)."})},
{key:"showClosed",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-closed",{cliDisplayName:"Show Closed Status",cliDisplayDescription:"Show the current close/reopen status in the channel topic (auto-updated)."})},
{key:"showClaimed",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-claimed",{cliDisplayName:"Show Claimed Status",cliDisplayDescription:"Show the current claim status in the channel topic (auto-updated)."})},
{key:"showPinned",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-pinned",{cliDisplayName:"Show Pinned Status",cliDisplayDescription:"Show the current pin status in the channel topic (auto-updated)."})},
{key:"showCreator",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-creator",{cliDisplayName:"Show Creator",cliDisplayDescription:"Show the creator of the ticket in the channel topic (auto-updated on transfer)."})},
{key:"showParticipants",checker:new api.ODCheckerBooleanStructure("opendiscord:topic-show-participants",{cliDisplayName:"Show Participants",cliDisplayDescription:"Show the first 5 participants of the ticket in the channel topic (auto-updated)."})},
],cliDisplayName:"Channel Topic",cliDisplayDescription:"Manage stats and text of ticket channel topics."})},
{key:"permissions",checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[
{key:"help",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-help","role",false,["admin","everyone","none"],{cliDisplayName:"Help",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"panel",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-panel","role",false,["admin","everyone","none"],{cliDisplayName:"Panel",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"ticket",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-ticket","role",false,["admin","everyone","none"],{cliDisplayName:"Ticket",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"close",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-close","role",false,["admin","everyone","none"],{cliDisplayName:"Close",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"delete",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-delete","role",false,["admin","everyone","none"],{cliDisplayName:"Delete",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"reopen",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-reopen","role",false,["admin","everyone","none"],{cliDisplayName:"Reopen",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"claim",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-claim","role",false,["admin","everyone","none"],{cliDisplayName:"Claim",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"unclaim",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unclaim","role",false,["admin","everyone","none"],{cliDisplayName:"Unclaim",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"pin",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-pin","role",false,["admin","everyone","none"],{cliDisplayName:"Pin",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"unpin",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-unpin","role",false,["admin","everyone","none"],{cliDisplayName:"Unpin",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"move",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-move","role",false,["admin","everyone","none"],{cliDisplayName:"Move",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"rename",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-rename","role",false,["admin","everyone","none"],{cliDisplayName:"Rename",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"add",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-add","role",false,["admin","everyone","none"],{cliDisplayName:"Add User",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"remove",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-remove","role",false,["admin","everyone","none"],{cliDisplayName:"Remove User",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"blacklist",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-blacklist","role",false,["admin","everyone","none"],{cliDisplayName:"Blacklist",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"stats",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-stats","role",false,["admin","everyone","none"],{cliDisplayName:"Stats",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"clear",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-clear","role",false,["admin","everyone","none"],{cliDisplayName:"Clear Tickets",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"autoclose",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autoclose","role",false,["admin","everyone","none"],{cliDisplayName:"Autoclose",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"autodelete",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-autodelete","role",false,["admin","everyone","none"],{cliDisplayName:"Autodelete",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"transfer",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-transfer","role",false,["admin","everyone","none"],{cliDisplayName:"Transfer",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"topic",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-topic","role",false,["admin","everyone","none"],{cliDisplayName:"Topic",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
{key:"priority",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:permissions-priority","role",false,["admin","everyone","none"],{cliDisplayName:"Priority",cliHideDescriptionInParent:true,cliDisplayDescription:"Set the permissions to 'everyone' for everyone, 'admin' for admin only, 'none' to disable or a custom discord role ID."})},
],cliDisplayName:"Permissions",cliDisplayDescription:"Manage all button & command permissions in the bot. (Visit docs for more info)"})},
{key:"closedCategory",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:closed-category",{property:"enabled",enabledValue:true,ignoreCheckIfDisabled:true,checker:new api.ODCheckerObjectStructure("opendiscord:closed-category",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:closed-category-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable closed category."})},
{key:"categoryId",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:closed-category","category",true,[],{cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where tickets will be moved to when closed."})},
],cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where tickets will be moved to when closed."}),cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where tickets will be moved to when closed."})},
{key:"backupCategory",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:backup-category",{property:"enabled",enabledValue:true,ignoreCheckIfDisabled:true,checker:new api.ODCheckerObjectStructure("opendiscord:backup-category",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:backup-category-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable backup category."})},
{key:"categoryId",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:backup-category","category",true,[],{cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where tickets will be created in when the original category is full (50 channels)."})},
],cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where tickets will be created in when the original category is full (50 channels)."}),cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where tickets will be created in when the original category is full (50 channels)."})},
{key:"claimedCategories",checker:new api.ODCheckerArrayStructure("opendiscord:claimed-categories",{allowDoubles:false,allowedTypes:["object"],cliDisplayPropertyName:"claim category",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:claimed-category",{children:[
{key:"user",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:claimed-user","user",false,[],{cliDisplayName:"User",cliDisplayDescription:"The discord user ID of a ticket claimer."})},
{key:"category",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:claimed-category","category",false,[],{cliDisplayName:"Category",cliDisplayDescription:"The discord category ID to move the ticket to."})}
],cliDisplayName:"Claimed Category",cliDisplayDescription:"Move claimed tickets to the matching channel category of the user that claimed the ticket."}),cliDisplayName:"Claimed Categories",cliDisplayDescription:"Move claimed tickets to the matching channel category of the user that claimed the ticket."})},
],cliDisplayName:"Ticket System",cliDisplayDescription:"Configure the 'Open Ticket' ticket system."})},
{key:"messages",checker:new api.ODCheckerObjectStructure("opendiscord:system-permissions",{children:[
//COMMAND PERMISSIONS
{key:"permissions",checker:new api.ODCheckerObjectStructure("opendiscord:permissions",{children:[
{key:"help",checker:createPermissionStructure("opendiscord:permissions-help","Help")},
{key:"panel",checker:createPermissionStructure("opendiscord:permissions-panel","Panel")},
{key:"ticket",checker:createPermissionStructure("opendiscord:permissions-ticket","Ticket")},
{key:"close",checker:createPermissionStructure("opendiscord:permissions-close","Close")},
{key:"delete",checker:createPermissionStructure("opendiscord:permissions-delete","Delete")},
{key:"reopen",checker:createPermissionStructure("opendiscord:permissions-reopen","Reopen")},
{key:"claim",checker:createPermissionStructure("opendiscord:permissions-claim","Claim")},
{key:"unclaim",checker:createPermissionStructure("opendiscord:permissions-unclaim","Unclaim")},
{key:"pin",checker:createPermissionStructure("opendiscord:permissions-pin","Pin")},
{key:"unpin",checker:createPermissionStructure("opendiscord:permissions-unpin","Unpin")},
{key:"move",checker:createPermissionStructure("opendiscord:permissions-move","Move")},
{key:"rename",checker:createPermissionStructure("opendiscord:permissions-rename","Rename")},
{key:"add",checker:createPermissionStructure("opendiscord:permissions-add","Add User")},
{key:"remove",checker:createPermissionStructure("opendiscord:permissions-remove","Remove User")},
{key:"blacklist",checker:createPermissionStructure("opendiscord:permissions-blacklist","Blacklist")},
{key:"stats",checker:createPermissionStructure("opendiscord:permissions-stats","Stats")},
{key:"clear",checker:createPermissionStructure("opendiscord:permissions-clear","Clear Tickets")},
{key:"autoclose",checker:createPermissionStructure("opendiscord:permissions-autoclose","Autoclose")},
{key:"autodelete",checker:createPermissionStructure("opendiscord:permissions-autodelete","Autodelete")},
{key:"transfer",checker:createPermissionStructure("opendiscord:permissions-transfer","Transfer")},
{key:"topic",checker:createPermissionStructure("opendiscord:permissions-topic","Topic")},
{key:"priority",checker:createPermissionStructure("opendiscord:permissions-priority","Priority")},
{key:"transcripts",checker:createPermissionStructure("opendiscord:permissions-transcripts","Transcripts History")},
],cliDisplayName:"Permissions",cliDisplayDescription:"Manage all button & command permissions in the bot. (Visit docs for more info)"})},
//LOGS
{key:"logs",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:logs",{property:"enabled",enabledValue:true,ignoreCheckIfDisabled:true,checker:new api.ODCheckerObjectStructure("opendiscord:logs",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:logs-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable discord logs in a discord channel."})},
{key:"channel",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:logs-channel","channel",false,[],{cliDisplayName:"Log Channel",cliDisplayDescription:"The log message channel ID."})},
//LOG MESSAGES
{key:"logMessages",checker:new api.ODCheckerObjectStructure("opendiscord:log-messages",{children:[
{key:"creation",checker:createMsgStructure("opendiscord:msg-creation","Ticket Created")},
{key:"closing",checker:createMsgStructure("opendiscord:msg-closing","Ticket Closed")},
{key:"deleting",checker:createMsgStructure("opendiscord:msg-deleting","Ticket Deleted")},
@@ -338,22 +375,23 @@ export const defaultGeneralStructure = new api.ODCheckerObjectStructure("opendis
{key:"topicChange",checker:createMsgStructure("opendiscord:msg-topic-change","Topic Changed")},
{key:"priorityChange",checker:createMsgStructure("opendiscord:msg-priority-change","Priority Changed")},
{key:"reactionRole",checker:createMsgStructure("opendiscord:msg-reaction-role","Reaction Role")},
],cliDisplayName:"Messages",cliDisplayDescription:"Manage all messages & DM's for each action of the bot. (Visit docs for more info)"})},
],cliDisplayName:"System",cliDisplayDescription:"Configure everything related to the ticket system."})}
],cliDisplayName:"Log Messages",cliDisplayDescription:"Manage all messages & DM's for each action of the bot. (Visit docs for more info)"})},
],cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage the 'Open Ticket' logs channel."}),cliDisplayName:"Discord Logs",cliDisplayDescription:"Manage the 'Open Ticket' logs channel."})},
],cliDisplayName:"General",cliDisplayDescription:"General settings for the bot."})
export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendiscord:options",{allowedTypes:["object"],cliDisplayPropertyName:"option",propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[
//TICKET
{name:"Ticket",priority:0,properties:[{key:"type",value:"ticket"}],checker:new api.ODCheckerObjectStructure("opendiscord:ticket",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],cliInitSkipKeys:["readonlyAdmins"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:ticket-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this ticket option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:ticket-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this ticket option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:ticket-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this ticket option."})},
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this ticket option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this ticket option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this ticket option."})},
//TICKET BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists
@@ -369,7 +407,7 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
{key:"ticketAdmins",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-ticket-admins","role",[],{allowDoubles:false,cliDisplayPropertyName:"ticket admin role",cliDisplayName:"Ticket Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to interact with this ticket option."},{cliDisplayName:"Ticket Admin Role",cliDisplayDescription:"The discord role ID of a ticket admin."})},
{key:"readonlyAdmins",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:ticket-readonly-admins","role",[],{allowDoubles:false,cliInitDefaultValue:[],cliDisplayPropertyName:"read-only ticket admin role",cliDisplayName:"Readonly Admin Roles",cliDisplayDescription:"A list of role IDs that are only able to read this ticket option."},{cliDisplayName:"Readonly Admin Role",cliDisplayDescription:"The discord role ID of a readonly admin."})},
{key:"allowCreationByBlacklistedUsers",checker:new api.ODCheckerBooleanStructure("opendiscord:ticket-allow-blacklisted-users",{cliDisplayName:"Allow Creation By Blacklisted Users",cliDisplayDescription:"When enabled, the blacklist doesn't apply to this ticket option/type and users are still able to create a ticket."})},
{key:"questions",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5,cliDisplayPropertyName:"question",cliDisplayName:"Questions",cliDisplayDescription:"A list of valid question IDs to ask before creating this ticket."},{cliDisplayName:"Question ID",cliDisplayDescription:"A valid question ID from the questions.json config.",cliAutocompleteFunc:async () => {
{key:"questions",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:option-questions","openticket","question-ids","question-ids-used",{allowDoubles:false,maxLength:5,cliDisplayPropertyName:"question",cliDisplayName:"Questions",cliDisplayDescription:"A list of valid question IDs to ask before creating this ticket."},{cliDisplayName:"Question ID",cliDisplayDescription:"A valid question ID from the questions.jsonc config.",cliAutocompleteFunc:async () => {
const uncheckedRawData = opendiscord.configs.get("opendiscord:questions").data
if (!Array.isArray(uncheckedRawData)) return null
const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id)
@@ -380,15 +418,8 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
{key:"channel",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel",{cliInitSkipKeys:["backupCategory","claimedCategory"],children:[
{key:"prefix",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-prefix",{maxLength:25,regex:/^[^\s]*$/,cliDisplayName:"Prefix",cliDisplayDescription:"The prefix of the name of the ticket channel. (e.g. 'question-')"})},
{key:"suffix",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-suffix",{choices:["user-name","user-nickname","user-id","random-number","random-hex","counter-dynamic","counter-fixed"],cliDisplayName:"Suffix",cliDisplayDescription:"The suffix mode to use. The number/text will be appended after the prefix."})},
{key:"category",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-category","category",true,[],{cliDisplayName:"Category",cliDisplayDescription:"The category the ticket will be created in. Leave empty for no category."})},
{key:"closedCategory",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-closed-category","category",true,[],{cliDisplayName:"Closed Category",cliDisplayDescription:"An additional category where the ticket will be moved to when closed."})},
{key:"backupCategory",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-backup-category","category",true,[],{cliDisplayName:"Backup Category",cliDisplayDescription:"An additional category where the ticket will be created in when the primary category is full (50 channels)."})},
{key:"claimedCategory",checker:new api.ODCheckerArrayStructure("opendiscord:ticket-channel-claimed-category",{allowDoubles:false,allowedTypes:["object"],cliDisplayPropertyName:"claim category",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:ticket-channel-claimed-category",{children:[
{key:"user",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-user","user",false,[],{cliDisplayName:"User",cliDisplayDescription:"A discord user ID of the ticket claimer."})},
{key:"category",checker:new api.ODCheckerCustomStructure_DiscordId("opendiscord:ticket-channel-claimed-category","category",false,[],{cliDisplayName:"Category",cliDisplayDescription:"A discord category ID to move the ticket to."})}
],cliDisplayName:"Claimed Category",cliDisplayDescription:"A collection of a user ID and a category ID. The ticket will be moved to the category when this user claims the ticket."}),cliDisplayName:"Claimed Categories",cliDisplayDescription:"Add categories to move the ticket to when a user claims a ticket."})},
{key:"topic",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-topic",{cliDisplayName:"Channel Topic",cliDisplayDescription:"The topic text of the ticket channel. Visible in the discord client when general.json 'channelTopic'.'showOptionTopic' is enabled."})},
{key:"topic",checker:new api.ODCheckerStringStructure("opendiscord:ticket-channel-topic",{cliDisplayName:"Channel Topic",cliDisplayDescription:"The topic text of the ticket channel. Visible in the discord client when general.jsonc 'channelTopic'.'showOptionTopic' is enabled."})},
],cliDisplayName:"Channel",cliDisplayDescription:"Manage all settings related to the ticket channel and categories."})},
//DM MESSAGE
@@ -445,14 +476,14 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
//WEBSITE
{name:"Website",priority:0,properties:[{key:"type",value:"website"}],checker:new api.ODCheckerObjectStructure("opendiscord:website",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:website-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this website option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:website-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this website option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:website-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this website option."})},
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this website option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this website option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this website option."})},
//WEBSITE BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists
@@ -470,15 +501,15 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
//REACTION ROLES
{name:"Reaction Role",priority:0,properties:[{key:"type",value:"role"}],checker:new api.ODCheckerObjectStructure("opendiscord:role",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:role-id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this role option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:role-name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this role option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:role-description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this role option."})},
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this role option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this role option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this role option."})},
//ROLE BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:ticket-button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:ticket-button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:ticket-button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists
@@ -496,13 +527,52 @@ export const defaultOptionsStructure = new api.ODCheckerArrayStructure("opendisc
{key:"removeRolesOnAdd",checker:new api.ODCheckerCustomStructure_DiscordIdArray("opendiscord:role-remove-roles","role",[],{allowDoubles:false,cliDisplayPropertyName:"role",cliDisplayName:"Remove Roles On Add",cliDisplayDescription:"An additional list of roles to remove when the roles of this option are added. (Can be used to select between roles)"},{cliDisplayName:"Remove Role",cliDisplayDescription:"The discord role ID you want to remove when other roles are added."})},
{key:"addOnMemberJoin",checker:new api.ODCheckerBooleanStructure("opendiscord:role-add-on-join",{cliDisplayName:"Add On Member Join",cliDisplayDescription:"Automatically add these roles to a user when joining the server."})},
],cliDisplayName:"Reaction Role Option",cliDisplayDescription:"Manage all settings of this reaction role option."})},
//SUB-PANEL
{name:"Reaction Role",priority:0,properties:[{key:"type",value:"sub-panel"}],checker:new api.ODCheckerObjectStructure("opendiscord:sub-panel",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:id","openticket","option-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this sub-panel option. Used in panels."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:name",{minLength:2,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this sub-panel option."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:description",{maxLength:256,cliDisplayName:"Description",cliDisplayDescription:"The description of this sub-panel option."})},
//SUB-PANEL BUTTON
{key:"button",checker:new api.ODCheckerObjectStructure("opendiscord:button",{children:[
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:button-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"label",checker:new api.ODCheckerStringStructure("opendiscord:button-label",{maxLength:80,cliDisplayName:"Label",cliDisplayDescription:"The label of the button. At least 1 of 2 (emoji/label) must be provided."})},
{key:"color",checker:new api.ODCheckerStringStructure("opendiscord:button-color",{choices:["gray","red","green","blue"],cliDisplayName:"Color",cliDisplayDescription:"The color of the button. Does not apply when using a dropdown panel."})},
],custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace)
//check if emoji & label exists
if (typeof value != "object") return false
else if (value && value["emoji"].length < 1 && value["label"].length < 1){
//label & emoji are both empty
checker.createMessage("opendiscord:invalid-button","error",`This button needs to have at least an "emoji" or "label"!`,lt,null,[`"emoji"`,`"label"`],locationId,locationDocs)
return false
}else return true
},cliDisplayName:"Button",cliDisplayDescription:"Customise the button layout of this sub-panel option."})},
//SUB-PANEL SETTINGS
{key:"subPanelId",checker:new api.ODCheckerStringStructure("ot-footers:panel-id",{custom:(checker,value,locationTrace,locationId,locationDocs) => {
const lt = checker.locationTraceDeref(locationTrace)
if (typeof value != "string") return false
if (getUnsafePanelIds().includes(value)){
//exists
return true
}else{
//doesn't exist
checker.createMessage("opendiscord:id-non-existent","error",`The panel id "${value}" doesn't exist!`,lt,null,[`"${value}"`],locationId,locationDocs)
return false
}
}})},
],cliDisplayName:"Sub-Panel Option",cliDisplayDescription:"Manage all settings of this sub-panel option."})},
],cliDisplayName:"Option",cliDisplayDescription:"Manage an option of one of the 3 types: ticket, website, role."}),cliDisplayName:"Options",cliDisplayDescription:"A list of all options in the bot. Here you can add, modify & remove ticket types, website buttons & reaction roles!"})
export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendiscord:panels",{allowedTypes:["object"],cliDisplayPropertyName:"panel",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:panels",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","dropdown"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:panel-id","openticket","panel-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this panel. Used in the /panel command."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:panel-name",{minLength:3,maxLength:50,cliDisplayName:"Name",cliDisplayDescription:"The name of this panel."})},
{key:"dropdown",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-dropdown",{cliDisplayName:"Dropdown",cliDisplayDescription:"Decide whether to use buttons or a dropdown in the panel. Dropdowns only support options of the 'ticket' type!"})},
{key:"options",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,minLength:1,maxLength:25,cliDisplayPropertyName:"option",cliDisplayName:"Options",cliDisplayDescription:"A list of valid option IDs to show in this panel."},{cliDisplayName:"Option ID",cliDisplayDescription:"A valid option ID from the options.json config.",cliAutocompleteFunc:async () => {
{key:"options",checker:new api.ODCheckerCustomStructure_UniqueIdArray("opendiscord:panel-options","openticket","option-ids","option-ids-used",{allowDoubles:false,minLength:1,maxLength:25,cliDisplayPropertyName:"option",cliDisplayName:"Options",cliDisplayDescription:"A list of valid option IDs to show in this panel."},{cliDisplayName:"Option ID",cliDisplayDescription:"A valid option ID from the options.jsonc config.",cliAutocompleteFunc:async () => {
const uncheckedRawData = opendiscord.configs.get("opendiscord:options").data
if (!Array.isArray(uncheckedRawData)) return null
const idList = uncheckedRawData.filter((option) => typeof option == "object" && typeof option["id"] == "string").map((option) => option.id)
@@ -516,6 +586,8 @@ export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendisco
//SETTINGS
{key:"settings",checker:new api.ODCheckerObjectStructure("opendiscord:panel-settings",{cliInitSkipKeys:["dropdownPlaceholder","describeOptionsCustomTitle"],children:[
{key:"dropdownPlaceholder",checker:new api.ODCheckerStringStructure("opendiscord:panel-settings-placeholder",{maxLength:100,cliInitDefaultValue:"Create a ticket!",cliDisplayName:"Dropdown Placeholder",cliDisplayDescription:"Configure the text displayed in the dropdown when nothing is selected."})},
{key:"maximumButtonsPerRow",checker:new api.ODCheckerNumberStructure("opendiscord:panel-settings-row-amount",{min:1,max:5,floatAllowed:false,cliInitDefaultValue:5,cliDisplayName:"Maximum Buttons Per Row",cliDisplayDescription:"Set the maximum amount of buttons in a single row before starting a new one."})},
{key:"enableMaxTicketsWarningInText",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-text",{cliDisplayName:"Enable Max Tickets Warning (Text)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the text contents of the panel."})},
{key:"enableMaxTicketsWarningInEmbed",checker:new api.ODCheckerBooleanStructure("opendiscord:panel-settings-maxtickets-embed",{cliDisplayName:"Enable Max Tickets Warning (Embed)",cliDisplayDescription:"Enable/disable the warning which shows how many tickets you can create in the embed of the panel."})},
@@ -527,20 +599,95 @@ export const defaultPanelsStructure = new api.ODCheckerArrayStructure("opendisco
],cliDisplayName:"Settings",cliDisplayDescription:"Manage additional settings & customisability for this panel."})},
],cliDisplayName:"Panel",cliDisplayDescription:"Manage, customise and configure a panel to your preference."}),cliDisplayName:"Panels",cliDisplayDescription:"A list of all panels in the bot. Here you can add, modify & remove existing panels or customise them to your preference."})
export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("opendiscord:questions",{allowedTypes:["object"],cliDisplayPropertyName:"question",propertyChecker:new api.ODCheckerObjectStructure("opendiscord:questions",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"type",checker:new api.ODCheckerStringStructure("opendiscord:question-type",{choices:["short","paragraph"],cliDisplayName:"Type",cliDisplayDescription:"The type of this question (short/paragraph)."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"length",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:question-length-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable length validation for this question."})},
{key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false,cliDisplayName:"Min Length",cliDisplayDescription:"The minimum amount of characters required."})},
{key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false,cliInitDefaultValue:100,cliDisplayName:"Max Length",cliDisplayDescription:"The maximum amount of characters allowed."})},
],cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."}),cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."})},
],cliDisplayName:"Question",cliDisplayDescription:"Manage, customise and configure a question to your preference."}),cliDisplayName:"Questions",cliDisplayDescription:"A list of all questions in the bot. Here you can add, modify & remove existing questions or customise them to your preference."})
export const defaultQuestionsStructure = new api.ODCheckerArrayStructure("opendiscord:questions",{allowedTypes:["object"],cliDisplayPropertyName:"question",propertyChecker:new api.ODCheckerObjectSwitchStructure("opendiscord:options",{objects:[
//SHORT QUESTION
{name:"Short Question",priority:0,properties:[{key:"type",value:"short"}],checker:new api.ODCheckerObjectStructure("opendiscord:short-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"length",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:question-length-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable length validation for this question."})},
{key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false,cliDisplayName:"Min Length",cliDisplayDescription:"The minimum amount of characters required."})},
{key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false,cliInitDefaultValue:100,cliDisplayName:"Max Length",cliDisplayDescription:"The maximum amount of characters allowed."})},
],cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."}),cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."})},
],cliDisplayName:"Short Question",cliDisplayDescription:"Manage, customise and configure the short question to your preference."})},
//PARAGRAPH QUESTION
{name:"Paragraph Question",priority:0,properties:[{key:"type",value:"paragraph"}],checker:new api.ODCheckerObjectStructure("opendiscord:paragraph-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"length",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:question-length",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:question-length",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:question-length-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable length validation for this question."})},
{key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-min",{min:0,max:1024,negativeAllowed:false,floatAllowed:false,cliDisplayName:"Min Length",cliDisplayDescription:"The minimum amount of characters required."})},
{key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:question-length-max",{min:1,max:1024,negativeAllowed:false,floatAllowed:false,cliInitDefaultValue:100,cliDisplayName:"Max Length",cliDisplayDescription:"The maximum amount of characters allowed."})},
],cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."}),cliDisplayName:"Length Validation",cliDisplayDescription:"Add length validation to the question. This way, the contents must be at least/most ... characters."})},
],cliDisplayName:"Paragraph Question",cliDisplayDescription:"Manage, customise and configure the paragraph question to your preference."})},
//TEXT DISPLAY QUESTION
{name:"Text Display Question",priority:0,properties:[{key:"type",value:"text-display"}],checker:new api.ODCheckerObjectStructure("opendiscord:text-display-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this text display. Used in ticket options."})},
{key:"textContents",checker:new api.ODCheckerStringStructure("opendiscord:text-contents",{minLength:1,maxLength:2048,cliDisplayName:"Text Contents",cliDisplayDescription:"The text contents to show in the modal."})},
],cliDisplayName:"Text Display Question",cliDisplayDescription:"Manage, customise and configure the text display question to your preference."})},
//DROPDOWN QUESTION
{name:"Dropdown Question",priority:0,properties:[{key:"type",value:"dropdown"}],checker:new api.ODCheckerObjectStructure("opendiscord:dropdown-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"placeholder",checker:new api.ODCheckerStringStructure("opendiscord:question-placeholder",{maxLength:100,cliDisplayName:"Placeholder",cliDisplayDescription:"The placeholder to show in the field when nothing has been written yet."})},
{key:"choices",checker:new api.ODCheckerArrayStructure("opendiscord:choices",{allowedTypes:["object"],minLength:1,maxLength:25,propertyChecker:new api.ODCheckerObjectStructure("opendiscord:choice",{children:[
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:choice-title",{minLength:1,maxLength:100,cliDisplayName:"Title",cliDisplayDescription:"The title of this choice."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:choice-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this choice."})},
{key:"emoji",checker:new api.ODCheckerCustomStructure_EmojiString("opendiscord:choice-emoji",0,1,true,{cliDisplayName:"Emoji",cliDisplayDescription:"The emoji of the choice. Leave empty to disable."})}
],cliDisplayName:"Choice",cliDisplayDescription:"A choice for this dropdown question."}),cliDisplayName:"Choices",cliDisplayPropertyName:"choice",cliDisplayDescription:"Manage all available choices of this dropdown question."})}
],cliDisplayName:"Dropdown Question",cliDisplayDescription:"Manage, customise and configure the dropdown question to your preference."})},
//RADIO SELECT QUESTION
{name:"Radio Select Question",priority:0,properties:[{key:"type",value:"radio-select"}],checker:new api.ODCheckerObjectStructure("opendiscord:radio-select-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"choices",checker:new api.ODCheckerArrayStructure("opendiscord:choices",{allowedTypes:["object"],minLength:2,maxLength:10,propertyChecker:new api.ODCheckerObjectStructure("opendiscord:choice",{children:[
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:choice-title",{minLength:1,maxLength:100,cliDisplayName:"Title",cliDisplayDescription:"The title of this choice."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:choice-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this choice."})},
{key:"selectedByDefault",checker:new api.ODCheckerBooleanStructure("opendiscord:choice-default",{cliDisplayName:"Selected By Default",cliDisplayDescription:"Should this choice be selected by default?"})}
],cliDisplayName:"Choice",cliDisplayDescription:"A choice for this radio select question."}),cliDisplayName:"Choices",cliDisplayPropertyName:"choice",cliDisplayDescription:"Manage all available choices of this radio select question."})}
],cliDisplayName:"Radio Select Question",cliDisplayDescription:"Manage, customise and configure the radio select question to your preference."})},
//CHECKBOX SELECT QUESTION
{name:"Checkbox Select Question",priority:0,properties:[{key:"type",value:"checkbox-select"}],checker:new api.ODCheckerObjectStructure("opendiscord:checkbox-select-question",{cliDisplayKeyInParentArray:"name",cliDisplayAdditionalKeysInParentArray:["id","type"],children:[
{key:"id",checker:new api.ODCheckerCustomStructure_UniqueId("opendiscord:question-id","openticket","question-ids",{regex:/^[A-Za-z0-9-éèçàêâôûî]+$/,minLength:3,maxLength:40,cliDisplayName:"Id",cliDisplayDescription:"The id of this question. Used in ticket options."})},
{key:"name",checker:new api.ODCheckerStringStructure("opendiscord:question-name",{minLength:3,maxLength:45,cliDisplayName:"Name",cliDisplayDescription:"The name of this question."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:question-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this question."})},
{key:"required",checker:new api.ODCheckerBooleanStructure("opendiscord:question-required",{cliDisplayName:"Required",cliDisplayDescription:"Is this question required? If not, it can be left empty."})},
{key:"limits",checker:new api.ODCheckerEnabledObjectStructure("opendiscord:amount",{property:"enabled",enabledValue:true,checker:new api.ODCheckerObjectStructure("opendiscord:amount",{children:[
{key:"enabled",checker:new api.ODCheckerBooleanStructure("opendiscord:amount-enabled",{cliDisplayName:"Enabled",cliDisplayDescription:"Enable/disable checking the min/max amount of required checkboxes."})},
{key:"min",checker:new api.ODCheckerNumberStructure("opendiscord:amount-min",{min:0,max:10,floatAllowed:false,cliDisplayName:"Min Amount",cliDisplayDescription:"The minimum amount of checkboxes required."})},
{key:"max",checker:new api.ODCheckerNumberStructure("opendiscord:amount-max",{min:1,max:10,floatAllowed:false,cliInitDefaultValue:10,cliDisplayName:"Max Amount",cliDisplayDescription:"The maximum amount of checkboxes allowed."})},
],cliDisplayName:"Checkbox Limits",cliDisplayDescription:"Verify the minimum or maximum amount of checkboxes required."}),cliDisplayName:"Checkbox Limits",cliDisplayDescription:"Verify the minimum or maximum amount of checkboxes required."})},
{key:"choices",checker:new api.ODCheckerArrayStructure("opendiscord:choices",{allowedTypes:["object"],minLength:1,maxLength:10,propertyChecker:new api.ODCheckerObjectStructure("opendiscord:choice",{children:[
{key:"title",checker:new api.ODCheckerStringStructure("opendiscord:choice-title",{minLength:1,maxLength:100,cliDisplayName:"Title",cliDisplayDescription:"The title of this choice."})},
{key:"description",checker:new api.ODCheckerStringStructure("opendiscord:choice-description",{maxLength:100,cliDisplayName:"Description",cliDisplayDescription:"The description of this choice."})},
{key:"selectedByDefault",checker:new api.ODCheckerBooleanStructure("opendiscord:choice-default",{cliDisplayName:"Selected By Default",cliDisplayDescription:"Should this choice be selected by default?"})}
],cliDisplayName:"Choice",cliDisplayDescription:"A choice for this checkbox select question."}),cliDisplayName:"Choices",cliDisplayPropertyName:"choice",cliDisplayDescription:"Manage all available choices of this checkbox select question."})}
],cliDisplayName:"Checkbox Select Question",cliDisplayDescription:"Manage, customise and configure the checkbox select question to your preference."})},
],cliDisplayName:"Question",cliDisplayDescription:"Manage a question of one of the 6 types: short, paragraph, text-display, dropdown, radio-select, checkbox-select."}),cliDisplayName:"Questions",cliDisplayDescription:"A list of all questions in the bot. Here you can add, modify & remove existing questions or customise them to your preference."})
export const defaultTranscriptsStructure = new api.ODCheckerObjectStructure("opendiscord:transcripts",{children:[
//GENERAL
+3 -3
View File
@@ -30,7 +30,7 @@ export async function loadCommandErrorHandlingCode(){
error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-invalid").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message)
}else if (error.type == "missing_option"){
error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-option-missing").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message)
}else if (error.type == "unknown_command" && generalConfig.data.system.sendErrorOnUnknownCommand){
}else if (error.type == "unknown_command" && generalConfig.data.ticketSystem.sendErrorOnUnknownCommand){
error.msg.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-unknown-command").build("text",{guild:error.msg.guild,channel:error.msg.channel,user:error.msg.author,error})).message)
}
})
@@ -459,7 +459,7 @@ const loadAutoCode = () => {
if (lastMessage){
//ticket has last message
const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value
const disableWhenNotClosed = generalConfig.data.system.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value
const disableWhenNotClosed = generalConfig.data.ticketSystem.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value
const enabled = (disableOnClaim || disableWhenNotClosed) ? false : ticket.get("opendiscord:autodelete-enabled").value
const days = ticket.get("opendiscord:autodelete-days").value
@@ -490,7 +490,7 @@ const loadAutoCode = () => {
if (!channel) return
//ticket has been created by this user
const disableOnClaim = ticket.option.get("opendiscord:autodelete-disable-claim").value && ticket.get("opendiscord:claimed").value
const disableWhenNotClosed = generalConfig.data.system.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value
const disableWhenNotClosed = generalConfig.data.ticketSystem.autodeleteRequiresClosedTicket && !ticket.get("opendiscord:closed").value
const enabled = (disableOnClaim || disableWhenNotClosed || !ticket.get("opendiscord:autodelete-enabled").value) ? false : ticket.option.get("opendiscord:autodelete-enable-leave")
if (enabled){
+5 -5
View File
@@ -14,8 +14,8 @@ export async function loadAllSlashCommands(){
if (!generalConfig.data.slashCommands) return
const allowedCommands: string[] = []
for (const key in generalConfig.data.system.permissions){
if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key)
for (const key in generalConfig.data.permissions){
if (generalConfig.data.permissions[key] != "none") allowedCommands.push(key)
}
//HELP
@@ -87,7 +87,7 @@ export async function loadAllSlashCommands(){
}))
//DELETE
if (allowedCommands.includes("delete") && generalConfig.data.system.enableDeleteWithoutTranscript) commands.add(new api.ODSlashCommand("opendiscord:delete",{
if (allowedCommands.includes("delete") && generalConfig.data.ticketSystem.enableDeleteWithoutTranscript) commands.add(new api.ODSlashCommand("opendiscord:delete",{
type:act.ChatInput,
name:"delete",
description:lang.getTranslation("commands.delete"),
@@ -654,8 +654,8 @@ export async function loadAllTextCommands(){
})
const allowedCommands: string[] = []
for (const key in generalConfig.data.system.permissions){
if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key)
for (const key in generalConfig.data.permissions){
if (generalConfig.data.permissions[key] != "none") allowedCommands.push(key)
}
//HELP
+350 -162
View File
@@ -5,121 +5,63 @@ export async function loadAllConfigs(){
const devconfigFlag = opendiscord.flags.get("opendiscord:dev-config")
const isDevconfig = devconfigFlag ? devconfigFlag.value : false
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:general","general.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultGeneralFormatter))
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:questions","questions.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultQuestionsFormatter))
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:options","options.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultOptionsFormatter))
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:panels","panels.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultPanelsFormatter))
opendiscord.configs.add(new api.ODJsonConfig("opendiscord:transcripts","transcripts.json",(isDevconfig) ? "./devconfig/" : "./config/",defaultTranscriptsFormatter))
opendiscord.configs.add(new api.ODJsonCommentsConfig("opendiscord:general","general.jsonc",(isDevconfig) ? "./devconfig/" : "./config/",defaultGeneralFormatter))
opendiscord.configs.add(new api.ODJsonCommentsConfig("opendiscord:questions","questions.jsonc",(isDevconfig) ? "./devconfig/" : "./config/",defaultQuestionsFormatter))
opendiscord.configs.add(new api.ODJsonCommentsConfig("opendiscord:options","options.jsonc",(isDevconfig) ? "./devconfig/" : "./config/",defaultOptionsFormatter))
opendiscord.configs.add(new api.ODJsonCommentsConfig("opendiscord:panels","panels.jsonc",(isDevconfig) ? "./devconfig/" : "./config/",defaultPanelsFormatter))
opendiscord.configs.add(new api.ODJsonCommentsConfig("opendiscord:transcripts","transcripts.jsonc",(isDevconfig) ? "./devconfig/" : "./config/",defaultTranscriptsFormatter))
}
//FORMATTERS
export const defaultGeneralFormatter = new fjs.ObjectFormatter(null,true,[
new fjs.ObjectFormatter("_INFO",true,[
new fjs.PropertyFormatter("support"),
new fjs.PropertyFormatter("discord"),
new fjs.PropertyFormatter("version"),
]),
export const defaultGeneralFormatter = new fjs.TopLevelCommentFormatter(new fjs.MultiCommentFormatter([
"Hi there! Thank you for installing Open Ticket.",
"----------------------------------------------",
"If you need any assistance with configuring the bot,",
"feel free to use the documentation or join our Discord server:",
"https://otdocs.dj-dj.be",
"https://discord.dj-dj.be",
"----------------------------------------------",
"SETUP:",
"1. Install the required dependencies using the command: \"npm install\"",
"2. Configure the bot in one of the following ways:",
" a. (easy) Using the Quick Setup CLI Tool",
" b. (difficult) Using the JSON files in `./config/`",
"",
"Start the Quick Setup CLI Tool using the command: \"npm run setup\"",
"After configuration, start the bot using the command: \"npm start\"",
"",
"Good luck! DJj123dj & contributors",
].join("\n")),new fjs.ObjectFormatter(null,true,[
new fjs.PropertyFormatter("_CONFIG_VERSION"),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Load the bot token from .env or the \"token\" field below. Leave \"token\" empty if using \"tokenFromENV\"."),
new fjs.PropertyFormatter("token"),
new fjs.PropertyFormatter("tokenFromENV"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("mainColor"),
new fjs.PropertyFormatter("language"),
new fjs.PropertyFormatter("prefix"),
new fjs.PropertyFormatter("mainColor",new fjs.SingleCommentFormatter("Hex color used in most embeds")),
new fjs.PropertyFormatter("language",new fjs.SingleCommentFormatter("Visit README.md for list")),
new fjs.PropertyFormatter("prefix",new fjs.SingleCommentFormatter("Prefix used in text commands")),
new fjs.PropertyFormatter("serverId"),
new fjs.ArrayFormatter("globalAdmins",false,new fjs.PropertyFormatter(null)),
new fjs.ArrayFormatter("globalAdmins",false,new fjs.PropertyFormatter(null),undefined,undefined,new fjs.SingleCommentFormatter("Have access to all commands")),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Enable/disable text or slash commands."),
new fjs.PropertyFormatter("slashCommands"),
new fjs.PropertyFormatter("textCommands"),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Configure the status of the bot."),
new fjs.ObjectFormatter("status",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("type"),
new fjs.PropertyFormatter("mode"),
new fjs.PropertyFormatter("type",new fjs.SingleCommentFormatter("Choices: listening, watching, playing, custom")),
new fjs.PropertyFormatter("mode",new fjs.SingleCommentFormatter("Choices: online, invisible, idle, dnd")),
new fjs.PropertyFormatter("text"),
new fjs.PropertyFormatter("state"),
new fjs.PropertyFormatter("state",new fjs.SingleCommentFormatter("Additional text (Leave empty to disable)")),
]),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("system",true,[
new fjs.PropertyFormatter("preferSlashOverText"),
new fjs.PropertyFormatter("sendErrorOnUnknownCommand"),
new fjs.PropertyFormatter("questionFieldsInCodeBlock"),
new fjs.PropertyFormatter("displayFieldsWithQuestions"),
new fjs.PropertyFormatter("showGlobalAdminsInPanelRoles"),
new fjs.PropertyFormatter("disableVerifyBars"),
new fjs.PropertyFormatter("useRedErrorEmbeds"),
new fjs.PropertyFormatter("alwaysShowReason"),
new fjs.PropertyFormatter("emojiStyle"),
new fjs.PropertyFormatter("pinEmoji"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("replyOnTicketCreation"),
new fjs.PropertyFormatter("replyOnReactionRole"),
new fjs.PropertyFormatter("askPriorityOnTicketCreation"),
new fjs.PropertyFormatter("removeParticipantsOnClose"),
new fjs.PropertyFormatter("disableAutocloseAfterReopen"),
new fjs.PropertyFormatter("autodeleteRequiresClosedTicket"),
new fjs.PropertyFormatter("adminOnlyDeleteWithoutTranscript"),
new fjs.PropertyFormatter("allowCloseBeforeMessage"),
new fjs.PropertyFormatter("allowCloseBeforeAdminMessage"),
new fjs.PropertyFormatter("useTranslatedConfigChecker"),
new fjs.PropertyFormatter("pinFirstTicketMessage"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("enableTicketClaimButtons"),
new fjs.PropertyFormatter("enableTicketCloseButtons"),
new fjs.PropertyFormatter("enableTicketPinButtons"),
new fjs.PropertyFormatter("enableTicketDeleteButtons"),
new fjs.PropertyFormatter("enableTicketActionWithReason"),
new fjs.PropertyFormatter("enableDeleteWithoutTranscript"),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("logs",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("channel"),
]),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("limits",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("globalMaximum"),
new fjs.PropertyFormatter("userMaximum"),
]),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("channelTopic",true,[
new fjs.PropertyFormatter("showOptionName"),
new fjs.PropertyFormatter("showOptionDescription"),
new fjs.PropertyFormatter("showOptionTopic"),
new fjs.PropertyFormatter("showPriority"),
new fjs.PropertyFormatter("showClosed"),
new fjs.PropertyFormatter("showClaimed"),
new fjs.PropertyFormatter("showPinned"),
new fjs.PropertyFormatter("showCreator"),
new fjs.PropertyFormatter("showParticipants"),
]),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("permissions",true,[
new fjs.PropertyFormatter("help"),
new fjs.PropertyFormatter("panel"),
new fjs.PropertyFormatter("ticket"),
new fjs.PropertyFormatter("close"),
new fjs.PropertyFormatter("delete"),
new fjs.PropertyFormatter("reopen"),
new fjs.PropertyFormatter("claim"),
new fjs.PropertyFormatter("unclaim"),
new fjs.PropertyFormatter("pin"),
new fjs.PropertyFormatter("unpin"),
new fjs.PropertyFormatter("move"),
new fjs.PropertyFormatter("rename"),
new fjs.PropertyFormatter("add"),
new fjs.PropertyFormatter("remove"),
new fjs.PropertyFormatter("blacklist"),
new fjs.PropertyFormatter("stats"),
new fjs.PropertyFormatter("clear"),
new fjs.PropertyFormatter("autoclose"),
new fjs.PropertyFormatter("autodelete"),
new fjs.PropertyFormatter("transfer"),
new fjs.PropertyFormatter("topic"),
new fjs.PropertyFormatter("priority"),
]),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("messages",true,[
new fjs.MultiCommentFormatter("Send ticket logs to a channel or in DM of the ticket creator."),
new fjs.ObjectFormatter("logs",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("channel"),
new fjs.ObjectFormatter("logMessages",true,[
new fjs.DefaultFormatter("creation",false),
new fjs.DefaultFormatter("closing",false),
new fjs.DefaultFormatter("deleting",false),
@@ -137,80 +79,267 @@ export const defaultGeneralFormatter = new fjs.ObjectFormatter(null,true,[
new fjs.DefaultFormatter("reactionRole",false)
]),
]),
])
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("A large collection of settings for the ticket system."),
new fjs.ObjectFormatter("ticketSystem",true,[
new fjs.PropertyFormatter("preferSlashOverText",new fjs.SingleCommentFormatter("Show slashcmds in help menu's")),
new fjs.PropertyFormatter("sendErrorOnUnknownCommand",new fjs.SingleCommentFormatter("Send error when command not found")),
new fjs.PropertyFormatter("questionFieldsInCodeBlock",new fjs.SingleCommentFormatter("Put question answers in code blocks")),
new fjs.PropertyFormatter("displayFieldsWithQuestions",new fjs.SingleCommentFormatter("Display embed fields together with question answers")),
new fjs.PropertyFormatter("showGlobalAdminsInPanelRoles",new fjs.SingleCommentFormatter("Include \"globalAdmins\" in panel admin lists")),
new fjs.PropertyFormatter("disableVerifyBars",new fjs.SingleCommentFormatter("Disable the (❌/✅) buttons")),
new fjs.PropertyFormatter("useRedErrorEmbeds",new fjs.SingleCommentFormatter("Make errors embeds always red")),
new fjs.PropertyFormatter("alwaysShowReason",new fjs.SingleCommentFormatter("Show reason even if none is provided")),
new fjs.PropertyFormatter("emojiStyle",new fjs.SingleCommentFormatter("The style of emoji's in embeds. Choices: before, after, double, disabled")),
new fjs.PropertyFormatter("pinEmoji",new fjs.SingleCommentFormatter("Channel emoji of pinned tickets (Leave empty to disable)")),
new fjs.PropertyFormatter("closeEmoji",new fjs.SingleCommentFormatter("Channel emoji of closed tickets (Leave empty to disable)")),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("replyOnTicketCreation",new fjs.SingleCommentFormatter("Reply with a msg when a ticket is created")),
new fjs.PropertyFormatter("replyOnReactionRole",new fjs.SingleCommentFormatter("Reply with a msg when a reaction role is used")),
new fjs.PropertyFormatter("askPriorityOnTicketCreation",new fjs.SingleCommentFormatter("Show a dropdown to select priority")),
new fjs.PropertyFormatter("removeParticipantsOnClose",new fjs.SingleCommentFormatter("Remove non-admins when ticket is closed")),
new fjs.PropertyFormatter("disableAutocloseAfterReopen",new fjs.SingleCommentFormatter("Disable autoclose after ticket got reopened")),
new fjs.PropertyFormatter("autodeleteRequiresClosedTicket",new fjs.SingleCommentFormatter("A ticket must be closed before autodelete works")),
new fjs.PropertyFormatter("adminOnlyDeleteWithoutTranscript",new fjs.SingleCommentFormatter("Only allow \"globalAdmins\" to delete a ticket without transcript")),
new fjs.PropertyFormatter("allowCloseBeforeMessage",new fjs.SingleCommentFormatter("Allow closing before a message is sent")),
new fjs.PropertyFormatter("allowCloseBeforeAdminMessage",new fjs.SingleCommentFormatter("Allow closing before an admin has sent a message")),
new fjs.PropertyFormatter("useTranslatedConfigChecker",new fjs.SingleCommentFormatter("Translate config errors in the console")),
new fjs.PropertyFormatter("pinFirstTicketMessage",new fjs.SingleCommentFormatter("Pin the ticket message to the channel")),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Enable/disable certain buttons & features of the bot."),
new fjs.PropertyFormatter("enableTicketClaimButtons"),
new fjs.PropertyFormatter("enableTicketCloseButtons"),
new fjs.PropertyFormatter("enableTicketPinButtons"),
new fjs.PropertyFormatter("enableTicketDeleteButtons"),
new fjs.PropertyFormatter("enableTicketActionWithReason"),
new fjs.PropertyFormatter("enableDeleteWithoutTranscript",new fjs.SingleCommentFormatter("Allow deleting tickets without transcript")),
new fjs.PropertyFormatter("enableCreateTicketForOtherUser",new fjs.SingleCommentFormatter("Allow creating tickets for other users")),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Set the maximum amount of simultaneous tickets."),
new fjs.ObjectFormatter("limits",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("globalMaximum"),
new fjs.PropertyFormatter("userMaximum"),
]),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Choose which data is shown in the channel topic."),
new fjs.ObjectFormatter("channelTopic",true,[
new fjs.PropertyFormatter("showOptionName"),
new fjs.PropertyFormatter("showOptionDescription"),
new fjs.PropertyFormatter("showOptionTopic"),
new fjs.PropertyFormatter("showPriority"),
new fjs.PropertyFormatter("showClosed"),
new fjs.PropertyFormatter("showClaimed"),
new fjs.PropertyFormatter("showPinned"),
new fjs.PropertyFormatter("showCreator"),
new fjs.PropertyFormatter("showParticipants"),
]),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Move closed tickets to a separate category."),
new fjs.ObjectFormatter("closedCategory",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("categoryId")
]),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Create tickets in a backup category when the original category exceeds 50 channels."),
new fjs.ObjectFormatter("backupCategory",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("categoryId")
]),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Move claimed tickets to a matching category of the user that claimed the ticket. Set to empty list [] to disable."),
new fjs.ArrayFormatter("claimedCategories",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("user"),
new fjs.PropertyFormatter("category"),
])),
]),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter([
"Set permissions for each individual command, button or action.",
"CHOICES:",
">> \"none\" -> Command disabled",
">> \"everyone\" -> Allowed for everyone",
">> \"admin\" -> Global & ticket admins only",
">> \"DISCORD_ROLE_ID\" -> Custom role only",
].join("\n")),
new fjs.ObjectFormatter("permissions",true,[
new fjs.PropertyFormatter("help"),
new fjs.PropertyFormatter("panel"),
new fjs.PropertyFormatter("ticket"),
new fjs.PropertyFormatter("close"),
new fjs.PropertyFormatter("delete"),
new fjs.PropertyFormatter("reopen"),
new fjs.PropertyFormatter("claim"),
new fjs.PropertyFormatter("unclaim"),
new fjs.PropertyFormatter("pin"),
new fjs.PropertyFormatter("unpin"),
new fjs.PropertyFormatter("move"),
new fjs.PropertyFormatter("rename"),
new fjs.PropertyFormatter("add"),
new fjs.PropertyFormatter("remove"),
new fjs.PropertyFormatter("blacklist"),
new fjs.PropertyFormatter("stats"),
new fjs.PropertyFormatter("clear"),
new fjs.PropertyFormatter("autoclose"),
new fjs.PropertyFormatter("autodelete"),
new fjs.PropertyFormatter("transfer"),
new fjs.PropertyFormatter("topic"),
new fjs.PropertyFormatter("priority"),
new fjs.PropertyFormatter("transcripts"),
]),
]))
export const defaultQuestionsFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectSwitchFormatter(null,[
export const defaultQuestionsFormatter = new fjs.TopLevelCommentFormatter(new fjs.MultiCommentFormatter([
"OPEN TICKET MODAL QUESTIONS",
"----------------------------------------------",
"Create customizable modal questions that will be shown before creating a ticket.",
"Each ticket option (config/options.jsonc) can contain a maximum of 5 questions.",
"There are 6 types of questions available: short, paragraph, dropdown, radio-select, checkbox-select, text-display",
"",
"TIP: Create new questions by copying everything between and including the {...} brackets of a question. Paste it after the last question and make sure that they are seperated by a comma."
].join("\n")),new fjs.ArrayFormatter(null,true,new fjs.ObjectSwitchFormatter(null,[
{key:"type",value:"short",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A short text input modal question."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("required"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("placeholder"),
new fjs.ObjectFormatter("length",true,[
new fjs.MultiCommentFormatter("Configure length limits for the answer."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("min"),
new fjs.PropertyFormatter("max"),
]),
])},
{key:"type",value:"paragraph",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A paragraph text input modal question."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("required"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("placeholder"),
new fjs.ObjectFormatter("length",true,[
new fjs.MultiCommentFormatter("Configure length limits for the answer."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("min"),
new fjs.PropertyFormatter("max"),
]),
])}
]))
export const defaultOptionsFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectSwitchFormatter(null,[
{key:"type",value:"ticket",formatter:new fjs.ObjectFormatter(null,true,[
])},
{key:"type",value:"text-display",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("Show text in a modal to provide extra details or explain questions."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("type"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("textContents"),
])},
{key:"type",value:"dropdown",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A dropdown menu input modal question with up to 25 choices. \"emoji\" & \"description\" fields are optional."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.PropertyFormatter("required"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("placeholder"),
new fjs.ArrayFormatter("choices",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("title"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("emoji"),
])),
])},
{key:"type",value:"radio-select",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A radio select input modal question with up to 10 choices."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.PropertyFormatter("required"),
new fjs.TextFormatter(""),
new fjs.ArrayFormatter("choices",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("title"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("selectedByDefault"),
])),
])},
{key:"type",value:"checkbox-select",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A checkbox select input modal question with up to 10 choices."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.PropertyFormatter("required"),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("limits",true,[
new fjs.MultiCommentFormatter("Configure checkbox amount limits for the answer."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("min"),
new fjs.PropertyFormatter("max"),
]),
new fjs.ArrayFormatter("choices",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("title"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("selectedByDefault"),
])),
])},
])))
export const defaultOptionsFormatter = new fjs.TopLevelCommentFormatter(new fjs.MultiCommentFormatter([
"OPEN TICKET BUTTON OPTIONS",
"----------------------------------------------",
"Create customizable ticket, website, reaction-role or sub-panel button options.",
"Up to 25 options can be added to each panel in (config/panels.jsonc)",
"There are 4 types of options available: ticket, website, role, sub-panel",
"",
"TIP: Create new options by copying everything between and including the {...} brackets of an option. Paste it after the last option and make sure that they are seperated by a comma."
].join("\n")),new fjs.ArrayFormatter(null,true,new fjs.ObjectSwitchFormatter(null,[
{key:"type",value:"ticket",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A ticket option creates a button to open a ticket."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("button",true,[
new fjs.MultiCommentFormatter("Configure the button style of this option. At least one of \"emoji\" or \"label\" must be provided."),
new fjs.PropertyFormatter("emoji"),
new fjs.PropertyFormatter("label"),
new fjs.PropertyFormatter("color"),
new fjs.PropertyFormatter("color",new fjs.SingleCommentFormatter("Choices: gray, red, green, blue")),
]),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Add up to 5 modal questions IDs from (config/questions.jsonc)."),
new fjs.ArrayFormatter("questions",false,new fjs.PropertyFormatter(null)),
new fjs.TextFormatter(""),
new fjs.ArrayFormatter("ticketAdmins",false,new fjs.PropertyFormatter(null)),
new fjs.ArrayFormatter("readonlyAdmins",false,new fjs.PropertyFormatter(null)),
new fjs.PropertyFormatter("allowCreationByBlacklistedUsers"),
new fjs.ArrayFormatter("questions",false,new fjs.PropertyFormatter(null)),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("channel",true,[
new fjs.MultiCommentFormatter("Configure the name, topic and category of the ticket option."),
new fjs.PropertyFormatter("prefix"),
new fjs.PropertyFormatter("suffix"),
new fjs.PropertyFormatter("category"),
new fjs.PropertyFormatter("backupCategory"),
new fjs.PropertyFormatter("closedCategory"),
new fjs.ArrayFormatter("claimedCategory",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("user"),
new fjs.PropertyFormatter("category"),
])),
new fjs.PropertyFormatter("topic"),
new fjs.PropertyFormatter("suffix",new fjs.SingleCommentFormatter("Choices: user-name, user-id, random-number, random-hex, counter-dynamic, counter-fixed")),
new fjs.PropertyFormatter("category",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("topic",new fjs.SingleCommentFormatter("Leave empty to disable")),
]),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("dmMessage",true,[
new fjs.MultiCommentFormatter("Send a customisable message in DM when creating a ticket."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("text"),
new fjs.PropertyFormatter("text",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.ObjectFormatter("embed",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("title"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("customColor"),
new fjs.PropertyFormatter("title",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("customColor",new fjs.SingleCommentFormatter("Leave empty to use default color")),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("image"),
new fjs.PropertyFormatter("thumbnail"),
new fjs.PropertyFormatter("image",new fjs.SingleCommentFormatter("Image URL. Leave empty to disable")),
new fjs.PropertyFormatter("thumbnail",new fjs.SingleCommentFormatter("Image URL. Leave empty to disable")),
new fjs.MultiCommentFormatter("Embed fields. Set to empty list [] to disable."),
new fjs.ArrayFormatter("fields",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("value"),
@@ -220,16 +349,18 @@ export const defaultOptionsFormatter = new fjs.ArrayFormatter(null,true,new fjs.
]),
]),
new fjs.ObjectFormatter("ticketMessage",true,[
new fjs.MultiCommentFormatter("Send a customisable message in the ticket with close, claim, delete, ... buttons."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("text"),
new fjs.PropertyFormatter("text",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.ObjectFormatter("embed",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("title"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("customColor"),
new fjs.PropertyFormatter("title",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("customColor",new fjs.SingleCommentFormatter("Leave empty to use default color")),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("image"),
new fjs.PropertyFormatter("thumbnail"),
new fjs.PropertyFormatter("image",new fjs.SingleCommentFormatter("Image URL. Leave empty to disable")),
new fjs.PropertyFormatter("thumbnail",new fjs.SingleCommentFormatter("Image URL. Leave empty to disable")),
new fjs.MultiCommentFormatter("Embed fields. Set to empty list [] to disable."),
new fjs.ArrayFormatter("fields",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("value"),
@@ -238,44 +369,52 @@ export const defaultOptionsFormatter = new fjs.ArrayFormatter(null,true,new fjs.
new fjs.PropertyFormatter("timestamp"),
]),
new fjs.ObjectFormatter("ping",true,[
new fjs.MultiCommentFormatter("Customise the user & role mentions of this ticket message."),
new fjs.PropertyFormatter("@here"),
new fjs.PropertyFormatter("@everyone"),
new fjs.ArrayFormatter("custom",true,new fjs.PropertyFormatter(null)),
new fjs.ArrayFormatter("custom",false,new fjs.PropertyFormatter(null)),
]),
]),
new fjs.ObjectFormatter("autoclose",true,[
new fjs.MultiCommentFormatter("Autoclose this ticket after a period of inactivity or when the creator leaves the server."),
new fjs.PropertyFormatter("enableInactiveHours"),
new fjs.PropertyFormatter("inactiveHours"),
new fjs.PropertyFormatter("enableUserLeave"),
new fjs.PropertyFormatter("disableOnClaim"),
]),
new fjs.ObjectFormatter("autodelete",true,[
new fjs.MultiCommentFormatter("Autodelete this ticket after a period of inactivity or when the creator leaves the server."),
new fjs.PropertyFormatter("enableInactiveDays"),
new fjs.PropertyFormatter("inactiveDays"),
new fjs.PropertyFormatter("enableUserLeave"),
new fjs.PropertyFormatter("disableOnClaim"),
]),
new fjs.ObjectFormatter("cooldown",true,[
new fjs.MultiCommentFormatter("Users must wait a certain period before being able to create another ticket of this type."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("cooldownMinutes"),
]),
new fjs.ObjectFormatter("limits",true,[
new fjs.MultiCommentFormatter("Set the maximum amount of simultaneous tickets of this option."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("globalMaximum"),
new fjs.PropertyFormatter("userMaximum"),
]),
new fjs.ObjectFormatter("slowMode",true,[
new fjs.MultiCommentFormatter("Enable slow-mode in the ticket channel."),
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("slowModeSeconds"),
]),
])},
{key:"type",value:"website",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A website option creates a button with a URL to an external website."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("button",true,[
new fjs.MultiCommentFormatter("Configure the button style of this option. At least one of \"emoji\" or \"label\" must be provided."),
new fjs.PropertyFormatter("emoji"),
new fjs.PropertyFormatter("label"),
]),
@@ -283,43 +422,75 @@ export const defaultOptionsFormatter = new fjs.ArrayFormatter(null,true,new fjs.
new fjs.PropertyFormatter("url"),
])},
{key:"type",value:"role",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A reaction-role option creates a button for members to choose roles."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("button",true,[
new fjs.MultiCommentFormatter("Configure the button style of this option. At least one of \"emoji\" or \"label\" must be provided."),
new fjs.PropertyFormatter("emoji"),
new fjs.PropertyFormatter("label"),
new fjs.PropertyFormatter("color"),
new fjs.PropertyFormatter("color",new fjs.SingleCommentFormatter("Choices: gray, red, green, blue")),
]),
new fjs.TextFormatter(""),
new fjs.ArrayFormatter("roles",false,new fjs.PropertyFormatter(null)),
new fjs.PropertyFormatter("mode"),
new fjs.ArrayFormatter("removeRolesOnAdd",false,new fjs.PropertyFormatter(null)),
new fjs.PropertyFormatter("addOnMemberJoin"),
new fjs.PropertyFormatter("mode",new fjs.SingleCommentFormatter("What to do with the roles. Choices: add&remove, add, remove")),
new fjs.ArrayFormatter("removeRolesOnAdd",false,new fjs.PropertyFormatter(null),undefined,undefined,new fjs.SingleCommentFormatter("Remove these old roles when new roles are added.")),
new fjs.PropertyFormatter("addOnMemberJoin",new fjs.SingleCommentFormatter("Add these roles automatically when joining the server.")),
])},
{key:"type",value:"sub-panel",formatter:new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A sub-panel option creates a button which sends another panel for additional options."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("type"),
new fjs.TextFormatter(""),
new fjs.ObjectFormatter("button",true,[
new fjs.MultiCommentFormatter("Configure the button style of this option. At least one of \"emoji\" or \"label\" must be provided."),
new fjs.PropertyFormatter("emoji"),
new fjs.PropertyFormatter("label"),
new fjs.PropertyFormatter("color",new fjs.SingleCommentFormatter("Choices: gray, red, green, blue")),
]),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("subPanelId",new fjs.SingleCommentFormatter("Choose a panel ID from (config/panels.jsonc)")),
])}
]))
])))
export const defaultPanelsFormatter = new fjs.ArrayFormatter(null,true,new fjs.ObjectFormatter(null,true,[
export const defaultPanelsFormatter = new fjs.TopLevelCommentFormatter(new fjs.MultiCommentFormatter([
"OPEN TICKET PANELS",
"----------------------------------------------",
"Create customizable panel messages with buttons or a dropdown.",
"Add up to 25 options to this panel from (config/options.jsonc)",
"Panels can be customised with text, images, colors and more.",
"",
"Spawn the panel in Discord using: /panel <id>",
"",
"TIP: Create new panels by copying everything between and including the {...} brackets of an panel. Paste it after the last panel and make sure that they are seperated by a comma."
].join("\n")),new fjs.ArrayFormatter(null,true,new fjs.ObjectFormatter(null,true,[
new fjs.MultiCommentFormatter("A panel is creates a message with up to 25 options as buttons or dropdown."),
new fjs.PropertyFormatter("id"),
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("dropdown"),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Add up to 5 option IDs from (config/options.jsonc)."),
new fjs.ArrayFormatter("options",false,new fjs.PropertyFormatter(null)),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("text"),
new fjs.PropertyFormatter("text",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.ObjectFormatter("embed",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.PropertyFormatter("title"),
new fjs.PropertyFormatter("description"),
new fjs.PropertyFormatter("title",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.PropertyFormatter("description",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("customColor"),
new fjs.PropertyFormatter("url"),
new fjs.PropertyFormatter("customColor",new fjs.SingleCommentFormatter("Leave empty to use default color")),
new fjs.PropertyFormatter("url",new fjs.SingleCommentFormatter("URL. Leave empty to disable")),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("image"),
new fjs.PropertyFormatter("thumbnail"),
new fjs.PropertyFormatter("image",new fjs.SingleCommentFormatter("Image URL. Leave empty to disable")),
new fjs.PropertyFormatter("thumbnail",new fjs.SingleCommentFormatter("Image URL. Leave empty to disable")),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("footer"),
new fjs.PropertyFormatter("footer",new fjs.SingleCommentFormatter("Leave empty to disable")),
new fjs.MultiCommentFormatter("Embed fields. Set to empty list [] to disable."),
new fjs.ArrayFormatter("fields",true,new fjs.ObjectFormatter(null,false,[
new fjs.PropertyFormatter("name"),
new fjs.PropertyFormatter("value"),
@@ -328,53 +499,70 @@ export const defaultPanelsFormatter = new fjs.ArrayFormatter(null,true,new fjs.O
new fjs.PropertyFormatter("timestamp"),
]),
new fjs.ObjectFormatter("settings",true,[
new fjs.PropertyFormatter("dropdownPlaceholder"),
new fjs.PropertyFormatter("dropdownPlaceholder",new fjs.SingleCommentFormatter("Leave empty to use default.")),
new fjs.PropertyFormatter("maximumButtonsPerRow"),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Display the maximum amount of tickets per user."),
new fjs.PropertyFormatter("enableMaxTicketsWarningInText"),
new fjs.PropertyFormatter("enableMaxTicketsWarningInEmbed"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("describeOptionsLayout"),
new fjs.MultiCommentFormatter("Automatically generate option descriptions from (config/options.jsonc)."),
new fjs.PropertyFormatter("describeOptionsLayout",new fjs.SingleCommentFormatter("Choices: simple, normal, detailed")),
new fjs.PropertyFormatter("describeOptionsCustomTitle"),
new fjs.PropertyFormatter("describeOptionsInText"),
new fjs.PropertyFormatter("describeOptionsInEmbedFields"),
new fjs.PropertyFormatter("describeOptionsInEmbedDescription"),
]),
]))
])))
export const defaultTranscriptsFormatter = new fjs.ObjectFormatter(null,true,[
export const defaultTranscriptsFormatter = new fjs.TopLevelCommentFormatter(new fjs.MultiCommentFormatter([
"OPEN TICKET TRANSCRIPTS",
"----------------------------------------------",
"Enable transcript creation when tickets are deleted. There are 2 available transcript types: HTML & Text",
"",
"HTML Transcripts (recommended):",
"Generate transcripts as HTML files to view in the browser. No server or domain required. HTML Transcripts use an external service to process and host the transcripts.",
"",
"Text Transcripts:",
"Generate transcripts as simple .txt files with limited details. Processing happens fully local.",
].join("\n")),new fjs.ObjectFormatter(null,true,[
new fjs.ObjectFormatter("general",true,[
new fjs.PropertyFormatter("enabled"),
new fjs.TextFormatter(""),
new fjs.MultiCommentFormatter("Choose which users and channel get the generated transcript."),
new fjs.PropertyFormatter("enableChannel"),
new fjs.PropertyFormatter("enableCreatorDM"),
new fjs.PropertyFormatter("enableParticipantDM"),
new fjs.PropertyFormatter("enableActiveAdminDM"),
new fjs.PropertyFormatter("enableEveryAdminDM"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("channel"),
new fjs.PropertyFormatter("mode"),
new fjs.PropertyFormatter("channel",new fjs.SingleCommentFormatter("Where to send transcripts. Leave empty when disabled.")),
new fjs.PropertyFormatter("mode",new fjs.SingleCommentFormatter("The type of transcript to use. Choices: html, text")),
]),
new fjs.ObjectFormatter("embedSettings",true,[
new fjs.PropertyFormatter("customColor"),
new fjs.MultiCommentFormatter("Customise the embed which contains the generated transcript file or URL."),
new fjs.PropertyFormatter("customColor",new fjs.SingleCommentFormatter("Leave empty to use default color")),
new fjs.PropertyFormatter("listAllParticipants"),
new fjs.PropertyFormatter("includeTicketStats"),
]),
new fjs.ObjectFormatter("textTranscriptStyle",true,[
new fjs.PropertyFormatter("layout"),
new fjs.MultiCommentFormatter("Customise layout of the text transcripts."),
new fjs.PropertyFormatter("layout",new fjs.SingleCommentFormatter("Choices: simple, normal, detailed")),
new fjs.PropertyFormatter("includeStats"),
new fjs.PropertyFormatter("includeIds"),
new fjs.PropertyFormatter("includeEmbeds"),
new fjs.PropertyFormatter("includeFiles"),
new fjs.PropertyFormatter("includeBotMessages"),
new fjs.TextFormatter(""),
new fjs.PropertyFormatter("fileMode"),
new fjs.PropertyFormatter("customFileName"),
new fjs.PropertyFormatter("fileMode",new fjs.SingleCommentFormatter("How to name the transcript file? Choices: custom, channel-name, channel-id, user-name, user-id")),
new fjs.PropertyFormatter("customFileName",new fjs.SingleCommentFormatter("Custom filename without extension")),
]),
new fjs.ObjectFormatter("htmlTranscriptStyle",true,[
new fjs.MultiCommentFormatter("Customise layout of the HTML transcripts."),
new fjs.ObjectFormatter("background",true,[
new fjs.PropertyFormatter("enableCustomBackground"),
new fjs.PropertyFormatter("backgroundColor"),
new fjs.PropertyFormatter("backgroundImage"),
new fjs.PropertyFormatter("backgroundColor",new fjs.SingleCommentFormatter("Leave empty to use Open Ticket color (#f8ba00)")),
new fjs.PropertyFormatter("backgroundImage",new fjs.SingleCommentFormatter("Image URL to fill entire background. Leave empty to disable")),
]),
new fjs.ObjectFormatter("header",true,[
new fjs.PropertyFormatter("enableCustomHeader"),
@@ -395,4 +583,4 @@ export const defaultTranscriptsFormatter = new fjs.ObjectFormatter(null,true,[
new fjs.PropertyFormatter("imageUrl"),
]),
]),
])
]))
+3 -3
View File
@@ -20,11 +20,11 @@ export async function loadAllHelpMenuComponents(){
if (!generalConfig) return
const prefix = generalConfig.data.prefix
const enableDeleteWithoutTranscript = generalConfig.data.system.enableDeleteWithoutTranscript
const enableDeleteWithoutTranscript = generalConfig.data.ticketSystem.enableDeleteWithoutTranscript
const allowedCommands: string[] = []
for (const key in generalConfig.data.system.permissions){
if (generalConfig.data.system.permissions[key] != "none") allowedCommands.push(key)
for (const key in generalConfig.data.permissions){
if (generalConfig.data.permissions[key] != "none") allowedCommands.push(key)
}
const general = helpmenu.get("opendiscord:general")
+1 -1
View File
@@ -7,7 +7,7 @@ export async function loadAllPosts(){
if (!transcriptConfig) return
//LOGS CHANNEL
if (generalConfig.data.system.logs.enabled) opendiscord.posts.add(new api.ODPost("opendiscord:logs",generalConfig.data.system.logs.channel))
if (generalConfig.data.logs.enabled) opendiscord.posts.add(new api.ODPost("opendiscord:logs",generalConfig.data.logs.channel))
//TRANSCRIPTS CHANNEL
if (transcriptConfig.data.general.enabled && transcriptConfig.data.general.enableChannel) opendiscord.posts.add(new api.ODPost("opendiscord:transcripts",transcriptConfig.data.general.channel))
-3
View File
@@ -71,9 +71,6 @@ export const loadTicketOption = (option:api.ODOptionsJsonConfig_TicketOption): a
new api.ODOptionData("opendiscord:channel-prefix",option.channel.prefix),
new api.ODOptionData("opendiscord:channel-suffix",option.channel.suffix),
new api.ODOptionData("opendiscord:channel-category",option.channel.category),
new api.ODOptionData("opendiscord:channel-category-closed",option.channel.closedCategory),
new api.ODOptionData("opendiscord:channel-category-backup",option.channel.backupCategory),
new api.ODOptionData("opendiscord:channel-categories-claimed",option.channel.claimedCategory),
new api.ODOptionData("opendiscord:channel-topic",option.channel.topic),
new api.ODOptionData("opendiscord:dm-message-enabled",option.dmMessage.enabled),
+2 -2
View File
@@ -93,7 +93,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): {
}
if (layout == "detailed"){
const optionAdmins = [...opt.get("opendiscord:admins").value]
if (generalConfig.data.system.showGlobalAdminsInPanelRoles){
if (generalConfig.data.ticketSystem.showGlobalAdminsInPanelRoles){
for (const admin of generalConfig.data.globalAdmins){
if (!optionAdmins.includes(admin)) optionAdmins.push(admin)
}
@@ -147,7 +147,7 @@ export function describePanelOptions(mode:"fields"|"text", panel:api.ODPanel): {
}
if (layout == "detailed"){
const optionAdmins = [...opt.get("opendiscord:admins").value]
if (generalConfig.data.system.showGlobalAdminsInPanelRoles){
if (generalConfig.data.ticketSystem.showGlobalAdminsInPanelRoles){
for (const admin of generalConfig.data.globalAdmins){
if (!optionAdmins.includes(admin)) optionAdmins.push(admin)
}
+5 -4
View File
@@ -20,7 +20,7 @@
INFORMATION:
============
Open Ticket v4.1.3 - © DJdj Development
Open Ticket v4.2.0 - © DJdj Development
support us: https://github.com/sponsors/DJj123dj
discord: https://discord.dj-dj.be
@@ -151,7 +151,8 @@ const main = async () => {
if (opendiscord.sharedFuses.getFuse("emojiTitleStyleLoading")){
//set emoji style based on config
opendiscord.sharedFuses.setFuse("emojiTitleStyle",generalConfig.data.system.emojiStyle)
const emojiStyle = (generalConfig.data && generalConfig.data.ticketSystem && generalConfig.data.ticketSystem.emojiStyle) ? generalConfig.data.ticketSystem.emojiStyle : "before"
opendiscord.sharedFuses.setFuse("emojiTitleStyle",emojiStyle)
}
//load database
@@ -225,7 +226,7 @@ const main = async () => {
}
//handle data migration (PART 2)
if (lastVersion) await (await import("./core/startup/manageMigration.js")).loadAllAfterInitVersionMigrations(lastVersion)
if (lastVersion) await (await import("./core/startup/manageMigration.js")).loadAfterStartupMigrations(lastVersion)
//load config checker
opendiscord.log("Loading config checker...","system")
@@ -253,7 +254,7 @@ const main = async () => {
if (opendiscord.sharedFuses.getFuse("checkerTranslationLoading")){
await (await import("./data/framework/checkerLoader.js")).loadAllConfigCheckerTranslations()
}
await opendiscord.events.get("onCheckerTranslationLoad").emit([opendiscord.checkers.translation,((generalConfig && generalConfig.data.system && generalConfig.data.system.useTranslatedConfigChecker) ? generalConfig.data.system.useTranslatedConfigChecker : false),opendiscord.checkers])
await opendiscord.events.get("onCheckerTranslationLoad").emit([opendiscord.checkers.translation,((generalConfig && generalConfig.data.ticketSystem && generalConfig.data.ticketSystem.useTranslatedConfigChecker) ? generalConfig.data.ticketSystem.useTranslatedConfigChecker : false),opendiscord.checkers])
await opendiscord.events.get("afterCheckerTranslationsLoaded").emit([opendiscord.checkers.translation,opendiscord.checkers])
//render config checker