Solved merge conflicts

This commit is contained in:
JasperAtSchool
2026-05-20 10:42:17 +02:00
247 changed files with 10788 additions and 25817 deletions
+12 -25
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET ADD USER SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:add-ticket-user"))
opendiscord.actions.get("opendiscord:add-ticket-user").workers.add([
new api.ODWorker("opendiscord:add-ticket-user",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:add-ticket-user",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to add user to ticket! Open Ticket doesn't support threads!")
@@ -34,44 +34,31 @@ export const registerActions = async () => {
opendiscord.log("Failed to add channel permission overwrites on add-ticket-user","error")
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket user adding!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value,hidden:true}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data})).message)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUserAdded").emit([ticket,user,data,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"add",reason,additionalData:data}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params
opendiscord.log(user.displayName+" added "+data.displayName+" to a ticket!","info",[
@@ -80,7 +67,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+129
View File
@@ -0,0 +1,129 @@
///////////////////////////////////////
//CALCULATE TICKET CATEGORY SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:calculate-ticket-category"))
opendiscord.actions.get("opendiscord:calculate-ticket-category").workers.add([
new api.ODWorker("opendiscord:default-category",2,async (instance,params,origin,cancel) => {
//handle default category
const {guild,user,channel,option,ticket,currentCategoryId} = params
const defaultCategoryId = option.get("opendiscord:channel-category").value
if (!defaultCategoryId){
//default category is disabled
instance.newCategoryId = null
instance.newCategoryMode = null
instance.newCategory = null
instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
}else{
const defaultCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,defaultCategoryId)
if (defaultCategory){
//default category is enabled
instance.newCategoryId = defaultCategoryId
instance.newCategoryMode = "default"
instance.newCategory = defaultCategory
instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
}else{
//default category is not found (do not switch categories)
opendiscord.log("Unable to find ticket category '"+defaultCategoryId+"' #1","error",[
{key:"categoryid",value:defaultCategoryId},
{key:"type",value:"default"}
])
instance.newCategoryId = null
instance.newCategoryMode = null
instance.newCategory = null
instance.shouldChangeCategory = false
}
}
}),
new api.ODWorker("opendiscord:close-category",1,async (instance,params,origin,cancel) => {
//handle close category
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 = generalConfig.data.ticketSystem.closedCategory.categoryId
if (!closeCategoryId) return
const closeCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,closeCategoryId)
if (closeCategory){
//close category is enabled
instance.newCategoryId = closeCategoryId
instance.newCategoryMode = "close"
instance.newCategory = closeCategory
instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
}else{
//close category is not found (do not switch categories)
opendiscord.log("Unable to find ticket category '"+closeCategoryId+"' #2","error",[
{key:"categoryid",value:closeCategoryId},
{key:"type",value:"close"}
])
instance.newCategoryId = null
instance.newCategoryMode = null
instance.newCategory = null
instance.shouldChangeCategory = false
}
}),
new api.ODWorker("opendiscord:claim-category",0,async (instance,params,origin,cancel) => {
//handle claim category
const {guild,user,channel,option,ticket,currentCategoryId} = params
if (!ticket) return
if (!ticket.get("opendiscord:claimed").value) return
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)
if (claimCategory){
//claim category is enabled
instance.newCategoryId = claimCategoryId
instance.newCategoryMode = "claim"
instance.newCategory = claimCategory
instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
}else{
//claim category is not found (do not switch categories)
opendiscord.log("Unable to find ticket category '"+claimCategoryId+"' #3","error",[
{key:"categoryid",value:claimCategoryId},
{key:"type",value:"claim"}
])
instance.newCategoryId = null
instance.newCategoryMode = null
instance.newCategory = null
instance.shouldChangeCategory = false
}
}),
new api.ODWorker("opendiscord:backup-category",-100,async (instance,params,origin,cancel) => {
//handle backup category
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 = generalConfig.data.ticketSystem.backupCategory.categoryId
if (!backupCategoryId) return
const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,backupCategoryId)
if (backupCategory){
//backup category is enabled
instance.newCategoryId = backupCategoryId
instance.newCategoryMode = "backup"
instance.newCategory = backupCategory
instance.shouldChangeCategory = (instance.newCategoryId !== currentCategoryId)
}else{
//backup category is not found (do not switch categories)
opendiscord.log("Unable to find ticket category '"+backupCategoryId+"' #4","error",[
{key:"categoryid",value:backupCategoryId},
{key:"type",value:"backup"}
])
instance.newCategoryId = null
instance.newCategoryMode = null
instance.newCategory = null
instance.shouldChangeCategory = false
}
})
])
}
+30
View File
@@ -0,0 +1,30 @@
///////////////////////////////////////
//CALCULATE TICKET NAME SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:calculate-ticket-name"))
opendiscord.actions.get("opendiscord:calculate-ticket-name").workers.add([
new api.ODWorker("opendiscord:calculate-ticket-name",0,async (instance,params,origin,cancel) => {
const {guild,user,channel,option,ticket,currentChannelName} = params
//calculate base channel name
const channelPrefix = option.get("opendiscord:channel-prefix").value
const channelSuffix = (ticket) ? ticket.get("opendiscord:channel-suffix").value : (await opendiscord.options.suffix.getSuffixFromOption(option,user,guild) ?? "unknown")
const channelRenamed = (ticket && ticket.exists("opendiscord:channel-renamed")) ? ticket.get("opendiscord:channel-renamed").value : null
const baseChannelName = (channelRenamed) ? channelRenamed : channelPrefix+channelSuffix
//calculate status emojis
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
instance.newChannelSuffix = channelSuffix
instance.shouldChangeName = (instance.newChannelName !== currentChannelName)
})
])
}
+39 -219
View File
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET CLAIMING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:claim-ticket"))
opendiscord.actions.get("opendiscord:claim-ticket").workers.add([
new api.ODWorker("opendiscord:claim-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:claim-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to claim ticket! Open Ticket doesn't support threads!")
@@ -22,67 +23,66 @@ export const registerActions = async () => {
ticket.get("opendiscord:busy").value = true
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-claimed",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-claimed",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-claimed",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-claimed",user.id,1,"increase")
//update category
//calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
const rawClaimCategory = ticket.option.get("opendiscord:channel-categories-claimed").value.find((c) => c.user == user.id)
const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null
if (claimCategory){
try {
channel.setParent(claimCategory,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = "claimed"
ticket.get("opendiscord:category").value = claimCategory
}catch(e){
opendiscord.log("Unable to move ticket to 'claimed category'!","error",[
const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("claim-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
const originalCategoryName = channel.parent?.name ?? "<unknown>"
const newCategoryName = categoryResult.newCategory?.name ?? "<unknown>"
try{
await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
})
ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
ticket.get("opendiscord:category").value = categoryResult.newCategoryId
}catch(err){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-claim",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
opendiscord.log("Unable to move ticket to claimed category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"categoryid",value:claimCategory}
{key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket claiming!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(source,{guild,channel,user,ticket,reason})).message)
if (params.sendMessage){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user,ticket,reason})).message)
if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
messageType:"claim-message",
messageOrigin:"other",
messageAuthor:user.id,
messageReason:reason
},false)
}
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketClaimed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"claim",reason,additionalData:null}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" claimed a ticket!","info",[
@@ -91,7 +91,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
@@ -99,184 +99,4 @@ export const registerActions = async () => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
}
export const registerVerifyBars = async () => {
//CLAIM TICKET TICKET MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.claim
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already claimed
if (ticket.get("opendiscord:claimed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start claiming ticket
if (params.data == "reason"){
//claim with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
}else{
//claim without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:claim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}
})
])
opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").failure.add([
new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
})
])
//CLAIM TICKET UNCLAIM MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket-unclaim-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-unclaim-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.claim
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already claimed
if (ticket.get("opendiscord:claimed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start claiming ticket
if (params.data == "reason"){
//claim with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("unclaim-message",{guild,channel,user,ticket}))
}else{
//claim without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:claim-ticket").run("unclaim-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("unclaim-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").failure.add([
new api.ODWorker("opendiscord:back-to-unclaim-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason}))
})
])
}
+8 -8
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//CLEAR TICKETS SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:clear-tickets"))
opendiscord.actions.get("opendiscord:clear-tickets").workers.add([
new api.ODWorker("opendiscord:clear-tickets",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:clear-tickets",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,filter,list} = params
await opendiscord.events.get("onTicketsClear").emit([list,user,channel,filter])
@@ -43,21 +43,21 @@ export const registerActions = async () => {
instance.list = nameList
await opendiscord.events.get("afterTicketsCleared").emit([list,user,channel,filter])
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,filter,list:instance.list ?? []}))
if (logChannel) logChannel.send(await opendiscord.builders.messages.getSafe("opendiscord:clear-logs").build(origin,{guild,channel,user,filter,list:instance.list ?? []}))
}
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,filter,list} = params
opendiscord.log(user.displayName+" cleared "+list.length+" tickets!","info",[
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"filter",value:filter}
])
})
+41 -208
View File
@@ -1,16 +1,17 @@
///////////////////////////////////////
//TICKET CLOSING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:close-ticket"))
opendiscord.actions.get("opendiscord:close-ticket").workers.add([
new api.ODWorker("opendiscord:close-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:close-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to close ticket! Open Ticket doesn't support threads!")
@@ -25,29 +26,34 @@ export const registerActions = async () => {
ticket.get("opendiscord:reopened-by").value = null
ticket.get("opendiscord:reopened-on").value = null
if (source == "autoclose") ticket.get("opendiscord:autoclosed").value = true
if (origin == "autoclose") ticket.get("opendiscord:autoclosed").value = true
ticket.get("opendiscord:open").value = false
ticket.get("opendiscord:busy").value = true
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-closed",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-closed",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-closed",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-closed",user.id,1,"increase")
//update category
//calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
const closeCategory = ticket.option.get("opendiscord:channel-category-closed").value
if (closeCategory !== ""){
try {
channel.setParent(closeCategory,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = "closed"
ticket.get("opendiscord:category").value = closeCategory
}catch(e){
opendiscord.log("Unable to move ticket to 'closed category'!","error",[
const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("close-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
const originalCategoryName = channel.parent?.name ?? "<unknown>"
const newCategoryName = categoryResult.newCategory?.name ?? "<unknown>"
try{
await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
})
ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
ticket.get("opendiscord:category").value = categoryResult.newCategoryId
}catch(err){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-close",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
opendiscord.log("Unable to move ticket to closed category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"categoryid",value:closeCategory}
{key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
}
@@ -93,7 +99,7 @@ export const registerActions = async () => {
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:[],
@@ -109,44 +115,39 @@ export const registerActions = async () => {
})
channel.permissionOverwrites.set(permissions)
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket closing!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(source,{guild,channel,user,ticket,reason})).message)
if (params.sendMessage){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason})).message)
if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
messageType:"close-message",
messageOrigin:"other",
messageAuthor:user.id,
messageReason:reason
},false)
}
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketClosed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"close",reason,additionalData:null}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" closed a ticket!","info",[
@@ -155,7 +156,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
@@ -163,172 +164,4 @@ export const registerActions = async () => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
}
export const registerVerifyBars = async () => {
//CLOSE TICKET TICKET MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").success.add([
new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.close,"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("button",{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already closed
if (ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:lang.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
//start closing ticket
if (params.data == "reason"){
//close with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
}else{
//close without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:close-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}
})
])
opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").failure.add([
new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
})
])
//CLOSE TICKET REOPEN MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket-reopen-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").success.add([
new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.close,"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("button",{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already closed
if (ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:lang.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
//start closing ticket
if (params.data == "reason"){
//close with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("reopen-message",{guild,channel,user,ticket}))
}else{
//close without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:close-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("reopen-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").failure.add([
new api.ODWorker("opendiscord:back-to-reopen-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
})
])
}
+50 -68
View File
@@ -1,63 +1,36 @@
///////////////////////////////////////
//TICKET CREATION SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:create-ticket"))
opendiscord.actions.get("opendiscord:create-ticket").workers.add([
new api.ODWorker("opendiscord:create-ticket",3,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:create-ticket",3,async (instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
await opendiscord.events.get("onTicketCreate").emit([user])
await opendiscord.events.get("onTicketChannelCreation").emit([option,user])
//get channel properties
const channelPrefix = option.get("opendiscord:channel-prefix").value
const channelCategory = option.get("opendiscord:channel-category").value
const channelBackupCategory = option.get("opendiscord:channel-category-backup").value
const channelTopicText = option.get("opendiscord:channel-topic").value
const channelSuffix = await opendiscord.options.suffix.getSuffixFromOption(option,user,guild)
const channelName = channelPrefix+channelSuffix
//handle category
let category: string|null = null
let categoryMode: "backup"|"normal"|null = null
if (channelCategory != ""){
//category enabled
const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
if (!normalCategory){
//default category was not found
opendiscord.log("Ticket Creation Error: Unable to find category! #1","error",[
{key:"categoryid",value:channelCategory},
{key:"backup",value:"false"}
])
}else{
//default category was found
if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){
//use backup category
const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
if (!backupCategory){
//default category was not found
opendiscord.log("Ticket Creation Error: Unable to find category! #2","error",[
{key:"categoryid",value:channelBackupCategory},
{key:"backup",value:"true"}
])
}else{
category = backupCategory.id
categoryMode = "backup"
}
}else{
//use default category
category = normalCategory.id
categoryMode = "normal"
}
}
}
//calculate channel name
const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("create-ticket",{guild,user,option,channel:null,ticket:null,currentChannelName:null})
if (!channelNameResult) return opendiscord.log("Ticket Creation Error: Unable to calculate ticket name.","error")
const channelName = (channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined") ? channelNameResult.newChannelName : "ot-unnamed-ticket"
const channelSuffix = (typeof channelNameResult.newChannelSuffix !== "undefined") ? channelNameResult.newChannelSuffix : "unknown"
//calculate category
const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("create-ticket",{guild,user,option,channel:null,ticket:null,currentCategoryId:null})
if (!categoryResult) return opendiscord.log("Ticket Creation Error: Unable to calculate ticket category.","error")
const ticketCategoryId = (categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined") ? categoryResult.newCategoryId : undefined
const ticketCategoryMode = (categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryMode !== "undefined") ? categoryResult.newCategoryMode : undefined
//handle permissions
const permissions: discord.OverwriteResolvable[] = [{
@@ -118,15 +91,15 @@ export const registerActions = async () => {
//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({
@@ -134,7 +107,7 @@ export const registerActions = async () => {
name:channelName,
nsfw:false,
topic:(channelTopics.length > 0) ? channelTopics.join(" • ") : undefined,
parent:category,
parent:ticketCategoryId,
reason:"Ticket Created By "+user.displayName,
permissionOverwrites:permissions,
rateLimitPerUser:slowMode
@@ -148,6 +121,7 @@ export const registerActions = async () => {
new api.ODTicketData("opendiscord:ticket-message",null),
new api.ODTicketData("opendiscord:participants",participants),
new api.ODTicketData("opendiscord:channel-suffix",channelSuffix),
new api.ODTicketData("opendiscord:channel-renamed",null),
new api.ODTicketData("opendiscord:previous-creators",[]),
new api.ODTicketData("opendiscord:open",true),
@@ -167,8 +141,8 @@ export const registerActions = async () => {
new api.ODTicketData("opendiscord:pinned-on",null),
new api.ODTicketData("opendiscord:for-deletion",false),
new api.ODTicketData("opendiscord:category",category),
new api.ODTicketData("opendiscord:category-mode",categoryMode),
new api.ODTicketData("opendiscord:category",ticketCategoryId ?? null),
new api.ODTicketData("opendiscord:category-mode",ticketCategoryMode ?? null),
new api.ODTicketData("opendiscord:autoclose-enabled",option.get("opendiscord:autoclose-enable-hours").value),
new api.ODTicketData("opendiscord:autoclose-hours",(option.get("opendiscord:autoclose-enable-hours").value ? option.get("opendiscord:autoclose-hours").value : 0)),
@@ -184,8 +158,8 @@ export const registerActions = async () => {
])
//manage stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-created",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-created",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-created",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-created",user.id,1,"increase")
//manage bot permissions
await opendiscord.events.get("onTicketPermissionsCreated").emit([option,opendiscord.permissions,channel,user])
@@ -197,7 +171,7 @@ export const registerActions = async () => {
instance.ticket = ticket
opendiscord.tickets.add(ticket)
}),
new api.ODWorker("opendiscord:send-ticket-message",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:send-ticket-message",2,async (instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
const {ticket,channel} = instance
@@ -207,17 +181,23 @@ export const registerActions = async () => {
//check if ticket message is enabled
if (!option.get("opendiscord:ticket-message-enabled").value) return
try {
const msg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build(source,{guild,channel,user,ticket})).message)
const ticketMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build(origin,{guild,channel,user,ticket})).message)
ticket.get("opendiscord:ticket-message").value = msg.id
if (ticketMsg) await interactiveMsgState.setMsgState({channel,message:ticketMsg},{
messageType:"ticket-message",
messageOrigin:"other",
messageAuthor:user.id
},false)
ticket.get("opendiscord:ticket-message").value = ticketMsg.id
//pin ticket message (if required)
if (generalConfig.data.system.pinFirstTicketMessage && msg.pinnable) await msg.pin("Ticket Message")
if (generalConfig.data.ticketSystem.pinFirstTicketMessage && ticketMsg.pinnable) await ticketMsg.pin("Ticket Message")
//manage stats
await opendiscord.stats.get("opendiscord:ticket").setStat("opendiscord:messages-sent",ticket.id.value,1,"increase")
await opendiscord.statistics.get("opendiscord:ticket").setStat("opendiscord:messages-sent",ticket.id.value,1,"increase")
await opendiscord.events.get("afterTicketMainMessageCreated").emit([ticket,msg,channel,user])
await opendiscord.events.get("afterTicketMainMessageCreated").emit([ticket,ticketMsg,channel,user])
}catch(err){
process.emit("uncaughtException",err)
//something went wrong while sending the ticket message
@@ -225,20 +205,22 @@ export const registerActions = async () => {
}
await opendiscord.events.get("afterTicketCreated").emit([ticket,user,channel])
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
const {ticket,channel} = instance
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(source,{guild,channel,user,ticket}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,answers,option} = params
const {ticket,channel} = instance
@@ -249,7 +231,7 @@ export const registerActions = async () => {
{key:"userid",value:user.id,hidden:true},
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"option",value:option.id.value}
])
})
+10 -10
View File
@@ -1,13 +1,13 @@
///////////////////////////////////////
//TICKET CREATION SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:create-ticket-permissions"))
opendiscord.actions.get("opendiscord:create-ticket-permissions").workers.add([
new api.ODWorker("opendiscord:check-blacklist",4,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:check-blacklist",4,(instance,params,origin,cancel) => {
if (!params.option.get("opendiscord:allow-blacklisted-users").value && opendiscord.blacklist.exists(params.user.id)){
instance.valid = false
instance.reason = "blacklist"
@@ -19,7 +19,7 @@ export const registerActions = async () => {
return cancel()
}
}),
new api.ODWorker("opendiscord:check-cooldown",3,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:check-cooldown",3,(instance,params,origin,cancel) => {
const cooldown = opendiscord.cooldowns.get("opendiscord:option-cooldown_"+params.option.id.value)
if (cooldown && cooldown instanceof api.ODTimeoutCooldown && cooldown.use(params.user.id)){
instance.valid = false
@@ -36,16 +36,16 @@ export const registerActions = async () => {
return cancel()
}
}),
new api.ODWorker("opendiscord:check-global-limits",2,(instance,params,source,cancel) => {
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 const registerActions = async () => {
{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",[
@@ -67,7 +67,7 @@ export const registerActions = async () => {
return cancel()
}
}),
new api.ODWorker("opendiscord:check-option-limits",1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:check-option-limits",1,(instance,params,origin,cancel) => {
if (!params.option.exists("opendiscord:limits-enabled") || !params.option.get("opendiscord:limits-enabled").value) return
const allTickets = opendiscord.tickets.getFiltered((ticket) => ticket.option.id.value == params.option.id.value)
@@ -97,7 +97,7 @@ export const registerActions = async () => {
return cancel()
}
}),
new api.ODWorker("opendiscord:valid",0,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:valid",0,(instance,params,origin,cancel) => {
instance.valid = true
instance.reason = null
cancel()
+40 -14
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TRANSCRIPT CREATION SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:create-transcript"))
opendiscord.actions.get("opendiscord:create-transcript").workers.add([
new api.ODWorker("opendiscord:select-compiler",4,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:select-compiler",4,async (instance,params,origin,cancel) => {
const {channel,user,ticket} = params
if (channel.type != discord.ChannelType.GuildText) return cancel()
if (!transcriptConfig.data.general.enabled) return cancel()
@@ -29,10 +29,15 @@ export const registerActions = async () => {
if (transcriptConfig.data.general.mode == "text") instance.compiler = opendiscord.transcripts.get("opendiscord:text-compiler")
else if (transcriptConfig.data.general.mode == "html") instance.compiler = opendiscord.transcripts.get("opendiscord:html-compiler")
}),
new api.ODWorker("opendiscord:init-transcript",3,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:init-transcript",3,async (instance,params,origin,cancel) => {
const {channel,user,ticket} = params
if (channel.type != discord.ChannelType.GuildText) return cancel()
if (!transcriptConfig.data.general.enabled) return cancel()
if (!instance.compiler){
instance.success = false
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:init-transcript) => Instance is missing transcript compiler!")
}
//run transcript compiler init()
await opendiscord.events.get("onTranscriptInit").emit([opendiscord.transcripts,ticket,channel,user])
@@ -63,7 +68,7 @@ export const registerActions = async () => {
}
await opendiscord.events.get("afterTranscriptInitiated").emit([opendiscord.transcripts,ticket,channel,user])
}),
new api.ODWorker("opendiscord:compile-transcript",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:compile-transcript",2,async (instance,params,origin,cancel) => {
const {channel,user,ticket} = params
if (channel.type != discord.ChannelType.GuildText) return cancel()
if (!instance.compiler){
@@ -71,6 +76,11 @@ export const registerActions = async () => {
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:compile-transcript) => Instance is missing transcript compiler!")
}
if (typeof instance.initData == "undefined"){
instance.success = false
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:compile-transcript) => Instance is missing transcript initData!")
}
//run transcript compiler compile()
await opendiscord.events.get("onTranscriptCompile").emit([opendiscord.transcripts,ticket,channel,user])
@@ -93,15 +103,31 @@ export const registerActions = async () => {
}
await opendiscord.events.get("afterTranscriptCompiled").emit([opendiscord.transcripts,ticket,channel,user])
}),
new api.ODWorker("opendiscord:ready-transcript",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:ready-transcript",1,async (instance,params,origin,cancel) => {
if (!instance.compiler){
instance.success = false
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript compiler! (1)")
}
if (!instance.result){
instance.success = false
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript result!")
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript result! (1)")
}
//run transcript compiler ready()
utilities.runAsync(async () => {
if (!instance.compiler){
instance.success = false
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript compiler! (2)")
}
if (!instance.result){
instance.success = false
cancel()
throw new api.ODSystemError("ODAction(ot:create-transcript):ODWorker(ot:ready-transcript) => Instance is missing transcript result! (2)")
}
await opendiscord.events.get("onTranscriptReady").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user])
if (instance.compiler.ready){
try{
@@ -109,9 +135,9 @@ export const registerActions = async () => {
//send channel message
if (transcriptConfig.data.general.enableChannel && channelMessage){
if (instance.pendingMessage && instance.pendingMessage.message && instance.pendingMessage.success){
if (instance.pendingMessage && instance.pendingMessage.success){
//edit "pending" message to be the "ready" message
instance.pendingMessage.message.edit(channelMessage.message)
instance.pendingMessage.message.edit(utilities.getMessageFromBuildResult(channelMessage,"message"))
}else{
//send ready message to channel
const post = opendiscord.posts.get("opendiscord:transcripts")
@@ -149,11 +175,11 @@ export const registerActions = async () => {
})
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:transcripts-created",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:transcripts-created",params.user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:transcripts-created",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:transcripts-created",params.user.id,1,"increase")
await opendiscord.events.get("afterTranscriptCreated").emit([opendiscord.transcripts,instance.result.ticket,instance.result.channel,instance.result.user])
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {user,channel,ticket} = params
opendiscord.log(user.displayName+" created a transcript!","info",[
{key:"user",value:user.username},
@@ -161,8 +187,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"option",value:ticket.option.id.value},
{key:"method",value:source,hidden:true},
{key:"compiler",value:instance.compiler.id.value},
{key:"method",value:origin,hidden:true},
{key:"compiler",value:instance.compiler?.id.value ?? "<unknown-compiler>"},
])
})
])
+17 -383
View File
@@ -1,16 +1,16 @@
///////////////////////////////////////
//TICKET DELETION SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:delete-ticket"))
opendiscord.actions.get("opendiscord:delete-ticket").workers.add([
new api.ODWorker("opendiscord:delete-ticket",3,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:delete-ticket",3,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to delete ticket! Open Ticket doesn't support threads!")
@@ -20,31 +20,18 @@ export const registerActions = async () => {
ticket.get("opendiscord:for-deletion").value = true
ticket.get("opendiscord:busy").value = true
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket deletion!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason})).message)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(origin,{guild,channel,user,ticket,reason})).message)
//create transcript
if (!params.withoutTranscript){
const transcriptRes = await opendiscord.actions.get("opendiscord:create-transcript").run(source,{guild,channel,user,ticket})
const transcriptRes = await opendiscord.actions.get("opendiscord:create-transcript").run(origin,{guild,channel,user,ticket})
//transcript failure
if (typeof transcriptRes.success == "boolean" && !transcriptRes.success && transcriptRes.compiler){
const {compiler} = transcriptRes
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transcript-error").build(source,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message)
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transcript-error").build(origin,{guild,channel,user,ticket,compiler,reason:transcriptRes.errorReason ?? null})).message)
.catch((reason) => opendiscord.log("Unable to send transcript failure to ticket channel!","error",[{key:"id",value:channel.id}]))
//undo deletion
@@ -59,8 +46,8 @@ export const registerActions = async () => {
}
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-deleted",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-deleted",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-deleted",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-deleted",user.id,1,"increase")
//delete ticket from manager
opendiscord.tickets.remove(ticket.id)
@@ -68,21 +55,21 @@ export const registerActions = async () => {
//delete permissions from manager
await (await import("../data/framework/permissionLoader.js")).removeTicketPermissions(ticket)
}),
new api.ODWorker("opendiscord:discord-logs",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",2,async (instance,params,origin,cancel) => {
//logs before channel deletion => channel might still be used in log embeds
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(source,{guild,channel,user,ticket,mode:"delete",reason,additionalData:null}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:delete-channel",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
//delete channel & events
await opendiscord.events.get("onTicketChannelDeletion").emit([ticket,channel,user])
@@ -94,7 +81,7 @@ export const registerActions = async () => {
await opendiscord.events.get("afterTicketDeleted").emit([ticket,user,reason])
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" deleted a ticket!","info",[
@@ -103,7 +90,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source},
{key:"method",value:origin},
{key:"transcript",value:(!params.withoutTranscript).toString()},
])
})
@@ -113,357 +100,4 @@ export const registerActions = async () => {
params.ticket.get("opendiscord:busy").value = false
params.ticket.get("opendiscord:for-deletion").value = false
})
}
export const registerVerifyBars = async () => {
//DELETE TICKET TICKET MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").success.add([
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"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("button",{guild,channel,user,permissions:["support"]}))
return cancel()
}
//don't allow deleteWithoutTranscript to non-global-admins when enabled
if (params.data == "no-transcript" && generalConfig.data.system.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()
}
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
//delete with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
}else{
//delete without reason
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript:(params.data == "no-transcript")})
//update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
ticket.get("opendiscord:for-deletion").value = true
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}
})
])
opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").failure.add([
new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
})
])
//DELETE TICKET CLOSE MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-close-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").success.add([
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"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("button",{guild,channel,user,permissions:["support"]}))
return cancel()
}
//don't allow deleteWithoutTranscript to non-global-admins when enabled
if (params.data == "no-transcript" && generalConfig.data.system.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()
}
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
//delete with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("close-message",{guild,channel,user,ticket}))
}else{
//delete without reason
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")})
//update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
ticket.get("opendiscord:for-deletion").value = true
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("close-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").failure.add([
new api.ODWorker("opendiscord:back-to-close-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason}))
})
])
//DELETE TICKET REOPEN MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-reopen-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-reopen-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").success.add([
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"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("button",{guild,channel,user,permissions:["support"]}))
return cancel()
}
//don't allow deleteWithoutTranscript to non-global-admins when enabled
if (params.data == "no-transcript" && generalConfig.data.system.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()
}
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
//delete with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("reopen-message",{guild,channel,user,ticket}))
}else{
//delete without reason
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run("reopen-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")})
//update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
ticket.get("opendiscord:for-deletion").value = true
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("reopen-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").failure.add([
new api.ODWorker("opendiscord:back-to-reopen-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
})
])
//DELETE TICKET AUTOCLOSE MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket-autoclose-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").success.add([
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"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("button",{guild,channel,user,permissions:["support"]}))
return cancel()
}
//don't allow deleteWithoutTranscript to non-global-admins when enabled
if (params.data == "no-transcript" && generalConfig.data.system.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()
}
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
//delete with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("autoclose-message",{guild,channel,user,ticket}))
}else{
//delete without reason
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript:(params.data == "no-transcript")})
//update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
ticket.get("opendiscord:for-deletion").value = true
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("autoclose-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").failure.add([
new api.ODWorker("opendiscord:back-to-autoclose-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket}))
})
])
}
+47 -113
View File
@@ -1,76 +1,43 @@
///////////////////////////////////////
//TRANSCRIPT ERROR SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//TRANSCRIPT ERROR RETRY
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:transcript-error-retry",/^od:transcript-error-retry_([^_]+)/))
opendiscord.responders.buttons.get("opendiscord:transcript-error-retry").workers.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.delete
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"]
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch data
const originalOrigin = instance.interaction.customId.split("_")[1] as api.ODActionManagerIdMappings["opendiscord:delete-ticket"]["origin"]
//start deleting ticket (without reason)
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false})
//update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
ticket.get("opendiscord:for-deletion").value = true
opendiscord.actions.get("opendiscord:delete-ticket").run(originalOrigin,{guild,channel,user,ticket,reason:"Transcript Error (Retried)",sendMessage:false,withoutTranscript:false})
ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Retried)"}))
}),
new api.ODWorker("opendiscord:logs",-1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,async (instance,params,origin,cancel) => {
const {user,channel} = instance
if (channel.isDMBased()) return
opendiscord.log(user.displayName+" retried deleting a ticket with transcript!","info",[
@@ -78,7 +45,7 @@ export const registerButtonResponders = async () => {
{key:"userid",value:user.id,hidden:true},
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
@@ -86,68 +53,35 @@ export const registerButtonResponders = async () => {
//TRANSCRIPT ERROR CONTINUE
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:transcript-error-continue",/^od:transcript-error-continue_([^_]+)/))
opendiscord.responders.buttons.get("opendiscord:transcript-error-continue").workers.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.delete
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"]
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//start deleting ticket (without reason)
//fetch data
const originalOrigin = instance.interaction.customId.split("_")[1] as api.ODActionManagerIdMappings["opendiscord:delete-ticket"]["origin"]
//start deleting ticket (without reason & without transcript)
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true})
//update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
ticket.get("opendiscord:for-deletion").value = true
opendiscord.actions.get("opendiscord:delete-ticket").run(originalOrigin,{guild,channel,user,ticket,reason:"Transcript Error (Continued)",sendMessage:false,withoutTranscript:true})
ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason:"Transcript Error (Continued)"}))
}),
new api.ODWorker("opendiscord:logs",-1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,async (instance,params,origin,cancel) => {
const {user,channel} = instance
if (channel.isDMBased()) return
opendiscord.log(user.displayName+" continued deleting a ticket without transcript!","info",[
@@ -155,7 +89,7 @@ export const registerButtonResponders = async () => {
{key:"userid",value:user.id,hidden:true},
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+13 -23
View File
@@ -1,32 +1,22 @@
///////////////////////////////////////
//VERIFYBAR SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
export const registerButtonResponders = async () => {
//VERIFYBAR SUCCESS
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-success",/^od:verifybar-success_([^_]+)/))
opendiscord.responders.buttons.get("opendiscord:verifybar-success").workers.add(
new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,source,cancel) => {
const id = instance.interaction.customId.split("_")[1]
const customData = instance.interaction.customId.split("_")[2] as string|undefined
export async function registerButtonResponders(){
//HANDLE VERIFYBAR BUTTON
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-button",/^od:verifybar\|([^|]+)\|([^|]+)/))
opendiscord.responders.buttons.get("opendiscord:verifybar-button").workers.add(
new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,origin,cancel) => {
const match = /^od:verifybar\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const verifyBarId = match[1]
const verifyButtonId = match[2]
const verifybar = opendiscord.verifybars.get(id)
const verifybar = opendiscord.verifybars.get(verifyBarId)
if (!verifybar) return
if (verifybar.success) await verifybar.success.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message})
})
)
//VERIFYBAR FAILURE
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:verifybar-failure",/^od:verifybar-failure_([^_]+)/))
opendiscord.responders.buttons.get("opendiscord:verifybar-failure").workers.add(
new api.ODWorker("opendiscord:handle-verifybar",0,async (instance,params,source,cancel) => {
const id = instance.interaction.customId.split("_")[1]
const customData = instance.interaction.customId.split("_")[2] as string|undefined
const verifybar = opendiscord.verifybars.get(id)
if (!verifybar) return
if (verifybar.failure) await verifybar.failure.executeWorkers(instance,"verifybar",{data:customData ?? null,verifybarMessage:instance.message})
await verifybar.activate(instance,verifyButtonId)
})
)
}
+47 -102
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET MOVING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:move-ticket"))
opendiscord.actions.get("opendiscord:move-ticket").workers.add([
new api.ODWorker("opendiscord:move-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:move-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to move ticket! Open Ticket doesn't support threads!")
@@ -17,78 +17,31 @@ export const registerActions = async () => {
ticket.option = data
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-moved",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-moved",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-moved",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-moved",user.id,1,"increase")
//get new channel properties
const channelPrefix = ticket.option.get("opendiscord:channel-prefix").value
const channelSuffix = ticket.get("opendiscord:channel-suffix").value
const channelCategory = ticket.option.get("opendiscord:channel-category").value
const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value
const rawClaimCategory = ticket.option.get("opendiscord:channel-categories-claimed").value.find((c) => c.user == user.id)
const claimCategory = (rawClaimCategory) ? rawClaimCategory.category : null
const closeCategory = ticket.option.get("opendiscord:channel-category-closed").value
const channelTopic = ticket.option.get("opendiscord:channel-topic").value
//handle category
let category: string|null = null
let categoryMode: "backup"|"normal"|"closed"|"claimed"|null = null
if (claimCategory){
//use claim category
category = claimCategory
categoryMode = "claimed"
}else if (closeCategory != "" && ticket.get("opendiscord:closed").value){
//use close category
category = closeCategory
categoryMode = "closed"
}else if (channelCategory != ""){
//category enabled
const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
if (!normalCategory){
//default category was not found
opendiscord.log("Ticket Move Error: Unable to find category! #1","error",[
{key:"categoryid",value:channelCategory},
{key:"backup",value:"false"}
//calculate & update category
const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("move-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
const originalCategoryName = channel.parent?.name ?? "<unknown>"
const newCategoryName = categoryResult.newCategory?.name ?? "<unknown>"
try{
await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
})
ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
ticket.get("opendiscord:category").value = categoryResult.newCategoryId
}catch(err){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-move",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
opendiscord.log("Unable to move ticket to moved category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
}else{
//default category was found
if (normalCategory.children.cache.size >= 50 && channelBackupCategory != ""){
//use backup category
const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
if (!backupCategory){
//default category was not found
opendiscord.log("Ticket Move Error: Unable to find category! #2","error",[
{key:"categoryid",value:channelBackupCategory},
{key:"backup",value:"true"}
])
}else{
category = backupCategory.id
categoryMode = "backup"
}
}else{
//use default category
category = normalCategory.id
categoryMode = "normal"
}
}
}
try {
//only move category when not the same.
if (channel.parentId != category) await utilities.timedAwait(channel.setParent(category,{lockPermissions:false}),2500,(err) => {
opendiscord.log("Failed to change channel category on ticket move","error")
})
ticket.get("opendiscord:category-mode").value = categoryMode
ticket.get("opendiscord:category").value = category
}catch(e){
opendiscord.log("Unable to move ticket to 'moved category'!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"categoryid",value:category ?? "/"}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
//handle permissions
const permissions: discord.OverwriteResolvable[] = [{
type:discord.OverwriteType.Role,
@@ -153,58 +106,50 @@ export const registerActions = async () => {
ticket.get("opendiscord:participants").value = participants
ticket.get("opendiscord:participants").refreshDatabase()
//rename channel (and give error when crashed)
const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
const originalName = channel.name
const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channelPrefix+channelSuffix)
try{
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket move","error")
})
}catch(err){
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName:newName})).message)
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
//calculate channel name
const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("move-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
const originalName = channel.name
const newName = channelNameResult.newChannelName
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket moving!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket move","error")
})
}catch(err){
opendiscord.log("Unable to rename channel while moving ticket! Waiting until ratelimit expires...","warning",[
{key:"oldName",value:originalName},
{key:"newName",value:newName}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-move",{guild,channel,user,originalName,newName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data})).message)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketMoved").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"move",reason,additionalData:data}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" moved a ticket!","info",[
@@ -213,7 +158,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+38 -221
View File
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET PINNING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:pin-ticket"))
opendiscord.actions.get("opendiscord:pin-ticket").workers.add([
new api.ODWorker("opendiscord:pin-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:pin-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to pin ticket! Open Ticket doesn't support threads!")
@@ -22,66 +23,66 @@ export const registerActions = async () => {
ticket.get("opendiscord:busy").value = true
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-pinned",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-pinned",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-pinned",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-pinned",user.id,1,"increase")
//move to top of category
if (channel.parent){
await channel.setPosition(0,{reason:"Ticket Pinned!"})
}
//rename channel (and give error when crashed)
const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
const originalName = channel.name
const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channel.name)
try{
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket pin","error")
})
}catch(err){
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message)
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
//calculate channel name
const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("pin-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
const originalName = channel.name
const newName = channelNameResult.newChannelName
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket pinning!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"message",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket pin","error")
})
}catch(err){
opendiscord.log("Unable to rename channel while pinning ticket! Waiting until ratelimit expires...","warning",[
{key:"oldName",value:originalName},
{key:"newName",value:newName}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-pin",{guild,channel,user,originalName,newName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(source,{guild,channel,user,ticket,reason})).message)
if (params.sendMessage){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason})).message)
if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
messageType:"pin-message",
messageOrigin:"other",
messageAuthor:user.id,
messageReason:reason
},false)
}
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketPinned").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"pin",reason,additionalData:null}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" pinned a ticket!","info",[
@@ -90,192 +91,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerVerifyBars = async () => {
//PIN TICKET TICKET MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.pin
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already pinned
if (ticket.get("opendiscord:pinned").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start pinning ticket
if (params.data == "reason"){
//pin with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
}else{
//pin without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:pin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}
})
])
opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").failure.add([
new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
})
])
//PIN TICKET UNPIN MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket-unpin-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-unpin-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.pin
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already pinned
if (ticket.get("opendiscord:pinned").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start pinning ticket
if (params.data == "reason"){
//pin with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("unpin-message",{guild,channel,user,ticket}))
}else{
//pin without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:pin-ticket").run("unpin-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("unpin-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").failure.add([
new api.ODWorker("opendiscord:back-to-unpin-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason}))
})
])
opendiscord.actions.get("opendiscord:pin-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
}
+9 -9
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//REACTION ROLE SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:reaction-role"))
opendiscord.actions.get("opendiscord:reaction-role").workers.add([
new api.ODWorker("opendiscord:reaction-role",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:reaction-role",2,async (instance,params,origin,cancel) => {
const {guild,user,option,overwriteMode} = params
const role = opendiscord.roles.get(option.id)
if (!role) throw new api.ODSystemError("ODAction(ot:reaction-role) => Unknown reaction role (ODRole)")
@@ -83,25 +83,25 @@ export const registerActions = async () => {
instance.result = result
await opendiscord.events.get("afterRolesUpdated").emit([user,role])
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,user,option,overwriteMode} = params
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(source,{guild,user,role:instance.role,result:instance.result}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,user,option} = params
opendiscord.log(user.displayName+" updated his roles!","info",[
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"option",value:option.id.value}
])
})
+12 -24
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET REMOVE USER SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:remove-ticket-user"))
opendiscord.actions.get("opendiscord:remove-ticket-user").workers.add([
new api.ODWorker("opendiscord:remove-ticket-user",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:remove-ticket-user",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to remove user from ticket! Open Ticket doesn't support threads!")
@@ -29,43 +29,31 @@ export const registerActions = async () => {
opendiscord.log("Failed to remove channel permission overwrites on remove-ticket-user","error")
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket user removal!","error",[
{key:"channel",value:channel.id},
{key:"message",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data})).message)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUserRemoved").emit([ticket,user,data,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"remove",reason,additionalData:data}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,data} = params
opendiscord.log(user.displayName+" removed "+data.displayName+" from a ticket!","info",[
@@ -74,7 +62,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+29 -34
View File
@@ -1,72 +1,67 @@
///////////////////////////////////////
//TICKET RENAMING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:rename-ticket"))
opendiscord.actions.get("opendiscord:rename-ticket").workers.add([
new api.ODWorker("opendiscord:rename-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:rename-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,data} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to rename ticket! Open Ticket doesn't support threads!")
await opendiscord.events.get("onTicketRename").emit([ticket,user,channel,reason])
//rename channel (and give error when crashed)
const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
//update ticket
ticket.get("opendiscord:channel-renamed").value = data
const originalName = channel.name
const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(data)
try{
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket rename","error")
})
}catch(err){
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName:data})).message)
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
//calculate channel name
const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("rename-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
const originalName = channel.name
const newName = channelNameResult.newChannelName
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket renaming!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket rename","error")
})
}catch(err){
opendiscord.log("Unable to rename channel while renaming ticket! Waiting until ratelimit expires...","warning",[
{key:"oldName",value:originalName},
{key:"newName",value:newName}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-rename",{guild,channel,user,originalName,newName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data})).message)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(origin,{guild,channel,user,ticket,reason,data})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketRenamed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"rename",reason,additionalData:data}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" renamed a ticket!","info",[
@@ -75,7 +70,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+40 -344
View File
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET REOPENING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:reopen-ticket"))
opendiscord.actions.get("opendiscord:reopen-ticket").workers.add([
new api.ODWorker("opendiscord:reopen-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:reopen-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to reopen ticket! Open Ticket doesn't support threads!")
@@ -28,65 +29,37 @@ export const registerActions = async () => {
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
}
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-reopened",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-reopened",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-reopened",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-reopened",user.id,1,"increase")
//update category
//calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
const channelCategory = ticket.option.get("opendiscord:channel-category").value
const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value
if (channelCategory !== ""){
//category enabled
try {
const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
if (!normalCategory){
//default category was not found
opendiscord.log("Ticket Reopening Error: Unable to find category! #1","error",[
{key:"categoryid",value:channelCategory},
{key:"backup",value:"false"}
])
}else{
//default category was found
if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){
//use backup category
const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
if (!backupCategory){
//default category was not found
opendiscord.log("Ticket Reopening Error: Unable to find category! #2","error",[
{key:"categoryid",value:channelBackupCategory},
{key:"backup",value:"true"}
])
}else{
//use backup category
channel.setParent(backupCategory,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = "backup"
ticket.get("opendiscord:category").value = backupCategory.id
}
}else{
//use default category
channel.setParent(normalCategory,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = "normal"
ticket.get("opendiscord:category").value = normalCategory.id
}
}
}catch(e){
opendiscord.log("Unable to move ticket to 'reopened category'!","error",[
const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("reopen-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
const originalCategoryName = channel.parent?.name ?? "<unknown>"
const newCategoryName = categoryResult.newCategory?.name ?? "<unknown>"
try{
await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
})
ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
ticket.get("opendiscord:category").value = categoryResult.newCategoryId
}catch(err){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-reopen",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
opendiscord.log("Unable to move ticket to reopened category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}else{
channel.setParent(null,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = null
ticket.get("opendiscord:category").value = null
}
}
@@ -141,43 +114,38 @@ export const registerActions = async () => {
})
channel.permissionOverwrites.set(permissions)
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket reopening!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(source,{guild,channel,user,ticket,reason})).message)
if (params.sendMessage){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason})).message)
if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
messageType:"reopen-message",
messageOrigin:"other",
messageAuthor:user.id,
messageReason:reason
},false)
}
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketReopened").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"reopen",reason,additionalData:null}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" reopened a ticket!","info",[
@@ -186,280 +154,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerVerifyBars = async () => {
//REOPEN TICKET TICKET MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.reopen
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not closed
if (!ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start reopening ticket
if (params.data == "reason"){
//reopen with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
}else{
//reopen without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}
})
])
opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").failure.add([
new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
})
])
//REOPEN TICKET CLOSE MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-close-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-close-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.reopen
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not closed
if (!ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start reopening ticket
if (params.data == "reason"){
//reopen with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("close-message",{guild,channel,user,ticket}))
}else{
//reopen without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run("close-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("close-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").failure.add([
new api.ODWorker("opendiscord:back-to-close-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason}))
})
])
//REOPEN TICKET AUTOCLOSE MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket-autoclose-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-autoclose-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.reopen
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not closed
if (!ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start reopening ticket
if (params.data == "reason"){
//reopen with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("autoclose-message",{guild,channel,user,ticket}))
}else{
//reopen without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run("autoclose-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("autoclose-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").failure.add([
new api.ODWorker("opendiscord:back-to-autoclose-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("other",{guild,channel,user,ticket}))
})
])
opendiscord.actions.get("opendiscord:reopen-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
}
+26 -38
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET TRANSFER SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:transfer-ticket"))
opendiscord.actions.get("opendiscord:transfer-ticket").workers.add([
new api.ODWorker("opendiscord:transfer-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:transfer-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason,newCreator} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to transfer ticket! Open Ticket doesn't support threads!")
@@ -33,12 +33,8 @@ export const registerActions = async () => {
}
//update stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:tickets-transferred",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:tickets-transferred",user.id,1,"increase")
//get new channel properties
const channelPrefix = ticket.option.get("opendiscord:channel-prefix").value
const channelSuffix = ticket.get("opendiscord:channel-suffix").value
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:tickets-transferred",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:tickets-transferred",user.id,1,"increase")
//handle permissions
const permissions: discord.OverwriteResolvable[] = [{
@@ -93,48 +89,40 @@ export const registerActions = async () => {
opendiscord.log("Failed to reset channel permissions on ticket transfer!","error")
}
//rename channel (and give error when crashed)
const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
const originalName = channel.name
const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channelPrefix+channelSuffix)
try{
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket transfer","error")
})
}catch(err){
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-transfer",{guild,channel,user,originalName,newName:newName})).message)
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
//calculate channel name
const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("transfer-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
const originalName = channel.name
const newName = channelNameResult.newChannelName
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket transferring!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket transfer","error")
})
}catch(err){
opendiscord.log("Unable to rename channel while transferring ticket! Waiting until ratelimit expires...","warning",[
{key:"oldName",value:originalName},
{key:"newName",value:newName}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-transfer",{guild,channel,user,originalName,newName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(source,{guild,channel,user,ticket,oldCreator,newCreator,reason})).message)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(origin,{guild,channel,user,ticket,oldCreator,newCreator,reason})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketTransferred").emit([ticket,user,channel,oldCreator,newCreator,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newCreator,reason} = params
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newCreator} = params
opendiscord.log(user.displayName+" transferred a ticket to '"+newCreator.displayName+"'!","info",[
@@ -143,7 +131,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+38 -255
View File
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET UNCLAIMING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:unclaim-ticket"))
opendiscord.actions.get("opendiscord:unclaim-ticket").workers.add([
new api.ODWorker("opendiscord:unclaim-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:unclaim-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to unclaim ticket! Open Ticket doesn't support threads!")
@@ -21,97 +22,63 @@ export const registerActions = async () => {
ticket.get("opendiscord:claimed-on").value = null
ticket.get("opendiscord:busy").value = true
//update category
//calculate & update category
if (typeof params.allowCategoryChange == "boolean" ? params.allowCategoryChange : true){
const channelCategory = ticket.option.get("opendiscord:channel-category").value
const channelBackupCategory = ticket.option.get("opendiscord:channel-category-backup").value
if (channelCategory !== ""){
//category enabled
try {
const normalCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelCategory)
if (!normalCategory){
//default category was not found
opendiscord.log("Ticket Unclaiming Error: Unable to find category! #1","error",[
{key:"categoryid",value:channelCategory},
{key:"backup",value:"false"}
])
}else{
//default category was found
if (normalCategory.children.cache.size >= 49 && channelBackupCategory != ""){
//use backup category
const backupCategory = await opendiscord.client.fetchGuildCategoryChannel(guild,channelBackupCategory)
if (!backupCategory){
//default category was not found
opendiscord.log("Ticket Unclaiming Error: Unable to find category! #2","error",[
{key:"categoryid",value:channelBackupCategory},
{key:"backup",value:"true"}
])
}else{
//use backup category
channel.setParent(backupCategory,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = "backup"
ticket.get("opendiscord:category").value = backupCategory.id
}
}else{
//use default category
channel.setParent(normalCategory,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = "normal"
ticket.get("opendiscord:category").value = normalCategory.id
}
}
}catch(e){
opendiscord.log("Unable to move ticket to 'unclaimed category'!","error",[
const categoryResult = await opendiscord.actions.get("opendiscord:calculate-ticket-category").run("unclaim-ticket",{guild,user,option:ticket.option,channel,ticket,currentCategoryId:channel.parentId})
if (categoryResult && categoryResult.shouldChangeCategory && typeof categoryResult.newCategoryId !== "undefined" && typeof categoryResult.newCategoryMode !== "undefined" && typeof categoryResult.newCategory !== "undefined"){
const originalCategoryName = channel.parent?.name ?? "<unknown>"
const newCategoryName = categoryResult.newCategory?.name ?? "<unknown>"
try{
await utilities.timedAwait(channel.setParent(categoryResult.newCategoryId,{lockPermissions:false}),3000,(err) => {
process.emit("uncaughtException",new Error("Error: Unable to change channel parent: "+err))
})
ticket.get("opendiscord:category-mode").value = categoryResult.newCategoryMode
ticket.get("opendiscord:category").value = categoryResult.newCategoryId
}catch(err){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-category").build("ticket-unclaim",{guild,channel,user,originalCategory:originalCategoryName,newCategory:newCategoryName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
opendiscord.log("Unable to move ticket to unclaimed category.","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true}
{key:"channelid",value:channel.id,hidden:true},
{key:"categoryid",value:categoryResult.newCategoryId ?? "/"}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}else{
channel.setParent(null,{lockPermissions:false})
ticket.get("opendiscord:category-mode").value = null
ticket.get("opendiscord:category").value = null
}
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket unclaiming!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(source,{guild,channel,user,ticket,reason})).message)
if (params.sendMessage){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason})).message)
if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
messageType:"unclaim-message",
messageOrigin:"other",
messageAuthor:user.id,
messageReason:reason
},false)
}
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUnclaimed").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"unclaim",reason,additionalData:null}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" unclaimed a ticket!","info",[
@@ -120,192 +87,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerVerifyBars = async () => {
//UNCLAIM TICKET TICKET MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.unclaim
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not claimed
if (!ticket.get("opendiscord:claimed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start unclaiming ticket
if (params.data == "reason"){
//unclaim with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
}else{
//unclaim without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unclaim-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}
})
])
opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").failure.add([
new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
})
])
//UNCLAIM TICKET CLAIM MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket-claim-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-claim-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.unclaim
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not claimed
if (!ticket.get("opendiscord:claimed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start unclaiming ticket
if (params.data == "reason"){
//unclaim with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("claim-message",{guild,channel,user,ticket}))
}else{
//unclaim without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unclaim-ticket").run("claim-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("claim-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").failure.add([
new api.ODWorker("opendiscord:back-to-claim-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason}))
})
])
opendiscord.actions.get("opendiscord:unclaim-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
}
+36 -219
View File
@@ -1,15 +1,16 @@
///////////////////////////////////////
//TICKET UNPINNING SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:unpin-ticket"))
opendiscord.actions.get("opendiscord:unpin-ticket").workers.add([
new api.ODWorker("opendiscord:unpin-ticket",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:unpin-ticket",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,reason} = params
if (channel.isThread()) throw new api.ODSystemError("Unable to unpin ticket! Open Ticket doesn't support threads!")
@@ -21,58 +22,58 @@ export const registerActions = async () => {
ticket.get("opendiscord:pinned-on").value = null
ticket.get("opendiscord:busy").value = true
//rename channel (and give error when crashed)
const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
const priorityEmoji = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value).channelEmoji ?? ""
const originalName = channel.name
const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channel.name)
try{
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket unpin","error")
})
}catch(err){
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message)
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
//calculate channel name
const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("unpin-ticket",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
const originalName = channel.name
const newName = channelNameResult.newChannelName
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on ticket unpinning!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket unpin","error")
})
}catch(err){
opendiscord.log("Unable to rename channel while unpinning ticket! Waiting until ratelimit expires...","warning",[
{key:"oldName",value:originalName},
{key:"newName",value:newName}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-unpin",{guild,channel,user,originalName,newName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(source,{guild,channel,user,ticket,reason})).message)
if (params.sendMessage){
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason})).message)
if (sentMsg) await interactiveMsgState.setMsgState({channel,message:sentMsg},{
messageType:"unpin-message",
messageOrigin:"other",
messageAuthor:user.id,
messageReason:reason
},false)
}
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketUnpinned").emit([ticket,user,channel,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,ticket,mode:"unpin",reason,additionalData:null}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
opendiscord.log(user.displayName+" unpinned a ticket!","info",[
@@ -81,192 +82,8 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerVerifyBars = async () => {
//UNPIN TICKET TICKET MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket-ticket-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-ticket-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.unpin
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not pinned
if (!ticket.get("opendiscord:pinned").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start unpining ticket
if (params.data == "reason"){
//unpin with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("ticket-message",{guild,channel,user,ticket}))
}else{
//unpin without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unpin-ticket").run("ticket-message",{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}
})
])
opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").failure.add([
new api.ODWorker("opendiscord:back-to-ticket-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
})
])
//UNPIN TICKET PIN MESSAGE
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket-pin-message",opendiscord.builders.messages.getSafe("opendiscord:verifybar-pin-message"),!generalConfig.data.system.disableVerifyBars))
opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").success.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.unpin
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
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()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not pinned
if (!ticket.get("opendiscord:pinned").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//start unpinning ticket
if (params.data == "reason"){
//unpin with reason
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("pin-message",{guild,channel,user,ticket}))
}else{
//unpin without reason
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unpin-ticket").run("pin-message",{guild,channel,user,ticket,reason:null,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("pin-message",{guild,channel,user,ticket,reason:null}))
}
})
])
opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").failure.add([
new api.ODWorker("opendiscord:back-to-pin-message",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
const {verifybarMessage} = params
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
const rawReason = (verifybarMessage && verifybarMessage.embeds[0] && verifybarMessage.embeds[0].fields[0]) ? verifybarMessage.embeds[0].fields[0].value : null
const reason = (rawReason == null) ? null : rawReason.substring(3,rawReason.length-3)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason}))
})
])
opendiscord.actions.get("opendiscord:unpin-ticket").workers.backupWorker = new api.ODWorker("opendiscord:cancel-busy",0,(instance,params) => {
//set busy to false in case of crash or cancel
params.ticket.get("opendiscord:busy").value = false
})
}
+24 -19
View File
@@ -1,15 +1,15 @@
///////////////////////////////////////
//TICKET TOPIC SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:update-ticket-priority"))
opendiscord.actions.get("opendiscord:update-ticket-priority").workers.add([
new api.ODWorker("opendiscord:update-ticket-priority",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:update-ticket-priority",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newPriority,reason} = params
if (channel.isThread() || !(channel instanceof discord.TextChannel)) throw new api.ODSystemError("Unable to set priority of ticket! Open Ticket doesn't support threads!")
@@ -20,32 +20,37 @@ export const registerActions = async () => {
ticket.get("opendiscord:busy").value = true
if (newPriority) ticket.get("opendiscord:priority").value = newPriority.priority
//rename channel (and give error when crashed)
const pinEmoji = ticket.get("opendiscord:pinned").value ? generalConfig.data.system.pinEmoji : ""
const priorityEmoji = newPriority.channelEmoji ?? ""
const originalName = channel.name
const newName = pinEmoji+priorityEmoji+utilities.trimEmojis(channel.name)
try{
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on ticket priority update","error")
})
}catch(err){
await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-priority",{guild,channel,user,originalName,newName})).message)
//calculate channel name
const channelNameResult = await opendiscord.actions.get("opendiscord:calculate-ticket-name").run("priority-change",{guild,user,option:ticket.option,channel,ticket,currentChannelName:channel.name})
if (channelNameResult && channelNameResult.shouldChangeName && typeof channelNameResult.newChannelName !== "undefined"){
const originalName = channel.name
const newName = channelNameResult.newChannelName
try{
await utilities.timedAwait(channel.setName(newName),2500,(err) => {
opendiscord.log("Failed to rename channel on priority change","error")
})
}catch(err){
opendiscord.log("Unable to rename channel while updating ticket priority! Waiting until ratelimit expires...","warning",[
{key:"oldName",value:originalName},
{key:"newName",value:newName}
])
const sentMsg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:error-channel-rename").build("ticket-priority",{guild,channel,user,originalName,newName})).message)
setTimeout(() => {if (sentMsg.deletable) sentMsg.delete()},7000) //autodelete error message
}
}
//reply with new message
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(source,{guild,channel,user,ticket,priority:newPriority,reason})).message)
if (params.sendMessage) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(origin,{guild,channel,user,ticket,priority:newPriority,reason})).message)
ticket.get("opendiscord:busy").value = false
await opendiscord.events.get("afterTicketPriorityChanged").emit([ticket,user,channel,oldPriority,newPriority,reason])
//update channel topic
await opendiscord.actions.get("opendiscord:update-ticket-topic").run("ticket-action",{guild,channel,user,ticket,sendMessage:false,newTopic:null})
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newPriority} = params
opendiscord.log(user.displayName+" changed the priority of a ticket!","info",[
@@ -54,7 +59,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"priority",value:newPriority.id.value},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+16 -16
View File
@@ -1,16 +1,16 @@
///////////////////////////////////////
//TICKET TOPIC SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
export const registerActions = async () => {
export async function registerActions(){
opendiscord.actions.add(new api.ODAction("opendiscord:update-ticket-topic"))
opendiscord.actions.get("opendiscord:update-ticket-topic").workers.add([
new api.ODWorker("opendiscord:update-ticket-topic",2,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:update-ticket-topic",2,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newTopic} = params
if (channel.isThread() || !(channel instanceof discord.TextChannel)) throw new api.ODSystemError("Unable to set topic of ticket! Open Ticket doesn't support threads!")
@@ -29,28 +29,28 @@ export const registerActions = async () => {
//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")
//reply with new message
if (params.sendMessage && newTopic) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(source,{guild,channel,user,ticket,topic:newTopic})).message)
if (params.sendMessage && newTopic) await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(origin,{guild,channel,user,ticket,topic:newTopic})).message)
ticket.get("opendiscord:busy").value = false
if (newTopic) await opendiscord.events.get("afterTicketTopicChanged").emit([ticket,user,channel,oldTopic,newTopic])
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user,ticket} = params
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",0,(instance,params,origin,cancel) => {
const {guild,channel,user,ticket,newTopic} = params
if (newTopic) opendiscord.log(user.displayName+" changed the topic of a ticket!","info",[
@@ -59,7 +59,7 @@ export const registerActions = async () => {
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"topic",value:newTopic},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+176
View File
@@ -0,0 +1,176 @@
///////////////////////////////////////
//OPEN TICKET UTILITY FUNCTIONS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
/**Fetch the interactive message state. If not present, auto replies with error and returns `null`. When `null` is received, the worker should be returned and canceled. */
export async function replyInteractiveMessageState(instance:api.ODButtonResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",channel:discord.TextBasedChannel,message:discord.Message|null,replacementCommandName:string){
//check message state
const {user,member,guild} = instance
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
if (!message){
//TODO TRANSLATION!!!
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"Unable to locate message of interaction. Use the command `{0}` instead.".replace("{0}",replacementCommandName),layout:"simple",customTitle:"Message State Error"}))
return null
}
const state = await interactiveMsgState.getMsgState({channel,message})
if (!state){
//TODO TRANSLATION!!!
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"This interaction is no longer valid or has expired. Use the command `{0}` instead. It is normal to receive this error after a major Open Ticket update.".replace("{0}",replacementCommandName),layout:"simple",customTitle:"Message State Expired"}))
return null
}else return state
}
/**Check the permissions for this command. If not allowed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyHasPermissions(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",commandName:keyof api.ODGeneralJsonConfig_SystemPermissions,settings?:api.ODPermissionSettings) {
//check permissions
const {user,member,channel,guild} = instance
const generalConfig = opendiscord.configs.get("opendiscord:general")
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}))
else if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild,channel,user,permissions:["support"]}))
return false
}else return true
}
/**Check if channel is in guild/server. If not, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyIsInGuild(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other"){
//check is in guild/server
const {user,member,channel,guild} = instance
if (!guild){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(origin,{channel,user}))
return false
}else return true
}
/**Check if channel is valid ticket. If not, auto replies with error and returns `null`. When `null` is received, the worker should be returned and canceled. */
export async function replyIsTicket(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other") {
//check if ticket exists
const {user,member,channel,guild} = instance
if (!channel) return null
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build(origin,{guild,channel,user}))
return null
}else return ticket
}
/**Check if ticket is not busy and available. If not, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyTicketIsAvailable(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
//return when busy
const {user,member,channel,guild} = instance
if (ticket.get("opendiscord:busy").value){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build(origin,{guild,channel,user}))
return false
}else return true
}
/**Check if ticket is open. If closed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyTicketMustBeOpen(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket){
//return when already closed
const {user,member,channel,guild} = instance
if (ticket.get("opendiscord:closed").value){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
return false
}else return true
}
/**Check if ticket is closed. If open, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyTicketMustBeClosed(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
//return when already open
const {user,member,channel,guild} = instance
if (!ticket.get("opendiscord:closed").value){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
return false
}else return true
}
/**Check if ticket is unclaimed. If claimed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyTicketMustBeUnclaimed(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
//return when already claimed
const {user,member,channel,guild} = instance
if (ticket.get("opendiscord:claimed").value){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
return false
}else return true
}
/**Check if ticket is claimed. If unclaimed, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyTicketMustBeClaimed(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
//return when already unclaimed
const {user,member,channel,guild} = instance
if (!ticket.get("opendiscord:claimed").value){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
return false
}else return true
}
/**Check if ticket is unpinned. If pinned, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyTicketMustBeUnpinned(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
//return when already pinned
const {user,member,channel,guild} = instance
if (ticket.get("opendiscord:pinned").value){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
return false
}else return true
}
/**Check if ticket is pinned. If unpinned, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyTicketMustBePinned(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket) {
//return when already unpinned
const {user,member,channel,guild} = instance
if (!ticket.get("opendiscord:pinned").value){
if (channel) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
return false
}else return true
}
/**Check if the ticket can be closed/deleted before a message has been sent by an admin or user. If not passing the test, auto replies with error and returns `false`. When `false` is received, the worker should be returned and canceled. */
export async function replyMessageMustBeSentBeforeClose(instance:api.ODButtonResponderInstance|api.ODCommandResponderInstance|api.ODDropdownResponderInstance,origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other",ticket:api.ODTicket,commandName:keyof api.ODGeneralJsonConfig_SystemPermissions) {
//return when not allowed because of missing messages
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.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.ticketSystem.allowCloseBeforeMessage || !generalConfig.data.ticketSystem.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
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.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
}
return true
}else return true
}
/**Update the ticket message from a given ticket channel. This should be used after every change to the `ODTicket` after an action. */
export async function updateTicketMessage(guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:api.ODTicket){
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (!ticketMessage || !user || !channel || !guild || channel.isDMBased()) return
try{
await ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
+49 -70
View File
@@ -1,15 +1,37 @@
///////////////////////////////////////
//BUTTON BUILDERS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const buttons = opendiscord.builders.buttons
const lang = opendiscord.languages
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerAllButtons = async () => {
verifybarButtons()
export async function registerAllButtons(){
//VERIFYBAR BUTTON
buttons.add(new api.ODButton("opendiscord:verifybar-button"))
buttons.get("opendiscord:verifybar-button").workers.add(
new api.ODWorker("opendiscord:verifybar-button",0,async (instance,params) => {
const {verifybar,verifyButtonId} = params
if (params.verifyButtonId.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-button => verifyButtonId '"+verifyButtonId+"' exceeds 40 characters limit!")
const color = ("customColor" in params && params.customColor) ? params.customColor : "gray"
//TODO TRANSLATION!!!
const defaultLabel = (params.defaultButtonType == "✅") ? "Accept" : "Cancel"
const defaultEmoji = (params.defaultButtonType == "✅") ? "✅" : "❌"
const label = ("customLabel" in params && params.customLabel) ? params.customLabel : (params.useDefaultLabels ? defaultLabel : null)
const emoji = ("customEmoji" in params && params.customEmoji) ? params.customEmoji : defaultEmoji
instance.setCustomId("od:verifybar|"+verifybar.id.value+"|"+verifyButtonId)
instance.setMode("button")
instance.setColor(color)
if (label) instance.setLabel(label)
if (emoji) instance.setEmoji(emoji)
})
)
errorButtons()
helpMenuButtons()
panelButtons()
@@ -18,50 +40,6 @@ export const registerAllButtons = async () => {
clearButtons()
}
const verifybarButtons = () => {
//VERIFYBAR SUCCESS
buttons.add(new api.ODButton("opendiscord:verifybar-success"))
buttons.get("opendiscord:verifybar-success").workers.add(
new api.ODWorker("opendiscord:verifybar-success",0,async (instance,params) => {
const {verifybar,customData,customColor,customLabel,customEmoji} = params
if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-success => customData exceeds 40 characters limit!")
const newData = (customData) ? "_"+customData : ""
const newColor = customColor ?? "gray"
const newLabel = customLabel ?? ""
const newEmoji = customEmoji ?? "✅"
instance.setCustomId("od:verifybar-success_"+verifybar.id.value+newData)
instance.setMode("button")
instance.setColor(newColor)
if (newLabel) instance.setLabel(newLabel)
if (newEmoji) instance.setEmoji(newEmoji)
})
)
//VERIFYBAR FAILURE
buttons.add(new api.ODButton("opendiscord:verifybar-failure"))
buttons.get("opendiscord:verifybar-failure").workers.add(
new api.ODWorker("opendiscord:verifybar-failure",0,async (instance,params) => {
const {verifybar,customData,customColor,customLabel,customEmoji} = params
if (customData && customData.length > 40) throw new api.ODSystemError("ODButton:opendiscord:verifybar-success => customData exceeds 40 characters limit!")
const newData = (customData) ? "_"+customData : ""
const newColor = customColor ?? "gray"
const newLabel = customLabel ?? ""
const newEmoji = customEmoji ?? "❌"
instance.setCustomId("od:verifybar-failure_"+verifybar.id.value+newData)
instance.setMode("button")
instance.setColor(newColor)
if (newLabel) instance.setLabel(newLabel)
if (newEmoji) instance.setEmoji(newEmoji)
})
)
}
const errorButtons = () => {
//ERROR TICKET DEPRECATED TRANSCRIPT
buttons.add(new api.ODButton("opendiscord:error-ticket-deprecated-transcript"))
@@ -201,11 +179,11 @@ const ticketButtons = () => {
//CLOSE TICKET
buttons.add(new api.ODButton("opendiscord:close-ticket"))
buttons.get("opendiscord:close-ticket").workers.add(
new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
instance.setCustomId("od:close-ticket_"+source)
instance.setCustomId("od:close-ticket")
instance.setColor("gray")
instance.setEmoji("🔒")
instance.setLabel(lang.getTranslation("actions.buttons.close"))
@@ -215,11 +193,11 @@ const ticketButtons = () => {
//DELETE TICKET
buttons.add(new api.ODButton("opendiscord:delete-ticket"))
buttons.get("opendiscord:delete-ticket").workers.add(
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
instance.setCustomId("od:delete-ticket_"+source)
instance.setCustomId("od:delete-ticket")
instance.setColor("red")
instance.setEmoji("✖")
instance.setLabel(lang.getTranslation("actions.buttons.delete"))
@@ -229,11 +207,11 @@ const ticketButtons = () => {
//REOPEN TICKET
buttons.add(new api.ODButton("opendiscord:reopen-ticket"))
buttons.get("opendiscord:reopen-ticket").workers.add(
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
instance.setCustomId("od:reopen-ticket_"+source)
instance.setCustomId("od:reopen-ticket")
instance.setColor("green")
instance.setEmoji("🔓")
instance.setLabel(lang.getTranslation("actions.buttons.reopen"))
@@ -243,11 +221,11 @@ const ticketButtons = () => {
//CLAIM TICKET
buttons.add(new api.ODButton("opendiscord:claim-ticket"))
buttons.get("opendiscord:claim-ticket").workers.add(
new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
instance.setCustomId("od:claim-ticket_"+source)
instance.setCustomId("od:claim-ticket")
instance.setColor("green")
instance.setEmoji("👋")
instance.setLabel(lang.getTranslation("actions.buttons.claim"))
@@ -257,11 +235,11 @@ const ticketButtons = () => {
//UNCLAIM TICKET
buttons.add(new api.ODButton("opendiscord:unclaim-ticket"))
buttons.get("opendiscord:unclaim-ticket").workers.add(
new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
instance.setCustomId("od:unclaim-ticket_"+source)
instance.setCustomId("od:unclaim-ticket")
instance.setColor("green")
instance.setEmoji("↩️")
instance.setLabel(lang.getTranslation("actions.buttons.unclaim"))
@@ -271,13 +249,13 @@ const ticketButtons = () => {
//PIN TICKET
buttons.add(new api.ODButton("opendiscord:pin-ticket"))
buttons.get("opendiscord:pin-ticket").workers.add(
new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
instance.setCustomId("od:pin-ticket_"+source)
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"))
})
)
@@ -285,13 +263,13 @@ const ticketButtons = () => {
//UNPIN TICKET
buttons.add(new api.ODButton("opendiscord:unpin-ticket"))
buttons.get("opendiscord:unpin-ticket").workers.add(
new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,origin) => {
const {guild,channel,ticket} = params
instance.setMode("button")
instance.setCustomId("od:unpin-ticket_"+source)
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"))
})
)
@@ -301,7 +279,7 @@ const transcriptButtons = () => {
//TRANSCRIPT HTML VISIT
buttons.add(new api.ODButton("opendiscord:transcript-html-visit"))
buttons.get("opendiscord:transcript-html-visit").workers.add(
new api.ODWorker("opendiscord:transcript-html-visit",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:transcript-html-visit",0,async (instance,params,origin) => {
const {result} = params
instance.setMode("url")
if (result.data) instance.setUrl(result.data.url)
@@ -314,9 +292,9 @@ const transcriptButtons = () => {
//TRANSCRIPT ERROR RETRY
buttons.add(new api.ODButton("opendiscord:transcript-error-retry"))
buttons.get("opendiscord:transcript-error-retry").workers.add(
new api.ODWorker("opendiscord:transcript-error-retry",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:transcript-error-retry",0,async (instance,params,origin) => {
instance.setMode("button")
instance.setCustomId("od:transcript-error-retry_"+source)
instance.setCustomId("od:transcript-error-retry_"+origin)
instance.setColor("gray")
instance.setEmoji("🔄")
instance.setLabel(lang.getTranslation("transcripts.errors.retry"))
@@ -326,9 +304,9 @@ const transcriptButtons = () => {
//TRANSCRIPT ERROR CONTINUE
buttons.add(new api.ODButton("opendiscord:transcript-error-continue"))
buttons.get("opendiscord:transcript-error-continue").workers.add(
new api.ODWorker("opendiscord:transcript-error-continue",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:transcript-error-continue",0,async (instance,params,origin) => {
instance.setMode("button")
instance.setCustomId("od:transcript-error-continue_"+source)
instance.setCustomId("od:transcript-error-continue_"+origin)
instance.setColor("red")
instance.setEmoji("✖")
instance.setLabel(lang.getTranslation("transcripts.errors.continue"))
@@ -340,12 +318,13 @@ const clearButtons = () => {
//CLEAR CONTINUE
buttons.add(new api.ODButton("opendiscord:clear-continue"))
buttons.get("opendiscord:clear-continue").workers.add(
new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,origin) => {
instance.setMode("button")
instance.setCustomId("od:clear-continue_"+source+"_"+params.filter)
instance.setCustomId("od:clear-continue")
instance.setColor("red")
instance.setEmoji("✖")
instance.setLabel(lang.getTranslation("actions.buttons.clear"))
instance.setDisabled(params.inProgress)
})
)
}
+2 -2
View File
@@ -1,12 +1,12 @@
///////////////////////////////////////
//DROPDOWN BUILDERS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const dropdowns = opendiscord.builders.dropdowns
export const registerAllDropdowns = async () => {
export async function registerAllDropdowns(){
panelDropdowns()
}
+169 -145
View File
@@ -1,7 +1,7 @@
///////////////////////////////////////
//EMBED BUILDERS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
import nodepath from "path"
@@ -9,7 +9,7 @@ const embeds = opendiscord.builders.embeds
const lang = opendiscord.languages
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerAllEmbeds = async () => {
export async function registerAllEmbeds(){
errorEmbeds()
helpMenuEmbeds()
statsEmbeds()
@@ -23,12 +23,12 @@ export const registerAllEmbeds = async () => {
extraEmbeds()
}
/**Utility function to get the translated "method" from the source. Mostly used in error embeds. */
const getMethodFromSource = (source:"slash"|"text"|"button"|"dropdown"|"modal"|"other"): string => {
if (source == "slash" || source == "text") return lang.getTranslation("params.lowercase.command")
else if (source == "button") return lang.getTranslation("params.lowercase.button")
else if (source == "dropdown") return lang.getTranslation("params.lowercase.dropdown")
else if (source == "modal") return lang.getTranslation("params.lowercase.modal")
/**Utility function to get the translated "method" from the origin. Mostly used in error embeds. */
const getMethodFromOrigin = (origin:"slash"|"text"|"button"|"dropdown"|"modal"|"other"): string => {
if (origin == "slash" || origin == "text") return lang.getTranslation("params.lowercase.command")
else if (origin == "button") return lang.getTranslation("params.lowercase.button")
else if (origin == "dropdown") return lang.getTranslation("params.lowercase.dropdown")
else if (origin == "modal") return lang.getTranslation("params.lowercase.modal")
else return lang.getTranslation("params.lowercase.method")
}
//lang.getTranslation()
@@ -37,12 +37,12 @@ const errorEmbeds = () => {
//ERROR
embeds.add(new api.ODEmbed("opendiscord:error"))
embeds.get("opendiscord:error").workers.add(
new api.ODWorker("opendiscord:error",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error",0,async (instance,params,origin) => {
const {user,error,layout,customTitle} = params
const method = getMethodFromSource(source)
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"))
@@ -154,10 +154,10 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions"))
embeds.get("opendiscord:error-no-permissions").workers.add(
new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-no-permissions",0,async (instance,params,origin) => {
const {user,permissions} = params
const method = getMethodFromSource(source)
const method = getMethodFromOrigin(origin)
const renderedPerms = permissions.map((perm) => {
if (perm == "developer") return "- "+lang.getTranslation("errors.permissions.developer")
@@ -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]))
@@ -180,12 +180,12 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS COOLDOWN
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-cooldown"))
embeds.get("opendiscord:error-no-permissions-cooldown").workers.add(
new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-no-permissions-cooldown",0,async (instance,params,origin) => {
const {user} = params
const method = getMethodFromSource(source)
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]))
@@ -196,12 +196,12 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS BLACKLISTED
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-blacklisted"))
embeds.get("opendiscord:error-no-permissions-blacklisted").workers.add(
new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-no-permissions-blacklisted",0,async (instance,params,origin) => {
const {user} = params
const method = getMethodFromSource(source)
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]))
@@ -211,10 +211,10 @@ const errorEmbeds = () => {
//ERROR NO PERMISSIONS LIMITS
embeds.add(new api.ODEmbed("opendiscord:error-no-permissions-limits"))
embeds.get("opendiscord:error-no-permissions-limits").workers.add(
new api.ODWorker("opendiscord:error-no-permissions-limits",0,async (instance,params,source) => {
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"))
@@ -227,12 +227,12 @@ const errorEmbeds = () => {
//ERROR RESPONDER TIMEOUT
embeds.add(new api.ODEmbed("opendiscord:error-responder-timeout"))
embeds.get("opendiscord:error-responder-timeout").workers.add(
new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-responder-timeout",0,async (instance,params,origin) => {
const {user} = params
const method = getMethodFromSource(source)
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]))
@@ -244,10 +244,10 @@ const errorEmbeds = () => {
//ERROR TICKET UNKNOWN
embeds.add(new api.ODEmbed("opendiscord:error-ticket-unknown"))
embeds.get("opendiscord:error-ticket-unknown").workers.add(
new api.ODWorker("opendiscord:error-ticket-unknown",0,async (instance,params,source) => {
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"))
@@ -258,10 +258,10 @@ const errorEmbeds = () => {
//ERROR TICKET DEPRECATED
embeds.add(new api.ODEmbed("opendiscord:error-ticket-deprecated"))
embeds.get("opendiscord:error-ticket-deprecated").workers.add(
new api.ODWorker("opendiscord:error-ticket-deprecated",0,async (instance,params,source) => {
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"))
@@ -272,7 +272,7 @@ const errorEmbeds = () => {
//ERROR OPTION UNKNOWN
embeds.add(new api.ODEmbed("opendiscord:error-option-unknown"))
embeds.get("opendiscord:error-option-unknown").workers.add(
new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-option-unknown",0,async (instance,params,origin) => {
const {user} = params
const renderedTicketOptions = opendiscord.options.getAll().map((option) => {
@@ -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"))
@@ -292,7 +292,7 @@ const errorEmbeds = () => {
//ERROR PANEL UNKNOWN
embeds.add(new api.ODEmbed("opendiscord:error-panel-unknown"))
embeds.get("opendiscord:error-panel-unknown").workers.add(
new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-panel-unknown",0,async (instance,params,origin) => {
const {user} = params
const renderedPanels = opendiscord.panels.getAll().map((panel) => {
@@ -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})
@@ -312,12 +312,12 @@ const errorEmbeds = () => {
//ERROR NOT IN GUILD
embeds.add(new api.ODEmbed("opendiscord:error-not-in-guild"))
embeds.get("opendiscord:error-not-in-guild").workers.add(
new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-not-in-guild",0,async (instance,params,origin) => {
const {user} = params
const method = getMethodFromSource(source)
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]))
@@ -327,19 +327,43 @@ const errorEmbeds = () => {
//ERROR CHANNEL RENAME
embeds.add(new api.ODEmbed("opendiscord:error-channel-rename"))
embeds.get("opendiscord:error-channel-rename").workers.add(
new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,origin) => {
const {channel,user,originalName,newName} = params
const method = (source == "ticket-move" || source == "ticket-pin" || source == "ticket-rename" || source == "ticket-unpin" || source == "ticket-priority" || source == "ticket-transfer") ? source : getMethodFromSource(source)
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"))
instance.setFooter(lang.getTranslationWithParams("errors.descriptions.channelRenameSource",[method]))
instance.addFields(
{name:lang.getTranslation("params.uppercase.originalName")+":",value:"```#"+originalName+"```",inline:false},
{name:lang.getTranslation("params.uppercase.newName")+":",value:"```#"+newName+"```",inline:false}
{name:lang.getTranslation("params.uppercase.originalName")+":",value:"```#"+originalName+"```",inline:true},
{name:lang.getTranslation("params.uppercase.newName")+":",value:"```#"+newName+"```",inline:true}
)
})
)
//ERROR CHANNEL CATEGORY
embeds.add(new api.ODEmbed("opendiscord:error-channel-category"))
embeds.get("opendiscord:error-channel-category").workers.add(
new api.ODWorker("opendiscord:error-channel-category",0,async (instance,params,origin) => {
const {channel,user,originalCategory,newCategory} = params
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.ticketSystem.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
//TODO TRANSLATION!!!
instance.setTitle(utilities.emojiTitle("❌","Unable To Change Category"))
instance.setAuthor(user.displayName,user.displayAvatarURL())
//TODO TRANSLATION!!!
instance.setDescription("Due to Discord rate limits, the channel category could not be changed immediately. It will be changed automatically within 10 minutes if the bot remains online.")
instance.setFooter(lang.getTranslationWithParams("errors.descriptions.channelRenameSource",[method]))
instance.addFields(
//TODO TRANSLATION!!!
{name:"Original Category"+":",value:"```"+originalCategory+"```",inline:true},
//TODO TRANSLATION!!!
{name:"New Category"+":",value:"```"+newCategory+"```",inline:true}
)
})
)
@@ -347,12 +371,12 @@ const errorEmbeds = () => {
//ERROR TICKET BUSY
embeds.add(new api.ODEmbed("opendiscord:error-ticket-busy"))
embeds.get("opendiscord:error-ticket-busy").workers.add(
new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:error-ticket-busy",0,async (instance,params,origin) => {
const {user} = params
const method = getMethodFromSource(source)
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]))
@@ -387,7 +411,7 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-global",0,async (instance,params) => {
const {guild,channel,user} = params
const scope = opendiscord.stats.get("opendiscord:global")
const scope = opendiscord.statistics.get("opendiscord:global")
if (!scope) return
const data = await scope.render("GLOBAL",guild,channel,user)
@@ -397,7 +421,7 @@ const statsEmbeds = () => {
if (opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(user,channel,guild))){
//show system data when owner or developer
const systemScope = opendiscord.stats.get("opendiscord:system")
const systemScope = opendiscord.statistics.get("opendiscord:system")
if (!systemScope) return
const systemData = await systemScope.render("GLOBAL",guild,channel,user)
instance.addFields({name:systemScope.name,value:systemData,inline:false})
@@ -411,9 +435,9 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-ticket",0,async (instance,params) => {
const {guild,channel,user,scopeData} = params
const scope = opendiscord.stats.get("opendiscord:ticket")
const participantsScope = opendiscord.stats.get("opendiscord:participants")
const messagesScope = opendiscord.stats.get("opendiscord:messages")
const scope = opendiscord.statistics.get("opendiscord:ticket")
const participantsScope = opendiscord.statistics.get("opendiscord:participants")
const messagesScope = opendiscord.statistics.get("opendiscord:messages")
if (!scope || !participantsScope || !messagesScope) return
const data = await scope.render(scopeData.id.value,guild,channel,user)
const participantsData = await participantsScope.render(scopeData.id.value,guild,channel,user)
@@ -433,7 +457,7 @@ const statsEmbeds = () => {
new api.ODWorker("opendiscord:stats-user",0,async (instance,params) => {
const {guild,channel,user,scopeData} = params
const scope = opendiscord.stats.get("opendiscord:user")
const scope = opendiscord.statistics.get("opendiscord:user")
if (!scope) return
const data = await scope.render(scopeData.id,guild,channel,user)
@@ -477,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)]))
@@ -510,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){
@@ -529,7 +553,7 @@ const ticketEmbeds = () => {
//TICKET CREATED
embeds.add(new api.ODEmbed("opendiscord:ticket-created"))
embeds.get("opendiscord:ticket-created").workers.add(
new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:ticket-created",0,async (instance,params,origin) => {
const {user} = params
instance.setColor(generalConfig.data.mainColor)
@@ -543,7 +567,7 @@ const ticketEmbeds = () => {
//TICKET CREATED DM
embeds.add(new api.ODEmbed("opendiscord:ticket-created-dm"))
embeds.get("opendiscord:ticket-created-dm").workers.add(
new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:ticket-created-dm",0,async (instance,params,origin) => {
const {user,ticket} = params
const embedOptions = ticket.option.get("opendiscord:dm-message-embed").value
@@ -563,10 +587,10 @@ const ticketEmbeds = () => {
//TICKET CREATED LOGS
embeds.add(new api.ODEmbed("opendiscord:ticket-created-logs"))
embeds.get("opendiscord:ticket-created-logs").workers.add(
new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:ticket-created-logs",0,async (instance,params,origin) => {
const {user,ticket} = params
const method = (source == "panel-button" || source == "panel-dropdown") ? lang.getTranslation("params.uppercase.panel") : (source == "slash" || source == "text") ? lang.getTranslation("params.uppercase.command") : lang.getTranslation("params.uppercase.system")
const method = (origin == "panel-button" || origin == "panel-dropdown") ? lang.getTranslation("params.uppercase.panel") : (origin == "slash" || origin == "text") ? lang.getTranslation("params.uppercase.command") : lang.getTranslation("params.uppercase.system")
const blacklisted = opendiscord.blacklist.exists(user.id) ? lang.getTranslation("params.uppercase.true") : lang.getTranslation("params.uppercase.false")
instance.setColor(generalConfig.data.mainColor)
@@ -586,7 +610,7 @@ const ticketEmbeds = () => {
//TICKET MESSAGE
embeds.add(new api.ODEmbed("opendiscord:ticket-message"))
embeds.get("opendiscord:ticket-message").workers.add(
new api.ODWorker("opendiscord:ticket-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:ticket-message",0,async (instance,params,origin) => {
const {user,ticket} = params
const embedOptions = ticket.option.get("opendiscord:ticket-message-embed").value
@@ -599,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+"```",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){
@@ -625,161 +649,161 @@ const ticketEmbeds = () => {
//TICKET CLOSED
embeds.add(new api.ODEmbed("opendiscord:close-message"))
embeds.get("opendiscord:close-message").workers.add(
new api.ODWorker("opendiscord:close-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:close-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET REOPENED
embeds.add(new api.ODEmbed("opendiscord:reopen-message"))
embeds.get("opendiscord:reopen-message").workers.add(
new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:reopen-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET DELETED
embeds.add(new api.ODEmbed("opendiscord:delete-message"))
embeds.get("opendiscord:delete-message").workers.add(
new api.ODWorker("opendiscord:delete-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:delete-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET CLAIMED
embeds.add(new api.ODEmbed("opendiscord:claim-message"))
embeds.get("opendiscord:claim-message").workers.add(
new api.ODWorker("opendiscord:claim-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:claim-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET UNCLAIMED
embeds.add(new api.ODEmbed("opendiscord:unclaim-message"))
embeds.get("opendiscord:unclaim-message").workers.add(
new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:unclaim-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET PINNED
embeds.add(new api.ODEmbed("opendiscord:pin-message"))
embeds.get("opendiscord:pin-message").workers.add(
new api.ODWorker("opendiscord:pin-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:pin-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
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 ?? "/")+"```"})
})
)
//TICKET UNPINNED
embeds.add(new api.ODEmbed("opendiscord:unpin-message"))
embeds.get("opendiscord:unpin-message").workers.add(
new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:unpin-message",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
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 ?? "/")+"```"})
})
)
//TICKET RENAMED
embeds.add(new api.ODEmbed("opendiscord:rename-message"))
embeds.get("opendiscord:rename-message").workers.add(
new api.ODWorker("opendiscord:rename-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:rename-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET MOVED
embeds.add(new api.ODEmbed("opendiscord:move-message"))
embeds.get("opendiscord:move-message").workers.add(
new api.ODWorker("opendiscord:move-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:move-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET USER ADDED
embeds.add(new api.ODEmbed("opendiscord:add-message"))
embeds.get("opendiscord:add-message").workers.add(
new api.ODWorker("opendiscord:add-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:add-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET USER REMOVED
embeds.add(new api.ODEmbed("opendiscord:remove-message"))
embeds.get("opendiscord:remove-message").workers.add(
new api.ODWorker("opendiscord:remove-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:remove-message",0,async (instance,params,origin) => {
const {user,ticket,reason,data} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//TICKET ACTION DM
embeds.add(new api.ODEmbed("opendiscord:ticket-action-dm"))
embeds.get("opendiscord:ticket-action-dm").workers.add(
new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:ticket-action-dm",0,async (instance,params,origin) => {
const {user,mode,ticket,reason,additionalData} = params
const channel = await opendiscord.tickets.getTicketChannel(ticket)
@@ -804,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")))
@@ -828,7 +852,7 @@ const ticketEmbeds = () => {
//TICKET ACTION LOGS
embeds.add(new api.ODEmbed("opendiscord:ticket-action-logs"))
embeds.get("opendiscord:ticket-action-logs").workers.add(
new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:ticket-action-logs",0,async (instance,params,origin) => {
const {user,mode,ticket,reason,additionalData} = params
const channel = await opendiscord.tickets.getTicketChannel(ticket)
@@ -840,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")))
@@ -858,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")))
@@ -884,7 +908,7 @@ const blacklistEmbeds = () => {
//BLACKLIST VIEW
embeds.add(new api.ODEmbed("opendiscord:blacklist-view"))
embeds.get("opendiscord:blacklist-view").workers.add(
new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:blacklist-view",0,async (instance,params,origin) => {
const {user} = params
const renderedUsers: string[] = []
@@ -904,7 +928,7 @@ const blacklistEmbeds = () => {
//BLACKLIST GET
embeds.add(new api.ODEmbed("opendiscord:blacklist-get"))
embeds.get("opendiscord:blacklist-get").workers.add(
new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:blacklist-get",0,async (instance,params,origin) => {
const {user,data} = params
const blacklist = opendiscord.blacklist.get(data.id)
@@ -914,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)])+"*")
})
@@ -923,35 +947,35 @@ const blacklistEmbeds = () => {
//BLACKLIST ADD
embeds.add(new api.ODEmbed("opendiscord:blacklist-add"))
embeds.get("opendiscord:blacklist-add").workers.add(
new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:blacklist-add",0,async (instance,params,origin) => {
const {user,data,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//BLACKLIST REMOVE
embeds.add(new api.ODEmbed("opendiscord:blacklist-remove"))
embeds.get("opendiscord:blacklist-remove").workers.add(
new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:blacklist-remove",0,async (instance,params,origin) => {
const {user,data,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//BLACKLIST DM
embeds.add(new api.ODEmbed("opendiscord:blacklist-dm"))
embeds.get("opendiscord:blacklist-dm").workers.add(
new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:blacklist-dm",0,async (instance,params,origin) => {
const {user,mode,data,reason} = params
const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAddDm") : lang.getTranslation("actions.titles.blacklistRemoveDm")
@@ -961,14 +985,14 @@ 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 ?? "/")+"```"})
})
)
//BLACKLIST LOGS
embeds.add(new api.ODEmbed("opendiscord:blacklist-logs"))
embeds.get("opendiscord:blacklist-logs").workers.add(
new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:blacklist-logs",0,async (instance,params,origin) => {
const {user,mode,data,reason} = params
const title = (mode == "add") ? lang.getTranslation("actions.titles.blacklistAdd") : lang.getTranslation("actions.titles.blacklistRemove")
@@ -980,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 ?? "/")+"```"})
})
)
}
@@ -989,7 +1013,7 @@ const transcriptEmbeds = () => {
//TRANSCRIPT TEXT READY
embeds.add(new api.ODEmbed("opendiscord:transcript-text-ready"))
embeds.get("opendiscord:transcript-text-ready").workers.add(
new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:transcript-text-ready",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler} = params
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
@@ -1007,11 +1031,11 @@ const transcriptEmbeds = () => {
}catch{}
}
if (source == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.text")]))
else if (source == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.text")]))
else if (source == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.text")]))
else if (source == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.text")]))
else if (source == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.text")]))
if (origin == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.text")]))
else if (origin == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.text")]))
else if (origin == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.text")]))
else if (origin == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.text")]))
else if (origin == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.text")]))
else instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdOther",[lang.getTranslation("params.lowercase.text")]))
})
)
@@ -1019,7 +1043,7 @@ const transcriptEmbeds = () => {
//TRANSCRIPT HTML READY
embeds.add(new api.ODEmbed("opendiscord:transcript-html-ready"))
embeds.get("opendiscord:transcript-html-ready").workers.add(
new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:transcript-html-ready",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,result} = params
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
@@ -1038,11 +1062,11 @@ const transcriptEmbeds = () => {
}catch{}
}
if (source == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.html")]))
else if (source == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.html")]))
else if (source == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.html")]))
else if (source == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.html")]))
else if (source == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.html")]))
if (origin == "channel") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdChannel",[lang.getTranslation("params.lowercase.html")]))
else if (origin == "creator-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdCreator",[lang.getTranslation("params.lowercase.html")]))
else if (origin == "participant-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdParticipant",[lang.getTranslation("params.lowercase.html")]))
else if (origin == "active-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdActiveAdmin",[lang.getTranslation("params.lowercase.html")]))
else if (origin == "every-admin-dm") instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdEveryAdmin",[lang.getTranslation("params.lowercase.html")]))
else instance.setDescription(lang.getTranslationWithParams("transcripts.success.createdOther",[lang.getTranslation("params.lowercase.html")]))
})
)
@@ -1050,7 +1074,7 @@ const transcriptEmbeds = () => {
//TRANSCRIPT HTML PROGRESS
embeds.add(new api.ODEmbed("opendiscord:transcript-html-progress"))
embeds.get("opendiscord:transcript-html-progress").workers.add(
new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:transcript-html-progress",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,remaining} = params
const remainingDate = new Date(new Date().getTime()+remaining)
@@ -1076,15 +1100,15 @@ const transcriptEmbeds = () => {
//TRANSCRIPT ERROR
embeds.add(new api.ODEmbed("opendiscord:transcript-error"))
embeds.get("opendiscord:transcript-error").workers.add(
new api.ODWorker("opendiscord:transcript-error",0,async (instance,params,source) => {
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 ?? "/")+"```"})
})
)
}
@@ -1093,7 +1117,7 @@ const roleEmbeds = () => {
//REACTION ROLE
embeds.add(new api.ODEmbed("opendiscord:reaction-role"))
embeds.get("opendiscord:reaction-role").workers.add(
new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:reaction-role",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1117,7 +1141,7 @@ const roleEmbeds = () => {
//REACTION ROLE DM
embeds.add(new api.ODEmbed("opendiscord:reaction-role-dm"))
embeds.get("opendiscord:reaction-role-dm").workers.add(
new api.ODWorker("opendiscord:reaction-role-dm",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:reaction-role-dm",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1143,7 +1167,7 @@ const roleEmbeds = () => {
//REACTION ROLE LOGS
embeds.add(new api.ODEmbed("opendiscord:reaction-role-logs"))
embeds.get("opendiscord:reaction-role-logs").workers.add(
new api.ODWorker("opendiscord:reaction-role-logs",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:reaction-role-logs",0,async (instance,params,origin) => {
const {guild,user,role,result} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1171,7 +1195,7 @@ const clearEmbeds = () => {
//CLEAR VERIFY MESSAGE
embeds.add(new api.ODEmbed("opendiscord:clear-verify-message"))
embeds.get("opendiscord:clear-verify-message").workers.add(
new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:clear-verify-message",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1189,7 +1213,7 @@ const clearEmbeds = () => {
//CLEAR MESSAGE
embeds.add(new api.ODEmbed("opendiscord:clear-message"))
embeds.get("opendiscord:clear-message").workers.add(
new api.ODWorker("opendiscord:clear-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:clear-message",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1206,7 +1230,7 @@ const clearEmbeds = () => {
//CLEAR LOGS
embeds.add(new api.ODEmbed("opendiscord:clear-logs"))
embeds.get("opendiscord:clear-logs").workers.add(
new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:clear-logs",0,async (instance,params,origin) => {
const {guild,channel,user,filter,list} = params
instance.setColor(generalConfig.data.mainColor)
@@ -1226,10 +1250,10 @@ const autoEmbeds = () => {
//AUTOCLOSE MESSAGE
embeds.add(new api.ODEmbed("opendiscord:autoclose-message"))
embeds.get("opendiscord:autoclose-message").workers.add(
new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:autoclose-message",0,async (instance,params,origin) => {
const {user,ticket} = params
const hours: number = ticket.get("opendiscord:autoclose-hours").value
const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autocloseLeave") : lang.getTranslationWithParams("actions.descriptions.autocloseTimeout",[hours.toString()])
const description = (origin == "leave") ? lang.getTranslation("actions.descriptions.autocloseLeave") : lang.getTranslationWithParams("actions.descriptions.autocloseTimeout",[hours.toString()])
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
@@ -1242,10 +1266,10 @@ const autoEmbeds = () => {
//AUTODELETE MESSAGE
embeds.add(new api.ODEmbed("opendiscord:autodelete-message"))
embeds.get("opendiscord:autodelete-message").workers.add(
new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:autodelete-message",0,async (instance,params,origin) => {
const {user,ticket} = params
const days: number = ticket.get("opendiscord:autodelete-days").value
const description = (source == "leave") ? lang.getTranslation("actions.descriptions.autodeleteLeave") : lang.getTranslationWithParams("actions.descriptions.autodeleteTimeout",[days.toString()])
const description = (origin == "leave") ? lang.getTranslation("actions.descriptions.autodeleteLeave") : lang.getTranslationWithParams("actions.descriptions.autodeleteTimeout",[days.toString()])
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
@@ -1258,56 +1282,56 @@ const autoEmbeds = () => {
//AUTOCLOSE ENABLE
embeds.add(new api.ODEmbed("opendiscord:autoclose-enable"))
embeds.get("opendiscord:autoclose-enable").workers.add(
new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:autoclose-enable",0,async (instance,params,origin) => {
const {user,ticket,reason,time} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//AUTODELETE ENABLE
embeds.add(new api.ODEmbed("opendiscord:autodelete-enable"))
embeds.get("opendiscord:autodelete-enable").workers.add(
new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:autodelete-enable",0,async (instance,params,origin) => {
const {user,ticket,reason,time} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//AUTOCLOSE DISABLE
embeds.add(new api.ODEmbed("opendiscord:autoclose-disable"))
embeds.get("opendiscord:autoclose-disable").workers.add(
new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:autoclose-disable",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//AUTODELETE DISABLE
embeds.add(new api.ODEmbed("opendiscord:autodelete-disable"))
embeds.get("opendiscord:autodelete-disable").workers.add(
new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:autodelete-disable",0,async (instance,params,origin) => {
const {user,ticket,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
}
@@ -1316,7 +1340,7 @@ const extraEmbeds = () => {
//TOPIC SET
embeds.add(new api.ODEmbed("opendiscord:topic-set"))
embeds.get("opendiscord:topic-set").workers.add(
new api.ODWorker("opendiscord:topic-set",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:topic-set",0,async (instance,params,origin) => {
const {user,topic} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
@@ -1330,21 +1354,21 @@ const extraEmbeds = () => {
//PRIORITY SET
embeds.add(new api.ODEmbed("opendiscord:priority-set"))
embeds.get("opendiscord:priority-set").workers.add(
new api.ODWorker("opendiscord:priority-set",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:priority-set",0,async (instance,params,origin) => {
const {user,priority,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
//PRIORITY GET
embeds.add(new api.ODEmbed("opendiscord:priority-get"))
embeds.get("opendiscord:priority-get").workers.add(
new api.ODWorker("opendiscord:priority-get",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:priority-get",0,async (instance,params,origin) => {
const {user,priority} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
@@ -1357,14 +1381,14 @@ const extraEmbeds = () => {
//TRANSFER MESSAGE
embeds.add(new api.ODEmbed("opendiscord:transfer-message"))
embeds.get("opendiscord:transfer-message").workers.add(
new api.ODWorker("opendiscord:transfer-message",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:transfer-message",0,async (instance,params,origin) => {
const {user,oldCreator,newCreator,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
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 ?? "/")+"```"})
})
)
}
+3 -3
View File
@@ -1,14 +1,14 @@
///////////////////////////////////////
//FILE BUILDERS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const files = opendiscord.builders.files
const lang = opendiscord.languages
const transcriptConfig = opendiscord.configs.get("opendiscord:transcripts")
export const registerAllFiles = async () => {
export async function registerAllFiles(){
transcriptFiles()
}
@@ -17,7 +17,7 @@ const transcriptFiles = () => {
//TEXT TRANSCRIPT
files.add(new api.ODFile("opendiscord:text-transcript"))
files.get("opendiscord:text-transcript").workers.add(
new api.ODWorker("opendiscord:text-transcript",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:text-transcript",0,async (instance,params,origin) => {
const {guild,channel,user,ticket,compiler,result} = params
const fileMode = transcriptConfig.data.textTranscriptStyle.fileMode
+179 -471
View File
File diff suppressed because it is too large Load Diff
+27 -27
View File
@@ -1,23 +1,23 @@
///////////////////////////////////////
//MODAL BUILDERS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const modals = opendiscord.builders.modals
const lang = opendiscord.languages
export const registerAllModals = async () => {
export async function registerAllModals(){
ticketModals()
}
const ticketModals = () => {
//TICKET QUESTIONS
modals.add(new api.ODModal("opendiscord:ticket-questions"))
modals.get("opendiscord:ticket-questions").workers.add(
new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,source) => {
new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,origin) => {
const {option} = params
instance.setCustomId("od:ticket-questions_"+option.id.value+"_"+source)
instance.setCustomId("od:ticket-questions_"+option.id.value+"_"+origin)
instance.setTitle(option.exists("opendiscord:name") ? option.get("opendiscord:name").value : option.id.value)
const questionIds = option.get("opendiscord:questions").value
questionIds.forEach((id) => {
@@ -30,7 +30,7 @@ const ticketModals = () => {
required:question.get("opendiscord:required").value,
placeholder:(question.get("opendiscord:placeholder").value) ? question.get("opendiscord:placeholder").value : undefined,
minLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-min").value : undefined,
maxLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : undefined
maxLength:Math.min(1024-6,(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : (1024-6)) //embed field limit - 6x` characters
})
else if (question instanceof api.ODParagraphQuestion) instance.addQuestion({
customId:question.id.value,
@@ -39,7 +39,7 @@ const ticketModals = () => {
required:question.get("opendiscord:required").value,
placeholder:(question.get("opendiscord:placeholder").value) ? question.get("opendiscord:placeholder").value : undefined,
minLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-min").value : undefined,
maxLength:(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : undefined
maxLength:Math.min(1024-6,(question.get("opendiscord:length-enabled").value) ? question.get("opendiscord:length-max").value : (1024-6)) //embed field limit - 6x` characters
})
})
})
@@ -48,10 +48,10 @@ const ticketModals = () => {
//CLOSE TICKET REASON
modals.add(new api.ODModal("opendiscord:close-ticket-reason"))
modals.get("opendiscord:close-ticket-reason").workers.add(
new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,source) => {
const {ticket} = params
new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,origin) => {
const {channel,message} = params
instance.setCustomId("od:close-ticket-reason_"+ticket.id.value+"_"+source)
instance.setCustomId("od:close-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.close"))
instance.addQuestion({
customId:"reason",
@@ -66,10 +66,10 @@ const ticketModals = () => {
//REOPEN TICKET REASON
modals.add(new api.ODModal("opendiscord:reopen-ticket-reason"))
modals.get("opendiscord:reopen-ticket-reason").workers.add(
new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,source) => {
const {ticket} = params
new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,origin) => {
const {channel,message} = params
instance.setCustomId("od:reopen-ticket-reason_"+ticket.id.value+"_"+source)
instance.setCustomId("od:reopen-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.reopen"))
instance.addQuestion({
customId:"reason",
@@ -84,10 +84,10 @@ const ticketModals = () => {
//DELETE TICKET REASON
modals.add(new api.ODModal("opendiscord:delete-ticket-reason"))
modals.get("opendiscord:delete-ticket-reason").workers.add(
new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,source) => {
const {ticket} = params
new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,origin) => {
const {channel,message} = params
instance.setCustomId("od:delete-ticket-reason_"+ticket.id.value+"_"+source)
instance.setCustomId("od:delete-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.delete"))
instance.addQuestion({
customId:"reason",
@@ -102,10 +102,10 @@ const ticketModals = () => {
//CLAIM TICKET REASON
modals.add(new api.ODModal("opendiscord:claim-ticket-reason"))
modals.get("opendiscord:claim-ticket-reason").workers.add(
new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,source) => {
const {ticket} = params
new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,origin) => {
const {channel,message} = params
instance.setCustomId("od:claim-ticket-reason_"+ticket.id.value+"_"+source)
instance.setCustomId("od:claim-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.claim"))
instance.addQuestion({
customId:"reason",
@@ -120,10 +120,10 @@ const ticketModals = () => {
//UNCLAIM TICKET REASON
modals.add(new api.ODModal("opendiscord:unclaim-ticket-reason"))
modals.get("opendiscord:unclaim-ticket-reason").workers.add(
new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,source) => {
const {ticket} = params
new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,origin) => {
const {channel,message} = params
instance.setCustomId("od:unclaim-ticket-reason_"+ticket.id.value+"_"+source)
instance.setCustomId("od:unclaim-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.unclaim"))
instance.addQuestion({
customId:"reason",
@@ -138,10 +138,10 @@ const ticketModals = () => {
//PIN TICKET REASON
modals.add(new api.ODModal("opendiscord:pin-ticket-reason"))
modals.get("opendiscord:pin-ticket-reason").workers.add(
new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,source) => {
const {ticket} = params
new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,origin) => {
const {channel,message} = params
instance.setCustomId("od:pin-ticket-reason_"+ticket.id.value+"_"+source)
instance.setCustomId("od:pin-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.pin"))
instance.addQuestion({
customId:"reason",
@@ -156,10 +156,10 @@ const ticketModals = () => {
//UNPIN TICKET REASON
modals.add(new api.ODModal("opendiscord:unpin-ticket-reason"))
modals.get("opendiscord:unpin-ticket-reason").workers.add(
new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,source) => {
const {ticket} = params
new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,origin) => {
const {channel,message} = params
instance.setCustomId("od:unpin-ticket-reason_"+ticket.id.value+"_"+source)
instance.setCustomId("od:unpin-ticket-reason|"+channel.id+"|"+message.id)
instance.setTitle(lang.getTranslation("actions.buttons.unpin"))
instance.addQuestion({
customId:"reason",
+20 -33
View File
@@ -1,45 +1,32 @@
///////////////////////////////////////
//ADD COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//ADD COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:add",generalConfig.data.prefix,"add"))
opendiscord.responders.commands.get("opendiscord:add").workers.add([
new api.ODWorker("opendiscord:add",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:add",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.add,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check if in guild/Server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"add")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch data
const data = instance.options.getUser("user",true)
const reason = instance.options.getString("reason",false)
@@ -52,15 +39,15 @@ export const registerCommandResponders = async () => {
//start adding user to ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:add-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(source,{guild,channel,user,ticket,reason,data}))
await opendiscord.actions.get("opendiscord:add-ticket-user").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:add-message").build(origin,{guild,channel,user,ticket,reason,data}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'add' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+23 -53
View File
@@ -1,50 +1,33 @@
///////////////////////////////////////
//AUTOCLOSE COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//AUTOCLOSE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:autoclose",generalConfig.data.prefix,/^autoclose/))
opendiscord.responders.commands.get("opendiscord:autoclose").workers.add([
new api.ODWorker("opendiscord:autoclose",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:autoclose",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.autoclose,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"autoclose")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
//return when already closed
if (ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
if (!isTicketOpen) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -54,40 +37,27 @@ export const registerCommandResponders = async () => {
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autoclose-enabled").value = false
ticket.get("opendiscord:autoclose-hours").value = 0
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-disable").build(source,{guild,channel,user,ticket,reason}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-disable").build(origin,{guild,channel,user,ticket,reason}))
}else if (scope == "enable"){
const time = instance.options.getNumber("time",true)
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autoclose-enabled").value = true
ticket.get("opendiscord:autoclose-hours").value = time
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-enable").build(source,{guild,channel,user,ticket,reason,time}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-enable").build(origin,{guild,channel,user,ticket,reason,time}))
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on autoclose "+scope+"!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
const reason = instance.options.getString("reason",false)
opendiscord.log(instance.user.displayName+" used the 'autoclose "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"reason",value:reason ?? "/"},
])
})
+4 -4
View File
@@ -1,13 +1,13 @@
///////////////////////////////////////
//AUTOCOMPLETE COMMAND UTILS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
export const registerAutocompleteResponders = async () => {
export async function registerAutocompleteResponders(){
//PANEL ID AUTOCOMPLETE
opendiscord.responders.autocomplete.add(new api.ODAutocompleteResponder("opendiscord:panel-id","panel","id"))
opendiscord.responders.autocomplete.get("opendiscord:panel-id").workers.add(new api.ODWorker("opendiscord:panel-id",0,async (instance,params,source,cancel) => {
opendiscord.responders.autocomplete.get("opendiscord:panel-id").workers.add(new api.ODWorker("opendiscord:panel-id",0,async (instance,params,origin,cancel) => {
//create panel choices
const panelChoices : {name:string, value:string}[] = []
opendiscord.configs.get("opendiscord:panels").data.forEach((panel) => {
@@ -19,7 +19,7 @@ export const registerAutocompleteResponders = async () => {
//OPTION ID AUTOCOMPLETE
opendiscord.responders.autocomplete.add(new api.ODAutocompleteResponder("opendiscord:option-id",/ticket|move/,"id"))
opendiscord.responders.autocomplete.get("opendiscord:option-id").workers.add(new api.ODWorker("opendiscord:option-id",0,async (instance,params,source,cancel) => {
opendiscord.responders.autocomplete.get("opendiscord:option-id").workers.add(new api.ODWorker("opendiscord:option-id",0,async (instance,params,origin,cancel) => {
//create ticket choices
const ticketChoices : {name:string, value:string}[] = []
opendiscord.configs.get("opendiscord:options").data.forEach((option) => {
+21 -49
View File
@@ -1,45 +1,30 @@
///////////////////////////////////////
//AUTODELETE COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//AUTODELETE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:autodelete",generalConfig.data.prefix,/^autodelete/))
opendiscord.responders.commands.get("opendiscord:autodelete").workers.add([
new api.ODWorker("opendiscord:autodelete",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:autodelete",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.autodelete,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"autodelete")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -49,40 +34,27 @@ export const registerCommandResponders = async () => {
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autodelete-enabled").value = false
ticket.get("opendiscord:autodelete-days").value = 0
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-disable").build(source,{guild,channel,user,ticket,reason}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-disable").build(origin,{guild,channel,user,ticket,reason}))
}else if (scope == "enable"){
const time = instance.options.getNumber("time",true)
const reason = instance.options.getString("reason",false)
ticket.get("opendiscord:autodelete-enabled").value = true
ticket.get("opendiscord:autodelete-days").value = time
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-enable").build(source,{guild,channel,user,ticket,reason,time}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:autodelete-enable").build(origin,{guild,channel,user,ticket,reason,time}))
}
//update ticket message
const ticketMessage = await opendiscord.tickets.getTicketMessage(ticket)
if (ticketMessage){
try{
ticketMessage.edit((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket})).message)
}catch(e){
opendiscord.log("Unable to edit ticket message on autodelete "+scope+"!","error",[
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"messageid",value:ticketMessage.id},
{key:"option",value:ticket.option.id.value}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//update ticket message (no await)
openticketUtils.updateTicketMessage(guild,channel,user,ticket)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
const reason = instance.options.getString("reason",false)
opendiscord.log(instance.user.displayName+" used the 'autodelete "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"reason",value:reason ?? "/"},
])
})
+20 -20
View File
@@ -1,29 +1,29 @@
///////////////////////////////////////
//BLACKLIST COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//BLACKLIST COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:blacklist",generalConfig.data.prefix,/^blacklist/))
opendiscord.responders.commands.get("opendiscord:blacklist").workers.add([
new api.ODWorker("opendiscord:blacklist",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:blacklist",0,async (instance,params,origin,cancel) => {
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(source,{guild,channel,user,permissions:["support"]}))
else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(origin,{channel:instance.channel,user:instance.user}))
return cancel()
}
@@ -31,11 +31,11 @@ export const registerCommandResponders = async () => {
const scope = instance.options.getSubCommand()
if (!scope || (scope != "add" && scope != "get" && scope != "remove" && scope != "view")) return
if (scope == "view"){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-view").build(source,{guild,channel,user}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-view").build(origin,{guild,channel,user}))
}else if (scope == "get"){
const data = instance.options.getUser("user",true)
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-get").build(source,{guild,channel,user,data}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-get").build(origin,{guild,channel,user,data}))
}else if (scope == "add"){
const data = instance.options.getUser("user",true)
@@ -46,15 +46,15 @@ export const registerCommandResponders = async () => {
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
{key:"channelid",value:channel.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"reason",value:reason ?? "/"}
])
//manage stats
await opendiscord.stats.get("opendiscord:global").setStat("opendiscord:users-blacklisted",1,"increase")
await opendiscord.stats.get("opendiscord:user").setStat("opendiscord:users-blacklisted",user.id,1,"increase")
await opendiscord.statistics.get("opendiscord:global").setStat("opendiscord:users-blacklisted",1,"increase")
await opendiscord.statistics.get("opendiscord:user").setStat("opendiscord:users-blacklisted",user.id,1,"increase")
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-add").build(source,{guild,channel,user,data,reason}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-add").build(origin,{guild,channel,user,data,reason}))
}else if (scope == "remove"){
const data = instance.options.getUser("user",true)
@@ -65,14 +65,14 @@ export const registerCommandResponders = async () => {
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
{key:"channelid",value:channel.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"reason",value:reason ?? "/"}
])
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-remove").build(source,{guild,channel,user,data,reason}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:blacklist-remove").build(origin,{guild,channel,user,data,reason}))
}
}),
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:discord-logs",1,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
if (!guild) return
@@ -83,21 +83,21 @@ export const registerCommandResponders = async () => {
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(source,{guild,channel,user,mode:scope,data,reason}))
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(source,{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,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
opendiscord.log(instance.user.displayName+" used the 'blacklist "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+199 -83
View File
@@ -1,119 +1,235 @@
///////////////////////////////////////
//CLAIM COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//CLAIM COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:claim",generalConfig.data.prefix,"claim"))
opendiscord.responders.commands.get("opendiscord:claim").workers.add([
new api.ODWorker("opendiscord:claim",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:claim",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.claim,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already claimed
if (ticket.get("opendiscord:claimed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.claim"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
const claimUser = instance.options.getUser("user",false) ?? user
const reason = instance.options.getString("reason",false)
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
if (!isTicketUnclaimed) return cancel()
//start claiming ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:claim-ticket").run(source,{guild,channel,user:claimUser,ticket,reason,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(source,{guild,channel,user:claimUser,ticket,reason}))
const reason = instance.options.getString("reason",false)
const claimUser = instance.options.getUser("user",false) ?? user
await opendiscord.actions.get("opendiscord:claim-ticket").run(origin,{guild,channel,user:claimUser,ticket,reason,sendMessage:false})
//send message & set state
const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(origin,{guild,channel,user:claimUser,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"claim-message",
messageOrigin:origin,
messageAuthor:claimUser.id,
messageReason:reason
},sentMsg.ephemeral)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'claim' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//CLAIM TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:claim-ticket",/^od:claim-ticket/))
opendiscord.responders.buttons.get("opendiscord:claim-ticket").workers.add(
new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,source,cancel) => {
const originalSource = instance.interaction.customId.split("_")[1] as Exclude<api.ODActionManagerIds_Default["opendiscord:claim-ticket"]["source"],"slash"|"text">
new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
if (!hasPerms) return cancel()
if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:claim-ticket-ticket-message").activate(instance)
else if (originalSource == "unclaim-message") await opendiscord.verifybars.get("opendiscord:claim-ticket-unclaim-message").activate(instance)
else await instance.defer("update",false)
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/claim")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
if (!isTicketUnclaimed) return cancel()
//fetch state details
const verifybar = opendiscord.verifybars.get("opendiscord:claim-ticket")
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
}else if (originalMsgType == "ticket-message"){
//ticket message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:claim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "unclaim-message"){
//unclaim message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:claim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:unclaim-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
})
)
}
export const registerModalResponders = async () => {
//CLAIM WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:claim-ticket-reason",/^od:claim-ticket-reason_/))
opendiscord.responders.modals.get("opendiscord:claim-ticket-reason").workers.add([
new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!channel) return
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
const originalSource = instance.interaction.customId.split("_")[2] as Exclude<api.ODActionManagerIds_Default["opendiscord:claim-ticket"]["source"],"slash"|"text">
const reason = instance.values.getTextField("reason",true)
//claim with reason
if (originalSource == "ticket-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalSource == "unclaim-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("other",{guild,channel,user,ticket,reason}))
}else{
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:claim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
}
export async function registerVerifyBars(){
//CLAIM TICKET
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:claim-ticket"))
opendiscord.verifybars.get("opendiscord:claim-ticket").workers.add([
new api.ODWorker("opendiscord:claim-ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/claim")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
if (!isTicketUnclaimed) return cancel()
//fetch state details
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//start claiming ticket
if (params.selectedButtonId == "cancel"){
//CANCEL
if (originalMsgType == "ticket-message"){
//ticket message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "unclaim-message"){
//unclaim message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
}else if (params.selectedButtonId == "accept"){
//CLAIM TICKET
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "unclaim-message"){
//converted to claim message
await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"claim-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:null
},sentMsg.ephemeral)
}
}else if (params.selectedButtonId == "accept-with-reason"){
//CLAIM WITH REASON (MODAL)
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:claim-ticket-reason").build("other",{guild,channel,user,ticket,message}))
}
})
])
}
export async function registerModalResponders(){
//CLAIM WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:claim-ticket-reason",/^od:claim-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:claim-ticket-reason").workers.add([
new api.ODWorker("opendiscord:claim-ticket-reason",0,async (instance,params,origin,cancel) => {
const {guild,user} = instance
const match = /^od:claim-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const channel = await opendiscord.client.fetchTextChannel(match[1])
const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"claim")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/claim")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnclaimed = await openticketUtils.replyTicketMustBeUnclaimed(instance,origin,ticket)
if (!isTicketUnclaimed) return cancel()
//fetch state details
const reason = instance.values.getTextField("reason",true)
const originalMsgOrigin = state.data.messageOrigin
const originalMsgType = state.data.messageType
//start claiming ticket
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalMsgType == "unclaim-message"){
//converted to claim message
await opendiscord.actions.get("opendiscord:claim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"claim-message",
messageOrigin:originalMsgOrigin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}
})
])
}
+59 -39
View File
@@ -1,35 +1,31 @@
///////////////////////////////////////
//CLEAR COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const clearMsgState = opendiscord.states.get("opendiscord:clear-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//CLEAR COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:clear",generalConfig.data.prefix,"clear"))
opendiscord.responders.commands.get("opendiscord:clear").workers.add([
new api.ODWorker("opendiscord:clear",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:clear",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//responder checks
//check permissions (only allow global admins: ticket admins aren't allowed to clear tickets)
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.clear,"support",user,member,channel,guild,{allowChannelUserScope:false,allowChannelRoleScope:false})
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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"clear",{allowChannelUserScope:false,allowChannelRoleScope:false})
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//fetch data
const tempFilter = instance.options.getString("filter",false)
const filter = (tempFilter) ? tempFilter.toLowerCase() as api.ODTicketClearFilter : "all"
const list: string[] = []
const channelNameList: string[] = []
const ticketList = opendiscord.tickets.getAll().filter((ticket) => {
if (filter == "all") return true
else if (filter == "open" && ticket.get("opendiscord:open").value) return true
@@ -43,46 +39,70 @@ export const registerCommandResponders = async () => {
})
for (const ticket of ticketList){
const ticketChannel = await opendiscord.tickets.getTicketChannel(ticket)
if (ticketChannel) list.push("#"+ticketChannel.name)
if (ticketChannel) channelNameList.push("#"+ticketChannel.name)
}
//reply with clear verify
await instance.defer(true)
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:clear-verify-message").build(source,{guild,channel,user,filter,list}))
const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:clear-verify-message").build(origin,{guild,channel,user,filter,list:channelNameList,inProgress:false}))
if (sentMsg.success) await clearMsgState.setMsgState({channel,message:sentMsg.message,user},{
messageOrigin:origin,
clearFilter:filter,
clearChannelNameList:channelNameList
},sentMsg.ephemeral)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'clear' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//CLEAR CONTINUE BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:clear-continue",/^od:clear-continue_/))
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:clear-continue","od:clear-continue"))
opendiscord.responders.buttons.get("opendiscord:clear-continue").workers.add(
new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!guild || channel.isDMBased()) return
const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIds_Default["opendiscord:clear-tickets"]["source"]
const filter = instance.interaction.customId.split("_")[2] as api.ODTicketClearFilter
new api.ODWorker("opendiscord:clear-continue",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,message} = instance
//check message state
const state = await clearMsgState.getMsgState({channel,message,user})
if (!state){
//TODO TRANSLATION!!!
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(origin,{guild,channel,user,error:"This interaction is no longer valid or has expired. Use the command `{0}` instead. It is normal to receive this error after a major Open Ticket update.".replace("{0}","/clear"),layout:"simple",customTitle:"Message State Expired"}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"clear")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
//fetch state details
const originalUser = ((state.userId) ? await opendiscord.client.fetchUser(state.userId) : user) ?? user
const originalOrigin = state.data.messageOrigin
const originalClearFilter = state.data.clearFilter
const originalClearChannelNameList = state.data.clearChannelNameList
//start ticket clear
await instance.defer("update",true)
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:clear-verify-message").build(originalOrigin,{guild,channel,user:originalUser,filter:originalClearFilter,list:originalClearChannelNameList,inProgress:true}))
const list: string[] = []
const ticketList = opendiscord.tickets.getAll().filter((ticket) => {
if (filter == "all") return true
else if (filter == "open" && ticket.get("opendiscord:open").value) return true
else if (filter == "closed" && ticket.get("opendiscord:closed").value) return true
else if (filter == "claimed" && ticket.get("opendiscord:claimed").value) return true
else if (filter == "pinned" && ticket.get("opendiscord:pinned").value) return true
else if (filter == "unclaimed" && !ticket.get("opendiscord:claimed").value) return true
else if (filter == "unpinned" && !ticket.get("opendiscord:pinned").value) return true
else if (filter == "autoclosed" && ticket.get("opendiscord:closed").value) return true
if (originalClearFilter == "all") return true
else if (originalClearFilter == "open" && ticket.get("opendiscord:open").value) return true
else if (originalClearFilter == "closed" && ticket.get("opendiscord:closed").value) return true
else if (originalClearFilter == "claimed" && ticket.get("opendiscord:claimed").value) return true
else if (originalClearFilter == "pinned" && ticket.get("opendiscord:pinned").value) return true
else if (originalClearFilter == "unclaimed" && !ticket.get("opendiscord:claimed").value) return true
else if (originalClearFilter == "unpinned" && !ticket.get("opendiscord:pinned").value) return true
else if (originalClearFilter == "autoclosed" && ticket.get("opendiscord:closed").value) return true
else return false
})
for (const ticket of ticketList){
@@ -90,8 +110,8 @@ export const registerButtonResponders = async () => {
if (ticketChannel) list.push("#"+ticketChannel.name)
}
await opendiscord.actions.get("opendiscord:clear-tickets").run(originalSource,{guild,channel,user,filter,list:ticketList})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:clear-message").build(originalSource,{guild,channel,user,filter,list}))
await opendiscord.actions.get("opendiscord:clear-tickets").run(originalOrigin,{guild,channel,user,filter:originalClearFilter,list:ticketList})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:clear-message").build(originalOrigin,{guild,channel,user,filter:originalClearFilter,list}))
})
)
}
+204 -92
View File
@@ -1,131 +1,243 @@
///////////////////////////////////////
//CLOSE COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//CLOSE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:close",generalConfig.data.prefix,"close"))
opendiscord.responders.commands.get("opendiscord:close").workers.add([
new api.ODWorker("opendiscord:close",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:close",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.close,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already closed
if (ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.close"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
if (!isTicketOpen) return cancel()
const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"close")
if (!messagesHaveBeenSent) return cancel()
//start closing ticket
await instance.defer(false)
const reason = instance.options.getString("reason",false)
await opendiscord.actions.get("opendiscord:close-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(source,{guild,channel,user,ticket,reason}))
await opendiscord.actions.get("opendiscord:close-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
//send message & set state
const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(origin,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"close-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'close' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//CLOSE TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:close-ticket",/^od:close-ticket_/))
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:close-ticket",/^od:close-ticket/))
opendiscord.responders.buttons.get("opendiscord:close-ticket").workers.add(
new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,source,cancel) => {
const originalSource = instance.interaction.customId.split("_")[1] as Exclude<api.ODActionManagerIds_Default["opendiscord:close-ticket"]["source"],"slash"|"text"|"autoclose">
new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,message,user,member} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
if (!hasPerms) return cancel()
if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:close-ticket-ticket-message").activate(instance)
else if (originalSource == "reopen-message") await opendiscord.verifybars.get("opendiscord:close-ticket-reopen-message").activate(instance)
else await instance.defer("update",false)
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/close")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
if (!isTicketOpen) return cancel()
const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"close")
if (!messagesHaveBeenSent) return cancel()
//fetch state details
const verifybar = opendiscord.verifybars.get("opendiscord:close-ticket")
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
}else if (originalMsgType == "ticket-message"){
//ticket message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:close-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "reopen-message"){
//reopen message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:close-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:reopen-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
})
)
}
export const registerModalResponders = async () => {
//CLOSE WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:close-ticket-reason",/^od:close-ticket-reason_/))
opendiscord.responders.modals.get("opendiscord:close-ticket-reason").workers.add([
new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!channel) return
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
export async function registerVerifyBars(){
//CLOSE TICKET VERIFYBAR
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:close-ticket"))
opendiscord.verifybars.get("opendiscord:close-ticket").workers.add([
new api.ODWorker("opendiscord:close-ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild,message} = instance
const originalSource = instance.interaction.customId.split("_")[2] as Exclude<api.ODActionManagerIds_Default["opendiscord:close-ticket"]["source"],"slash"|"text"|"autoclose">
const reason = instance.values.getTextField("reason",true)
//close with reason
if (originalSource == "ticket-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalSource == "reopen-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("other",{guild,channel,user,ticket,reason}))
}else{
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:close-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/close")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
if (!isTicketOpen) return cancel()
const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"close")
if (!messagesHaveBeenSent) return cancel()
//fetch state details
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//start closing ticket
if (params.selectedButtonId == "cancel"){
//CANCEL
if (originalMsgType == "ticket-message"){
//ticket message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "reopen-message"){
//reopen message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
}else if (params.selectedButtonId == "accept"){
//CLOSE TICKET
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "reopen-message"){
//converted to close message
await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"close-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:null
},sentMsg.ephemeral)
}
}else if (params.selectedButtonId == "accept-with-reason"){
//CLOSE WITH REASON (MODAL)
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:close-ticket-reason").build("other",{guild,channel,user,ticket,message}))
}
})
])
}
export async function registerModalResponders(){
//CLOSE WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:close-ticket-reason",/^od:close-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:close-ticket-reason").workers.add([
new api.ODWorker("opendiscord:close-ticket-reason",0,async (instance,params,origin,cancel) => {
const {guild,user} = instance
const match = /^od:close-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const channel = await opendiscord.client.fetchTextChannel(match[1])
const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"close")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/close")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
if (!isTicketOpen) return cancel()
//fetch state details
const reason = instance.values.getTextField("reason",true)
const originalMsgOrigin = state.data.messageOrigin
const originalMsgType = state.data.messageType
//start closing ticket
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalMsgType == "reopen-message"){
//converted to close message
await opendiscord.actions.get("opendiscord:close-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"close-message",
messageOrigin:originalMsgOrigin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}
})
])
}
+220 -99
View File
@@ -1,64 +1,42 @@
///////////////////////////////////////
//DELETE COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//DELETE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:delete",generalConfig.data.prefix,"delete"))
opendiscord.responders.commands.get("opendiscord:delete").workers.add([
new api.ODWorker("opendiscord:delete",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:delete",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.delete,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
if (!hasPerms) return cancel()
//return when not allowed because of missing messages
if (!permsResult.isAdmin && (!generalConfig.data.system.allowCloseBeforeMessage || !generalConfig.data.system.allowCloseBeforeAdminMessage)){
const analysis = await opendiscord.transcripts.collector.ticketUserMessagesAnalysis(ticket,guild,channel)
if (analysis && !generalConfig.data.system.allowCloseBeforeMessage && analysis.totalMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
if (analysis && !generalConfig.data.system.allowCloseBeforeAdminMessage && analysis.adminMessages < 1){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,layout:"simple",error:lang.getTranslation("errors.descriptions.closeBeforeAdminMessage"),customTitle:lang.getTranslation("errors.titles.noPermissions")}))
return cancel()
}
}
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketOpen = await openticketUtils.replyTicketMustBeOpen(instance,origin,ticket)
if (!isTicketOpen) return cancel()
const reason = instance.options.getString("reason",false)
const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false
const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"delete")
if (!messagesHaveBeenSent) return cancel()
//don't allow deleteWithoutTranscript to non-global-admins when enabled
if (withoutTranscript && generalConfig.data.system.adminOnlyDeleteWithoutTranscript){
const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false
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()
@@ -67,84 +45,227 @@ export const registerCommandResponders = async () => {
//start deleting ticket
await instance.defer(false)
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(source,{guild,channel,user,ticket,reason}))
await opendiscord.actions.get("opendiscord:delete-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript})
const reason = instance.options.getString("reason",false)
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(origin,{guild,channel,user,ticket,reason}))
await opendiscord.actions.get("opendiscord:delete-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript})
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'delete' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//DELETE TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:delete-ticket",/^od:delete-ticket/))
opendiscord.responders.buttons.get("opendiscord:delete-ticket").workers.add(
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,source,cancel) => {
const originalSource = instance.interaction.customId.split("_")[1] as Exclude<api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"],"slash"|"text"|"autodelete"|"clear">
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,message,user,member} = instance
if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-ticket-message").activate(instance)
else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-close-message").activate(instance)
else if (originalSource == "reopen-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-reopen-message").activate(instance)
else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("opendiscord:delete-ticket-autoclose-message").activate(instance)
else await instance.defer("update",false)
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/delete")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"delete")
if (!messagesHaveBeenSent) return cancel()
//fetch state details
const verifybar = opendiscord.verifybars.get("opendiscord:delete-ticket")
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
}else if (originalMsgType == "ticket-message"){
//ticket message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "close-message"){
//close message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:close-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}else if (originalMsgType == "reopen-message"){
//reopen message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:reopen-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}else if (originalMsgType == "autoclose-message"){
//autoclose message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:delete-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:autoclose-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket}))
}
})
)
}
export const registerModalResponders = async () => {
//REOPEN WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:delete-ticket-reason",/^od:delete-ticket-reason_/))
export async function registerVerifyBars(){
//DELETE TICKET
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:delete-ticket"))
opendiscord.verifybars.get("opendiscord:delete-ticket").workers.add([
new api.ODWorker("opendiscord:delete-ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/delete")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const messagesHaveBeenSent = await openticketUtils.replyMessageMustBeSentBeforeClose(instance,origin,ticket,"delete")
if (!messagesHaveBeenSent) return cancel()
//don't allow deleteWithoutTranscript to non-global-admins when enabled
const withoutTranscript = (params.selectedButtonId == "accept-without-transcript")
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()
}
}
//fetch state details
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//start deleting ticket
if (params.selectedButtonId == "cancel"){
//CANCEL
if (originalMsgType == "ticket-message"){
//ticket message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "close-message"){
//close message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}else if (originalMsgType == "reopen-message"){
//reopen message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}else if (originalMsgType == "autoclose-message"){
//autoclose message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("verifybar",{guild,channel,user:originalUser,ticket}))
}
}else if (params.selectedButtonId == "accept" || params.selectedButtonId == "accept-without-transcript"){
//DELETE TICKET
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true,withoutTranscript})
ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalMsgType == "close-message"){
//converted to delete message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason:null}))
}else if (originalMsgType == "reopen-message"){
//converted to delete message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason:null}))
}else if (originalMsgType == "autoclose-message"){
//converted to delete message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false,withoutTranscript})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason:null}))
}
}else if (params.selectedButtonId == "accept-with-reason"){
//DELETE WITH REASON (MODAL)
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:delete-ticket-reason").build("other",{guild,channel,user,ticket,message}))
}
})
])
}
export async function registerModalResponders(){
//DELETE WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:delete-ticket-reason",/^od:delete-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:delete-ticket-reason").workers.add([
new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!channel) return
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
new api.ODWorker("opendiscord:delete-ticket-reason",0,async (instance,params,origin,cancel) => {
const {guild,user} = instance
const originalSource = instance.interaction.customId.split("_")[2] as Exclude<api.ODActionManagerIds_Default["opendiscord:delete-ticket"]["source"],"slash"|"text"|"autodelete"|"clear">
const match = /^od:delete-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const channel = await opendiscord.client.fetchTextChannel(match[1])
const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"delete")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/delete")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch state details
const reason = instance.values.getTextField("reason",true)
const originalMsgOrigin = state.data.messageOrigin
const originalMsgType = state.data.messageType
//delete with reason
if (originalSource == "ticket-message"){
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false})
//update ticket (for ticket message) => no-await doesn't wait for the action to set this variable
ticket.get("opendiscord:for-deletion").value = true
//start deleting ticket
//don't await DELETE action => else it will update the message after the channel has been deleted
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false})
ticket.get("opendiscord:for-deletion").value = true //disable ticket message buttons
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalSource == "close-message"){
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason}))
}else if (originalSource == "reopen-message"){
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason}))
}else if (originalSource == "autoclose-message"){
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build("other",{guild,channel,user,ticket,reason}))
}else{
await instance.defer("update",false)
//don't await DELETE action => else it will update the message after the channel has been deleted
opendiscord.actions.get("opendiscord:delete-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true,withoutTranscript:false})
}else if (originalMsgType == "close-message"){
//converted to delete message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
}else if (originalMsgType == "reopen-message"){
//converted to delete message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
}else if (originalMsgType == "autoclose-message"){
//converted to delete message
opendiscord.actions.get("opendiscord:delete-ticket").run(originalMsgType,{guild,channel,user,ticket,reason,sendMessage:false,withoutTranscript:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:delete-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
}
})
])
+14 -18
View File
@@ -1,50 +1,46 @@
///////////////////////////////////////
//HELP COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//HELP COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:help",generalConfig.data.prefix,"help"))
opendiscord.responders.commands.get("opendiscord:help").workers.add([
new api.ODWorker("opendiscord:help",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:help",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.help,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"help")
if (!hasPerms) return cancel()
//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"
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build(source,{mode,page:0}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:help-menu").build(origin,{mode,page:0}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'help' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//HELP MENU SWITCH BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-switch",/^od:help-menu-switch_(slash|text)/))
opendiscord.responders.buttons.get("opendiscord:help-menu-switch").workers.add(
new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,origin,cancel) => {
const mode = instance.interaction.customId.split("_")[1] as "slash"|"text"
const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/)
const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0
@@ -59,7 +55,7 @@ export const registerButtonResponders = async () => {
//HELP MENU PREVIOUS BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-previous",/^od:help-menu-previous/))
opendiscord.responders.buttons.get("opendiscord:help-menu-previous").workers.add(
new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,origin,cancel) => {
const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/)
const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/)
const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0
@@ -73,7 +69,7 @@ export const registerButtonResponders = async () => {
//HELP MENU NEXT BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:help-menu-next",/^od:help-menu-next/))
opendiscord.responders.buttons.get("opendiscord:help-menu-next").workers.add(
new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:update-help-menu",0,async (instance,params,origin,cancel) => {
const switchButton = instance.getMessageComponent("button",/^od:help-menu-switch_(slash|text)/)
const pageButton = instance.getMessageComponent("button",/^od:help-menu-page_([0-9]+)/)
const currentPage = (pageButton && pageButton.customId) ? Number(pageButton.customId.split("_")[1]) : 0
+22 -34
View File
@@ -1,48 +1,36 @@
///////////////////////////////////////
//MOVE COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//MOVE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:move",generalConfig.data.prefix,"move"))
opendiscord.responders.commands.get("opendiscord:move").workers.add([
new api.ODWorker("opendiscord:move",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:move",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.move,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check if in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"move")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch data
const id = instance.options.getString("id",true)
const reason = instance.options.getString("reason",false)
const option = opendiscord.options.get(id)
//return if unknown option
if (!option || !(option instanceof api.ODTicketOption)){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.titles.unknownOption"),layout:"simple"}))
@@ -56,15 +44,15 @@ export const registerCommandResponders = async () => {
//start moving ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:move-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:option})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(source,{guild,channel,user,ticket,reason,data:option}))
await opendiscord.actions.get("opendiscord:move-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data:option})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:move-message").build(origin,{guild,channel,user,ticket,reason,data:option}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'move' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+22 -23
View File
@@ -1,42 +1,41 @@
///////////////////////////////////////
//STATS COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//PANEL COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:panel",generalConfig.data.prefix,/^panel/))
opendiscord.responders.commands.get("opendiscord:panel").workers.add([
new api.ODWorker("opendiscord:panel",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:panel",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.panel,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild || instance.channel.type == discord.ChannelType.GroupDM){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//get panel data
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"panel")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch data
const id = instance.options.getString("id",true)
const panel = opendiscord.panels.get(id)
if (!panel){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-panel-unknown").build(source,{guild,channel,user}))
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-panel-unknown").build(origin,{guild,channel,user}))
return cancel()
}
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:panel-ready").build(source,{guild,channel,user,panel}))
const panelMessage = await instance.channel.send((await opendiscord.builders.messages.getSafe("opendiscord:panel").build(source,{guild,channel,user,panel})).message)
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:panel-ready").build(origin,{guild,channel,user,panel}))
const panelMessage = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:panel").build(origin,{guild,channel,user,panel})).message)
//add panel to database (this way, the bot knows where all panels are located)
const globalDatabase = opendiscord.databases.get("opendiscord:global")
@@ -47,12 +46,12 @@ export const registerCommandResponders = async () => {
await globalDatabase.set("opendiscord:panel-update",panelMessage.channel.id+"_"+panelMessage.id,panel.id.value)
}
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'panel' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+197 -113
View File
@@ -1,151 +1,235 @@
///////////////////////////////////////
//PIN COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//PIN COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:pin",generalConfig.data.prefix,"pin"))
opendiscord.responders.commands.get("opendiscord:pin").workers.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.pin
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
return cancel()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:pin",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:pin",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.pin,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when already pinned
if (ticket.get("opendiscord:pinned").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.pin"),layout:"simple"}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
if (!isTicketUnpinned) return cancel()
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
const reason = instance.options.getString("reason",false)
//start pinning ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:pin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(source,{guild,channel,user,ticket,reason}))
const reason = instance.options.getString("reason",false)
await opendiscord.actions.get("opendiscord:pin-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
//send message & set state
const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(origin,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"pin-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'pin' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//PIN TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:pin-ticket",/^od:pin-ticket/))
opendiscord.responders.buttons.get("opendiscord:pin-ticket").workers.add(
new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,source,cancel) => {
const originalSource = instance.interaction.customId.split("_")[1] as Exclude<api.ODActionManagerIds_Default["opendiscord:pin-ticket"]["source"],"slash"|"text">
new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:pin-ticket-ticket-message").activate(instance)
else if (originalSource == "unpin-message") await opendiscord.verifybars.get("opendiscord:pin-ticket-unpin-message").activate(instance)
else await instance.defer("update",false)
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/pin")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
if (!isTicketUnpinned) return cancel()
//fetch state details
const verifybar = opendiscord.verifybars.get("opendiscord:pin-ticket")
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
}else if (originalMsgType == "ticket-message"){
//ticket message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:pin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "unpin-message"){
//unpin message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:pin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:unpin-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
})
)
}
export const registerModalResponders = async () => {
//PIN WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:pin-ticket-reason",/^od:pin-ticket-reason_/))
opendiscord.responders.modals.get("opendiscord:pin-ticket-reason").workers.add([
new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!channel) return
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
const originalSource = instance.interaction.customId.split("_")[2] as Exclude<api.ODActionManagerIds_Default["opendiscord:pin-ticket"]["source"],"slash"|"text">
const reason = instance.values.getTextField("reason",true)
//pin with reason
if (originalSource == "ticket-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalSource == "unpin-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("other",{guild,channel,user,ticket,reason}))
}else{
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:pin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
}
export async function registerVerifyBars(){
//PIN TICKET
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:pin-ticket"))
opendiscord.verifybars.get("opendiscord:pin-ticket").workers.add([
new api.ODWorker("opendiscord:pin-ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/pin")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
if (!isTicketUnpinned) return cancel()
//fetch state details
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//start pinning ticket
if (params.selectedButtonId == "cancel"){
//CANCEL
if (originalMsgType == "ticket-message"){
//ticket message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "unpin-message"){
//unpin message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
}else if (params.selectedButtonId == "accept"){
//PIN TICKET
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "unpin-message"){
//converted to pin message
await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"pin-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:null
},sentMsg.ephemeral)
}
}else if (params.selectedButtonId == "accept-with-reason"){
//PIN WITH REASON (MODAL)
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:pin-ticket-reason").build("other",{guild,channel,user,ticket,message}))
}
})
])
}
export async function registerModalResponders(){
//PIN WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:pin-ticket-reason",/^od:pin-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:pin-ticket-reason").workers.add([
new api.ODWorker("opendiscord:pin-ticket-reason",0,async (instance,params,origin,cancel) => {
const {guild,user} = instance
const match = /^od:pin-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const channel = await opendiscord.client.fetchTextChannel(match[1])
const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"pin")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/pin")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketUnpinned = await openticketUtils.replyTicketMustBeUnpinned(instance,origin,ticket)
if (!isTicketUnpinned) return cancel()
//fetch state details
const reason = instance.values.getTextField("reason",true)
const originalMsgOrigin = state.data.messageOrigin
const originalMsgType = state.data.messageType
//start pinning ticket
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalMsgType == "unpin-message"){
//converted to pin message
await opendiscord.actions.get("opendiscord:pin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"pin-message",
messageOrigin:originalMsgOrigin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}
})
])
}
+21 -35
View File
@@ -1,44 +1,30 @@
///////////////////////////////////////
//PRIORITY COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//PRIORITY COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:priority",generalConfig.data.prefix,"priority"))
opendiscord.responders.commands.get("opendiscord:priority").workers.add([
new api.ODWorker("opendiscord:priority",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:priority",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.priority,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"priority")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -56,21 +42,21 @@ export const registerCommandResponders = async () => {
//start changing ticket priority
await instance.defer(false)
await opendiscord.actions.get("opendiscord:update-ticket-priority").run(source,{guild,channel,user,ticket,newPriority:priority,sendMessage:false,reason})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(source,{guild,channel,user,ticket,priority,reason}))
await opendiscord.actions.get("opendiscord:update-ticket-priority").run(origin,{guild,channel,user,ticket,newPriority:priority,sendMessage:false,reason})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-set").build(origin,{guild,channel,user,ticket,priority,reason}))
}else if (scope == "get"){
const priority = opendiscord.priorities.getFromPriorityLevel(ticket.get("opendiscord:priority").value)
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-get").build(source,{guild,channel,user,ticket,priority}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:priority-get").build(origin,{guild,channel,user,ticket,priority}))
}
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
opendiscord.log(instance.user.displayName+" used the 'priority "+scope+"' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+19 -32
View File
@@ -1,45 +1,32 @@
///////////////////////////////////////
//REMOVE COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//REMOVE COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:remove",generalConfig.data.prefix,"remove"))
opendiscord.responders.commands.get("opendiscord:remove").workers.add([
new api.ODWorker("opendiscord:remove",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:remove",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.remove,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"remove")
if (!hasPerms) return cancel()
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch data
const data = instance.options.getUser("user",true)
const reason = instance.options.getString("reason",false)
@@ -52,15 +39,15 @@ export const registerCommandResponders = async () => {
//start removing user from ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:remove-ticket-user").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(source,{guild,channel,user,ticket,reason,data}))
await opendiscord.actions.get("opendiscord:remove-ticket-user").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:remove-message").build(origin,{guild,channel,user,ticket,reason,data}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'remove' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+21 -34
View File
@@ -1,59 +1,46 @@
///////////////////////////////////////
//RENAME COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//RENAME COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:rename",generalConfig.data.prefix,"rename"))
opendiscord.responders.commands.get("opendiscord:rename").workers.add([
new api.ODWorker("opendiscord:rename",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:rename",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.rename,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"rename")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch data
const name = instance.options.getString("name",true)
const reason = instance.options.getString("reason",false)
//start renaming ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:rename-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,data:name})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(source,{guild,channel,user,ticket,reason,data:name}))
await opendiscord.actions.get("opendiscord:rename-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,data:name})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:rename-message").build(origin,{guild,channel,user,ticket,reason,data:name}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'rename' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+224 -86
View File
@@ -1,123 +1,261 @@
///////////////////////////////////////
//REOPEN COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//REOPEN COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:reopen",generalConfig.data.prefix,"reopen"))
opendiscord.responders.commands.get("opendiscord:reopen").workers.add([
new api.ODWorker("opendiscord:reopen",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:reopen",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,member} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.reopen,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not closed
if (!ticket.get("opendiscord:closed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.reopen"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
const reason = instance.options.getString("reason",false)
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
if (!isTicketClosed) return cancel()
//start reopening ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(source,{guild,channel,user,ticket,reason}))
const reason = instance.options.getString("reason",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
//send message & set state
const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(origin,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"reopen-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'reopen' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//REOPEN TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:reopen-ticket",/^od:reopen-ticket/))
opendiscord.responders.buttons.get("opendiscord:reopen-ticket").workers.add(
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,source,cancel) => {
const originalSource = instance.interaction.customId.split("_")[1] as Exclude<api.ODActionManagerIds_Default["opendiscord:reopen-ticket"]["source"],"slash"|"text">
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,message,user,member} = instance
if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-ticket-message").activate(instance)
else if (originalSource == "close-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-close-message").activate(instance)
else if (originalSource == "autoclose-message") await opendiscord.verifybars.get("opendiscord:reopen-ticket-autoclose-message").activate(instance)
else await instance.defer("update",false)
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/reopen")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
if (!isTicketClosed) return cancel()
//fetch state details
const verifybar = opendiscord.verifybars.get("opendiscord:reopen-ticket")
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
}else if (originalMsgType == "ticket-message"){
//ticket message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:reopen-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "close-message"){
//close message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:reopen-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:close-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}else if (originalMsgType == "autoclose-message"){
//autoclose message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:reopen-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:autoclose-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket}))
}
})
)
}
export const registerModalResponders = async () => {
//REOPEN WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:reopen-ticket-reason",/^od:reopen-ticket-reason_/))
opendiscord.responders.modals.get("opendiscord:reopen-ticket-reason").workers.add([
new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!channel) return
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
const originalSource = instance.interaction.customId.split("_")[2] as Exclude<api.ODActionManagerIds_Default["opendiscord:reopen-ticket"]["source"],"slash"|"text">
const reason = instance.values.getTextField("reason",true)
//reopen with reason
if (originalSource == "ticket-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalSource == "close-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
}else if (originalSource == "autoclose-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("other",{guild,channel,user,ticket,reason}))
}else{
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
}
export async function registerVerifyBars(){
//REOPEN TICKET
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:reopen-ticket"))
opendiscord.verifybars.get("opendiscord:reopen-ticket").workers.add([
new api.ODWorker("opendiscord:reopen-ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/reopen")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
if (!isTicketClosed) return cancel()
//fetch state details
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//start reopening ticket
if (params.selectedButtonId == "cancel"){
//CANCEL
if (originalMsgType == "ticket-message"){
//ticket message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "close-message"){
//close message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:close-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}else if (originalMsgType == "autoclose-message"){
//autoclose message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:autoclose-message").build("verifybar",{guild,channel,user:originalUser,ticket}))
}
}else if (params.selectedButtonId == "accept"){
//REOPEN TICKET
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "close-message"){
//converted to reopen message
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"reopen-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:null
},sentMsg.ephemeral)
}else if (originalMsgType == "autoclose-message"){
//converted to reopen message
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"reopen-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:null
},sentMsg.ephemeral)
}
}else if (params.selectedButtonId == "accept-with-reason"){
//REOPEN WITH REASON (MODAL)
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:reopen-ticket-reason").build("other",{guild,channel,user,ticket,message}))
}
})
])
}
export async function registerModalResponders(){
//REOPEN WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:reopen-ticket-reason",/^od:reopen-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:reopen-ticket-reason").workers.add([
new api.ODWorker("opendiscord:reopen-ticket-reason",0,async (instance,params,origin,cancel) => {
const {guild,user} = instance
const match = /^od:reopen-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const channel = await opendiscord.client.fetchTextChannel(match[1])
const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"reopen")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/reopen")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClosed = await openticketUtils.replyTicketMustBeClosed(instance,origin,ticket)
if (!isTicketClosed) return cancel()
//fetch state details
const reason = instance.values.getTextField("reason",true)
const originalMsgOrigin = state.data.messageOrigin
const originalMsgType = state.data.messageType
//start reopening ticket
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalMsgType == "close-message"){
//converted to reopen message
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"reopen-message",
messageOrigin:originalMsgOrigin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}else if (originalMsgType == "autoclose-message"){
//converted to reopen message
await opendiscord.actions.get("opendiscord:reopen-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:reopen-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"reopen-message",
messageOrigin:originalMsgOrigin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}
})
])
}
+9 -11
View File
@@ -1,30 +1,28 @@
///////////////////////////////////////
//ROLE BUTTON (not command)
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//ROLE OPTION BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:role-option",/^od:role-option_/))
opendiscord.responders.buttons.get("opendiscord:role-option").workers.add(
new api.ODWorker("opendiscord:role-option",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:role-option",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//responder checks
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//get option data
const optionId = instance.interaction.customId.split("_")[2]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODRoleOption)){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
@@ -33,10 +31,10 @@ export const registerButtonResponders = async () => {
const res = await opendiscord.actions.get("opendiscord:reaction-role").run("panel-button",{guild,user,option,overwriteMode:null})
if (!res.result || !res.role){
//error
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive role update data from worker!",layout:"advanced"}))
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}))
})
)
}
+18 -77
View File
@@ -1,117 +1,58 @@
///////////////////////////////////////
//STATS COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//STATS COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:stats",generalConfig.data.prefix,/^stats/))
opendiscord.responders.commands.get("opendiscord:stats").workers.add([
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.stats
//command is disabled
if (permissionMode == "none"){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}
//reset subcommand is owner/developer only
if (instance.options.getSubCommand() == "reset"){
if (!opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]}))
return cancel()
}else return
}
//permissions for normal scopes
if (permissionMode == "everyone") return
else if (permissionMode == "admin"){
if (!opendiscord.permissions.hasPermissions("support",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["support"]}))
return cancel()
}else return
}else{
if (!instance.guild || !instance.member){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #1",layout:"advanced"}))
return cancel()
}
const role = await opendiscord.client.fetchGuildRole(instance.guild,permissionMode)
if (!role){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Permission Error: Not in Server #2",layout:"advanced"}))
return cancel()
}
if (!role.members.has(instance.member.id)){
//no permissions
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else return
}
}),
new api.ODWorker("opendiscord:stats",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:stats",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
if (generalConfig.data.system.permissions.stats === "none"){
//command is disabled
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build("button",{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:[]}))
return cancel()
}else if (instance.options.getSubCommand() === "reset" && !opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
if (instance.options.getSubCommand() === "reset" && !opendiscord.permissions.hasPermissions("owner",await opendiscord.permissions.getPermissions(instance.user,instance.channel,instance.guild))){
//reset --> owner/developer role is required
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user,permissions:["owner","developer"]}))
return cancel()
}else{
//default permissions check
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.stats,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"stats")
if (!hasPerms) return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//responder checks
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
if (!scope || (scope != "global" && scope != "ticket" && scope != "user" && scope != "reset")) return
if (scope == "global"){
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-global").build(source,{guild,channel,user}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-global").build(origin,{guild,channel,user}))
}else if (scope == "ticket"){
const id = instance.options.getChannel("ticket",false)?.id ?? channel.id
const ticket = opendiscord.tickets.get(id)
if (ticket) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket").build(source,{guild,channel,user,scopeData:ticket}))
else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket-unknown").build(source,{guild,channel,user,id}))
if (ticket) await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket").build(origin,{guild,channel,user,scopeData:ticket}))
else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-ticket-unknown").build(origin,{guild,channel,user,id}))
}else if (scope == "user"){
const statsUser = instance.options.getUser("user",false) ?? user
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-user").build(source,{guild,channel,user,scopeData:statsUser}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-user").build(origin,{guild,channel,user,scopeData:statsUser}))
}else if (scope == "reset"){
const reason = instance.options.getString("reason",false)
opendiscord.stats.reset()
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-reset").build(source,{guild,channel,user,reason}))
opendiscord.statistics.reset()
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:stats-reset").build(origin,{guild,channel,user,reason}))
}
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
const scope = instance.options.getSubCommand()
let data: string
if (scope == "ticket"){
@@ -123,7 +64,7 @@ export const registerCommandResponders = async () => {
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source},
{key:"method",value:origin},
{key:"data",value:data},
])
})
+81 -96
View File
@@ -1,173 +1,161 @@
///////////////////////////////////////
//TICKET COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
async function checkTicketCreationPerms(instance:api.ODButtonResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance|api.ODCommandResponderInstance,source:api.ODActionManagerIds_Default["opendiscord:create-ticket-permissions"]["source"],guild:discord.Guild,user:discord.User,option:api.ODTicketOption){
async function checkTicketCreationPerms(instance:api.ODButtonResponderInstance|api.ODDropdownResponderInstance|api.ODModalResponderInstance|api.ODCommandResponderInstance,origin:api.ODActionManagerIdMappings["opendiscord:create-ticket-permissions"]["origin"],guild:discord.Guild,user:discord.User,option:api.ODTicketOption){
//check ticket permissions
const permsRes = await opendiscord.actions.get("opendiscord:create-ticket-permissions").run(source,{guild,user,option})
const permsRes = await opendiscord.actions.get("opendiscord:create-ticket-permissions").run(origin,{guild,user,option})
if (!permsRes.valid && instance.channel){
//error
const newSource = (source === "slash" || source === "text") ? source : "other"
if (permsRes.reason == "blacklist") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-blacklisted").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user}))
else if (permsRes.reason == "cooldown") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-cooldown").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,until:permsRes.cooldownUntil}))
else if (permsRes.reason == "global-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"}))
else if (permsRes.reason == "global-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"}))
else if (permsRes.reason == "option-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"}))
else if (permsRes.reason == "option-user-limit") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"}))
else if (permsRes.reason == "custom") instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,layout:"simple",error:permsRes.customReason ?? lang.getTranslation("errors.descriptions.unableToCreateTicket")+" `Unknown invalid_permission_reason => no reason specified by plugin`",customTitle:lang.getTranslation("errors.titles.permissionError")}))
else instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newSource,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"}))
const newOrigin = (origin === "slash" || origin === "text") ? origin : "other"
if (permsRes.reason == "blacklist") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-blacklisted").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
else if (permsRes.reason == "cooldown") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-cooldown").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,until:permsRes.cooldownUntil}))
else if (permsRes.reason == "global-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global"}))
else if (permsRes.reason == "global-user-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"global-user"}))
else if (permsRes.reason == "option-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option"}))
else if (permsRes.reason == "option-user-limit") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-no-permissions-limits").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,limit:"option-user"}))
else if (permsRes.reason == "custom") await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,layout:"simple",error:permsRes.customReason ?? lang.getTranslation("errors.descriptions.unableToCreateTicket")+" `Unknown invalid_permission_reason => no reason specified by plugin`",customTitle:lang.getTranslation("errors.titles.permissionError")}))
else await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(newOrigin,{guild:instance.guild,channel:instance.channel,user:instance.user,error:"Unknown invalid_permission reason => calculation failed #1",layout:"advanced"}))
return false
}else return true
}
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//TICKET COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:ticket",generalConfig.data.prefix,/^ticket/))
opendiscord.responders.commands.get("opendiscord:ticket").workers.add([
new api.ODWorker("opendiscord:ticket",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.ticket,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"ticket")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//get option data
const optionId = instance.options.getString("id",true)
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
//start ticket creation
if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){
//send modal
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build(source,{guild,channel,user,option}))
//SEND MODAL
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build(origin,{guild,channel,user,option}))
}else{
//check ticket permissions
if (!(await checkTicketCreationPerms(instance,source,guild,user,option))) return cancel()
//create ticket
//check ticket permissions (modals need check after submit)
if (!(await checkTicketCreationPerms(instance,origin,guild,user,option))) return cancel()
//CREATE TICKET
await instance.defer(true)
const res = await opendiscord.actions.get("opendiscord:create-ticket").run(source,{guild,user,answers:[],option})
const res = await opendiscord.actions.get("opendiscord:create-ticket").run(origin,{guild,user,answers:[],option})
if (!res.channel || !res.ticket){
//error
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"}))
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()
}
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(source,{guild,channel:res.channel,user,ticket:res.ticket}))
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:ticket-created").build(origin,{guild,channel:res.channel,user,ticket:res.ticket}))
}
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'ticket' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//TICKET OPTION BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:ticket-option",/^od:ticket-option_/))
opendiscord.responders.buttons.get("opendiscord:ticket-option").workers.add(
new api.ODWorker("opendiscord:ticket-option",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:ticket-option",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//responder checks
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//get option
//get option data
const optionId = instance.interaction.customId.split("_")[2]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
//start ticket creation
if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){
//send modal
//SEND MODAL
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build("panel-button",{guild,channel,user,option}))
}else{
//check ticket permissions
//check ticket permissions (modals need check after submit)
if (!(await checkTicketCreationPerms(instance,"panel-button",guild,user,option))) return cancel()
//create ticket
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
//CREATE TICKET
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){
//error
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"}))
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}))
}
})
)
}
export const registerDropdownResponders = async () => {
export async function registerDropdownResponders(){
//PANEL DROPDOWN TICKETS DROPDOWN RESPONDER
opendiscord.responders.dropdowns.add(new api.ODDropdownResponder("opendiscord:panel-dropdown-tickets",/^od:panel-dropdown_/))
opendiscord.responders.dropdowns.get("opendiscord:panel-dropdown-tickets").workers.add(
new api.ODWorker("opendiscord:panel-dropdown-tickets",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:panel-dropdown-tickets",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel:instance.channel,user:instance.user}))
return cancel()
}
//responder checks
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
//get option
//get option data
const optionId = instance.values.getStringValues()[0].split("_")[2]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel:instance.channel,user:instance.user}))
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel:instance.channel,user:instance.user}))
return cancel()
}
//start ticket creation
if (option.exists("opendiscord:questions") && option.get("opendiscord:questions").value.length > 0){
//send modal
//SEND MODAL
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:ticket-questions").build("panel-dropdown",{guild,channel,user,option}))
}else{
//check ticket permissions
//check ticket permissions (modals need check after submit)
if (!(await checkTicketCreationPerms(instance,"panel-dropdown",guild,user,option))) return cancel()
//create ticket
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
//CREATE TICKET
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){
//error
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel:instance.channel,user,error:"Unable to receive ticket or channel from callback! #1",layout:"advanced"}))
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)
@@ -181,31 +169,29 @@ export const registerDropdownResponders = async () => {
)
}
export const registerModalResponders = async () => {
export async function registerModalResponders(){
//TICKET QUESTIONS RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:ticket-questions",/^od:ticket-questions_/))
opendiscord.responders.modals.get("opendiscord:ticket-questions").workers.add([
new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:ticket-questions",0,async (instance,params,origin,cancel) => {
const {guild,channel,user} = instance
await instance.defer((generalConfig.data.system.replyOnTicketCreation) ? "reply" : "update",true)
if (!channel) throw new api.ODSystemError("The 'Ticket Questions' modal requires a channel for responding!")
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
//responder checks
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const originalSource = instance.interaction.customId.split("_")[2] as ("panel-button"|"panel-dropdown"|"slash"|"text"|"other")
//get option
//get option data
const optionId = instance.interaction.customId.split("_")[1]
const option = opendiscord.options.get(optionId)
if (!option || !(option instanceof api.ODTicketOption)){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(source,{guild:instance.guild,channel,user:instance.user}))
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-option-unknown").build(origin,{guild:instance.guild,channel,user:instance.user}))
return cancel()
}
//check ticket permissions (modals need check after submit)
const originalOrigin = instance.interaction.customId.split("_")[2] as ("panel-button"|"panel-dropdown"|"slash"|"text"|"other")
if (!(await checkTicketCreationPerms(instance,originalOrigin,guild,user,option))) return cancel()
//get answers
const answers: {id:string,name:string,type:"short"|"paragraph",value:string|null}[] = []
option.get("opendiscord:questions").value.forEach((id) => {
@@ -227,18 +213,17 @@ export const registerModalResponders = async () => {
})
}
})
await instance.defer((generalConfig.data.ticketSystem.replyOnTicketCreation) ? "reply" : "update",true)
//check ticket permissions
if (!(await checkTicketCreationPerms(instance,originalSource,guild,user,option))) return cancel()
//create ticket
const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalSource,{guild,user,answers,option})
//CREATE TICKET
const res = await opendiscord.actions.get("opendiscord:create-ticket").run(originalOrigin,{guild,user,answers,option})
if (!res.channel || !res.ticket){
//error
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build(source,{guild,channel,user,error:"Unable to receive ticket or channel from callback! #2",layout:"advanced"}))
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(originalSource,{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}))
})
])
}
+19 -34
View File
@@ -1,44 +1,29 @@
///////////////////////////////////////
//TOPIC COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//TOPIC COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:topic",generalConfig.data.prefix,"topic"))
opendiscord.responders.commands.get("opendiscord:topic").workers.add([
new api.ODWorker("opendiscord:topic",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:topic",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.topic,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/Server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"topic")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//subcommands
const scope = instance.options.getSubCommand()
@@ -48,16 +33,16 @@ export const registerCommandResponders = async () => {
const topic = instance.options.getString("topic",true)
//start changing ticket topic
await instance.defer(false)
await opendiscord.actions.get("opendiscord:update-ticket-topic").run(source,{guild,channel,user,ticket,newTopic:topic,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(source,{guild,channel,user,ticket,topic}))
await opendiscord.actions.get("opendiscord:update-ticket-topic").run(origin,{guild,channel,user,ticket,newTopic:topic,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:topic-set").build(origin,{guild,channel,user,ticket,topic}))
}
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'topic set' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+21 -34
View File
@@ -1,60 +1,47 @@
///////////////////////////////////////
//TRANSFER COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//TRANSFER COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:transfer",generalConfig.data.prefix,"transfer"))
opendiscord.responders.commands.get("opendiscord:transfer").workers.add([
new api.ODWorker("opendiscord:transfer",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:transfer",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.transfer,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/Server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"transfer")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
//fetch data
const oldCreator = await opendiscord.tickets.getTicketUser(ticket,"creator") ?? opendiscord.client.client.user
const newCreator = instance.options.getUser("user",true)
const reason = instance.options.getString("reason",false)
//start transferring ticket ownership
await instance.defer(false)
await opendiscord.actions.get("opendiscord:transfer-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false,newCreator})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(source,{guild,channel,user,ticket,oldCreator,newCreator,reason}))
await opendiscord.actions.get("opendiscord:transfer-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false,newCreator})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:transfer-message").build(origin,{guild,channel,user,ticket,oldCreator,newCreator,reason}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'transfer' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
+192 -75
View File
@@ -1,116 +1,233 @@
///////////////////////////////////////
//UNCLAIM COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//UNCLAIM COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:unclaim",generalConfig.data.prefix,"unclaim"))
opendiscord.responders.commands.get("opendiscord:unclaim").workers.add([
new api.ODWorker("opendiscord:unclaim",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:unclaim",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.unclaim,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/Server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not claimed
if (!ticket.get("opendiscord:claimed").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unclaim"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
const reason = instance.options.getString("reason",false)
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
if (!isTicketClaimed) return cancel()
//start unclaiming ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(source,{guild,channel,user,ticket,reason}))
const reason = instance.options.getString("reason",false)
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
//send message & set state
const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(origin,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"unclaim-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'unclaim' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//UNCLAIM TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unclaim-ticket",/^od:unclaim-ticket/))
opendiscord.responders.buttons.get("opendiscord:unclaim-ticket").workers.add(
new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,source,cancel) => {
const originalSource = instance.interaction.customId.split("_")[1] as Exclude<api.ODActionManagerIds_Default["opendiscord:unclaim-ticket"]["source"],"slash"|"text">
new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,message} = instance
if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unclaim-ticket-ticket-message").activate(instance)
else if (originalSource == "claim-message") await opendiscord.verifybars.get("opendiscord:unclaim-ticket-claim-message").activate(instance)
else await instance.defer("update",false)
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unclaim")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
if (!isTicketClaimed) return cancel()
//fetch state details
const verifybar = opendiscord.verifybars.get("opendiscord:unclaim-ticket")
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
}else if (originalMsgType == "ticket-message"){
//ticket message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unclaim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "claim-message"){
//claim message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unclaim-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:claim-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
})
)
}
export const registerModalResponders = async () => {
export async function registerVerifyBars(){
//UNCLAIM TICKET
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unclaim-ticket"))
opendiscord.verifybars.get("opendiscord:unclaim-ticket").workers.add([
new api.ODWorker("opendiscord:unclaim-ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unclaim")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
if (!isTicketClaimed) return cancel()
//fetch state details
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//start unclaiming ticket
if (params.selectedButtonId == "cancel"){
//CANCEL
if (originalMsgType == "ticket-message"){
//ticket message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "claim-message"){
//claim message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:claim-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
}else if (params.selectedButtonId == "accept"){
//UNCLAIM TICKET
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "claim-message"){
//converted to unclaim message
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"unclaim-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:null
},sentMsg.ephemeral)
}
}else if (params.selectedButtonId == "accept-with-reason"){
//UNCLAIM WITH REASON (MODAL)
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unclaim-ticket-reason").build("other",{guild,channel,user,ticket,message}))
}
})
])
}
export async function registerModalResponders(){
//UNCLAIM WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unclaim-ticket-reason",/^od:unclaim-ticket-reason_/))
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unclaim-ticket-reason",/^od:unclaim-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:unclaim-ticket-reason").workers.add([
new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!channel) return
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
new api.ODWorker("opendiscord:unclaim-ticket-reason",0,async (instance,params,origin,cancel) => {
const {guild,user} = instance
const match = /^od:unclaim-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const channel = await opendiscord.client.fetchTextChannel(match[1])
const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unclaim")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const originalSource = instance.interaction.customId.split("_")[2] as Exclude<api.ODActionManagerIds_Default["opendiscord:unclaim-ticket"]["source"],"slash"|"text">
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unclaim")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketClaimed = await openticketUtils.replyTicketMustBeClaimed(instance,origin,ticket)
if (!isTicketClaimed) return cancel()
//fetch state details
const reason = instance.values.getTextField("reason",true)
const originalMsgOrigin = state.data.messageOrigin
const originalMsgType = state.data.messageType
//unclaim with reason
if (originalSource == "ticket-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
//start claiming ticket
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalSource == "claim-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build("other",{guild,channel,user,ticket,reason}))
}else{
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
}else if (originalMsgType == "claim-message"){
//converted to unclaim message
await opendiscord.actions.get("opendiscord:unclaim-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unclaim-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"unclaim-message",
messageOrigin:originalMsgOrigin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}
})
])
+193 -76
View File
@@ -1,116 +1,233 @@
///////////////////////////////////////
//UNPIN COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import {opendiscord, api, utilities, openticketUtils} from "../index.js"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
const lang = opendiscord.languages
const interactiveMsgState = opendiscord.states.get("opendiscord:interactive-message")
export const registerCommandResponders = async () => {
export async function registerCommandResponders(){
//UNPIN COMMAND RESPONDER
opendiscord.responders.commands.add(new api.ODCommandResponder("opendiscord:unpin",generalConfig.data.prefix,"unpin"))
opendiscord.responders.commands.get("opendiscord:unpin").workers.add([
new api.ODWorker("opendiscord:unpin",0,async (instance,params,source,cancel) => {
new api.ODWorker("opendiscord:unpin",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild} = instance
//check permissions
const permsResult = await opendiscord.permissions.checkCommandPerms(generalConfig.data.system.permissions.unpin,"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(source,{guild,channel,user,permissions:["support"]}))
return cancel()
}
//check is in guild/Server
if (!guild){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user}))
return cancel()
}
//check if ticket exists
const ticket = opendiscord.tickets.get(channel.id)
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return cancel()
}
//return when not pinned yet
if (!ticket.get("opendiscord:pinned").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error").build("button",{guild,channel,user,error:opendiscord.languages.getTranslation("errors.actionInvalid.unpin"),layout:"simple"}))
return cancel()
}
//return when busy
if (ticket.get("opendiscord:busy").value){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-busy").build("button",{guild,channel,user}))
return cancel()
}
const reason = instance.options.getString("reason",false)
//start unpinning ticket
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
if (!isTicketPinned) return cancel()
//start unpining ticket
await instance.defer(false)
await opendiscord.actions.get("opendiscord:unpin-ticket").run(source,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(source,{guild,channel,user,ticket,reason}))
const reason = instance.options.getString("reason",false)
await opendiscord.actions.get("opendiscord:unpin-ticket").run(origin,{guild,channel,user,ticket,reason,sendMessage:false})
//send message & set state
const sentMsg = await instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(origin,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"unpin-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,cancel) => {
new api.ODWorker("opendiscord:logs",-1,(instance,params,origin,cancel) => {
opendiscord.log(instance.user.displayName+" used the 'unpin' command!","info",[
{key:"user",value:instance.user.username},
{key:"userid",value:instance.user.id,hidden:true},
{key:"channelid",value:instance.channel.id,hidden:true},
{key:"method",value:source}
{key:"method",value:origin}
])
})
])
}
export const registerButtonResponders = async () => {
export async function registerButtonResponders(){
//UNPIN TICKET BUTTON RESPONDER
opendiscord.responders.buttons.add(new api.ODButtonResponder("opendiscord:unpin-ticket",/^od:unpin-ticket/))
opendiscord.responders.buttons.get("opendiscord:unpin-ticket").workers.add(
new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,source,cancel) => {
const originalSource = instance.interaction.customId.split("_")[1] as Exclude<api.ODActionManagerIds_Default["opendiscord:unpin-ticket"]["source"],"slash"|"text">
new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,origin,cancel) => {
const {guild,channel,user,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
if (!hasPerms) return cancel()
if (originalSource == "ticket-message") await opendiscord.verifybars.get("opendiscord:unpin-ticket-ticket-message").activate(instance)
else if (originalSource == "pin-message") await opendiscord.verifybars.get("opendiscord:unpin-ticket-pin-message").activate(instance)
else await instance.defer("update",false)
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unpin")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
if (!isTicketPinned) return cancel()
//fetch state details
const verifybar = opendiscord.verifybars.get("opendiscord:unpin-ticket")
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//send verifybar
if (generalConfig.data.ticketSystem.disableVerifyBars){
//verifybar disabled, directly run response
await verifybar.activate(instance,"accept")
}else if (originalMsgType == "ticket-message"){
//ticket message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unpin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:ticket-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "pin-message"){
//pin message verifybar
const modifiedMsg = opendiscord.components.modifiers.get("opendiscord:unpin-ticket-verifybar").modify(opendiscord.builders.messages.getSafe("opendiscord:pin-message"),originalMsgType,{guild,channel,user,verifybar})
await instance.update(await modifiedMsg.build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
})
)
}
export const registerModalResponders = async () => {
export async function registerVerifyBars(){
//UNPIN TICKET
opendiscord.verifybars.add(new api.ODVerifyBar("opendiscord:unpin-ticket"))
opendiscord.verifybars.get("opendiscord:unpin-ticket").workers.add([
new api.ODWorker("opendiscord:unpin-ticket",0,async (instance,params,origin,cancel) => {
const {user,member,channel,guild,message} = instance
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || channel.isDMBased()) return cancel()
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unpin")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
if (!isTicketPinned) return cancel()
//fetch state details
const originalUser = ((state.data.messageAuthor) ? await opendiscord.client.fetchUser(state.data.messageAuthor) : user) ?? user
const originalReason = state.data.messageReason ?? null
const originalMsgType = state.data.messageType
//start unpinning ticket
if (params.selectedButtonId == "cancel"){
//CANCEL
if (originalMsgType == "ticket-message"){
//ticket message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "pin-message"){
//pin message
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:pin-message").build("verifybar",{guild,channel,user:originalUser,ticket,reason:originalReason}))
}
}else if (params.selectedButtonId == "accept"){
//UNPIN TICKET
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("verifybar",{guild,channel,user,ticket}))
}else if (originalMsgType == "pin-message"){
//converted to unpin message
await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("verifybar",{guild,channel,user,ticket,reason:null}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"unpin-message",
messageOrigin:origin,
messageAuthor:user.id,
messageReason:null
},sentMsg.ephemeral)
}
}else if (params.selectedButtonId == "accept-with-reason"){
//UNPIN WITH REASON (MODAL)
instance.modal(await opendiscord.builders.modals.getSafe("opendiscord:unpin-ticket-reason").build("other",{guild,channel,user,ticket,message}))
}
})
])
}
export async function registerModalResponders(){
//UNPIN WITH REASON MODAL RESPONDER
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unpin-ticket-reason",/^od:unpin-ticket-reason_/))
opendiscord.responders.modals.add(new api.ODModalResponder("opendiscord:unpin-ticket-reason",/^od:unpin-ticket-reason\|([^|]+)\|([^|]+)/))
opendiscord.responders.modals.get("opendiscord:unpin-ticket-reason").workers.add([
new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,source,cancel) => {
const {guild,channel,user} = instance
if (!channel) return
if (!guild){
//error
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build(source,{channel,user:instance.user}))
return cancel()
}
const ticket = opendiscord.tickets.get(instance.interaction.customId.split("_")[1])
if (!ticket || channel.isDMBased()){
instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-ticket-unknown").build("button",{guild,channel,user}))
return
}
new api.ODWorker("opendiscord:unpin-ticket-reason",0,async (instance,params,origin,cancel) => {
const {guild,user} = instance
const match = /^od:unpin-ticket-reason\|([^|]+)\|([^|]+)/.exec(instance.interaction.customId)
if (!match) return cancel()
const channel = await opendiscord.client.fetchTextChannel(match[1])
const message = await opendiscord.client.fetchChannelMessage(match[1],match[2])
//responder checks
const hasPerms = await openticketUtils.replyHasPermissions(instance,origin,"unpin")
if (!hasPerms) return cancel()
const isInGuild = await openticketUtils.replyIsInGuild(instance,origin)
if (!isInGuild || !guild || !channel || channel.isDMBased()) return cancel()
const originalSource = instance.interaction.customId.split("_")[2] as Exclude<api.ODActionManagerIds_Default["opendiscord:unpin-ticket"]["source"],"slash"|"text">
const state = await openticketUtils.replyInteractiveMessageState(instance,origin,channel,message,"/unpin")
if (!state) return cancel()
const ticket = await openticketUtils.replyIsTicket(instance,origin)
if (!ticket) return cancel()
const isAvailable = await openticketUtils.replyTicketIsAvailable(instance,origin,ticket)
if (!isAvailable) return cancel()
const isTicketPinned = await openticketUtils.replyTicketMustBePinned(instance,origin,ticket)
if (!isTicketPinned) return cancel()
//fetch state details
const reason = instance.values.getTextField("reason",true)
const originalMsgOrigin = state.data.messageOrigin
const originalMsgType = state.data.messageType
//unpin with reason
if (originalSource == "ticket-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
//start pinning ticket
await instance.defer("update",false)
if (originalMsgType == "ticket-message"){
//ticket message
await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:true})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build("other",{guild,channel,user,ticket}))
}else if (originalSource == "pin-message"){
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:false})
await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build("other",{guild,channel,user,ticket,reason}))
}else{
await instance.defer("update",false)
await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalSource,{guild,channel,user,ticket,reason,sendMessage:true})
}else if (originalMsgType == "pin-message"){
//converted to unpin message
await opendiscord.actions.get("opendiscord:unpin-ticket").run(originalMsgType,{guild,channel,user,ticket,reason:null,sendMessage:false})
const sentMsg = await instance.update(await opendiscord.builders.messages.getSafe("opendiscord:unpin-message").build(originalMsgType,{guild,channel,user,ticket,reason}))
if (sentMsg.success) await interactiveMsgState.setMsgState({channel,message:sentMsg.message},{
messageType:"unpin-message",
messageOrigin:originalMsgOrigin,
messageAuthor:user.id,
messageReason:reason
},sentMsg.ephemeral)
}
})
])
+13
View File
@@ -0,0 +1,13 @@
Open Discord Components:
------------------------
The "Components" system will be the new way of creating message and modal templates in Open Discord with support for Discord components v2.
Messages, embeds, modals, buttons, etc are currently constructed using the "Builders" system located in `./src/builders/...`.
This will be replaced with the new component factories in `./src/components/...`.
### Timing
Messages, modals & components will slowly be migrated to the new system during upcoming updates. The full migration will happen after `Open Ticket v4.3` and the HTML Transcripts v3 are ready for it.
For more information, contact [DJj123dj](https://github.com/DJj123dj) on Discord, Github or via email
+138
View File
@@ -0,0 +1,138 @@
///////////////////////////////////////
//VERIFYBAR MESSAGE MODIFIERS
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index.js"
import * as discord from "discord.js"
const modifiers = opendiscord.components.modifiers
const lang = opendiscord.languages
const generalConfig = opendiscord.configs.get("opendiscord:general")
export async function addVerifyButton(instance:api.ODMessageInstance|api.ODComponentFactoryInstance<api.ODMessageComponent>,params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:api.ODVerifyBar<string>},defaultButtonType:"✅"|"❌",useDefaultLabels:boolean,verifyButtonId:string,customLabel?:string,customColor?:api.ODValidButtonColor,customEmoji?:string){
const {guild,channel,user,verifybar} = params
if (instance instanceof api.ODMessageInstance){
//message builders
instance.addComponent(await opendiscord.builders.buttons.getSafe("opendiscord:verifybar-button").build("verifybar",{
guild,channel,user,verifybar,
defaultButtonType,useDefaultLabels,customColor,customEmoji,customLabel,
verifyButtonId
}))
}else{
//message components
throw new api.ODSystemError("registerAllVerifyBarModifiers addVerifyButton() => verifybar doesn't support ODComponents v2 yet!")
//const message = instance.getComponent()
//if (!message) return
//const actionRow: api.ODActionRowComponent|null = message.getComponentsOfType("action-row")[0]
//if (actionRow) actionRow.addComponent(new api.ODButtonComponent("opendiscord:verifybar-button",{
// //TODO
//}),"end")
}
}
export async function registerAllVerifyBarModifiers(){
//CLOSE TICKET VERIFYBAR
modifiers.add(new api.ODMessageComponentModifier("opendiscord:close-ticket-verifybar"))
modifiers.get("opendiscord:close-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:close-ticket-verifybar",100,async (instance,params,origin,cancel) => {
if (instance instanceof api.ODMessageInstance){
instance.data.components = [] //clear actionrow
}else{
throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
}
//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.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//REOPEN TICKET VERIFYBAR
modifiers.add(new api.ODMessageComponentModifier("opendiscord:reopen-ticket-verifybar"))
modifiers.get("opendiscord:reopen-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:reopen-ticket-verifybar",100,async (instance,params,origin,cancel) => {
if (instance instanceof api.ODMessageInstance){
instance.data.components = [] //clear actionrow
}else{
throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
}
//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.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//DELETE TICKET VERIFYBAR
modifiers.add(new api.ODMessageComponentModifier("opendiscord:delete-ticket-verifybar"))
modifiers.get("opendiscord:delete-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:delete-ticket-verifybar",100,async (instance,params,origin,cancel) => {
if (instance instanceof api.ODMessageInstance){
instance.data.components = [] //clear actionrow
}else{
throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
}
//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.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
modifiers.add(new api.ODMessageComponentModifier("opendiscord:claim-ticket-verifybar"))
modifiers.get("opendiscord:claim-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:claim-ticket-verifybar",100,async (instance,params,origin,cancel) => {
if (instance instanceof api.ODMessageInstance){
instance.data.components = [] //clear actionrow
}else{
throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
}
//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.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//UNCLAIM TICKET VERIFYBAR
modifiers.add(new api.ODMessageComponentModifier("opendiscord:unclaim-ticket-verifybar"))
modifiers.get("opendiscord:unclaim-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:unclaim-ticket-verifybar",100,async (instance,params,origin,cancel) => {
if (instance instanceof api.ODMessageInstance){
instance.data.components = [] //clear actionrow
}else{
throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
}
//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.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//PIN TICKET VERIFYBAR
modifiers.add(new api.ODMessageComponentModifier("opendiscord:pin-ticket-verifybar"))
modifiers.get("opendiscord:pin-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:pin-ticket-verifybar",100,async (instance,params,origin,cancel) => {
if (instance instanceof api.ODMessageInstance){
instance.data.components = [] //clear actionrow
}else{
throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
}
//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.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
//UNPIN TICKET VERIFYBAR
modifiers.add(new api.ODMessageComponentModifier("opendiscord:unpin-ticket-verifybar"))
modifiers.get("opendiscord:unpin-ticket-verifybar").workers.add(new api.ODWorker("opendiscord:unpin-ticket-verifybar",100,async (instance,params,origin,cancel) => {
if (instance instanceof api.ODMessageInstance){
instance.data.components = [] //clear actionrow
}else{
throw new api.ODSystemError("registerAllVerifyBarModifiers()... => verifybars don't support ODComponents v2 yet!")
}
//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.ticketSystem.enableTicketActionWithReason) await addVerifyButton(instance,params,"✅",false,api.ODVerifyButtonId.AcceptWithReason,lang.getTranslation("actions.buttons.withReason"),"blue","✏️")
}))
}
+43
View File
@@ -0,0 +1,43 @@
//EXPORT FRAMEWORK
export * from "@open-discord-bots/framework/api"
//EXPORT OPEN TICKET MAPPINGS
export * from "./mappings/action.js"
export * from "./mappings/base.js"
export * from "./mappings/builder.js"
export * from "./mappings/checker.js"
export * from "./mappings/client.js"
export * from "./mappings/code.js"
export * from "./mappings/component.js"
export * from "./mappings/config.js"
export * from "./mappings/console.js"
export * from "./mappings/cooldown.js"
export * from "./mappings/database.js"
export * from "./mappings/event.js"
export * from "./mappings/flag.js"
export * from "./mappings/fuse.js"
export * from "./mappings/helpmenu.js"
export * from "./mappings/language.js"
export * from "./mappings/permission.js"
export * from "./mappings/plugin.js"
export * from "./mappings/post.js"
export * from "./mappings/progressbar.js"
export * from "./mappings/responder.js"
export * from "./mappings/session.js"
export * from "./mappings/startscreen.js"
export * from "./mappings/state.js"
export * from "./mappings/statistic.js"
export * from "./mappings/verifybar.js"
//EXPORT OPENTICKET MODULES
export * from "./api/blacklist.js"
export * from "./api/option.js"
export * from "./api/panel.js"
export * from "./api/priority.js"
export * from "./api/question.js"
export * from "./api/role.js"
export * from "./api/ticket.js"
export * from "./api/transcript.js"
//EXPORT MAIN MODULE
export { ODOpenTicketMain } from "./main.js"
-64
View File
@@ -1,64 +0,0 @@
//MAIN MODULE
export * from "./main"
//BASE MODULES
export * from "./modules/base"
export * from "./modules/event"
export * from "./modules/config"
export * from "./modules/database"
export * from "./modules/language"
export * from "./modules/flag"
export * from "./modules/console"
export * from "./modules/defaults"
export * from "./modules/plugin"
export * from "./modules/checker"
export * from "./modules/client"
export * from "./modules/worker"
export * from "./modules/builder"
export * from "./modules/responder"
export * from "./modules/action"
export * from "./modules/permission"
export * from "./modules/helpmenu"
export * from "./modules/session"
export * from "./modules/stat"
export * from "./modules/code"
export * from "./modules/cooldown"
export * from "./modules/post"
export * from "./modules/verifybar"
export * from "./modules/progressbar"
export * from "./modules/startscreen"
//OPENTICKET DEFAULT MODULES
export * from "./defaults/base"
export * from "./defaults/event"
export * from "./defaults/config"
export * from "./defaults/database"
export * from "./defaults/plugin"
export * from "./defaults/checker"
export * from "./defaults/client"
export * from "./defaults/language"
export * from "./defaults/builder"
export * from "./defaults/responder"
export * from "./defaults/action"
export * from "./defaults/flag"
export * from "./defaults/permission"
export * from "./defaults/helpmenu"
export * from "./defaults/session"
export * from "./defaults/stat"
export * from "./defaults/worker"
export * from "./defaults/code"
export * from "./defaults/cooldown"
export * from "./defaults/post"
export * from "./defaults/progressbar"
export * from "./defaults/startscreen"
export * from "./defaults/console"
//OPENTICKET MODULES
export * from "./openticket/question"
export * from "./openticket/option"
export * from "./openticket/panel"
export * from "./openticket/ticket"
export * from "./openticket/blacklist"
export * from "./openticket/transcript"
export * from "./openticket/role"
export * from "./openticket/priority"
@@ -1,8 +1,7 @@
///////////////////////////////////////
//OPENTICKET BLACKLIST MODULE
///////////////////////////////////////
import { ODManager, ODManagerData, ODValidId } from "../modules/base"
import { ODDebugger } from "../modules/console"
import * as api from "@open-discord-bots/framework/api"
/**## ODBlacklist `class`
* This is an Open Ticket blacklisted user.
@@ -11,22 +10,22 @@ import { ODDebugger } from "../modules/console"
*
* Create this class & add it to the `ODBlacklistManager` to blacklist someone!
*/
export class ODBlacklist extends ODManagerData {
export class ODBlacklist extends api.ODManagerData {
/**The reason why this user got blacklisted. (optional) */
#reason: string|null
private rawReason: string|null
constructor(id:ODValidId,reason:string|null){
constructor(id:api.ODValidId,reason:string|null){
super(id)
this.#reason = reason
this.rawReason = reason
}
/**The reason why this user got blacklisted. (optional) */
set reason(reason:string|null) {
this.#reason = reason
this.rawReason = reason
this._change()
}
get reason(){
return this.#reason
return this.rawReason
}
}
@@ -37,8 +36,8 @@ export class ODBlacklist extends ODManagerData {
*
* All `ODBlacklist`'s added, removed & edited in this list will be synced automatically with the database.
*/
export class ODBlacklistManager extends ODManager<ODBlacklist> {
constructor(debug:ODDebugger){
export class ODBlacklistManager extends api.ODManager<ODBlacklist> {
constructor(debug:api.ODDebugger){
super(debug,"blacklist")
}
}
-45
View File
@@ -1,45 +0,0 @@
///////////////////////////////////////
//BASE MODULE
///////////////////////////////////////
import { ODVersion, ODVersionManager, ODValidId } from "../modules/base"
/**## ODVersionManagerIds_Default `interface`
* This interface is a list of ids available in the `ODVersionManager` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODVersionManagerIds_Default {
"opendiscord:version":ODVersion,
"opendiscord:last-version":ODVersion,
"opendiscord:api":ODVersion,
"opendiscord:transcripts":ODVersion,
"opendiscord:livestatus":ODVersion
}
/**## ODFlagManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFlagManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.flags`!
*/
export class ODVersionManager_Default extends ODVersionManager {
get<VersionId extends keyof ODVersionManagerIds_Default>(id:VersionId): ODVersionManagerIds_Default[VersionId]
get(id:ODValidId): ODVersion|null
get(id:ODValidId): ODVersion|null {
return super.get(id)
}
remove<VersionId extends keyof ODVersionManagerIds_Default>(id:VersionId): ODVersionManagerIds_Default[VersionId]
remove(id:ODValidId): ODVersion|null
remove(id:ODValidId): ODVersion|null {
return super.remove(id)
}
exists(id:keyof ODVersionManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-549
View File
@@ -1,549 +0,0 @@
///////////////////////////////////////
//DEFAULT BUILDER MODULE
///////////////////////////////////////
import { ODValidButtonColor, ODValidId } from "../modules/base"
import { ODBuilderManager, ODButton, ODButtonInstance, ODButtonManager, ODDropdown, ODDropdownInstance, ODDropdownManager, ODEmbed, ODEmbedInstance, ODEmbedManager, ODFile, ODFileInstance, ODFileManager, ODMessage, ODMessageInstance, ODMessageManager, ODModal, ODModalInstance, ODModalManager } from "../modules/builder"
import { ODWorkerManager_Default } from "./worker"
import { ODTicket, ODTicketClearFilter } from "../openticket/ticket"
import { ODPermissionEmbedType } from "../defaults/permission"
import { ODTextCommandErrorInvalidOption, ODTextCommandErrorMissingOption, ODTextCommandErrorUnknownCommand } from "../modules/client"
import { ODPanel } from "../openticket/panel"
import { ODRoleOption, ODTicketOption, ODWebsiteOption } from "../openticket/option"
import { ODVerifyBar } from "../modules/verifybar"
import * as discord from "discord.js"
import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript"
import { ODRole, ODRoleUpdateResult } from "../openticket/role"
import { ODPriorityLevel } from "../openticket/priority"
/**## ODBuilderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODBuilderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.builders`!
*/
export class ODBuilderManager_Default extends ODBuilderManager {
declare buttons: ODButtonManager_Default
declare dropdowns: ODDropdownManager_Default
declare files: ODFileManager_Default
declare embeds: ODEmbedManager_Default
declare messages: ODMessageManager_Default
declare modals: ODModalManager_Default
}
/**## ODButtonManagerIds_Default `interface`
* This interface is a list of ids available in the `ODButtonManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODButtonManagerIds_Default {
"opendiscord:verifybar-success":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"opendiscord:verifybar-success"},
"opendiscord:verifybar-failure":{source:"verifybar"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,customData?:string,customColor?:ODValidButtonColor,customLabel?:string,customEmoji?:string},workers:"opendiscord:verifybar-failure"},
"opendiscord:error-ticket-deprecated-transcript":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{},workers:"opendiscord:error-ticket-deprecated-transcript"},
"opendiscord:help-menu-previous":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-previous"},
"opendiscord:help-menu-next":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-next"},
"opendiscord:help-menu-page":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-page"}
"opendiscord:help-menu-switch":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu-switch"},
"opendiscord:ticket-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODTicketOption},workers:"opendiscord:ticket-option"},
"opendiscord:website-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODWebsiteOption},workers:"opendiscord:website-option"},
"opendiscord:role-option":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,option:ODRoleOption},workers:"opendiscord:role-option"}
"opendiscord:visit-ticket":{source:"ticket-created"|"dm"|"logs"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:visit-ticket"},
"opendiscord:close-ticket":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:close-ticket"},
"opendiscord:delete-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:delete-ticket"},
"opendiscord:reopen-ticket":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:reopen-ticket"},
"opendiscord:claim-ticket":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:claim-ticket"},
"opendiscord:unclaim-ticket":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unclaim-ticket"},
"opendiscord:pin-ticket":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:pin-ticket"},
"opendiscord:unpin-ticket":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unpin-ticket"},
"opendiscord:transcript-html-visit":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-visit"},
"opendiscord:transcript-error-retry":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error-retry"},
"opendiscord:transcript-error-continue":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error-continue"},
"opendiscord:clear-continue":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-continue"},
}
/**## ODButtonManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButtonManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.builders.buttons`!
*/
export class ODButtonManager_Default extends ODButtonManager {
get<ButtonId extends keyof ODButtonManagerIds_Default>(id:ButtonId): ODButton_Default<ODButtonManagerIds_Default[ButtonId]["source"],ODButtonManagerIds_Default[ButtonId]["params"],ODButtonManagerIds_Default[ButtonId]["workers"]>
get(id:ODValidId): ODButton<string,any>|null
get(id:ODValidId): ODButton<string,any>|null {
return super.get(id)
}
remove<ButtonId extends keyof ODButtonManagerIds_Default>(id:ButtonId): ODButton_Default<ODButtonManagerIds_Default[ButtonId]["source"],ODButtonManagerIds_Default[ButtonId]["params"],ODButtonManagerIds_Default[ButtonId]["workers"]>
remove(id:ODValidId): ODButton<string,any>|null
remove(id:ODValidId): ODButton<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODButtonManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<ButtonId extends keyof ODButtonManagerIds_Default>(id:ButtonId): ODButton_Default<ODButtonManagerIds_Default[ButtonId]["source"],ODButtonManagerIds_Default[ButtonId]["params"],ODButtonManagerIds_Default[ButtonId]["workers"]>
getSafe(id:ODValidId): ODButton<string,any>
getSafe(id:ODValidId): ODButton<string,any> {
return super.getSafe(id)
}
}
/**## ODButton_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButton class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODButton`'s!
*/
export class ODButton_Default<Source extends string, Params, WorkerIds extends string> extends ODButton<Source,Params> {
declare workers: ODWorkerManager_Default<ODButtonInstance,Source,Params,WorkerIds>
}
/**## ODDropdownManagerIds_Default `interface`
* This interface is a list of ids available in the `ODDropdownManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDropdownManagerIds_Default {
"opendiscord:panel-dropdown-tickets":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel,options:ODTicketOption[]},workers:"opendiscord:panel-dropdown-tickets"}
}
/**## ODDropdownManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdownManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.builders.dropdowns`!
*/
export class ODDropdownManager_Default extends ODDropdownManager {
get<DropdownId extends keyof ODDropdownManagerIds_Default>(id:DropdownId): ODDropdown_Default<ODDropdownManagerIds_Default[DropdownId]["source"],ODDropdownManagerIds_Default[DropdownId]["params"],ODDropdownManagerIds_Default[DropdownId]["workers"]>
get(id:ODValidId): ODDropdown<string,any>|null
get(id:ODValidId): ODDropdown<string,any>|null {
return super.get(id)
}
remove<DropdownId extends keyof ODDropdownManagerIds_Default>(id:DropdownId): ODDropdown_Default<ODDropdownManagerIds_Default[DropdownId]["source"],ODDropdownManagerIds_Default[DropdownId]["params"],ODDropdownManagerIds_Default[DropdownId]["workers"]>
remove(id:ODValidId): ODDropdown<string,any>|null
remove(id:ODValidId): ODDropdown<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODDropdownManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<DropdownId extends keyof ODDropdownManagerIds_Default>(id:DropdownId): ODDropdown_Default<ODDropdownManagerIds_Default[DropdownId]["source"],ODDropdownManagerIds_Default[DropdownId]["params"],ODDropdownManagerIds_Default[DropdownId]["workers"]>
getSafe(id:ODValidId): ODDropdown<string,any>
getSafe(id:ODValidId): ODDropdown<string,any> {
return super.getSafe(id)
}
}
/**## ODDropdown_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdown class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODDropdown`'s!
*/
export class ODDropdown_Default<Source extends string, Params, WorkerIds extends string> extends ODDropdown<Source,Params> {
declare workers: ODWorkerManager_Default<ODDropdownInstance,Source,Params,WorkerIds>
}
/**## ODFileManagerIds_Default `interface`
* This interface is a list of ids available in the `ODFileManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFileManagerIds_Default {
"opendiscord:text-transcript":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,result:ODTranscriptCompilerCompileResult<any>},workers:"opendiscord:text-transcript"}
}
/**## ODFileManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFileManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.builders.files`!
*/
export class ODFileManager_Default extends ODFileManager {
get<FileId extends keyof ODFileManagerIds_Default>(id:FileId): ODFile_Default<ODFileManagerIds_Default[FileId]["source"],ODFileManagerIds_Default[FileId]["params"],ODFileManagerIds_Default[FileId]["workers"]>
get(id:ODValidId): ODFile<string,any>|null
get(id:ODValidId): ODFile<string,any>|null {
return super.get(id)
}
remove<FileId extends keyof ODFileManagerIds_Default>(id:FileId): ODFile_Default<ODFileManagerIds_Default[FileId]["source"],ODFileManagerIds_Default[FileId]["params"],ODFileManagerIds_Default[FileId]["workers"]>
remove(id:ODValidId): ODFile<string,any>|null
remove(id:ODValidId): ODFile<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODFileManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<FileId extends keyof ODFileManagerIds_Default>(id:FileId): ODFile_Default<ODFileManagerIds_Default[FileId]["source"],ODFileManagerIds_Default[FileId]["params"],ODFileManagerIds_Default[FileId]["workers"]>
getSafe(id:ODValidId): ODFile<string,any>
getSafe(id:ODValidId): ODFile<string,any> {
return super.getSafe(id)
}
}
/**## ODFile_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFile class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODFile`'s!
*/
export class ODFile_Default<Source extends string, Params, WorkerIds extends string> extends ODFile<Source,Params> {
declare workers: ODWorkerManager_Default<ODFileInstance,Source,Params,WorkerIds>
}
/**## ODEmbedManagerIds_Default `interface`
* This interface is a list of ids available in the `ODEmbedManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODEmbedManagerIds_Default {
"opendiscord:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced",customTitle?:string},workers:"opendiscord:error"},
"opendiscord:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"opendiscord:error-option-missing"},
"opendiscord:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"opendiscord:error-option-invalid"},
"opendiscord:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"opendiscord:error-unknown-command"},
"opendiscord:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"opendiscord:error-no-permissions"},
"opendiscord:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"opendiscord:error-no-permissions-cooldown"},
"opendiscord:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-no-permissions-blacklisted"},
"opendiscord:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"opendiscord:error-no-permissions-limits"},
"opendiscord:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-responder-timeout"},
"opendiscord:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-unknown"},
"opendiscord:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-deprecated"},
"opendiscord:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-option-unknown"},
"opendiscord:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-panel-unknown"},
"opendiscord:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-not-in-guild"},
"opendiscord:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"ticket-priority"|"ticket-transfer"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"opendiscord:error-channel-rename"},
"opendiscord:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-busy"},
"opendiscord:help-menu":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu"},
"opendiscord:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:stats-global"},
"opendiscord:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"opendiscord:stats-ticket"},
"opendiscord:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"opendiscord:stats-user"|"opendiscord:easter-egg"},
"opendiscord:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"opendiscord:stats-reset"},
"opendiscord:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"opendiscord:stats-ticket-unknown"},
"opendiscord:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel"},
"opendiscord:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created"},
"opendiscord:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-dm"},
"opendiscord:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-logs"},
"opendiscord:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-message"},
"opendiscord:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:close-message"},
"opendiscord:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:reopen-message"},
"opendiscord:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:delete-message"},
"opendiscord:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:claim-message"},
"opendiscord:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unclaim-message"},
"opendiscord:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:pin-message"},
"opendiscord:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unpin-message"},
"opendiscord:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"opendiscord:rename-message"},
"opendiscord:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"opendiscord:move-message"},
"opendiscord:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:add-message"},
"opendiscord:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:remove-message"},
"opendiscord:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-dm"},
"opendiscord:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-logs"},
"opendiscord:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:blacklist-view"},
"opendiscord:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"opendiscord:blacklist-get"},
"opendiscord:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-add"},
"opendiscord:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-remove"}
"opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"},
"opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"},
"opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string},null>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"},
"opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-ready"},
"opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"},
"opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error"},
"opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"},
"opendiscord:reaction-role-dm":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-dm"},
"opendiscord:reaction-role-logs":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-logs"},
"opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"},
"opendiscord:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-message"},
"opendiscord:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-logs"},
"opendiscord:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autoclose-message"},
"opendiscord:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autodelete-message"},
"opendiscord:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autoclose-enable"},
"opendiscord:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autodelete-enable"},
"opendiscord:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autoclose-disable"},
"opendiscord:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autodelete-disable"},
"opendiscord:topic-set":{source:"slash"|"text"|"ticket-action"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,topic:string},workers:"opendiscord:topic-set"},
"opendiscord:priority-set":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel,reason:string|null},workers:"opendiscord:priority-set"},
"opendiscord:priority-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel},workers:"opendiscord:priority-get"},
"opendiscord:transfer-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,oldCreator:discord.User,newCreator:discord.User,reason:string|null},workers:"opendiscord:transfer-message"},
}
/**## ODEmbedManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEmbedManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.builders.embeds`!
*/
export class ODEmbedManager_Default extends ODEmbedManager {
get<EmbedId extends keyof ODEmbedManagerIds_Default>(id:EmbedId): ODEmbed_Default<ODEmbedManagerIds_Default[EmbedId]["source"],ODEmbedManagerIds_Default[EmbedId]["params"],ODEmbedManagerIds_Default[EmbedId]["workers"]>
get(id:ODValidId): ODEmbed<string,any>|null
get(id:ODValidId): ODEmbed<string,any>|null {
return super.get(id)
}
remove<EmbedId extends keyof ODEmbedManagerIds_Default>(id:EmbedId): ODEmbed_Default<ODEmbedManagerIds_Default[EmbedId]["source"],ODEmbedManagerIds_Default[EmbedId]["params"],ODEmbedManagerIds_Default[EmbedId]["workers"]>
remove(id:ODValidId): ODEmbed<string,any>|null
remove(id:ODValidId): ODEmbed<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODEmbedManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<EmbedId extends keyof ODEmbedManagerIds_Default>(id:EmbedId): ODEmbed_Default<ODEmbedManagerIds_Default[EmbedId]["source"],ODEmbedManagerIds_Default[EmbedId]["params"],ODEmbedManagerIds_Default[EmbedId]["workers"]>
getSafe(id:ODValidId): ODEmbed<string,any>
getSafe(id:ODValidId): ODEmbed<string,any> {
return super.getSafe(id)
}
}
/**## ODEmbed_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEmbed class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODEmbed`'s!
*/
export class ODEmbed_Default<Source extends string, Params, WorkerIds extends string> extends ODEmbed<Source,Params> {
declare workers: ODWorkerManager_Default<ODEmbedInstance,Source,Params,WorkerIds>
}
/**## ODMessageManagerIds_Default `interface`
* This interface is a list of ids available in the `ODMessageManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODMessageManagerIds_Default {
"opendiscord:verifybar-ticket-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-ticket-message"},
"opendiscord:verifybar-close-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-close-message"},
"opendiscord:verifybar-reopen-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-reopen-message"},
"opendiscord:verifybar-claim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-claim-message"},
"opendiscord:verifybar-unclaim-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-unclaim-message"},
"opendiscord:verifybar-pin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-pin-message"},
"opendiscord:verifybar-unpin-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-unpin-message"}
"opendiscord:verifybar-autoclose-message":{source:"verifybar",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,verifybar:ODVerifyBar,originalMessage:discord.Message<boolean>},workers:"opendiscord:verifybar-autoclose-message"}
"opendiscord:error":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:string,layout:"simple"|"advanced",customTitle?:string},workers:"opendiscord:error"},
"opendiscord:error-option-missing":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorMissingOption},workers:"opendiscord:error-option-missing"},
"opendiscord:error-option-invalid":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorInvalidOption},workers:"opendiscord:error-option-invalid"},
"opendiscord:error-unknown-command":{source:"slash"|"text"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,error:ODTextCommandErrorUnknownCommand},workers:"opendiscord:error-unknown-command"},
"opendiscord:error-no-permissions":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,permissions:ODPermissionEmbedType[]},workers:"opendiscord:error-no-permissions"},
"opendiscord:error-no-permissions-cooldown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,until?:Date},workers:"opendiscord:error-no-permissions-cooldown"},
"opendiscord:error-no-permissions-blacklisted":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-no-permissions-blacklisted"},
"opendiscord:error-no-permissions-limits":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,limit:"global"|"global-user"|"option"|"option-user"},workers:"opendiscord:error-no-permissions-limits"},
"opendiscord:error-responder-timeout":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-responder-timeout"},
"opendiscord:error-ticket-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-unknown"},
"opendiscord:error-ticket-deprecated":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-deprecated"},
"opendiscord:error-option-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-option-unknown"},
"opendiscord:error-panel-unknown":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-panel-unknown"},
"opendiscord:error-not-in-guild":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-not-in-guild"},
"opendiscord:error-channel-rename":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"ticket-pin"|"ticket-unpin"|"ticket-rename"|"ticket-move"|"ticket-priority"|"ticket-transfer"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"opendiscord:error-channel-rename"},
"opendiscord:error-ticket-busy":{source:"slash"|"text"|"button"|"dropdown"|"modal"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:error-ticket-busy"},
"opendiscord:help-menu":{source:"slash"|"text"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu"},
"opendiscord:stats-global":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:stats-global"},
"opendiscord:stats-ticket":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:ODTicket},workers:"opendiscord:stats-ticket"},
"opendiscord:stats-user":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,scopeData:discord.User},workers:"opendiscord:stats-user"|"opendiscord:easter-egg"},
"opendiscord:stats-reset":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,reason:string|null},workers:"opendiscord:stats-reset"},
"opendiscord:stats-ticket-unknown":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,id:string},workers:"opendiscord:stats-ticket-unknown"},
"opendiscord:panel":{source:"slash"|"text"|"auto-update"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel-layout"|"opendiscord:panel-components"},
"opendiscord:panel-ready":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,panel:ODPanel},workers:"opendiscord:panel-ready"},
"opendiscord:ticket-created":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created"},
"opendiscord:ticket-created-dm":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-dm"},
"opendiscord:ticket-created-logs":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-created-logs"},
"opendiscord:ticket-message":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:ticket-message-layout"|"opendiscord:ticket-message-components"|"opendiscord:ticket-message-disable-components"},
"opendiscord:close-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"autoclose"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:close-message"},
"opendiscord:reopen-message":{source:"slash"|"text"|"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:reopen-message"},
"opendiscord:delete-message":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:delete-message"},
"opendiscord:claim-message":{source:"slash"|"text"|"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:claim-message"},
"opendiscord:unclaim-message":{source:"slash"|"text"|"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unclaim-message"},
"opendiscord:pin-message":{source:"slash"|"text"|"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:pin-message"},
"opendiscord:unpin-message":{source:"slash"|"text"|"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:unpin-message"},
"opendiscord:rename-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:string},workers:"opendiscord:rename-message"},
"opendiscord:move-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:ODTicketOption},workers:"opendiscord:move-message"},
"opendiscord:add-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:add-message"},
"opendiscord:remove-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null,data:discord.User},workers:"opendiscord:remove-message"},
"opendiscord:ticket-action-dm":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-dm"},
"opendiscord:ticket-action-logs":{source:"slash"|"text"|"ticket-message"|"close-message"|"reopen-message"|"delete-message"|"claim-message"|"unclaim-message"|"pin-message"|"unpin-message"|"autoclose-message"|"autoclose"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"close"|"reopen"|"delete"|"claim"|"unclaim"|"pin"|"unpin"|"rename"|"move"|"add"|"remove",ticket:ODTicket,reason:string|null,additionalData:null|string|discord.User|ODTicketOption},workers:"opendiscord:ticket-action-logs"},
"opendiscord:blacklist-view":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User},workers:"opendiscord:blacklist-view"},
"opendiscord:blacklist-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User},workers:"opendiscord:blacklist-get"},
"opendiscord:blacklist-add":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-add"},
"opendiscord:blacklist-remove":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,data:discord.User,reason:string|null},workers:"opendiscord:blacklist-remove"},
"opendiscord:blacklist-dm":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-dm"},
"opendiscord:blacklist-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,mode:"add"|"remove",data:discord.User,reason:string|null},workers:"opendiscord:blacklist-logs"},
"opendiscord:transcript-text-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{contents:string},null>,result:ODTranscriptCompilerCompileResult<{contents:string}>},workers:"opendiscord:transcript-text-ready"},
"opendiscord:transcript-html-ready":{source:"channel"|"creator-dm"|"participant-dm"|"active-admin-dm"|"every-admin-dm"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,result:ODTranscriptCompilerCompileResult<{url:string,availableUntil:Date}>},workers:"opendiscord:transcript-html-ready"},
"opendiscord:transcript-html-progress":{source:"channel"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<{url:string,availableUntil:Date},{auth:string}>,remaining:number},workers:"opendiscord:transcript-html-progress"},
"opendiscord:transcript-error":{source:"slash"|"text"|"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"autodelete"|"clear"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,compiler:ODTranscriptCompiler<any,object|null>,reason:string|null},workers:"opendiscord:transcript-error"},
"opendiscord:reaction-role":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role"},
"opendiscord:reaction-role-dm":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-dm"},
"opendiscord:reaction-role-logs":{source:"panel-button"|"other",params:{guild:discord.Guild,user:discord.User,role:ODRole,result:ODRoleUpdateResult[]},workers:"opendiscord:reaction-role-logs"},
"opendiscord:clear-verify-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-verify-message"},
"opendiscord:clear-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-message"},
"opendiscord:clear-logs":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,filter:ODTicketClearFilter,list:string[]},workers:"opendiscord:clear-logs"},
"opendiscord:autoclose-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autoclose-message"},
"opendiscord:autodelete-message":{source:"timeout"|"leave"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:autodelete-message"},
"opendiscord:autoclose-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autoclose-enable"},
"opendiscord:autodelete-enable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,time:number,reason:string|null},workers:"opendiscord:autodelete-enable"},
"opendiscord:autoclose-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autoclose-disable"},
"opendiscord:autodelete-disable":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,reason:string|null},workers:"opendiscord:autodelete-disable"},
"opendiscord:topic-set":{source:"slash"|"text"|"ticket-action"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,topic:string},workers:"opendiscord:topic-set"},
"opendiscord:priority-set":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel,reason:string|null},workers:"opendiscord:priority-set"},
"opendiscord:priority-get":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriorityLevel},workers:"opendiscord:priority-get"},
"opendiscord:transfer-message":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,oldCreator:discord.User,newCreator:discord.User,reason:string|null},workers:"opendiscord:transfer-message"},
}
/**## ODMessageManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODMessageManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.builders.messages`!
*/
export class ODMessageManager_Default extends ODMessageManager {
get<MessageId extends keyof ODMessageManagerIds_Default>(id:MessageId): ODMessage_Default<ODMessageManagerIds_Default[MessageId]["source"],ODMessageManagerIds_Default[MessageId]["params"],ODMessageManagerIds_Default[MessageId]["workers"]>
get(id:ODValidId): ODMessage<string,any>|null
get(id:ODValidId): ODMessage<string,any>|null {
return super.get(id)
}
remove<MessageId extends keyof ODMessageManagerIds_Default>(id:MessageId): ODMessage_Default<ODMessageManagerIds_Default[MessageId]["source"],ODMessageManagerIds_Default[MessageId]["params"],ODMessageManagerIds_Default[MessageId]["workers"]>
remove(id:ODValidId): ODMessage<string,any>|null
remove(id:ODValidId): ODMessage<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODMessageManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<MessageId extends keyof ODMessageManagerIds_Default>(id:MessageId): ODMessage_Default<ODMessageManagerIds_Default[MessageId]["source"],ODMessageManagerIds_Default[MessageId]["params"],ODMessageManagerIds_Default[MessageId]["workers"]>
getSafe(id:ODValidId): ODMessage<string,any>
getSafe(id:ODValidId): ODMessage<string,any> {
return super.getSafe(id)
}
}
/**## ODMessage_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODMessage class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODMessage`'s!
*/
export class ODMessage_Default<Source extends string, Params, WorkerIds extends string> extends ODMessage<Source,Params> {
declare workers: ODWorkerManager_Default<ODMessageInstance,Source,Params,WorkerIds>
}
/**## ODModalManagerIds_Default `interface`
* This interface is a list of ids available in the `ODModalManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODModalManagerIds_Default {
"opendiscord:ticket-questions":{source:"panel-button"|"panel-dropdown"|"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,option:ODTicketOption},workers:"opendiscord:ticket-questions"}
"opendiscord:close-ticket-reason":{source:"ticket-message"|"reopen-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:close-ticket-reason"}
"opendiscord:reopen-ticket-reason":{source:"ticket-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:reopen-ticket-reason"}
"opendiscord:delete-ticket-reason":{source:"ticket-message"|"reopen-message"|"close-message"|"autoclose-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:delete-ticket-reason"}
"opendiscord:claim-ticket-reason":{source:"ticket-message"|"unclaim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:claim-ticket-reason"}
"opendiscord:unclaim-ticket-reason":{source:"ticket-message"|"claim-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unclaim-ticket-reason"}
"opendiscord:pin-ticket-reason":{source:"ticket-message"|"unpin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:pin-ticket-reason"}
"opendiscord:unpin-ticket-reason":{source:"ticket-message"|"pin-message"|"other",params:{guild:discord.Guild,channel:discord.TextBasedChannel,user:discord.User,ticket:ODTicket},workers:"opendiscord:unpin-ticket-reason"}
}
/**## ODModalManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModalManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.builders.modals`!
*/
export class ODModalManager_Default extends ODModalManager {
get<ModalId extends keyof ODModalManagerIds_Default>(id:ModalId): ODModal_Default<ODModalManagerIds_Default[ModalId]["source"],ODModalManagerIds_Default[ModalId]["params"],ODModalManagerIds_Default[ModalId]["workers"]>
get(id:ODValidId): ODModal<string,any>|null
get(id:ODValidId): ODModal<string,any>|null {
return super.get(id)
}
remove<ModalId extends keyof ODModalManagerIds_Default>(id:ModalId): ODModal_Default<ODModalManagerIds_Default[ModalId]["source"],ODModalManagerIds_Default[ModalId]["params"],ODModalManagerIds_Default[ModalId]["workers"]>
remove(id:ODValidId): ODModal<string,any>|null
remove(id:ODValidId): ODModal<string,any>|null {
return super.remove(id)
}
exists(id:keyof ODModalManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getSafe<ModalId extends keyof ODModalManagerIds_Default>(id:ModalId): ODModal_Default<ODModalManagerIds_Default[ModalId]["source"],ODModalManagerIds_Default[ModalId]["params"],ODModalManagerIds_Default[ModalId]["workers"]>
getSafe(id:ODValidId): ODModal<string,any>
getSafe(id:ODValidId): ODModal<string,any> {
return super.getSafe(id)
}
}
/**## ODModal_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModal class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODModal`'s!
*/
export class ODModal_Default<Source extends string, Params, WorkerIds extends string> extends ODModal<Source,Params> {
declare workers: ODWorkerManager_Default<ODModalInstance,Source,Params,WorkerIds>
}
-385
View File
@@ -1,385 +0,0 @@
///////////////////////////////////////
//DEFAULT CONFIG CHECKER MODULE
///////////////////////////////////////
import { ODLanguageManager_Default } from "../api"
import { ODValidId } from "../modules/base"
import { ODCheckerManager, ODChecker, ODCheckerTranslationRegister, ODCheckerRenderer, ODCheckerFunctionManager, ODCheckerResult, ODCheckerFunction } from "../modules/checker"
import ansis from "ansis"
/**## ODCheckerManagerIds_Default `interface`
* This interface is a list of ids available in the `ODCheckerManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCheckerManagerIds_Default {
"opendiscord:general":ODChecker,
"opendiscord:questions":ODChecker,
"opendiscord:options":ODChecker,
"opendiscord:panels":ODChecker,
"opendiscord:transcripts":ODChecker
}
/**## ODCheckerManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCheckerManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.checkers`!
*/
export class ODCheckerManager_Default extends ODCheckerManager {
declare translation: ODCheckerTranslationRegister_Default
declare renderer: ODCheckerRenderer_Default
declare functions: ODCheckerFunctionManager_Default
get<CheckerId extends keyof ODCheckerManagerIds_Default>(id:CheckerId): ODCheckerManagerIds_Default[CheckerId]
get(id:ODValidId): ODChecker|null
get(id:ODValidId): ODChecker|null {
return super.get(id)
}
remove<CheckerId extends keyof ODCheckerManagerIds_Default>(id:CheckerId): ODCheckerManagerIds_Default[CheckerId]
remove(id:ODValidId): ODChecker|null
remove(id:ODValidId): ODChecker|null {
return super.remove(id)
}
exists(id:keyof ODCheckerManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODCheckerRenderer_Default `default_class`
* This is a special class that adds type definitions & features to the ODCheckerRenderer class.
* It contains the code that renders the default config checker.
*
* This default class is made for the global variable `opendiscord.checkers.renderer`!
*/
export class ODCheckerRenderer_Default extends ODCheckerRenderer {
extraHeaderText: string[] = []
extraFooterText: string[] = []
extraTopText: string[] = []
extraBottomText: string[] = []
horizontalFiller: string = "="
verticalFiller: string = "|"
descriptionSeparator: string = " => "
headerSeparator: string = " => "
footerTipPrefix: string = "=> "
disableHeader: boolean = false
disableFooter: boolean = false
getComponents(compact:boolean, renderEmpty:boolean, translation:ODCheckerTranslationRegister_Default, data:ODCheckerResult): string[] {
const tm = translation
const t = {
headerOpenticket:tm.get("other","opendiscord:header-openticket") ?? "OPEN TICKET",
headerConfigchecker:tm.get("other","opendiscord:header-configchecker") ?? "CONFIG CHECKER",
headerDescription:tm.get("other","opendiscord:header-description") ?? "check for errors in your config files!",
footerError:tm.get("other","opendiscord:footer-error") ?? "the bot won't start until all {0}'s are fixed!",
footerWarning:tm.get("other","opendiscord:footer-warning") ?? "it's recommended to fix all {0}'s before starting!",
footerSupport:tm.get("other","opendiscord:footer-support") ?? "SUPPORT: {0} - DOCS: {1}",
error:tm.get("other","opendiscord:type-error") ?? "[ERROR]",
warning:tm.get("other","opendiscord:type-warning") ?? "[WARNING]",
info:tm.get("other","opendiscord:type-info") ?? "[INFO]",
compactInfo:tm.get("other","opendiscord:compact-information") ?? "use {0} for more information!",
dataPath:tm.get("other","opendiscord:data-path") ?? "path",
dataDocs:tm.get("other","opendiscord:data-docs") ?? "docs",
dataMessage:tm.get("other","opendiscord:data-message") ?? "message"
}
const hasErrors = data.messages.filter((m) => m.type == "error").length > 0
const hasWarnings = data.messages.filter((m) => m.type == "warning").length > 0
const hasInfo = data.messages.filter((m) => m.type == "info").length > 0
if (!renderEmpty && !hasErrors && !hasWarnings && (!hasInfo || compact)) return []
const headerText = ansis.bold.hex("#f8ba00")(t.headerOpenticket)+" "+t.headerConfigchecker+this.headerSeparator+ansis.hex("#f8ba00")(t.headerDescription)
const footerErrorText = (hasErrors) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerError,[ansis.bold.red(t.error)])) : ""
const footerWarningText = (hasWarnings) ? this.footerTipPrefix+ansis.gray(tm.insertTranslationParams(t.footerWarning,[ansis.bold.yellow(t.warning)])) : ""
const footerSupportText = tm.insertTranslationParams(t.footerSupport,[ansis.green("https://discord.dj-dj.be"),ansis.green("https://otdocs.dj-dj.be")])
const bottomCompactInfo = (compact) ? ansis.gray(tm.insertTranslationParams(t.compactInfo,[ansis.bold.green("npm start -- --checker")])) : ""
const finalHeader = [headerText,...this.extraHeaderText]
const finalFooter = [footerErrorText,footerWarningText,footerSupportText,...this.extraFooterText]
const finalTop = [...this.extraTopText]
const finalBottom = [bottomCompactInfo,...this.extraBottomText]
const borderLength = this.#getLongestLength([...finalHeader,...finalFooter])
const finalComponents: string[] = []
//header
if (!this.disableHeader){
finalHeader.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.#createBlockFromText(text,borderLength))
})
}
finalComponents.push(this.#getHorizontalDivider(borderLength+4))
//top
finalTop.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.verticalFiller+" "+text)
})
finalComponents.push(this.verticalFiller)
//messages
if (compact){
//use compact messages
data.messages.forEach((msg,index) => {
//compact mode doesn't render info
if (msg.type == "info") return
//check if translation available & use it if possible
const rawTranslation = tm.get("message",msg.messageId.value)
const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message
if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`))
else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`))
const pathSplitter = msg.path ? ":" : ""
finalComponents.push(this.verticalFiller+ansis.bold(this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`))
if (index != data.messages.length-1) finalComponents.push(this.verticalFiller)
})
}else{
//use full messages
data.messages.forEach((msg,index) => {
//check if translation available & use it if possible
const rawTranslation = tm.get("message",msg.messageId.value)
const translatedMessage = (rawTranslation) ? tm.insertTranslationParams(rawTranslation,msg.translationParams) : msg.message
if (msg.type == "error") finalComponents.push(this.verticalFiller+" "+ansis.bold.red(`${t.error} ${translatedMessage}`))
else if (msg.type == "warning") finalComponents.push(this.verticalFiller+" "+ansis.bold.yellow(`${t.warning} ${translatedMessage}`))
else if (msg.type == "info") finalComponents.push(this.verticalFiller+" "+ansis.bold.blue(`${t.info} ${translatedMessage}`))
const pathSplitter = msg.path ? ":" : ""
finalComponents.push(this.verticalFiller+" "+ansis.bold((t.dataPath)+this.descriptionSeparator)+ansis.cyan(`${ansis.magenta(msg.filepath+pathSplitter)} ${msg.path}`))
if (msg.locationDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataDocs+this.descriptionSeparator)+ansis.italic.gray(msg.locationDocs))
if (msg.messageDocs) finalComponents.push(this.verticalFiller+" "+ansis.bold(t.dataMessage+this.descriptionSeparator)+ansis.italic.gray(msg.messageDocs))
if (index != data.messages.length-1) finalComponents.push(this.verticalFiller)
})
}
//bottom
finalComponents.push(this.verticalFiller)
finalBottom.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.verticalFiller+" "+text)
})
//footer
finalComponents.push(this.#getHorizontalDivider(borderLength+4))
if (!this.disableFooter){
finalFooter.forEach((text) => {
if (text.length < 1) return
finalComponents.push(this.#createBlockFromText(text,borderLength))
})
finalComponents.push(this.#getHorizontalDivider(borderLength+4))
}
//return all components
return finalComponents
}
/**Get the length of the longest string in the array. */
#getLongestLength(texts:string[]): number {
return Math.max(...texts.map((t) => ansis.strip(t).length))
}
/**Get a horizontal divider used between different parts of the config checker result. */
#getHorizontalDivider(width:number): string {
if (width > 2) width = width-2
else return this.verticalFiller+this.verticalFiller
let divider = this.verticalFiller + this.horizontalFiller.repeat(width) + this.verticalFiller
return divider
}
/**Create a block of text with a vertical divider on the left & right side. */
#createBlockFromText(text:string,width:number): string {
if (width < 3) return this.verticalFiller+this.verticalFiller
let newWidth = width-ansis.strip(text).length+1
let final = this.verticalFiller+" "+text+" ".repeat(newWidth)+this.verticalFiller
return final
}
}
/**## ODCheckerTranslationRegisterOtherIds_Default `interface`
* This interface is a list of ids available in the `ODCheckerTranslationRegister_Default` class.
* It's used to generate typescript declarations for this class.
*/
export type ODCheckerTranslationRegisterOtherIds_Default = (
"opendiscord:header-openticket"|
"opendiscord:header-configchecker"|
"opendiscord:header-description"|
"opendiscord:type-error"|
"opendiscord:type-warning"|
"opendiscord:type-info"|
"opendiscord:data-path"|
"opendiscord:data-docs"|
"opendiscord:data-message"|
"opendiscord:compact-information"|
"opendiscord:footer-error"|
"opendiscord:footer-warning"|
"opendiscord:footer-support"
)
/**## ODCheckerTranslationRegisterMessageIds_Default `interface`
* This interface is a list of ids available in the `ODCheckerTranslationRegister_Default` class.
* It's used to generate typescript declarations for this class.
*/
export type ODCheckerTranslationRegisterMessageIds_Default = (
"opendiscord:invalid-type"|
"opendiscord:property-missing"|
"opendiscord:property-optional"|
"opendiscord:object-disabled"|
"opendiscord:null-invalid"|
"opendiscord:switch-invalid-type"|
"opendiscord:object-switch-invalid-type"|
"opendiscord:string-too-short"|
"opendiscord:string-too-long"|
"opendiscord:string-length-invalid"|
"opendiscord:string-starts-with"|
"opendiscord:string-ends-with"|
"opendiscord:string-contains"|
"opendiscord:string-inverted-contains"|
"opendiscord:string-choices"|
"opendiscord:string-lowercase"|
"opendiscord:string-uppercase"|
"opendiscord:string-special-characters"|
"opendiscord:string-no-spaces"|
"opendiscord:string-regex"|
"opendiscord:string-capital-word"|
"opendiscord:string-capital-sentence"|
"opendiscord:string-punctuation"|
"opendiscord:number-nan"|
"opendiscord:number-too-short"|
"opendiscord:number-too-long"|
"opendiscord:number-length-invalid"|
"opendiscord:number-too-small"|
"opendiscord:number-too-large"|
"opendiscord:number-not-equal"|
"opendiscord:number-step"|
"opendiscord:number-step-offset"|
"opendiscord:number-starts-with"|
"opendiscord:number-ends-with"|
"opendiscord:number-contains"|
"opendiscord:number-inverted-contains"|
"opendiscord:number-choices"|
"opendiscord:number-float"|
"opendiscord:number-negative"|
"opendiscord:number-positive"|
"opendiscord:number-zero"|
"opendiscord:boolean-true"|
"opendiscord:boolean-false"|
"opendiscord:array-empty-disabled"|
"opendiscord:array-empty-required"|
"opendiscord:array-too-short"|
"opendiscord:array-too-long"|
"opendiscord:array-length-invalid"|
"opendiscord:array-invalid-types"|
"opendiscord:array-double"|
"opendiscord:discord-invalid-id"|
"opendiscord:discord-invalid-id-options"|
"opendiscord:discord-invalid-token"|
"opendiscord:color-invalid"|
"opendiscord:emoji-too-short"|
"opendiscord:emoji-too-long"|
"opendiscord:emoji-custom"|
"opendiscord:emoji-invalid"|
"opendiscord:url-invalid"|
"opendiscord:url-invalid-http"|
"opendiscord:url-invalid-protocol"|
"opendiscord:url-invalid-hostname"|
"opendiscord:url-invalid-extension"|
"opendiscord:url-invalid-path"|
"opendiscord:id-not-unique"|
"opendiscord:id-non-existent"|
"opendiscord:invalid-language"|
"opendiscord:invalid-button"|
"opendiscord:unused-option"|
"opendiscord:unused-question"|
"opendiscord:dropdown-option"
)
/**## ODCheckerTranslationRegister_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCheckerTranslationRegister class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.checkers.translation`!
*/
export class ODCheckerTranslationRegister_Default extends ODCheckerTranslationRegister {
get(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): string
get(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): string
get(type:"message"|"other", id:string): string|null
get(type:"message"|"other", id:string): string|null {
return super.get(type,id)
}
set(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default, translation:string): boolean
set(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default, translation:string): boolean
set(type:"message"|"other", id:string, translation:string): boolean
set(type:"message"|"other", id:string, translation:string): boolean {
return super.set(type,id,translation)
}
delete(type:"other", id:ODCheckerTranslationRegisterOtherIds_Default): boolean
delete(type:"message", id:ODCheckerTranslationRegisterMessageIds_Default): boolean
delete(type:"message"|"other", id:string): boolean
delete(type:"message"|"other", id:string): boolean {
return super.delete(type,id)
}
quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default)
quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:string)
quickTranslate(manager:ODLanguageManager_Default, translationId:string, type:"other"|"message", id:ODCheckerTranslationRegisterOtherIds_Default|ODCheckerTranslationRegisterMessageIds_Default|string){
super.quickTranslate(manager,translationId,type,id)
}
}
/**## ODCheckerFunctionManagerIds_Default `interface`
* This interface is a list of ids available in the `ODCheckerFunctionManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCheckerFunctionManagerIds_Default {
"opendiscord:unused-options":ODCheckerFunction,
"opendiscord:unused-questions":ODCheckerFunction,
"opendiscord:dropdown-options":ODCheckerFunction
}
/**## ODCheckerFunctionManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCheckerFunctionManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.checkers.functions`!
*/
export class ODCheckerFunctionManager_Default extends ODCheckerFunctionManager {
get<CheckerFunctionId extends keyof ODCheckerFunctionManagerIds_Default>(id:CheckerFunctionId): ODCheckerFunctionManagerIds_Default[CheckerFunctionId]
get(id:ODValidId): ODCheckerFunction|null
get(id:ODValidId): ODCheckerFunction|null {
return super.get(id)
}
remove<CheckerFunctionId extends keyof ODCheckerFunctionManagerIds_Default>(id:CheckerFunctionId): ODCheckerFunctionManagerIds_Default[CheckerFunctionId]
remove(id:ODValidId): ODCheckerFunction|null
remove(id:ODValidId): ODCheckerFunction|null {
return super.remove(id)
}
exists(id:keyof ODCheckerFunctionManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-207
View File
@@ -1,207 +0,0 @@
///////////////////////////////////////
//DEFAULT CLIENT MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODClientManager, ODSlashCommand, ODTextCommand, ODSlashCommandManager, ODTextCommandManager, ODSlashCommandInteractionCallback, ODTextCommandInteractionCallback, ODContextMenu, ODContextMenuManager, ODContextMenuInteractionCallback } from "../modules/client"
/** (CONTRIBUTOR GUIDE) HOW TO ADD NEW COMMANDS?
* - Register the command in loadAllSlashCommands() & loadAllTextCommands() in (./src/data/framework/commandLoader.ts)
* - Add autocomplete for the command in OD(Slash/Text)CommandManagerIds_Default in (./src/core/api/defaults/client.ts)
* - Add the command to the help menu in (./src/data/framework/helpMenuLoader.ts)
* - If required, new config variables should be added (incl. logs, dm-logs & permissions).
* - Update the Open Ticket Documentation.
* - If the command contains complex logic or can be executed from a button/dropdown, it should be placed inside an `ODAction`.
* - Check all files, test the bot carefully & try a lot of different scenario's with different settings.
*/
/**## ODClientManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODClientManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.client`!
*/
export class ODClientManager_Default extends ODClientManager {
declare slashCommands: ODSlashCommandManager_Default
declare textCommands: ODTextCommandManager_Default
declare contextMenus: ODContextMenuManager_Default
}
/**## ODSlashCommandManagerIds_Default `interface`
* This interface is a list of ids available in the `ODSlashCommandManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODSlashCommandManagerIds_Default {
"opendiscord:help":ODSlashCommand,
"opendiscord:panel":ODSlashCommand,
"opendiscord:ticket":ODSlashCommand,
"opendiscord:close":ODSlashCommand,
"opendiscord:delete":ODSlashCommand,
"opendiscord:reopen":ODSlashCommand,
"opendiscord:claim":ODSlashCommand,
"opendiscord:unclaim":ODSlashCommand,
"opendiscord:pin":ODSlashCommand,
"opendiscord:unpin":ODSlashCommand,
"opendiscord:move":ODSlashCommand,
"opendiscord:rename":ODSlashCommand,
"opendiscord:add":ODSlashCommand,
"opendiscord:remove":ODSlashCommand,
"opendiscord:blacklist":ODSlashCommand,
"opendiscord:stats":ODSlashCommand,
"opendiscord:clear":ODSlashCommand,
"opendiscord:autoclose":ODSlashCommand,
"opendiscord:autodelete":ODSlashCommand,
"opendiscord:topic":ODSlashCommand,
"opendiscord:priority":ODSlashCommand,
"opendiscord:transfer":ODSlashCommand,
}
/**## ODSlashCommandManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODSlashCommandManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.client.slashCommands`!
*/
export class ODSlashCommandManager_Default extends ODSlashCommandManager {
get<SlashCommandId extends keyof ODSlashCommandManagerIds_Default>(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId]
get(id:ODValidId): ODSlashCommand|null
get(id:ODValidId): ODSlashCommand|null {
return super.get(id)
}
remove<SlashCommandId extends keyof ODSlashCommandManagerIds_Default>(id:SlashCommandId): ODSlashCommandManagerIds_Default[SlashCommandId]
remove(id:ODValidId): ODSlashCommand|null
remove(id:ODValidId): ODSlashCommand|null {
return super.remove(id)
}
exists(id:keyof ODSlashCommandManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
onInteraction(commandName:keyof ODSlashCommandManagerIds_Default, callback:ODSlashCommandInteractionCallback): void
onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void
onInteraction(commandName:string|RegExp, callback:ODSlashCommandInteractionCallback): void {
return super.onInteraction(commandName,callback)
}
}
/**## ODTextCommandManagerIds_Default `interface`
* This interface is a list of ids available in the `ODTextCommandManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODTextCommandManagerIds_Default {
"opendiscord:dump":ODTextCommand,
"opendiscord:help":ODTextCommand,
"opendiscord:panel":ODTextCommand,
"opendiscord:close":ODTextCommand,
"opendiscord:delete":ODTextCommand,
"opendiscord:reopen":ODTextCommand,
"opendiscord:claim":ODTextCommand,
"opendiscord:unclaim":ODTextCommand,
"opendiscord:pin":ODTextCommand,
"opendiscord:unpin":ODTextCommand,
"opendiscord:move":ODTextCommand,
"opendiscord:rename":ODTextCommand,
"opendiscord:add":ODTextCommand,
"opendiscord:remove":ODTextCommand,
"opendiscord:blacklist-view":ODTextCommand,
"opendiscord:blacklist-add":ODTextCommand,
"opendiscord:blacklist-remove":ODTextCommand,
"opendiscord:blacklist-get":ODTextCommand,
"opendiscord:stats-global":ODTextCommand,
"opendiscord:stats-reset":ODTextCommand,
"opendiscord:stats-ticket":ODTextCommand,
"opendiscord:stats-user":ODTextCommand,
"opendiscord:clear":ODTextCommand,
"opendiscord:autoclose-disable":ODTextCommand,
"opendiscord:autoclose-enable":ODTextCommand,
"opendiscord:autodelete-disable":ODTextCommand,
"opendiscord:autodelete-enable":ODTextCommand,
"opendiscord:topic-set":ODTextCommand,
"opendiscord:priority-set":ODTextCommand,
"opendiscord:priority-get":ODTextCommand,
"opendiscord:transfer":ODTextCommand,
}
/**## ODTextCommandManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODTextCommandManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.client.textCommands`!
*/
export class ODTextCommandManager_Default extends ODTextCommandManager {
get<TextCommandId extends keyof ODTextCommandManagerIds_Default>(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId]
get(id:ODValidId): ODTextCommand|null
get(id:ODValidId): ODTextCommand|null {
return super.get(id)
}
remove<TextCommandId extends keyof ODTextCommandManagerIds_Default>(id:TextCommandId): ODTextCommandManagerIds_Default[TextCommandId]
remove(id:ODValidId): ODTextCommand|null
remove(id:ODValidId): ODTextCommand|null {
return super.remove(id)
}
exists(id:keyof ODTextCommandManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
onInteraction(commandPrefix:string, commandName:string|RegExp, callback:ODTextCommandInteractionCallback): void {
return super.onInteraction(commandPrefix,commandName,callback)
}
}
/**## ODContextMenuManagerIds_Default `interface`
* This interface is a list of ids available in the `ODContextMenuManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODContextMenuManagerIds_Default {
//"opendiscord:test-menu":ODContextMenu
}
/**## ODContextMenuManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODContextMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.client.contextMenus`!
*/
export class ODContextMenuManager_Default extends ODContextMenuManager {
get<ContextMenuId extends keyof ODContextMenuManagerIds_Default>(id:ContextMenuId): ODContextMenuManagerIds_Default[ContextMenuId]
get(id:ODValidId): ODContextMenu|null
get(id:ODValidId): ODContextMenu|null {
return super.get(id)
}
remove<ContextMenuId extends keyof ODContextMenuManagerIds_Default>(id:ContextMenuId): ODContextMenuManagerIds_Default[ContextMenuId]
remove(id:ODValidId): ODContextMenu|null
remove(id:ODValidId): ODContextMenu|null {
return super.remove(id)
}
exists(id:keyof ODContextMenuManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
onInteraction(menuName:keyof ODContextMenuManagerIds_Default, callback:ODContextMenuInteractionCallback): void
onInteraction(menuName:string|RegExp, callback:ODContextMenuInteractionCallback): void
onInteraction(menuName:string|RegExp, callback:ODContextMenuInteractionCallback): void {
return super.onInteraction(menuName,callback)
}
}
-57
View File
@@ -1,57 +0,0 @@
///////////////////////////////////////
//DEFAULT CODE MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODCode, ODCodeManager } from "../modules/code"
/**## ODCodeManagerIds_Default `interface`
* This interface is a list of ids available in the `ODCodeManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCodeManagerIds_Default {
"opendiscord:command-error-handling":ODCode,
"opendiscord:start-listening-interactions":ODCode,
"opendiscord:panel-database-cleaner":ODCode,
"opendiscord:suffix-database-cleaner":ODCode,
"opendiscord:option-database-cleaner":ODCode,
"opendiscord:user-database-cleaner":ODCode,
"opendiscord:ticket-database-cleaner":ODCode,
"opendiscord:panel-auto-update":ODCode,
"opendiscord:ticket-saver":ODCode,
"opendiscord:blacklist-saver":ODCode,
"opendiscord:auto-role-on-join":ODCode,
"opendiscord:autoclose-timeout":ODCode,
"opendiscord:autoclose-leave":ODCode,
"opendiscord:autodelete-timeout":ODCode,
"opendiscord:autodelete-leave":ODCode,
"opendiscord:ticket-anti-busy":ODCode,
}
/**## ODCodeManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCodeManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.code`!
*/
export class ODCodeManager_Default extends ODCodeManager {
get<CodeId extends keyof ODCodeManagerIds_Default>(id:CodeId): ODCodeManagerIds_Default[CodeId]
get(id:ODValidId): ODCode|null
get(id:ODValidId): ODCode|null {
return super.get(id)
}
remove<CodeId extends keyof ODCodeManagerIds_Default>(id:CodeId): ODCodeManagerIds_Default[CodeId]
remove(id:ODValidId): ODCode|null
remove(id:ODValidId): ODCode|null {
return super.remove(id)
}
exists(id:keyof ODCodeManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-42
View File
@@ -1,42 +0,0 @@
///////////////////////////////////////
//DEFAULT CONSOLE MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODLiveStatusUrlSource, ODLiveStatusManager, ODLiveStatusSource } from "../modules/console"
/**## ODLiveStatusManagerIds_Default `interface`
* This interface is a list of ids available in the `ODLiveStatusManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODLiveStatusManagerIds_Default {
"opendiscord:default-djdj-dev":ODLiveStatusUrlSource
}
/**## ODLiveStatusManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODLiveStatusManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.livestatus`!
*/
export class ODLiveStatusManager_Default extends ODLiveStatusManager {
get<LiveStatusId extends keyof ODLiveStatusManagerIds_Default>(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId]
get(id:ODValidId): ODLiveStatusSource|null
get(id:ODValidId): ODLiveStatusSource|null {
return super.get(id)
}
remove<LiveStatusId extends keyof ODLiveStatusManagerIds_Default>(id:LiveStatusId): ODLiveStatusManagerIds_Default[LiveStatusId]
remove(id:ODValidId): ODLiveStatusSource|null
remove(id:ODValidId): ODLiveStatusSource|null {
return super.remove(id)
}
exists(id:keyof ODLiveStatusManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-42
View File
@@ -1,42 +0,0 @@
///////////////////////////////////////
//DEFAULT COOLDOWN MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODCooldown, ODCooldownManager } from "../modules/cooldown"
/**## ODCooldownManagerIds_Default `interface`
* This interface is a list of ids available in the `ODCooldownManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCooldownManagerIds_Default {
}
/**## ODCooldownManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCooldownManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.cooldowns`!
*/
export class ODCooldownManager_Default extends ODCooldownManager {
get<CooldownId extends keyof ODCooldownManagerIds_Default>(id:CooldownId): ODCooldownManagerIds_Default[CooldownId]
get(id:ODValidId): ODCooldown<object>|null
get(id:ODValidId): ODCooldown<object>|null {
return super.get(id)
}
remove<CooldownId extends keyof ODCooldownManagerIds_Default>(id:CooldownId): ODCooldownManagerIds_Default[CooldownId]
remove(id:ODValidId): ODCooldown<object>|null
remove(id:ODValidId): ODCooldown<object>|null {
return super.remove(id)
}
exists(id:keyof ODCooldownManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-257
View File
@@ -1,257 +0,0 @@
///////////////////////////////////////
//DEFAULT DATABASE MODULE
///////////////////////////////////////
import { ODOptionalPromise, ODValidId, ODValidJsonType } from "../modules/base"
import { ODDatabaseManager, ODDatabase, ODFormattedJsonDatabase } from "../modules/database"
import { ODTicketJson } from "../openticket/ticket"
import { ODOptionJson } from "../openticket/option"
/**## ODDatabaseManagerIds_Default `interface`
* This interface is a list of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDatabaseManagerIds_Default {
"opendiscord:global":ODFormattedJsonDatabase_DefaultGlobal,
"opendiscord:stats":ODFormattedJsonDatabase,
"opendiscord:tickets":ODFormattedJsonDatabase_DefaultTickets,
"opendiscord:users":ODFormattedJsonDatabase_DefaultUsers,
"opendiscord:options":ODFormattedJsonDatabase_DefaultOptions,
}
/**## ODDatabaseManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDatabaseManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.databases`!
*/
export class ODDatabaseManager_Default extends ODDatabaseManager {
get<DatabaseId extends keyof ODDatabaseManagerIds_Default>(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId]
get(id:ODValidId): ODDatabase|null
get(id:ODValidId): ODDatabase|null {
return super.get(id)
}
remove<DatabaseId extends keyof ODDatabaseManagerIds_Default>(id:DatabaseId): ODDatabaseManagerIds_Default[DatabaseId]
remove(id:ODValidId): ODDatabase|null
remove(id:ODValidId): ODDatabase|null {
return super.remove(id)
}
exists(id:keyof ODDatabaseManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultGlobal `type`
* This interface is a list of ids available in the `ODFormattedJsonDatabase_DefaultGlobal` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultGlobal {
"opendiscord:panel-message":string,
"opendiscord:panel-update":string,
"opendiscord:option-suffix-counter":number,
"opendiscord:option-suffix-history":string[],
"opendiscord:last-version":string
}
/**## ODFormattedJsonDatabase_DefaultGlobal `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `global.json` database!
*/
export class ODFormattedJsonDatabase_DefaultGlobal extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean> {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId, key:string): ODOptionalPromise<ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined> {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean> {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultGlobal, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean> {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultGlobal>(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultGlobal[CategoryId]}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
return super.getCategory(category)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultTickets `type`
* This interface is a list of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultTickets {
"opendiscord:ticket":ODTicketJson
}
/**## ODFormattedJsonDatabase_DefaultTickets `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `tickets.json` database!
*/
export class ODFormattedJsonDatabase_DefaultTickets extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean> {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId, key:string): ODOptionalPromise<ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined> {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean> {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultTickets, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean> {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultTickets>(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultTickets[CategoryId]}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
return super.getCategory(category)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultUsers `type`
* This interface is a list of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultUsers {
"opendiscord:blacklist":ODTicketJson
}
/**## ODFormattedJsonDatabase_DefaultUsers `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `users.json` database!
*/
export class ODFormattedJsonDatabase_DefaultUsers extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean> {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId, key:string): ODOptionalPromise<ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined> {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean> {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultUsers, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean> {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultUsers>(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultUsers[CategoryId]}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
return super.getCategory(category)
}
}
/**## ODFormattedJsonDatabaseIds_DefaultOptions `type`
* This interface is a list of ids available in the `ODDatabaseManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFormattedJsonDatabaseIds_DefaultOptions {
"opendiscord:used-option":ODOptionJson
}
/**## ODFormattedJsonDatabase_DefaultOptions `default_class`
* This is a special class that adds type definitions & typescript to the ODFormattedJsonDatabase class.
* It doesn't add any extra features!
*
* This default class is made for the `options.json` database!
*/
export class ODFormattedJsonDatabase_DefaultOptions extends ODFormattedJsonDatabase {
set<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId, key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean>
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean> {
return super.set(category,key,value)
}
get<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId, key:string): ODOptionalPromise<ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined>
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined> {
return super.get(category,key)
}
delete<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean>
delete(category:string, key:string): ODOptionalPromise<boolean> {
return super.delete(category,key)
}
exists(category:keyof ODFormattedJsonDatabaseIds_DefaultOptions, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean>
exists(category:string, key:string): ODOptionalPromise<boolean> {
return super.exists(category,key)
}
getCategory<CategoryId extends keyof ODFormattedJsonDatabaseIds_DefaultOptions>(category:CategoryId): ODOptionalPromise<{key:string, value:ODFormattedJsonDatabaseIds_DefaultOptions[CategoryId]}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined>
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
return super.getCategory(category)
}
}
-390
View File
@@ -1,390 +0,0 @@
///////////////////////////////////////
//DEFAULT EVENT MODULE
///////////////////////////////////////
//BASE MODULES
import { ODPromiseVoid, ODValidId } from "../modules/base"
import { ODConsoleManager, ODError } from "../modules/console"
import { ODCheckerResult, ODCheckerStorage } from "../modules/checker"
import { ODDefaultsManager } from "../modules/defaults"
import { ODLanguage } from "../modules/language"
import { ODClientActivityManager } from "../modules/client"
import { ODEvent, ODEventManager } from "../modules/event"
import * as discord from "discord.js"
//DEFAULT MODULES
import { ODPluginClassManager_Default, ODPluginManager_Default } from "./plugin"
import { ODConfigManager_Default} from "./config"
import { ODDatabaseManager_Default } from "./database"
import { ODFlagManager_Default } from "./flag"
import { ODSessionManager_Default } from "./session"
import { ODLanguageManager_Default } from "./language"
import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./checker"
import { ODClientManager_Default, ODContextMenuManager_Default, ODSlashCommandManager_Default, ODTextCommandManager_Default } from "./client"
import { ODBuilderManager_Default, ODButtonManager_Default, ODDropdownManager_Default, ODEmbedManager_Default, ODFileManager_Default, ODMessageManager_Default, ODModalManager_Default } from "./builder"
import { ODAutocompleteResponderManager_Default, ODButtonResponderManager_Default, ODCommandResponderManager_Default, ODContextMenuResponderManager_Default, ODDropdownResponderManager_Default, ODModalResponderManager_Default, ODResponderManager_Default } from "./responder"
import { ODActionManager_Default } from "./action"
import { ODPermissionManager_Default } from "./permission"
import { ODHelpMenuManager_Default } from "./helpmenu"
import { ODStatsManager_Default } from "./stat"
import { ODCodeManager_Default } from "./code"
import { ODCooldownManager_Default } from "./cooldown"
import { ODPostManager_Default } from "./post"
import { ODVerifyBarManager_Default } from "./verifybar"
import { ODStartScreenManager_Default } from "./startscreen"
import { ODLiveStatusManager_Default } from "./console"
import { ODProgressBarManager_Default, ODProgressBarRendererManager_Default } from "./progressbar"
//OPEN TICKET MODULES
import { ODOptionManager, ODTicketOption } from "../openticket/option"
import { ODPanel, ODPanelManager } from "../openticket/panel"
import { ODTicket, ODTicketClearFilter, ODTicketManager } from "../openticket/ticket"
import { ODQuestionManager } from "../openticket/question"
import { ODBlacklistManager } from "../openticket/blacklist"
import { ODTranscriptManager_Default } from "../openticket/transcript"
import { ODRole, ODRoleManager } from "../openticket/role"
import { ODPriorityLevel, ODPriorityManager_Default } from "../openticket/priority"
/**## ODEventIds_Default `interface`
* This interface is a list of ids available in the `ODEvent_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODEventIds_Default {
//error handling
"onErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin) => ODPromiseVoid>
"afterErrorHandling": ODEvent_Default<(error:Error, origin:NodeJS.UncaughtExceptionOrigin, message:ODError) => ODPromiseVoid>
//plugins
"afterPluginsLoaded": ODEvent_Default<(plugins:ODPluginManager_Default) => ODPromiseVoid>
"onPluginClassLoad": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid>
"afterPluginClassesLoaded": ODEvent_Default<(classes:ODPluginClassManager_Default, plugins:ODPluginManager_Default) => ODPromiseVoid>
//flags
"onFlagLoad": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
"afterFlagsLoaded": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
"onFlagInit": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
"afterFlagsInitiated": ODEvent_Default<(flags:ODFlagManager_Default) => ODPromiseVoid>
//progress bars
"onProgressBarRendererLoad": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid>
"afterProgressBarRenderersLoaded": ODEvent_Default<(renderers:ODProgressBarRendererManager_Default) => ODPromiseVoid>
"onProgressBarLoad": ODEvent_Default<(progressbars:ODProgressBarManager_Default) => ODPromiseVoid>
"afterProgressBarsLoaded": ODEvent_Default<(progressbars:ODProgressBarManager_Default) => ODPromiseVoid>
//configs
"onConfigLoad": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
"afterConfigsLoaded": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
"onConfigInit": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
"afterConfigsInitiated": ODEvent_Default<(configs:ODConfigManager_Default) => ODPromiseVoid>
//databases
"onDatabaseLoad": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
"afterDatabasesLoaded": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
"onDatabaseInit": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
"afterDatabasesInitiated": ODEvent_Default<(databases:ODDatabaseManager_Default) => ODPromiseVoid>
//languages
"onLanguageLoad": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"afterLanguagesLoaded": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"onLanguageInit": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"afterLanguagesInitiated": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"onLanguageSelect": ODEvent_Default<(languages:ODLanguageManager_Default) => ODPromiseVoid>
"afterLanguagesSelected": ODEvent_Default<(main:ODLanguage|null, backup:ODLanguage|null, languages:ODLanguageManager_Default) => ODPromiseVoid>
//sessions
"onSessionLoad": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid>
"afterSessionsLoaded": ODEvent_Default<(languages:ODSessionManager_Default) => ODPromiseVoid>
//config checkers
"onCheckerLoad": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckersLoaded": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerFunctionLoad": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckerFunctionsLoaded": ODEvent_Default<(functions:ODCheckerFunctionManager_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerExecute": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckersExecuted": ODEvent_Default<(result:ODCheckerResult, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerTranslationLoad": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, enabled:boolean, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckerTranslationsLoaded": ODEvent_Default<(translations:ODCheckerTranslationRegister_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerRender": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"afterCheckersRendered": ODEvent_Default<(renderer:ODCheckerRenderer_Default, checkers:ODCheckerManager_Default) => ODPromiseVoid>
"onCheckerQuit": ODEvent_Default<(checkers:ODCheckerManager_Default) => ODPromiseVoid>
//plugin loading before client
"onPluginBeforeClientLoad": ODEvent_Default<() => ODPromiseVoid>,
"afterPluginBeforeClientLoaded": ODEvent_Default<() => ODPromiseVoid>,
//client configuration
"onClientLoad": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"afterClientLoaded": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"onClientInit": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"afterClientInitiated": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"onClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"afterClientReady": ODEvent_Default<(client:ODClientManager_Default) => ODPromiseVoid>
"onClientActivityLoad": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
"afterClientActivityLoaded": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
"onClientActivityInit": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
"afterClientActivityInitiated": ODEvent_Default<(activity:ODClientActivityManager, client:ODClientManager_Default) => ODPromiseVoid>
//priority levels
"onPriorityLoad": ODEvent_Default<(priorities:ODPriorityManager_Default) => ODPromiseVoid>
"afterPrioritiesLoaded": ODEvent_Default<(priorities:ODPriorityManager_Default) => ODPromiseVoid>
//client slash commands
"onSlashCommandLoad": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"afterSlashCommandsLoaded": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"onSlashCommandRegister": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"afterSlashCommandsRegistered": ODEvent_Default<(slash:ODSlashCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
//client context menus
"onContextMenuLoad": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"afterContextMenusLoaded": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"onContextMenuRegister": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
"afterContextMenusRegistered": ODEvent_Default<(menu:ODContextMenuManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
//client text commands
"onTextCommandLoad": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default,) => ODPromiseVoid>
"afterTextCommandsLoaded": ODEvent_Default<(text:ODTextCommandManager_Default, client:ODClientManager_Default) => ODPromiseVoid>
//plugin loading before managers
"onPluginBeforeManagerLoad": ODEvent_Default<() => ODPromiseVoid>,
"afterPluginBeforeManagerLoaded": ODEvent_Default<() => ODPromiseVoid>,
//questions
"onQuestionLoad": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid>
"afterQuestionsLoaded": ODEvent_Default<(questions:ODQuestionManager) => ODPromiseVoid>
//options
"onOptionLoad": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid>
"afterOptionsLoaded": ODEvent_Default<(options:ODOptionManager) => ODPromiseVoid>
//panels
"onPanelLoad": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid>
"afterPanelsLoaded": ODEvent_Default<(panels:ODPanelManager) => ODPromiseVoid>
"onPanelSpawn": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid>
"afterPanelSpawned": ODEvent_Default<(panel:ODPanel) => ODPromiseVoid>
//tickets
"onTicketLoad": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid>
"afterTicketsLoaded": ODEvent_Default<(tickets:ODTicketManager) => ODPromiseVoid>
//ticket creation
"onTicketChannelCreation": ODEvent_Default<(option:ODTicketOption, user:discord.User) => ODPromiseVoid>
"afterTicketChannelCreated": ODEvent_Default<(option:ODTicketOption, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"onTicketChannelDeletion": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"afterTicketChannelDeleted": ODEvent_Default<(ticket:ODTicket, user:discord.User) => ODPromiseVoid>
"onTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"afterTicketPermissionsCreated": ODEvent_Default<(option:ODTicketOption, permissions:ODPermissionManager_Default, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"onTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
"afterTicketMainMessageCreated": ODEvent_Default<(ticket:ODTicket, message:discord.Message, channel:discord.GuildTextBasedChannel, user:discord.User) => ODPromiseVoid>
//ticket actions
"onTicketCreate": ODEvent_Default<(creator:discord.User) => ODPromiseVoid>
"afterTicketCreated": ODEvent_Default<(ticket:ODTicket, creator:discord.User, channel:discord.GuildTextBasedChannel) => ODPromiseVoid>
"onTicketClose": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketClosed": ODEvent_Default<(ticket:ODTicket, closer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketReopen": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketReopened": ODEvent_Default<(ticket:ODTicket, reopener:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketDelete": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketDeleted": ODEvent_Default<(ticket:ODTicket, deleter:discord.User, reason:string|null) => ODPromiseVoid>
"onTicketMove": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketMoved": ODEvent_Default<(ticket:ODTicket, mover:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketClaim": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketClaimed": ODEvent_Default<(ticket:ODTicket, claimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUnclaim": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUnclaimed": ODEvent_Default<(ticket:ODTicket, unclaimer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketPin": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketPinned": ODEvent_Default<(ticket:ODTicket, pinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUnpin": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUnpinned": ODEvent_Default<(ticket:ODTicket, unpinner:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUserAdd": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUserAdded": ODEvent_Default<(ticket:ODTicket, adder:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketUserRemove": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketUserRemoved": ODEvent_Default<(ticket:ODTicket, remover:discord.User, user:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketRename": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"afterTicketRenamed": ODEvent_Default<(ticket:ODTicket, renamer:discord.User, channel:discord.GuildTextBasedChannel, reason:string|null) => ODPromiseVoid>
"onTicketsClear": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid>
"afterTicketsCleared": ODEvent_Default<(tickets:ODTicket[], clearer:discord.User, channel:discord.GuildTextBasedChannel, filter:ODTicketClearFilter) => ODPromiseVoid>
"onTicketTopicChange": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldTopic:string, newTopic:string) => ODPromiseVoid>
"afterTicketTopicChanged": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldTopic:string, newTopic:string) => ODPromiseVoid>
"onTicketPriorityChange": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldPriority:ODPriorityLevel, newPriority:ODPriorityLevel, reason:string|null) => ODPromiseVoid>
"afterTicketPriorityChanged": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldPriority:ODPriorityLevel, newPriority:ODPriorityLevel, reason:string|null) => ODPromiseVoid>
"onTicketTransfer": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldCreator:discord.User, newCreator:discord.User, reason:string|null) => ODPromiseVoid>
"afterTicketTransferred": ODEvent_Default<(ticket:ODTicket, changer:discord.User, channel:discord.GuildTextBasedChannel, oldCreator:discord.User, newCreator:discord.User, reason:string|null) => ODPromiseVoid>
//roles
"onRoleLoad": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid>
"afterRolesLoaded": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid>
"onRoleUpdate": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid>
"afterRolesUpdated": ODEvent_Default<(user:discord.User,role:ODRole) => ODPromiseVoid>
//blacklist
"onBlacklistLoad": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid>
"afterBlacklistLoaded": ODEvent_Default<(blacklist:ODBlacklistManager) => ODPromiseVoid>
//transcripts
"onTranscriptCompilerLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
"afterTranscriptCompilersLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
"onTranscriptHistoryLoad": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
"afterTranscriptHistoryLoaded": ODEvent_Default<(transcripts:ODTranscriptManager_Default) => ODPromiseVoid>
//transcript creation
"onTranscriptCreate": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptCreated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"onTranscriptInit": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptInitiated": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"onTranscriptCompile": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptCompiled": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"onTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
"afterTranscriptReady": ODEvent_Default<(transcripts:ODTranscriptManager_Default,ticket:ODTicket,channel:discord.TextChannel,user:discord.User) => ODPromiseVoid>
//plugin loading before builders
"onPluginBeforeBuilderLoad": ODEvent_Default<() => ODPromiseVoid>,
"afterPluginBeforeBuilderLoaded": ODEvent_Default<() => ODPromiseVoid>,
//builders
"onButtonBuilderLoad": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterButtonBuildersLoaded": ODEvent_Default<(buttons:ODButtonManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onDropdownBuilderLoad": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterDropdownBuildersLoaded": ODEvent_Default<(dropdowns:ODDropdownManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onFileBuilderLoad": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterFileBuildersLoaded": ODEvent_Default<(files:ODFileManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onEmbedBuilderLoad": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterEmbedBuildersLoaded": ODEvent_Default<(embeds:ODEmbedManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onMessageBuilderLoad": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterMessageBuildersLoaded": ODEvent_Default<(messages:ODMessageManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onModalBuilderLoad": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterModalBuildersLoaded": ODEvent_Default<(modals:ODModalManager_Default, builders:ODBuilderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
//plugin loading before responders
"onPluginBeforeResponderLoad": ODEvent_Default<() => ODPromiseVoid>,
"afterPluginBeforeResponderLoaded": ODEvent_Default<() => ODPromiseVoid>,
//responders
"onCommandResponderLoad": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterCommandRespondersLoaded": ODEvent_Default<(commands:ODCommandResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onButtonResponderLoad": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterButtonRespondersLoaded": ODEvent_Default<(buttons:ODButtonResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onDropdownResponderLoad": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterDropdownRespondersLoaded": ODEvent_Default<(dropdowns:ODDropdownResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onModalResponderLoad": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterModalRespondersLoaded": ODEvent_Default<(modals:ODModalResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onContextMenuResponderLoad": ODEvent_Default<(menus:ODContextMenuResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterContextMenuRespondersLoaded": ODEvent_Default<(menus:ODContextMenuResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"onAutocompleteResponderLoad": ODEvent_Default<(autocomplete:ODAutocompleteResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
"afterAutocompleteRespondersLoaded": ODEvent_Default<(autocomplete:ODAutocompleteResponderManager_Default, responders:ODResponderManager_Default, actions:ODActionManager_Default) => ODPromiseVoid>
//plugin loading before finalizations
"onPluginBeforeFinalizationLoad": ODEvent_Default<() => ODPromiseVoid>,
"afterPluginBeforeFinalizationLoaded": ODEvent_Default<() => ODPromiseVoid>,
//actions
"onActionLoad": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid>
"afterActionsLoaded": ODEvent_Default<(actions:ODActionManager_Default) => ODPromiseVoid>
//verifybars
"onVerifyBarLoad": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid>
"afterVerifyBarsLoaded": ODEvent_Default<(verifybars:ODVerifyBarManager_Default) => ODPromiseVoid>
//permissions
"onPermissionLoad": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid>
"afterPermissionsLoaded": ODEvent_Default<(permissions:ODPermissionManager_Default) => ODPromiseVoid>
//posts
"onPostLoad": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
"afterPostsLoaded": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
"onPostInit": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
"afterPostsInitiated": ODEvent_Default<(posts:ODPostManager_Default) => ODPromiseVoid>
//cooldowns
"onCooldownLoad": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
"afterCooldownsLoaded": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
"onCooldownInit": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
"afterCooldownsInitiated": ODEvent_Default<(cooldowns:ODCooldownManager_Default) => ODPromiseVoid>
//help menu
"onHelpMenuCategoryLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
"afterHelpMenuCategoriesLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
"onHelpMenuComponentLoad": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
"afterHelpMenuComponentsLoaded": ODEvent_Default<(menu:ODHelpMenuManager_Default) => ODPromiseVoid>
//stats
"onStatScopeLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"afterStatScopesLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"onStatLoad": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"afterStatsLoaded": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"onStatInit": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
"afterStatsInitiated": ODEvent_Default<(stats:ODStatsManager_Default) => ODPromiseVoid>
//plugin loading before code
"onPluginBeforeCodeLoad": ODEvent_Default<() => ODPromiseVoid>,
"afterPluginBeforeCodeLoaded": ODEvent_Default<() => ODPromiseVoid>,
//code
"onCodeLoad": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
"afterCodeLoaded": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
"onCodeExecute": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
"afterCodeExecuted": ODEvent_Default<(code:ODCodeManager_Default) => ODPromiseVoid>
//livestatus
"onLiveStatusSourceLoad": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid>
"afterLiveStatusSourcesLoaded": ODEvent_Default<(livestatus:ODLiveStatusManager_Default) => ODPromiseVoid>
//startscreen
"onStartScreenLoad": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
"afterStartScreensLoaded": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
"onStartScreenRender": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
"afterStartScreensRendered": ODEvent_Default<(startscreen:ODStartScreenManager_Default) => ODPromiseVoid>
//ready
"beforeReadyForUsage": ODEvent_Default<() => ODPromiseVoid>
"onReadyForUsage": ODEvent_Default<() => ODPromiseVoid>
}
/**## ODEventManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEvent class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.events`!
*/
export class ODEventManager_Default extends ODEventManager {
get<StartScreenId extends keyof ODEventIds_Default>(id:StartScreenId): ODEventIds_Default[StartScreenId]
get(id:ODValidId): ODEvent|null
get(id:ODValidId): ODEvent|null {
return super.get(id)
}
remove<StartScreenId extends keyof ODEventIds_Default>(id:StartScreenId): ODEventIds_Default[StartScreenId]
remove(id:ODValidId): ODEvent|null
remove(id:ODValidId): ODEvent|null {
return super.remove(id)
}
exists(id:keyof ODEventIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODEventManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODEvent class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.events`!
*/
export class ODEvent_Default<Callback extends ((...args:any) => ODPromiseVoid)> extends ODEvent {
listen(callback:Callback): void {
return super.listen(callback)
}
listenOnce(callback:Callback): void {
return super.listenOnce(callback)
}
wait(): Promise<Parameters<Callback>>
wait(): Promise<any[]> {
return super.wait()
}
emit(params:Parameters<Callback>): Promise<void> {
return super.emit(params)
}
}
-57
View File
@@ -1,57 +0,0 @@
///////////////////////////////////////
//DEFAULT PROCESS MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODFlagManager, ODFlag } from "../modules/flag"
/**## ODFlagManagerIds_Default `interface`
* This interface is a list of ids available in the `ODFlagManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODFlagManagerIds_Default {
"opendiscord:no-migration":ODFlag,
"opendiscord:dev-config":ODFlag,
"opendiscord:dev-database":ODFlag,
"opendiscord:debug":ODFlag,
"opendiscord:crash":ODFlag,
"opendiscord:no-transcripts":ODFlag,
"opendiscord:no-checker":ODFlag,
"opendiscord:checker":ODFlag,
"opendiscord:no-easter":ODFlag,
"opendiscord:no-plugins":ODFlag,
"opendiscord:soft-plugins":ODFlag,
"opendiscord:force-slash-update":ODFlag,
"opendiscord:no-compile":ODFlag,
"opendiscord:compile-only":ODFlag,
"opendiscord:silent":ODFlag,
"opendiscord:cli":ODFlag,
}
/**## ODFlagManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODFlagManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.flags`!
*/
export class ODFlagManager_Default extends ODFlagManager {
get<FlagId extends keyof ODFlagManagerIds_Default>(id:FlagId): ODFlagManagerIds_Default[FlagId]
get(id:ODValidId): ODFlag|null
get(id:ODValidId): ODFlag|null {
return super.get(id)
}
remove<FlagId extends keyof ODFlagManagerIds_Default>(id:FlagId): ODFlagManagerIds_Default[FlagId]
remove(id:ODValidId): ODFlag|null
remove(id:ODValidId): ODFlag|null {
return super.remove(id)
}
exists(id:keyof ODFlagManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-338
View File
@@ -1,338 +0,0 @@
///////////////////////////////////////
//DEFAULT HELP MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODHelpMenuCategory, ODHelpMenuCommandComponent, ODHelpMenuComponent, ODHelpMenuManager } from "../modules/helpmenu"
/** (CONTRIBUTOR GUIDE) HOW TO ADD NEW COMMANDS?
* - Register the command in loadAllSlashCommands() & loadAllTextCommands() in (./src/data/framework/commandLoader.ts)
* - Add autocomplete for the command in OD(Slash/Text)CommandManagerIds_Default in (./src/core/api/defaults/client.ts)
* - Add the command to the help menu in (./src/data/framework/helpMenuLoader.ts)
* - If required, new config variables should be added (incl. logs, dm-logs & permissions).
* - Update the Open Ticket Documentation.
* - If the command contains complex logic or can be executed from a button/dropdown, it should be placed inside an `ODAction`.
* - Check all files, test the bot carefully & try a lot of different scenario's with different settings.
*/
/**## ODHelpMenuManagerIds_Default `interface`
* This interface is a list of ids available in the `ODHelpMenuManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerIds_Default {
"opendiscord:general":ODHelpMenuCategory_DefaultGeneral,
"opendiscord:ticket-basic":ODHelpMenuCategory_DefaultTicketBasic,
"opendiscord:ticket-advanced":ODHelpMenuCategory_DefaultTicketAdvanced,
"opendiscord:ticket-user":ODHelpMenuCategory_DefaultTicketUser,
"opendiscord:admin":ODHelpMenuCategory_DefaultAdmin,
"opendiscord:advanced":ODHelpMenuCategory_DefaultAdvanced,
"opendiscord:extra":ODHelpMenuCategory_DefaultExtra
}
/**## ODHelpMenuManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.helpmenu`!
*/
export class ODHelpMenuManager_Default extends ODHelpMenuManager {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerIds_Default>(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuCategory|null
get(id:ODValidId): ODHelpMenuCategory|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerIds_Default>(id:HelpMenuCategoryId): ODHelpMenuManagerIds_Default[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuCategory|null
remove(id:ODValidId): ODHelpMenuCategory|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultGeneral `type`
* This interface is a list of ids available in the `ODHelpMenuCategory_DefaultGeneral` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultGeneral {
"opendiscord:help":ODHelpMenuCommandComponent,
"opendiscord:ticket":ODHelpMenuCommandComponent|null
}
/**## ODHelpMenuCategory_DefaultGeneral `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:general` category in `opendiscord.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultGeneral extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultGeneral>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultGeneral>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultGeneral[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultGeneral): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultTicketBasic `type`
* This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketBasic` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultTicketBasic {
"opendiscord:close":ODHelpMenuCommandComponent,
"opendiscord:delete":ODHelpMenuCommandComponent,
"opendiscord:reopen":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultTicketBasic `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultTicketBasic extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketBasic[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketBasic): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced `type`
* This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketAdvanced` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced {
"opendiscord:pin":ODHelpMenuCommandComponent,
"opendiscord:unpin":ODHelpMenuCommandComponent,
"opendiscord:move":ODHelpMenuCommandComponent,
"opendiscord:rename":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultTicketAdvanced `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultTicketAdvanced extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketAdvanced): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultTicketUser `type`
* This interface is a list of ids available in the `ODHelpMenuCategory_DefaultTicketUser` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultTicketUser {
"opendiscord:claim":ODHelpMenuCommandComponent,
"opendiscord:unclaim":ODHelpMenuCommandComponent,
"opendiscord:add":ODHelpMenuCommandComponent,
"opendiscord:remove":ODHelpMenuCommandComponent,
"opendiscord:transfer":ODHelpMenuCommandComponent,
}
/**## ODHelpMenuCategory_DefaultTicketUser `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:ticket` category in `opendiscord.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultTicketUser extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultTicketUser[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultTicketUser): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultAdmin `type`
* This interface is a list of ids available in the `ODHelpMenuCategory_DefaultAdmin` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultAdmin {
"opendiscord:panel":ODHelpMenuCommandComponent,
"opendiscord:blacklist-view":ODHelpMenuCommandComponent,
"opendiscord:blacklist-add":ODHelpMenuCommandComponent,
"opendiscord:blacklist-remove":ODHelpMenuCommandComponent,
"opendiscord:blacklist-get":ODHelpMenuCommandComponent
}
/**## ODHelpMenuCategory_DefaultAdmin `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:admin` category in `opendiscord.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultAdmin extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdmin>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdmin>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdmin[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultAdmin): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultAdvanced `type`
* This interface is a list of ids available in the `ODHelpMenuCategory_DefaultAdvanced` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultAdvanced {
"opendiscord:stats-global":ODHelpMenuCommandComponent,
"opendiscord:stats-reset":ODHelpMenuCommandComponent,
"opendiscord:stats-ticket":ODHelpMenuCommandComponent,
"opendiscord:stats-user":ODHelpMenuCommandComponent,
"opendiscord:autoclose-disable":ODHelpMenuCommandComponent,
"opendiscord:autoclose-enable":ODHelpMenuCommandComponent,
"opendiscord:autodelete-disable":ODHelpMenuCommandComponent,
"opendiscord:autodelete-enable":ODHelpMenuCommandComponent,
"opendiscord:topic-set":ODHelpMenuCommandComponent,
"opendiscord:priority-set":ODHelpMenuCommandComponent,
}
/**## ODHelpMenuCategory_DefaultAdvanced `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:advanced` category in `opendiscord.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultAdvanced extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultAdvanced>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultAdvanced[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultAdvanced): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODHelpMenuManagerCategoryIds_DefaultExtra `type`
* This interface is a list of ids available in the `ODHelpMenuCategory_DefaultExtra` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODHelpMenuManagerCategoryIds_DefaultExtra {}
/**## ODHelpMenuCategory_DefaultExtra `default_class`
* This is a special class that adds type definitions & typescript to the ODHelpMenuManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:general` category in `opendiscord.helpmenu`!
*/
export class ODHelpMenuCategory_DefaultExtra extends ODHelpMenuCategory {
get<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultExtra>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId]
get(id:ODValidId): ODHelpMenuComponent|null
get(id:ODValidId): ODHelpMenuComponent|null {
return super.get(id)
}
remove<HelpMenuCategoryId extends keyof ODHelpMenuManagerCategoryIds_DefaultExtra>(id:HelpMenuCategoryId): ODHelpMenuManagerCategoryIds_DefaultExtra[HelpMenuCategoryId]
remove(id:ODValidId): ODHelpMenuComponent|null
remove(id:ODValidId): ODHelpMenuComponent|null {
return super.remove(id)
}
exists(id:keyof ODHelpMenuManagerCategoryIds_DefaultExtra): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-31
View File
@@ -1,31 +0,0 @@
///////////////////////////////////////
//DEFAULT PERMISSION MODULE
///////////////////////////////////////
import { ODDebugger } from "../modules/console"
import { ODPermissionManager } from "../modules/permission"
import { ODClientManager_Default } from "./client"
/**## ODPermissionManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODPermissionManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.permissions`!
*/
export class ODPermissionManager_Default extends ODPermissionManager {
constructor(debug:ODDebugger,client:ODClientManager_Default){
super(debug,client,true)
}
}
/**## ODPermissionEmbedType `type`
* This type contains all types available in the `opendiscord:no-permissions` embed.
*/
export type ODPermissionEmbedType = (
"developer"|
"owner"|
"admin"|
"moderator"|
"support"|
"member"|
"discord-administrator"
)
-77
View File
@@ -1,77 +0,0 @@
///////////////////////////////////////
//DEFAULT POST MODULE
///////////////////////////////////////
import { ODValidId, ODManagerData } from "../modules/base"
import { ODPlugin, ODPluginClassManager, ODPluginManager } from "../modules/plugin"
/**## ODPluginManagerIds_Default `interface`
* This interface is a list of ids available in the `ODPluginManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODPluginManagerIds_Default {}
/**## ODPluginManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODPluginManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.plugins`!
*/
export class ODPluginManager_Default extends ODPluginManager {
declare classes: ODPluginClassManager_Default
get<PluginId extends keyof ODPluginManagerIds_Default>(id:PluginId): ODPluginManagerIds_Default[PluginId]
get(id:ODValidId): ODPlugin|null
get(id:ODValidId): ODPlugin|null {
return super.get(id)
}
remove<PluginId extends keyof ODPluginManagerIds_Default>(id:PluginId): ODPluginManagerIds_Default[PluginId]
remove(id:ODValidId): ODPlugin|null
remove(id:ODValidId): ODPlugin|null {
return super.remove(id)
}
exists(id:keyof ODPluginManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODPluginClassManagerIds_Default `interface`
* This interface is a list of ids available in the `ODPluginClassManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODPluginClassManagerIds_Default {}
/**## ODPluginClassManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODPluginClassManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.plugins.classes`!
*/
export class ODPluginClassManager_Default extends ODPluginClassManager {
get<PluginClassId extends keyof ODPluginClassManagerIds_Default>(id:PluginClassId): ODPluginClassManagerIds_Default[PluginClassId]
get(id:ODValidId): ODManagerData|null
get(id:ODValidId): ODManagerData|null {
return super.get(id)
}
remove<PluginClassId extends keyof ODPluginClassManagerIds_Default>(id:PluginClassId): ODPluginClassManagerIds_Default[PluginClassId]
remove(id:ODValidId): ODManagerData|null
remove(id:ODValidId): ODManagerData|null {
return super.remove(id)
}
exists(id:keyof ODPluginClassManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-44
View File
@@ -1,44 +0,0 @@
///////////////////////////////////////
//DEFAULT POST MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODPost, ODPostManager } from "../modules/post"
import * as discord from "discord.js"
/**## ODPostManagerIds_Default `interface`
* This interface is a list of ids available in the `ODPostManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODPostManagerIds_Default {
"opendiscord:logs":ODPost<discord.GuildTextBasedChannel>|null,
"opendiscord:transcripts":ODPost<discord.GuildTextBasedChannel>|null
}
/**## ODPostManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODPostManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.code`!
*/
export class ODPostManager_Default extends ODPostManager {
get<PostId extends keyof ODPostManagerIds_Default>(id:PostId): ODPostManagerIds_Default[PostId]
get(id:ODValidId): ODPost<discord.GuildBasedChannel>|null
get(id:ODValidId): ODPost<discord.GuildBasedChannel>|null {
return super.get(id)
}
remove<PostId extends keyof ODPostManagerIds_Default>(id:PostId): ODPostManagerIds_Default[PostId]
remove(id:ODValidId): ODPost<discord.GuildBasedChannel>|null
remove(id:ODValidId): ODPost<discord.GuildBasedChannel>|null {
return super.remove(id)
}
exists(id:keyof ODPostManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-171
View File
@@ -1,171 +0,0 @@
///////////////////////////////////////
//DEFAULT PROGRESS BAR MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODValidConsoleColor } from "../modules/console"
import { ODManualProgressBar, ODProgressBar, ODProgressBarManager, ODProgressBarRenderer, ODProgressBarRendererManager } from "../modules/progressbar"
import ansis from "ansis"
/**## ODProgressBarRenderer_DefaultSettingsLabel `type`
* All available label types for the default progress bar renderer
*/
export type ODProgressBarRenderer_DefaultSettingsLabel = "value"|"percentage"|"fraction"|"time-ms"|"time-sec"|"time-min"
/**## ODProgressBarRenderer_DefaultSettings `interface`
* This interface contains the settings for the default progress bar renderer.
*/
export interface ODProgressBarRenderer_DefaultSettings {
/**The color of the progress bar border. */
borderColor:ODValidConsoleColor|"openticket",
/**The color of the progress bar (filled side). */
filledBarColor:ODValidConsoleColor|"openticket",
/**The color of the progress bar (empty side). */
emptyBarColor:ODValidConsoleColor|"openticket",
/**The color of the text before the progress bar. */
prefixColor:ODValidConsoleColor|"openticket",
/**The color of the text after the progress bar. */
suffixColor:ODValidConsoleColor|"openticket",
/**The color of the progress bar label. */
labelColor:ODValidConsoleColor|"openticket",
/**The character used in the left border. */
leftBorderChar:string,
/**The character used in the right border. */
rightBorderChar:string,
/**The character used in the filled side of the progress bar. */
filledBarChar:string,
/**The character used in the empty side of the progress bar. */
emptyBarChar:string,
/**The label type. (will show a number related to the progress) */
labelType:ODProgressBarRenderer_DefaultSettingsLabel,
/**The position of the label. */
labelPosition:"start"|"end",
/**The width of the bar. (50 characters by default) */
barWidth:number,
/**Show the bar. */
showBar:boolean,
/**Show the label. */
showLabel:boolean,
/**Show the border. */
showBorder:boolean,
}
export class ODProgressBarRenderer_Default extends ODProgressBarRenderer<ODProgressBarRenderer_DefaultSettings> {
constructor(id:ODValidId,settings:ODProgressBarRenderer_DefaultSettings){
super(id,(settings,min,max,value,rawPrefix,rawSuffix) => {
const percentage = (value-min)/(max-min)
const barLevel = Math.round(percentage*settings.barWidth)
const borderAnsis = (settings.borderColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.borderColor]
const filledBarAnsis = (settings.filledBarColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.filledBarColor]
const emptyBarAnsis = (settings.emptyBarColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.emptyBarColor]
const labelAnsis = (settings.labelColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.labelColor]
const prefixAnsis = (settings.prefixColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.prefixColor]
const suffixAnsis = (settings.suffixColor == "openticket") ? ansis.hex("#f8ba00") : ansis[settings.suffixColor]
const leftBorder = (settings.showBorder) ? borderAnsis(settings.leftBorderChar) : ""
const rightBorder = (settings.showBorder) ? borderAnsis(settings.rightBorderChar) : ""
const bar = (settings.showBar) ? filledBarAnsis(settings.filledBarChar.repeat(barLevel))+emptyBarAnsis(settings.emptyBarChar.repeat(settings.barWidth-barLevel)) : ""
const prefix = (rawPrefix) ? prefixAnsis(rawPrefix)+" " : ""
const suffix = (rawSuffix) ? " "+suffixAnsis(rawSuffix) : ""
let label: string
if (!settings.showLabel) label = ""
if (settings.labelType == "fraction") label = labelAnsis(value+"/"+max)
else if (settings.labelType == "percentage") label = labelAnsis(Math.round(percentage*100)+"%")
else if (settings.labelType == "time-ms") label = labelAnsis(value+"ms")
else if (settings.labelType == "time-sec") label = labelAnsis(Math.round(value*10)/10+"sec")
else if (settings.labelType == "time-min") label = labelAnsis(Math.round(value*10)/10+"min")
else label = labelAnsis(value.toString())
const labelWithPrefixAndSuffix = prefix+label+suffix
return (settings.labelPosition == "start") ? labelWithPrefixAndSuffix+" "+leftBorder+bar+rightBorder : leftBorder+bar+rightBorder+" "+labelWithPrefixAndSuffix
},settings)
}
}
/**## ODProgressBarRendererManagerIds_Default `interface`
* This interface is a list of ids available in the `ODProgressBarRendererManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODProgressBarRendererManagerIds_Default {
"opendiscord:value-renderer":ODProgressBarRenderer_Default,
"opendiscord:fraction-renderer":ODProgressBarRenderer_Default,
"opendiscord:percentage-renderer":ODProgressBarRenderer_Default,
"opendiscord:time-ms-renderer":ODProgressBarRenderer_Default,
"opendiscord:time-sec-renderer":ODProgressBarRenderer_Default,
"opendiscord:time-min-renderer":ODProgressBarRenderer_Default,
}
/**## ODProgressBarRendererManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODProgressBarRendererManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.progressbars.renderers`!
*/
export class ODProgressBarRendererManager_Default extends ODProgressBarRendererManager {
get<ProgressBarId extends keyof ODProgressBarRendererManagerIds_Default>(id:ProgressBarId): ODProgressBarRendererManagerIds_Default[ProgressBarId]
get(id:ODValidId): ODProgressBarRenderer<{}>|null
get(id:ODValidId): ODProgressBarRenderer<{}>|null {
return super.get(id)
}
remove<ProgressBarId extends keyof ODProgressBarRendererManagerIds_Default>(id:ProgressBarId): ODProgressBarRendererManagerIds_Default[ProgressBarId]
remove(id:ODValidId): ODProgressBarRenderer<{}>|null
remove(id:ODValidId): ODProgressBarRenderer<{}>|null {
return super.remove(id)
}
exists(id:keyof ODProgressBarRendererManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODProgressBarManagerIds_Default `interface`
* This interface is a list of ids available in the `ODProgressBarManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODProgressBarManagerIds_Default {
"opendiscord:slash-command-remove":ODManualProgressBar,
"opendiscord:slash-command-create":ODManualProgressBar,
"opendiscord:slash-command-update":ODManualProgressBar,
"opendiscord:context-menu-remove":ODManualProgressBar,
"opendiscord:context-menu-create":ODManualProgressBar,
"opendiscord:context-menu-update":ODManualProgressBar,
}
/**## ODProgressBarManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODProgressBarManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.progressbars`!
*/
export class ODProgressBarManager_Default extends ODProgressBarManager {
declare renderers: ODProgressBarRendererManager_Default
get<ProgressBarId extends keyof ODProgressBarManagerIds_Default>(id:ProgressBarId): ODProgressBarManagerIds_Default[ProgressBarId]
get(id:ODValidId): ODProgressBar|null
get(id:ODValidId): ODProgressBar|null {
return super.get(id)
}
remove<ProgressBarId extends keyof ODProgressBarManagerIds_Default>(id:ProgressBarId): ODProgressBarManagerIds_Default[ProgressBarId]
remove(id:ODValidId): ODProgressBar|null
remove(id:ODValidId): ODProgressBar|null {
return super.remove(id)
}
exists(id:keyof ODProgressBarManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-355
View File
@@ -1,355 +0,0 @@
///////////////////////////////////////
//DEFAULT RESPONDER MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODAutocompleteResponder, ODAutocompleteResponderInstance, ODAutocompleteResponderManager, ODButtonResponder, ODButtonResponderInstance, ODButtonResponderManager, ODCommandResponder, ODCommandResponderInstance, ODCommandResponderManager, ODContextMenuResponder, ODContextMenuResponderInstance, ODContextMenuResponderManager, ODDropdownResponder, ODDropdownResponderInstance, ODDropdownResponderManager, ODModalResponder, ODModalResponderInstance, ODModalResponderManager, ODResponderManager } from "../modules/responder"
import { ODWorkerManager_Default } from "./worker"
/**## ODResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders`!
*/
export class ODResponderManager_Default extends ODResponderManager {
declare commands: ODCommandResponderManager_Default
declare buttons: ODButtonResponderManager_Default
declare dropdowns: ODDropdownResponderManager_Default
declare modals: ODModalResponderManager_Default
declare contextMenus: ODContextMenuResponderManager_Default
declare autocomplete: ODAutocompleteResponderManager_Default
}
/**## ODCommandResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODCommandResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODCommandResponderManagerIds_Default {
"opendiscord:help":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:help"|"opendiscord:logs"},
"opendiscord:stats":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:stats"|"opendiscord:logs"},
"opendiscord:panel":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:panel"|"opendiscord:logs"},
"opendiscord:ticket":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:ticket"|"opendiscord:logs"},
"opendiscord:blacklist":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:blacklist"|"opendiscord:discord-logs"|"opendiscord:logs"},
"opendiscord:close":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:close"|"opendiscord:logs"},
"opendiscord:reopen":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:reopen"|"opendiscord:logs"},
"opendiscord:delete":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:delete"|"opendiscord:logs"},
"opendiscord:claim":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:claim"|"opendiscord:logs"},
"opendiscord:unclaim":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:unclaim"|"opendiscord:logs"},
"opendiscord:pin":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:pin"|"opendiscord:logs"},
"opendiscord:unpin":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:unpin"|"opendiscord:logs"},
"opendiscord:rename":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:rename"|"opendiscord:logs"},
"opendiscord:move":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:move"|"opendiscord:logs"},
"opendiscord:add":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:add"|"opendiscord:logs"},
"opendiscord:remove":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:remove"|"opendiscord:logs"},
"opendiscord:clear":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:clear"|"opendiscord:logs"},
"opendiscord:topic":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:topic"|"opendiscord:logs"},
"opendiscord:priority":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:priority"|"opendiscord:logs"},
"opendiscord:transfer":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:transfer"|"opendiscord:logs"},
"opendiscord:autoclose":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:autoclose"|"opendiscord:logs"},
"opendiscord:autodelete":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:autodelete"|"opendiscord:logs"},
}
/**## ODCommandResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCommandResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.commands`!
*/
export class ODCommandResponderManager_Default extends ODCommandResponderManager {
get<CommandResponderId extends keyof ODCommandResponderManagerIds_Default>(id:CommandResponderId): ODCommandResponder_Default<ODCommandResponderManagerIds_Default[CommandResponderId]["source"],ODCommandResponderManagerIds_Default[CommandResponderId]["params"],ODCommandResponderManagerIds_Default[CommandResponderId]["workers"]>
get(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null
get(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null {
return super.get(id)
}
remove<CommandResponderId extends keyof ODCommandResponderManagerIds_Default>(id:CommandResponderId): ODCommandResponder_Default<ODCommandResponderManagerIds_Default[CommandResponderId]["source"],ODCommandResponderManagerIds_Default[CommandResponderId]["params"],ODCommandResponderManagerIds_Default[CommandResponderId]["workers"]>
remove(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null
remove(id:ODValidId): ODCommandResponder<"slash"|"text",any>|null {
return super.remove(id)
}
exists(id:keyof ODCommandResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODCommandResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODCommandResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODCommandResponder`'s!
*/
export class ODCommandResponder_Default<Source extends "slash"|"text", Params, WorkerIds extends string> extends ODCommandResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODCommandResponderInstance,Source,Params,WorkerIds>
}
/**## ODButtonResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODButtonResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODButtonResponderManagerIds_Default {
"opendiscord:verifybar-success":{source:"button",params:{},workers:"opendiscord:handle-verifybar"},
"opendiscord:verifybar-failure":{source:"button",params:{},workers:"opendiscord:handle-verifybar"},
"opendiscord:help-menu-switch":{source:"button",params:{},workers:"opendiscord:update-help-menu"},
"opendiscord:help-menu-previous":{source:"button",params:{},workers:"opendiscord:update-help-menu"},
"opendiscord:help-menu-next":{source:"button",params:{},workers:"opendiscord:update-help-menu"},
"opendiscord:ticket-option":{source:"button",params:{},workers:"opendiscord:ticket-option"},
"opendiscord:role-option":{source:"button",params:{},workers:"opendiscord:role-option"},
"opendiscord:claim-ticket":{source:"button",params:{},workers:"opendiscord:claim-ticket"},
"opendiscord:unclaim-ticket":{source:"button",params:{},workers:"opendiscord:unclaim-ticket"},
"opendiscord:pin-ticket":{source:"button",params:{},workers:"opendiscord:pin-ticket"},
"opendiscord:unpin-ticket":{source:"button",params:{},workers:"opendiscord:unpin-ticket"},
"opendiscord:close-ticket":{source:"button",params:{},workers:"opendiscord:close-ticket"},
"opendiscord:reopen-ticket":{source:"button",params:{},workers:"opendiscord:reopen-ticket"},
"opendiscord:delete-ticket":{source:"button",params:{},workers:"opendiscord:delete-ticket"},
"opendiscord:transcript-error-retry":{source:"button",params:{},workers:"opendiscord:permissions"|"opendiscord:delete-ticket"|"opendiscord:logs"},
"opendiscord:transcript-error-continue":{source:"button",params:{},workers:"opendiscord:permissions"|"opendiscord:delete-ticket"|"opendiscord:logs"},
"opendiscord:clear-continue":{source:"button",params:{},workers:"opendiscord:clear-continue"},
}
/**## ODButtonResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButtonResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.buttons`!
*/
export class ODButtonResponderManager_Default extends ODButtonResponderManager {
get<ButtonResponderId extends keyof ODButtonResponderManagerIds_Default>(id:ButtonResponderId): ODButtonResponder_Default<ODButtonResponderManagerIds_Default[ButtonResponderId]["source"],ODButtonResponderManagerIds_Default[ButtonResponderId]["params"],ODButtonResponderManagerIds_Default[ButtonResponderId]["workers"]>
get(id:ODValidId): ODButtonResponder<"button",any>|null
get(id:ODValidId): ODButtonResponder<"button",any>|null {
return super.get(id)
}
remove<ButtonResponderId extends keyof ODButtonResponderManagerIds_Default>(id:ButtonResponderId): ODButtonResponder_Default<ODButtonResponderManagerIds_Default[ButtonResponderId]["source"],ODButtonResponderManagerIds_Default[ButtonResponderId]["params"],ODButtonResponderManagerIds_Default[ButtonResponderId]["workers"]>
remove(id:ODValidId): ODButtonResponder<"button",any>|null
remove(id:ODValidId): ODButtonResponder<"button",any>|null {
return super.remove(id)
}
exists(id:keyof ODButtonResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODButtonResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODButtonResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODButtonResponder`'s!
*/
export class ODButtonResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODButtonResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODButtonResponderInstance,Source,Params,WorkerIds>
}
/**## ODDropdownResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODDropdownResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDropdownResponderManagerIds_Default {
"opendiscord:panel-dropdown-tickets":{source:"dropdown",params:{},workers:"opendiscord:panel-dropdown-tickets"},
}
/**## ODDropdownResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdownResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.dropdowns`!
*/
export class ODDropdownResponderManager_Default extends ODDropdownResponderManager {
get<DropdownResponderId extends keyof ODDropdownResponderManagerIds_Default>(id:DropdownResponderId): ODDropdownResponder_Default<ODDropdownResponderManagerIds_Default[DropdownResponderId]["source"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["params"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["workers"]>
get(id:ODValidId): ODDropdownResponder<"dropdown",any>|null
get(id:ODValidId): ODDropdownResponder<"dropdown",any>|null {
return super.get(id)
}
remove<DropdownResponderId extends keyof ODDropdownResponderManagerIds_Default>(id:DropdownResponderId): ODDropdownResponder_Default<ODDropdownResponderManagerIds_Default[DropdownResponderId]["source"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["params"],ODDropdownResponderManagerIds_Default[DropdownResponderId]["workers"]>
remove(id:ODValidId): ODDropdownResponder<"dropdown",any>|null
remove(id:ODValidId): ODDropdownResponder<"dropdown",any>|null {
return super.remove(id)
}
exists(id:keyof ODDropdownResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODDropdownResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODDropdownResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODDropdownResponder`'s!
*/
export class ODDropdownResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODDropdownResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODDropdownResponderInstance,Source,Params,WorkerIds>
}
/**## ODModalResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODModalResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODModalResponderManagerIds_Default {
"opendiscord:ticket-questions":{source:"modal",params:{},workers:"opendiscord:ticket-questions"},
"opendiscord:close-ticket-reason":{source:"modal",params:{},workers:"opendiscord:close-ticket-reason"},
"opendiscord:reopen-ticket-reason":{source:"modal",params:{},workers:"opendiscord:reopen-ticket-reason"},
"opendiscord:delete-ticket-reason":{source:"modal",params:{},workers:"opendiscord:delete-ticket-reason"},
"opendiscord:claim-ticket-reason":{source:"modal",params:{},workers:"opendiscord:claim-ticket-reason"},
"opendiscord:unclaim-ticket-reason":{source:"modal",params:{},workers:"opendiscord:unclaim-ticket-reason"},
"opendiscord:pin-ticket-reason":{source:"modal",params:{},workers:"opendiscord:pin-ticket-reason"},
"opendiscord:unpin-ticket-reason":{source:"modal",params:{},workers:"opendiscord:unpin-ticket-reason"},
}
/**## ODModalResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModalResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.dropdowns`!
*/
export class ODModalResponderManager_Default extends ODModalResponderManager {
get<ModalResponderId extends keyof ODModalResponderManagerIds_Default>(id:ModalResponderId): ODModalResponder_Default<ODModalResponderManagerIds_Default[ModalResponderId]["source"],ODModalResponderManagerIds_Default[ModalResponderId]["params"],ODModalResponderManagerIds_Default[ModalResponderId]["workers"]>
get(id:ODValidId): ODModalResponder<"modal",any>|null
get(id:ODValidId): ODModalResponder<"modal",any>|null {
return super.get(id)
}
remove<ModalResponderId extends keyof ODModalResponderManagerIds_Default>(id:ModalResponderId): ODModalResponder_Default<ODModalResponderManagerIds_Default[ModalResponderId]["source"],ODModalResponderManagerIds_Default[ModalResponderId]["params"],ODModalResponderManagerIds_Default[ModalResponderId]["workers"]>
remove(id:ODValidId): ODModalResponder<"modal",any>|null
remove(id:ODValidId): ODModalResponder<"modal",any>|null {
return super.remove(id)
}
exists(id:keyof ODModalResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODModalResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODModalResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODModalResponder`'s!
*/
export class ODModalResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODModalResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODModalResponderInstance,Source,Params,WorkerIds>
}
/**## ODContextMenuResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODContextMenuResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODContextMenuResponderManagerIds_Default {
//"opendiscord:example":{source:"context-menu",params:{},workers:"opendiscord:example"},
}
/**## ODContextMenuResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODContextMenuResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.contextMenus`!
*/
export class ODContextMenuResponderManager_Default extends ODContextMenuResponderManager {
get<ModalResponderId extends keyof ODContextMenuResponderManagerIds_Default>(id:ModalResponderId): ODContextMenuResponder_Default<ODContextMenuResponderManagerIds_Default[ModalResponderId]["source"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["params"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["workers"]>
get(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null
get(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null {
return super.get(id)
}
remove<ModalResponderId extends keyof ODContextMenuResponderManagerIds_Default>(id:ModalResponderId): ODContextMenuResponder_Default<ODContextMenuResponderManagerIds_Default[ModalResponderId]["source"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["params"],ODContextMenuResponderManagerIds_Default[ModalResponderId]["workers"]>
remove(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null
remove(id:ODValidId): ODContextMenuResponder<"context-menu",any>|null {
return super.remove(id)
}
exists(id:keyof ODContextMenuResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODContextMenuResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODContextMenuResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODContextMenuResponder`'s!
*/
export class ODContextMenuResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODContextMenuResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODContextMenuResponderInstance,Source,Params,WorkerIds>
}
/**## ODAutocompleteResponderManagerIds_Default `interface`
* This interface is a list of ids available in the `ODAutocompleteResponderManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODAutocompleteResponderManagerIds_Default {
"opendiscord:panel-id":{source:"autocomplete",params:{},workers:"opendiscord:panel-id"},
"opendiscord:option-id":{source:"autocomplete",params:{},workers:"opendiscord:option-id"}
}
/**## ODAutocompleteResponderManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODAutocompleteResponderManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.responders.autocomplete`!
*/
export class ODAutocompleteResponderManager_Default extends ODAutocompleteResponderManager {
get<ModalResponderId extends keyof ODAutocompleteResponderManagerIds_Default>(id:ModalResponderId): ODAutocompleteResponder_Default<ODAutocompleteResponderManagerIds_Default[ModalResponderId]["source"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["params"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["workers"]>
get(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null
get(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null {
return super.get(id)
}
remove<ModalResponderId extends keyof ODAutocompleteResponderManagerIds_Default>(id:ModalResponderId): ODAutocompleteResponder_Default<ODAutocompleteResponderManagerIds_Default[ModalResponderId]["source"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["params"],ODAutocompleteResponderManagerIds_Default[ModalResponderId]["workers"]>
remove(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null
remove(id:ODValidId): ODAutocompleteResponder<"autocomplete",any>|null {
return super.remove(id)
}
exists(id:keyof ODAutocompleteResponderManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODAutocompleteResponder_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODAutocompleteResponder class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODAutocompleteResponder`'s!
*/
export class ODAutocompleteResponder_Default<Source extends string, Params, WorkerIds extends string> extends ODAutocompleteResponder<Source,Params> {
declare workers: ODWorkerManager_Default<ODAutocompleteResponderInstance,Source,Params,WorkerIds>
}
-42
View File
@@ -1,42 +0,0 @@
///////////////////////////////////////
//DEFAULT SESSION MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODSession, ODSessionManager } from "../modules/session"
/**## ODSessionManagerIds_Default `interface`
* This interface is a list of ids available in the `ODSessionManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODSessionManagerIds_Default {
//"test-session":ODSession
}
/**## ODSessionManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODSessionManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.sessions`!
*/
export class ODSessionManager_Default extends ODSessionManager {
get<SessionId extends keyof ODSessionManagerIds_Default>(id:SessionId): ODSessionManagerIds_Default[SessionId]
get(id:ODValidId): ODSession|null
get(id:ODValidId): ODSession|null {
return super.get(id)
}
remove<SessionId extends keyof ODSessionManagerIds_Default>(id:SessionId): ODSessionManagerIds_Default[SessionId]
remove(id:ODValidId): ODSession|null
remove(id:ODValidId): ODSession|null {
return super.remove(id)
}
exists(id:keyof ODSessionManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-48
View File
@@ -1,48 +0,0 @@
///////////////////////////////////////
//DEFAULT STARTSCREEN MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODStartScreenCategoryComponent, ODStartScreenComponent, ODStartScreenFlagsCategoryComponent, ODStartScreenHeaderComponent, ODStartScreenLiveStatusCategoryComponent, ODStartScreenLogoComponent, ODStartScreenManager, ODStartScreenPluginsCategoryComponent, ODStartScreenPropertiesCategoryComponent } from "../modules/startscreen"
/**## ODStartScreenManagerIds_Default `interface`
* This interface is a list of ids available in the `ODStartScreenManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStartScreenManagerIds_Default {
"opendiscord:logo":ODStartScreenLogoComponent,
"opendiscord:header":ODStartScreenHeaderComponent,
"opendiscord:flags":ODStartScreenFlagsCategoryComponent,
"opendiscord:plugins":ODStartScreenPluginsCategoryComponent,
"opendiscord:stats":ODStartScreenPropertiesCategoryComponent,
"opendiscord:livestatus":ODStartScreenLiveStatusCategoryComponent,
"opendiscord:logs":ODStartScreenCategoryComponent
}
/**## ODStartScreenManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODStartScreenManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.startscreen`!
*/
export class ODStartScreenManager_Default extends ODStartScreenManager {
get<StartScreenId extends keyof ODStartScreenManagerIds_Default>(id:StartScreenId): ODStartScreenManagerIds_Default[StartScreenId]
get(id:ODValidId): ODStartScreenComponent|null
get(id:ODValidId): ODStartScreenComponent|null {
return super.get(id)
}
remove<StartScreenId extends keyof ODStartScreenManagerIds_Default>(id:StartScreenId): ODStartScreenManagerIds_Default[StartScreenId]
remove(id:ODValidId): ODStartScreenComponent|null
remove(id:ODValidId): ODStartScreenComponent|null {
return super.remove(id)
}
exists(id:keyof ODStartScreenManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-472
View File
@@ -1,472 +0,0 @@
///////////////////////////////////////
//DEFAULT SESSION MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODStatScope, ODStatGlobalScope, ODStatsManager, ODStat, ODBasicStat, ODDynamicStat, ODValidStatValue, ODStatScopeSetMode } from "../modules/stat"
/**## ODStatsManagerIds_Default `interface`
* This interface is a list of ids available in the `ODStatsManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatsManagerIds_Default {
"opendiscord:global":ODStatGlobalScope_DefaultGlobal,
"opendiscord:system":ODStatGlobalScope_DefaultSystem,
"opendiscord:user":ODStatScope_DefaultUser,
"opendiscord:ticket":ODStatScope_DefaultTicket,
"opendiscord:participants":ODStatScope_DefaultParticipants,
"opendiscord:messages":ODStatScope_DefaultMessages,
}
/**## ODStatsManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.stats`!
*/
export class ODStatsManager_Default extends ODStatsManager {
get<StatsId extends keyof ODStatsManagerIds_Default>(id:StatsId): ODStatsManagerIds_Default[StatsId]
get(id:ODValidId): ODStatScope|null
get(id:ODValidId): ODStatScope|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatsManagerIds_Default>(id:StatsId): ODStatsManagerIds_Default[StatsId]
remove(id:ODValidId): ODStatScope|null
remove(id:ODValidId): ODStatScope|null {
return super.remove(id)
}
exists(id:keyof ODStatsManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODStatGlobalScopeIds_DefaultGlobal `type`
* This interface is a list of ids available in the `ODStatGlobalScope_DefaultGlobal` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatGlobalScopeIds_DefaultGlobal {
"opendiscord:tickets-created":ODBasicStat,
"opendiscord:tickets-closed":ODBasicStat,
"opendiscord:tickets-deleted":ODBasicStat,
"opendiscord:tickets-reopened":ODBasicStat,
"opendiscord:tickets-autoclosed":ODBasicStat,
"opendiscord:tickets-autodeleted":ODBasicStat,
"opendiscord:tickets-claimed":ODBasicStat,
"opendiscord:tickets-pinned":ODBasicStat,
"opendiscord:tickets-moved":ODBasicStat,
"opendiscord:tickets-transferred":ODBasicStat,
"opendiscord:users-blacklisted":ODBasicStat,
"opendiscord:transcripts-created":ODBasicStat,
"opendiscord:ticket-volume":ODDynamicStat,
"opendiscord:average-tickets":ODDynamicStat,
}
/**## ODStatGlobalScope_DefaultGlobal `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:global` category in `opendiscord.stats`!
*/
export class ODStatGlobalScope_DefaultGlobal extends ODStatGlobalScope {
get<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId): ODStatGlobalScopeIds_DefaultGlobal[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatGlobalScopeIds_DefaultGlobal): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId): Promise<ODValidStatValue|null>
getStat(id:ODValidId): Promise<ODValidStatValue|null>
getStat(id:ODValidId): Promise<ODValidStatValue|null> {
return super.getStat(id)
}
getAllStats<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]> {
return super.getAllStats(id)
}
setStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean> {
return super.setStat(id,value,mode)
}
resetStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultGlobal>(id:ODValidId): Promise<ODValidStatValue|null>
resetStat(id:ODValidId): Promise<ODValidStatValue|null>
resetStat(id:ODValidId): Promise<ODValidStatValue|null> {
return super.resetStat(id)
}
}
/**## ODStatGlobalScopeIds_DefaultSystem `type`
* This interface is a list of ids available in the `ODStatScope_DefaultSystem` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatGlobalScopeIds_DefaultSystem {
"opendiscord:startup-date":ODDynamicStat,
"opendiscord:system-uptime":ODDynamicStat,
"opendiscord:version":ODDynamicStat
}
/**## ODStatGlobalScope_DefaultSystem `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:system` category in `opendiscord.stats`!
*/
export class ODStatGlobalScope_DefaultSystem extends ODStatGlobalScope {
get<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId): ODStatGlobalScopeIds_DefaultSystem[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatGlobalScopeIds_DefaultSystem): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId): Promise<ODValidStatValue|null>
getStat(id:ODValidId): Promise<ODValidStatValue|null>
getStat(id:ODValidId): Promise<ODValidStatValue|null> {
return super.getStat(id)
}
getAllStats<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]> {
return super.getAllStats(id)
}
setStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:StatsId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean> {
return super.setStat(id,value,mode)
}
resetStat<StatsId extends keyof ODStatGlobalScopeIds_DefaultSystem>(id:ODValidId): Promise<ODValidStatValue|null>
resetStat(id:ODValidId): Promise<ODValidStatValue|null>
resetStat(id:ODValidId): Promise<ODValidStatValue|null> {
return super.resetStat(id)
}
}
/**## ODStatScopeIds_DefaultUser `type`
* This interface is a list of ids available in the `ODStatScope_DefaultUser` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatScopeIds_DefaultUser {
"opendiscord:name":ODDynamicStat,
"opendiscord:role":ODDynamicStat,
"opendiscord:tickets-created":ODBasicStat,
"opendiscord:tickets-closed":ODBasicStat,
"opendiscord:tickets-deleted":ODBasicStat,
"opendiscord:tickets-reopened":ODBasicStat,
"opendiscord:tickets-claimed":ODBasicStat,
"opendiscord:tickets-pinned":ODBasicStat,
"opendiscord:tickets-moved":ODBasicStat,
"opendiscord:tickets-transferred":ODBasicStat,
"opendiscord:users-blacklisted":ODBasicStat,
"opendiscord:transcripts-created":ODBasicStat,
"opendiscord:current-tickets":ODDynamicStat,
}
/**## ODStatScope_DefaultUser `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:user` category in `opendiscord.stats`!
*/
export class ODStatScope_DefaultUser extends ODStatScope {
get<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId): ODStatScopeIds_DefaultUser[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId): ODStatScopeIds_DefaultUser[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatScopeIds_DefaultUser): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.getStat(id,scopeId)
}
getAllStats<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]> {
return super.getAllStats(id)
}
setStat<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean> {
return super.setStat(id,scopeId,value,mode)
}
resetStat<StatsId extends keyof ODStatScopeIds_DefaultUser>(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.resetStat(id,scopeId)
}
}
/**## ODStatScopeIds_DefaultTicket `type`
* This interface is a list of ids available in the `ODStatScope_DefaultTicket` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatScopeIds_DefaultTicket {
"opendiscord:name":ODDynamicStat,
"opendiscord:status":ODDynamicStat,
"opendiscord:claimed":ODDynamicStat,
"opendiscord:pinned":ODDynamicStat,
"opendiscord:creation-date":ODDynamicStat,
"opendiscord:creator":ODDynamicStat,
"opendiscord:ticket-age":ODDynamicStat,
"opendiscord:response-time":ODDynamicStat,
"opendiscord:resolution-time":ODDynamicStat,
}
/**## ODStatScope_DefaultTicket `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:ticket` category in `opendiscord.stats`!
*/
export class ODStatScope_DefaultTicket extends ODStatScope {
get<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId): ODStatScopeIds_DefaultTicket[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatScopeIds_DefaultTicket): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.getStat(id,scopeId)
}
getAllStats<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]> {
return super.getAllStats(id)
}
setStat<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean> {
return super.setStat(id,scopeId,value,mode)
}
resetStat<StatsId extends keyof ODStatScopeIds_DefaultTicket>(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.resetStat(id,scopeId)
}
}
/**## ODStatScopeIds_DefaultParticipants `type`
* This interface is a list of ids available in the `ODStatScope_DefaultParticipants` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatScopeIds_DefaultParticipants {
"opendiscord:participants":ODDynamicStat
}
/**## ODStatScope_DefaultParticipants `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:participants` category in `opendiscord.stats`!
*/
export class ODStatScope_DefaultParticipants extends ODStatScope {
get<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId): ODStatScopeIds_DefaultParticipants[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatScopeIds_DefaultParticipants): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.getStat(id,scopeId)
}
getAllStats<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]> {
return super.getAllStats(id)
}
setStat<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean> {
return super.setStat(id,scopeId,value,mode)
}
resetStat<StatsId extends keyof ODStatScopeIds_DefaultParticipants>(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.resetStat(id,scopeId)
}
}
/**## ODStatScopeIds_DefaultMessages `type`
* This interface is a list of ids available in the `ODStatScope_DefaultMessages` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODStatScopeIds_DefaultMessages {
"opendiscord:count":ODDynamicStat
}
/**## ODStatScope_DefaultMessages `default_class`
* This is a special class that adds type definitions & typescript to the ODStatsManager class.
* It doesn't add any extra features!
*
* This default class is made for the `opendiscord:participants` category in `opendiscord.stats`!
*/
export class ODStatScope_DefaultMessages extends ODStatScope {
get<StatsId extends keyof ODStatScopeIds_DefaultMessages>(id:StatsId): ODStatScopeIds_DefaultMessages[StatsId]
get(id:ODValidId): ODStat|null
get(id:ODValidId): ODStat|null {
return super.get(id)
}
remove<StatsId extends keyof ODStatScopeIds_DefaultMessages>(id:StatsId): ODStatScopeIds_DefaultMessages[StatsId]
remove(id:ODValidId): ODStat|null
remove(id:ODValidId): ODStat|null {
return super.remove(id)
}
exists(id:keyof ODStatScopeIds_DefaultMessages): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
getStat<StatsId extends keyof ODStatScopeIds_DefaultMessages>(id:StatsId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
getStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.getStat(id,scopeId)
}
getAllStats<StatsId extends keyof ODStatScopeIds_DefaultMessages>(id:StatsId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]>
getAllStats(id:ODValidId): Promise<{id:string,value:ODValidStatValue}[]> {
return super.getAllStats(id)
}
setStat<StatsId extends keyof ODStatScopeIds_DefaultMessages>(id:StatsId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean>
setStat(id:ODValidId, scopeId:string, value:ODValidStatValue, mode:ODStatScopeSetMode): Promise<boolean> {
return super.setStat(id,scopeId,value,mode)
}
resetStat<StatsId extends keyof ODStatScopeIds_DefaultMessages>(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null>
resetStat(id:ODValidId, scopeId:string): Promise<ODValidStatValue|null> {
return super.resetStat(id,scopeId)
}
}
-72
View File
@@ -1,72 +0,0 @@
///////////////////////////////////////
//DEFAULT VERIFYBAR MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODButtonResponderInstance } from "../modules/responder"
import { ODWorkerManager_Default } from "../defaults/worker"
import { ODVerifyBarManager, ODVerifyBar } from "../modules/verifybar"
import * as discord from "discord.js"
/**## ODVerifyBarManagerIds_Default `interface`
* This interface is a list of ids available in the `ODVerifyBarManager_Default` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODVerifyBarManagerIds_Default {
"opendiscord:claim-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:claim-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"},
"opendiscord:claim-ticket-unclaim-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:claim-ticket",failureWorkerIds:"opendiscord:back-to-unclaim-message"},
"opendiscord:unclaim-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unclaim-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"},
"opendiscord:unclaim-ticket-claim-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unclaim-ticket",failureWorkerIds:"opendiscord:back-to-claim-message"},
"opendiscord:pin-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:pin-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"},
"opendiscord:pin-ticket-unpin-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:pin-ticket",failureWorkerIds:"opendiscord:back-to-unpin-message"},
"opendiscord:unpin-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unpin-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"},
"opendiscord:unpin-ticket-pin-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:unpin-ticket",failureWorkerIds:"opendiscord:back-to-pin-message"},
"opendiscord:close-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:close-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"},
"opendiscord:close-ticket-reopen-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:close-ticket",failureWorkerIds:"opendiscord:back-to-reopen-message"},
"opendiscord:reopen-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:reopen-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"},
"opendiscord:reopen-ticket-close-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:reopen-ticket",failureWorkerIds:"opendiscord:back-to-close-message"},
"opendiscord:reopen-ticket-autoclose-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:reopen-ticket",failureWorkerIds:"opendiscord:back-to-autoclose-message"},
"opendiscord:delete-ticket-ticket-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-ticket-message"}
"opendiscord:delete-ticket-close-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-close-message"}
"opendiscord:delete-ticket-reopen-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-reopen-message"}
"opendiscord:delete-ticket-autoclose-message":{successWorkerIds:"opendiscord:permissions"|"opendiscord:delete-ticket",failureWorkerIds:"opendiscord:back-to-autoclose-message"}
}
/**## ODVerifyBarManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODVerifyBarManager class.
* It doesn't add any extra features!
*
* This default class is made for the global variable `opendiscord.verifybars`!
*/
export class ODVerifyBarManager_Default extends ODVerifyBarManager {
get<VerifyBarId extends keyof ODVerifyBarManagerIds_Default>(id:VerifyBarId): ODVerifyBar_Default<ODVerifyBarManagerIds_Default[VerifyBarId]["successWorkerIds"],ODVerifyBarManagerIds_Default[VerifyBarId]["failureWorkerIds"]>
get(id:ODValidId): ODVerifyBar|null
get(id:ODValidId): ODVerifyBar|null {
return super.get(id)
}
remove<VerifyBarId extends keyof ODVerifyBarManagerIds_Default>(id:VerifyBarId): ODVerifyBar_Default<ODVerifyBarManagerIds_Default[VerifyBarId]["successWorkerIds"],ODVerifyBarManagerIds_Default[VerifyBarId]["failureWorkerIds"]>
remove(id:ODValidId): ODVerifyBar|null
remove(id:ODValidId): ODVerifyBar|null {
return super.remove(id)
}
exists(id:keyof ODVerifyBarManagerIds_Default): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
/**## ODVerifyBar_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODVerifyBar class.
* It doesn't add any extra features!
*
* This default class is made for the default `ODVerifyBar`'s!
*/
export class ODVerifyBar_Default<SuccessWorkerIds extends string,FailureWorkerIds extends string> extends ODVerifyBar {
declare success: ODWorkerManager_Default<ODButtonResponderInstance,"verifybar",{data:string|null,verifybarMessage:discord.Message<boolean>|null},SuccessWorkerIds>
declare failure: ODWorkerManager_Default<ODButtonResponderInstance,"verifybar",{data:string|null,verifybarMessage:discord.Message<boolean>|null},FailureWorkerIds>
}
-35
View File
@@ -1,35 +0,0 @@
///////////////////////////////////////
//DEFAULT WORKER MODULE
///////////////////////////////////////
import { ODValidId } from "../modules/base"
import { ODWorker, ODWorkerManager } from "../modules/worker"
/**## ODWorkerManager_Default `default_class`
* This is a special class that adds type definitions & typescript to the ODWorkerManager class.
* It doesn't add any extra features!
*
* This default class is made for the worker manager in actions, builders & responders!
*/
export class ODWorkerManager_Default<Instance, Source extends string, Params, WorkerIds extends string> extends ODWorkerManager<Instance,Source,Params> {
get(id:WorkerIds): ODWorker<Instance,Source,Params>
get(id:ODValidId): ODWorker<Instance,Source,Params>|null
get(id:ODValidId): ODWorker<Instance,Source,Params>|null {
return super.get(id)
}
remove(id:WorkerIds): ODWorker<Instance,Source,Params>
remove(id:ODValidId): ODWorker<Instance,Source,Params>|null
remove(id:ODValidId): ODWorker<Instance,Source,Params>|null {
return super.remove(id)
}
exists(id:WorkerIds): boolean
exists(id:ODValidId): boolean
exists(id:ODValidId): boolean {
return super.exists(id)
}
}
-193
View File
@@ -1,193 +0,0 @@
//BASE MODULES
import { ODEnvHelper, ODVersion } from "./modules/base"
import { ODConsoleManager, ODConsoleMessage, ODConsoleMessageParam, ODConsoleMessageTypes, ODDebugFileManager, ODDebugger, ODError } from "./modules/console"
import { ODCheckerStorage } from "./modules/checker"
import { ODDefaultsManager } from "./modules/defaults"
//DEFAULT MODULES
import { ODVersionManager_Default } from "./defaults/base"
import { ODPluginManager_Default } from "./defaults/plugin"
import { ODEventManager_Default } from "./defaults/event"
import { ODConfigManager_Default} from "./defaults/config"
import { ODDatabaseManager_Default } from "./defaults/database"
import { ODFlagManager_Default } from "./defaults/flag"
import { ODSessionManager_Default } from "./defaults/session"
import { ODLanguageManager_Default } from "./defaults/language"
import { ODCheckerFunctionManager_Default, ODCheckerManager_Default, ODCheckerRenderer_Default, ODCheckerTranslationRegister_Default } from "./defaults/checker"
import { ODClientManager_Default } from "./defaults/client"
import { ODBuilderManager_Default } from "./defaults/builder"
import { ODResponderManager_Default } from "./defaults/responder"
import { ODActionManager_Default } from "./defaults/action"
import { ODPermissionManager_Default } from "./defaults/permission"
import { ODHelpMenuManager_Default } from "./defaults/helpmenu"
import { ODStatsManager_Default } from "./defaults/stat"
import { ODCodeManager_Default } from "./defaults/code"
import { ODCooldownManager_Default } from "./defaults/cooldown"
import { ODPostManager_Default } from "./defaults/post"
import { ODVerifyBarManager_Default } from "./defaults/verifybar"
import { ODProgressBarManager_Default } from "./defaults/progressbar"
import { ODStartScreenManager_Default } from "./defaults/startscreen"
import { ODLiveStatusManager_Default } from "./defaults/console"
//OPEN TICKET MODULES
import { ODOptionManager } from "./openticket/option"
import { ODPanelManager } from "./openticket/panel"
import { ODTicketManager } from "./openticket/ticket"
import { ODQuestionManager } from "./openticket/question"
import { ODBlacklistManager } from "./openticket/blacklist"
import { ODTranscriptManager_Default } from "./openticket/transcript"
import { ODRoleManager } from "./openticket/role"
import { ODPriorityManager_Default } from "./openticket/priority"
/**## ODMain `class`
* This is the main Open Ticket class.
* It contains all managers from the entire bot & has shortcuts to the event & logging system.
*
* This class can't be overwritten or extended & is available as the global variable `openticket`!
*/
export class ODMain {
/**The manager that handles all versions in the bot. */
versions: ODVersionManager_Default
/**The timestamp that the (node.js) process of the bot started. */
processStartupDate: Date = new Date()
/**The timestamp that the bot finished loading and is ready for usage. */
readyStartupDate: Date|null = null
/**The manager responsible for the debug file. (`otdebug.txt`) */
debugfile: ODDebugFileManager
/**The manager responsible for the console system. (logs, errors, etc) */
console: ODConsoleManager
/**The manager responsible for sending debug logs to the debug file. (`otdebug.txt`) */
debug: ODDebugger
/**The manager containing all Open Ticket events. */
events: ODEventManager_Default
/**The manager that handles & executes all plugins in the bot. */
plugins: ODPluginManager_Default
/**The manager that manages & checks all the console flags of the bot. (like `--debug`) */
flags: ODFlagManager_Default
/**The manager responsible for progress bars in the console. */
progressbars: ODProgressBarManager_Default
/**The manager that manages & contains all the config files of the bot. (like `config/general.json`) */
configs: ODConfigManager_Default
/**The manager that manages & contains all the databases of the bot. (like `database/global.json`) */
databases: ODDatabaseManager_Default
/**The manager that manages all the data sessions of the bot. (it's a temporary database) */
sessions: ODSessionManager_Default
/**The manager that manages all languages & translations of the bot. (but not for plugins) */
languages: ODLanguageManager_Default
/**The manager that handles & executes all config checkers in the bot. (the code that checks if you have something wrong in your config) */
checkers: ODCheckerManager_Default
/**The manager that manages all builders in the bot. (e.g. buttons, dropdowns, messages, modals, etc) */
builders: ODBuilderManager_Default
/**The manager that manages all responders in the bot. (e.g. commands, buttons, dropdowns, modals) */
responders: ODResponderManager_Default
/**The manager that manages all actions or procedures in the bot. (e.g. ticket-creation, ticket-deletion, ticket-claiming, etc) */
actions: ODActionManager_Default
/**The manager that manages all verify bars in the bot. (the ✅ ❌ buttons) */
verifybars: ODVerifyBarManager_Default
/**The manager that contains all permissions for commands & actions in the bot. (use it to check if someone has admin perms or not) */
permissions: ODPermissionManager_Default
/**The manager that contains all cooldowns of the bot. (e.g. ticket-cooldowns) */
cooldowns: ODCooldownManager_Default
/**The manager that manages & renders the Open Ticket help menu. (not the embed, but the text) */
helpmenu: ODHelpMenuManager_Default
/**The manager that manages, saves & renders the Open Ticket statistics. (not the embed, but the text & database) */
stats: ODStatsManager_Default
/**This manager is a place where you can put code that executes when the bot almost finishes the setup. (can be used for less important stuff that doesn't require an exact time-order) */
code: ODCodeManager_Default
/**The manager that manages all posts (static discord channels) in the bot. (e.g. (transcript) logs, etc) */
posts: ODPostManager_Default
/**The manager responsible for everything related to the client. (e.g. status, login, slash & text commands, etc) */
client: ODClientManager_Default
/**This manager contains A LOD of booleans. With these switches, you can turn off "default behaviours" from the bot. This is used if you want to replace the default Open Ticket code. */
defaults: ODDefaultsManager
/**This manager manages all the variables in the ENV. It reads from both the `.env` file & the `process.env`. (these 2 will be combined) */
env: ODEnvHelper
/**The manager responsible for the livestatus system. (remote console logs) */
livestatus: ODLiveStatusManager_Default
/**The manager responsible for the livestatus system. (remote console logs) */
startscreen: ODStartScreenManager_Default
//OPEN TICKET
/**The manager that manages all the data of questions in the bot. (these are used in options & tickets) */
questions: ODQuestionManager
/**The manager that manages all the data of options in the bot. (these are used for panels, ticket creation, reaction roles) */
options: ODOptionManager
/**The manager that manages all the data of panels in the bot. (panels contain the options) */
panels: ODPanelManager
/**The manager that manages all tickets in the bot. (here, you can get & edit a lot of data from tickets) */
tickets: ODTicketManager
/**The manager that manages the ticket blacklist. (people who are blacklisted can't create a ticket) */
blacklist: ODBlacklistManager
/**The manager that manages the ticket transcripts. (both the history & compilers) */
transcripts: ODTranscriptManager_Default
/**The manager that manages all reaction roles in the bot. (here, you can add additional data to roles) */
roles: ODRoleManager
/**The manager that manages all priority levels in the bot. (register/edit ticket priority levels) */
priorities: ODPriorityManager_Default
constructor(){
this.versions = new ODVersionManager_Default()
this.versions.add(ODVersion.fromString("opendiscord:version","v4.1.3"))
this.versions.add(ODVersion.fromString("opendiscord:api","v1.0.0"))
this.versions.add(ODVersion.fromString("opendiscord:transcripts","v2.1.0"))
this.versions.add(ODVersion.fromString("opendiscord:livestatus","v2.0.0"))
this.debugfile = new ODDebugFileManager("./","otdebug.txt",5000,this.versions.get("opendiscord:version"))
this.console = new ODConsoleManager(100,this.debugfile)
this.debug = new ODDebugger(this.console)
this.events = new ODEventManager_Default(this.debug)
this.plugins = new ODPluginManager_Default(this.debug)
this.flags = new ODFlagManager_Default(this.debug)
this.progressbars = new ODProgressBarManager_Default(this.debug)
this.configs = new ODConfigManager_Default(this.debug)
this.databases = new ODDatabaseManager_Default(this.debug)
this.sessions = new ODSessionManager_Default(this.debug)
this.languages = new ODLanguageManager_Default(this.debug,false)
this.checkers = new ODCheckerManager_Default(this.debug,new ODCheckerStorage(),new ODCheckerRenderer_Default(),new ODCheckerTranslationRegister_Default(),new ODCheckerFunctionManager_Default(this.debug))
this.builders = new ODBuilderManager_Default(this.debug)
this.client = new ODClientManager_Default(this.debug)
this.responders = new ODResponderManager_Default(this.debug,this.client)
this.actions = new ODActionManager_Default(this.debug)
this.verifybars = new ODVerifyBarManager_Default(this.debug)
this.permissions = new ODPermissionManager_Default(this.debug,this.client)
this.cooldowns = new ODCooldownManager_Default(this.debug)
this.helpmenu = new ODHelpMenuManager_Default(this.debug)
this.stats = new ODStatsManager_Default(this.debug)
this.code = new ODCodeManager_Default(this.debug)
this.posts = new ODPostManager_Default(this.debug)
this.defaults = new ODDefaultsManager()
this.env = new ODEnvHelper()
this.livestatus = new ODLiveStatusManager_Default(this.debug,this)
this.startscreen = new ODStartScreenManager_Default(this.debug,this.livestatus)
//OPEN TICKET
this.questions = new ODQuestionManager(this.debug)
this.options = new ODOptionManager(this.debug)
this.panels = new ODPanelManager(this.debug)
this.tickets = new ODTicketManager(this.debug,this.client)
this.blacklist = new ODBlacklistManager(this.debug)
this.transcripts = new ODTranscriptManager_Default(this.debug,this.tickets,this.client,this.permissions)
this.roles = new ODRoleManager(this.debug)
this.priorities = new ODPriorityManager_Default(this.debug)
}
/**Log a message to the console. But in the Open Ticket style :) */
log(message:ODConsoleMessage): void
log(message:ODError): void
log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void
log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){
if (message instanceof ODConsoleMessage) this.console.log(message)
else if (message instanceof ODError) this.console.log(message)
else if (["string","number","boolean","object"].includes(typeof message)) this.console.log(message,type,params)
}
}
-58
View File
@@ -1,58 +0,0 @@
///////////////////////////////////////
//ACTION MODULE
///////////////////////////////////////
import { ODId, ODManager, ODValidId, ODSystemError, ODManagerData } from "./base"
import { ODWorkerManager, ODWorkerCallback, ODWorker } from "./worker"
import { ODDebugger } from "./console"
/**## ODActionImplementation `class`
* This is an Open Ticket action implementation.
*
* It is a basic implementation of the `ODWorkerManager` used by all `ODAction` classes.
*
* This class can't be used stand-alone & needs to be extended from!
*/
export class ODActionImplementation<Source extends string,Params extends object,Result extends object> extends ODManagerData {
/**The manager that has all workers of this implementation */
workers: ODWorkerManager<object,Source,Params>
constructor(id:ODValidId, callback?:ODWorkerCallback<object,Source,Params>, priority?:number, callbackId?:ODValidId){
super(id)
this.workers = new ODWorkerManager("descending")
if (callback) this.workers.add(new ODWorker(callbackId ? callbackId : id,priority ?? 0,callback))
}
/**Execute all workers & return the result. */
async run(source:Source, params:Params): Promise<Partial<Result>> {
throw new ODSystemError("Tried to build an unimplemented ODResponderImplementation")
}
}
/**## ODActionManager `class`
* This is an Open Ticket action manager.
*
* It contains all Open Ticket actions. You can compare actions with some sort of "procedure".
* It's a complicated task that is divided into multiple functions.
*
* Some examples are `ticket-creation`, `ticket-closing`, `ticket-claiming`, ...
*
* It's recommended to use this system in combination with Open Ticket responders!
*/
export class ODActionManager extends ODManager<ODAction<string,{},{}>> {
constructor(debug:ODDebugger){
super(debug,"action")
}
}
export class ODAction<Source extends string,Params extends object,Result extends object> extends ODActionImplementation<Source,Params,Result> {
/**Run this action */
async run(source:Source, params:Params): Promise<Partial<Result>> {
//create instance
const instance = {}
//wait for workers to finish
await this.workers.executeWorkers(instance,source,params)
//return data generated by workers
return instance
}
}
-763
View File
@@ -1,763 +0,0 @@
///////////////////////////////////////
//BASE MODULE
///////////////////////////////////////
import * as fs from "fs"
import { ODConsoleWarningMessage, ODDebugger } from "./console"
/**## ODPromiseVoid `type`
* This is a simple type to represent a callback return value that could be a promise or not.
*/
export type ODPromiseVoid = void|Promise<void>
/**## ODOptionalPromise `type`
* This is a simple type to represent a type as normal value or a promise value.
*/
export type ODOptionalPromise<T> = T|Promise<T>
/**## ODValidButtonColor `type`
* This is a collection of all the possible button colors.
*/
export type ODValidButtonColor = "gray"|"red"|"green"|"blue"
/**## ODValidId `type`
* This is a valid Open Ticket identifier. It can be an `ODId` or `string`!
*
* You will see this type in many functions from Open Ticket.
*/
export type ODValidId = string|ODId
/**## ODValidJsonType `type`
* This is a collection of all types that can be stored in a JSON file!
*
* list: `string`, `number`, `boolean`, `array`, `object`, `null`
*/
export type ODValidJsonType = string|number|boolean|object|ODValidJsonType[]|null
/**## ODInterfaceWithPartialProperty `type`
* This is a utility type to create an interface where some properties are optional!
*/
export type ODInterfaceWithPartialProperty<Interface,Key extends keyof Interface> = Omit<Interface,Key> & Partial<Pick<Interface,Key>>
/**## ODDiscordIdType `type`
* A list of all available discord ID types. Used in the config checker.
*/
export type ODDiscordIdType = "role"|"server"|"channel"|"category"|"user"|"member"|"interaction"|"message"
/**## ODId `class`
* This is an Open Ticket identifier.
*
* It can only contain the following characters: `a-z`, `A-Z`, `0-9`, `:`, `-` & `_`
*
* You can use this class to assign a unique id when creating configs, databases, languages & more!
*/
export class ODId {
/**The full value of this `ODId` as a `string`. */
#value: string
/**The full value of this `ODId` as a `string`. */
set value(id:string){
this._change(this.#value,id)
this.#value = id
}
get value(){
return this.#value
}
/**The change listener for the parent `ODManager` of this `ODId`. */
#change: ((oldId:string,newId:string) => void)|null = null
constructor(id:ODValidId){
if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid constructor parameter => id:ODValidId")
if (typeof id == "string"){
//id is string
const result: string[] = []
const charregex = /[a-zA-Z0-9éèçàêâôûî\:\-\_]/
id.split("").forEach((char) => {
if (charregex.test(char)){
result.push(char)
}
})
if (result.length > 0) this.#value = result.join("")
else throw new ODSystemError("invalid ID at 'new ODID(id: "+id+")'")
}else{
//id is ODId
this.#value = id.#value
}
}
/**Returns a string representation of this id. (same as `this.value`) */
toString(){
return this.#value
}
/**The namespace of the id before `:`. (e.g. `openticket` for `openticket:autoclose-enabled`) */
getNamespace(){
const splitted = this.#value.split(":")
if (splitted.length > 1) return splitted[0]
else return ""
}
/**The identifier of the id after `:`. (e.g. `autoclose-enabled` for `openticket:autoclose-enabled`) */
getIdentifier(){
const splitted = this.#value.split(":")
if (splitted.length > 1){
splitted.shift()
return splitted.join(":")
}else return this.#value
}
/**Trigger an `onChange()` event in the parent `ODManager` of this class. */
protected _change(oldId:string,newId:string){
if (this.#change){
try{
this.#change(oldId,newId)
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Failed to execute _change() callback!")
}
}
}
/****(❌ SYSTEM ONLY!!)** Set the callback executed when a value inside this class changes. */
changed(callback:((oldId:string,newId:string) => void)|null){
this.#change = callback
}
}
/**## ODManagerChangeHelper `class`
* This is an Open Ticket manager change helper.
*
* It is used to let the "onChange" event in the `ODManager` class work.
* You can use this class when extending your own `ODManager`
*/
export class ODManagerChangeHelper {
#change: (() => void)|null = null
/**Trigger an `onChange()` event in the parent `ODManager` of this class. */
protected _change(){
if (this.#change){
try{
this.#change()
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Failed to execute _change() callback!")
}
}
}
/****(❌ SYSTEM ONLY!!)** Set the callback executed when a value inside this class changes. */
changed(callback:(() => void)|null){
this.#change = callback
}
}
/**## ODManagerData `class`
* This is Open Ticket manager data.
*
* It provides a template for all classes that are used in the `ODManager`.
*
* There is an `id:ODId` property & also some events used in the manager.
*/
export class ODManagerData extends ODManagerChangeHelper {
/**The id of this data. */
id: ODId
constructor(id:ODValidId){
if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid constructor parameter => id:ODValidId")
super()
this.id = new ODId(id)
}
}
/**## ODManagerCallback `type`
* This is a callback for the `onChange` and `onRemove` events in the `ODManager`
*/
export type ODManagerCallback<DataType extends ODManagerData> = (data:DataType) => void
/**## ODManagerAddCallback `type`
* This is a callback for the `onAdd` event in the `ODManager`
*/
export type ODManagerAddCallback<DataType extends ODManagerData> = (data:DataType, overwritten:boolean) => void
/**## ODManager `class`
* This is an Open Ticket manager.
*
* It can be used to store & manage classes based on their `ODId`.
* It is somewhat the same as the default JS `Map()`.
* You can extend this class when creating your own classes & managers.
*
* This class has many useful functions based on `ODId` (add, get, remove, getAll, getFiltered, exists, loopAll, ...)
*/
export class ODManager<DataType extends ODManagerData> extends ODManagerChangeHelper {
/**Alias to Open Ticket debugger. */
#debug?: ODDebugger
/**The message to send when debugging this manager. */
#debugname?: string
/**The map storing all data classes in this manager. */
#data: Map<string,DataType> = new Map()
/**An array storing all listeners when data is added. */
#addListeners: ODManagerAddCallback<DataType>[] = []
/**An array storing all listeners when data has changed. */
#changeListeners: ODManagerCallback<DataType>[] = []
/**An array storing all listeners when data is removed. */
#removeListeners: ODManagerCallback<DataType>[] = []
constructor(debug?:ODDebugger, debugname?:string){
super()
this.#debug = debug
this.#debugname = debugname
}
/**Add data to the manager. The `ODId` in the data class will be used as identifier! You can optionally select to overwrite existing data!*/
add(data:DataType|DataType[], overwrite?:boolean): boolean {
//repeat same command when data is an array
if (Array.isArray(data)){
data.forEach((arrayData) => {
this.add(arrayData,overwrite)
})
return false
}
//add listener for data id change => transfer data within manager
data.id.changed((oldId,newId) => {
this.#data.delete(oldId)
this.#data.set(newId,data)
})
//add data
let didOverwrite: boolean
if (this.#data.has(data.id.value)){
if (!overwrite) throw new ODSystemError("Id '"+data.id.value+"' already exists in "+this.#debugname+" manager. Use 'overwrite:true' to allow overwriting!")
this.#data.set(data.id.value,data)
didOverwrite = true
if (this.#debug) this.#debug.debug("Added new "+this.#debugname+" to manager",[{key:"id",value:data.id.value},{key:"overwrite",value:"true"}])
}else{
this.#data.set(data.id.value,data)
didOverwrite = false
if (this.#debug) this.#debug.debug("Added new "+this.#debugname+" to manager",[{key:"id",value:data.id.value},{key:"overwrite",value:"false"}])
}
//emit change listeners
data.changed(() => {
//notify change in upper-manager (because data in this manager changed)
this._change()
this.#changeListeners.forEach((cb) => {
try{
cb(data)
}catch(err){
throw new ODSystemError("Failed to run manager onChange() listener.\n"+err)
}
})
})
//emit add listeners
this.#addListeners.forEach((cb) => {
try{
cb(data,didOverwrite)
}catch(err){
throw new ODSystemError("Failed to run manager onAdd() listener.\n"+err)
}
})
//notify change in upper-manager (because data added)
this._change()
return didOverwrite
}
/**Get data that matches the `ODId`. Returns the found data.*/
get(id:ODValidId): DataType|null {
const newId = new ODId(id)
const data = this.#data.get(newId.value)
if (data) return data
else return null
}
/**Remove data that matches the `ODId`. Returns the removed data. */
remove(id:ODValidId): DataType|null {
const newId = new ODId(id)
const data = this.#data.get(newId.value)
if (!data){
if (this.#debug) this.#debug.debug("Removed "+this.#debugname+" from manager",[{key:"id",value:newId.value},{key:"found",value:"false"}])
return null
}else{
this.#data.delete(newId.value)
if (this.#debug) this.#debug.debug("Removed "+this.#debugname+" from manager",[{key:"id",value:newId.value},{key:"found",value:"true"}])
}
//remove all listeners
data.id.changed(null)
data.changed(null)
//emit remove listeners
this.#removeListeners.forEach((cb) => {
try{
cb(data)
}catch(err){
throw new ODSystemError("Failed to run manager onRemove() listener.\n"+err)
}
})
//notify change in upper-manager (because data removed)
this._change()
return data
}
/**Check if data that matches the `ODId` exists. Returns a boolean. */
exists(id:ODValidId): boolean {
const newId = new ODId(id)
if (this.#data.has(newId.value)) return true
else return false
}
/**Get all data inside this manager*/
getAll(): DataType[] {
return Array.from(this.#data.values())
}
/**Get all data that matches inside the filter function*/
getFiltered(predicate:(value:DataType, index:number, array:DataType[]) => unknown): DataType[] {
return Array.from(this.#data.values()).filter(predicate)
}
/**Get all data where the `ODId` matches the provided RegExp. */
getRegex(regex:RegExp): DataType[] {
return Array.from(this.#data.values()).filter((data) => regex.test(data.id.value))
}
/**Get the length/size/amount of the data inside this manager. */
getLength(){
return this.#data.size
}
/**Get a list of all the ids inside this manager*/
getIds(): ODId[] {
const ids = Array.from(this.#data.keys())
return ids.map((id) => new ODId(id))
}
/**Run an iterator over all data in this manager. This method also supports async-await behaviour!*/
async loopAll(cb:(data:DataType,id:ODId) => ODPromiseVoid): Promise<void> {
for (const data of this.getAll()){
await cb(data,data.id)
}
}
/**Use the Open Ticket debugger in this manager for logs*/
useDebug(debug?:ODDebugger, debugname?:string){
this.#debug = debug
this.#debugname = debugname
}
/**Listen for when data is added to this manager. */
onAdd(callback:ODManagerAddCallback<DataType>){
this.#addListeners.push(callback)
}
/**Listen for when data is changed in this manager. */
onChange(callback:ODManagerCallback<DataType>){
this.#changeListeners.push(callback)
}
/**Listen for when data is removed from this manager. */
onRemove(callback:ODManagerCallback<DataType>){
this.#removeListeners.push(callback)
}
}
/**## ODManagerWithSafety `class`
* This is an Open Ticket safe manager.
*
* It functions exactly the same as a normal `ODManager`, but it has 1 function extra!
* The `getSafe()` function will always return data, because when it doesn't find an id, it returns pre-configured backup data.
*/
export class ODManagerWithSafety<DataType extends ODManagerData> extends ODManager<DataType> {
/**The function that creates backup data returned in `getSafe()` when an id is missing in this manager. */
#backupCreator: () => DataType
/** Temporary storage for manager debug name. */
#debugname: string
constructor(backupCreator:() => DataType, debug?:ODDebugger, debugname?:string){
super(debug,debugname)
this.#backupCreator = backupCreator
this.#debugname = debugname ?? "unknown"
}
/**Get data that matches the `ODId`. Returns the backup data when not found.
*
* ### ⚠️ This should only be used when the data doesn't need to be written/edited
*/
getSafe(id:ODValidId): DataType {
const data = super.get(id)
if (!data){
process.emit("uncaughtException",new ODSystemError("ODManagerWithSafety:getSafe(\""+id+"\") => Unknown Id => Used backup data ("+this.#debugname+" manager)"))
return this.#backupCreator()
}
else return data
}
}
/**## ODVersionManager `class`
* A Open Ticket version manager.
*
* It is used to manage different `ODVersion`'s from the bot. You will use it to check which version of the bot is used.
*/
export class ODVersionManager extends ODManager<ODVersion> {
constructor(){
super()
}
}
/**## ODVersion `class`
* This is an Open Ticket version.
*
* It has many features like comparing versions & checking if they are compatible.
*
* You can use it in your own plugin, but most of the time you will use it to check the Open Ticket version!
*/
export class ODVersion extends ODManagerData {
/**The first number of the version (example: `v1.2.3` => `1`) */
primary: number
/**The second number of the version (example: `v1.2.3` => `2`) */
secondary: number
/**The third number of the version (example: `v1.2.3` => `3`) */
tertiary: number
constructor(id:ODValidId, primary:number, secondary:number, tertiary:number){
super(id)
if (typeof primary != "number") throw new ODSystemError("Invalid constructor parameter => primary:number")
if (typeof secondary != "number") throw new ODSystemError("Invalid constructor parameter => secondary:number")
if (typeof tertiary != "number") throw new ODSystemError("Invalid constructor parameter => tertiary:number")
this.primary = primary
this.secondary = secondary
this.tertiary = tertiary
}
/**Get the version from a string (also possible with `v` prefix)
* @example const version = api.ODVersion.fromString("id","v1.2.3") //creates version 1.2.3
*/
static fromString(id:ODValidId, version:string){
if (typeof id != "string" && !(id instanceof ODId)) throw new ODSystemError("Invalid function parameter => id:ODValidId")
if (typeof version != "string") throw new ODSystemError("Invalid function parameter => version:string")
const versionCheck = (version.startsWith("v")) ? version.substring(1) : version
const splittedVersion = versionCheck.split(".")
return new this(id,Number(splittedVersion[0]),Number(splittedVersion[1]),Number(splittedVersion[2]))
}
/**Get the version as a string (`noprefix:true` => with `v` prefix)
* @example
* new api.ODVersion(1,0,0).toString(false) //returns "v1.0.0"
* new api.ODVersion(1,0,0).toString(true) //returns "1.0.0"
*/
toString(noprefix?:boolean){
const prefix = noprefix ? "" : "v"
return prefix+[this.primary,this.secondary,this.tertiary].join(".")
}
/**Compare this version with another version and returns the result: `higher`, `lower` or `equal`
* @example
* new api.ODVersion(1,0,0).compare(new api.ODVersion(1,2,0)) //returns "lower"
* new api.ODVersion(1,3,0).compare(new api.ODVersion(1,2,0)) //returns "higher"
* new api.ODVersion(1,2,0).compare(new api.ODVersion(1,2,0)) //returns "equal"
*/
compare(comparator:ODVersion): "higher"|"lower"|"equal" {
if (!(comparator instanceof ODVersion)) throw new ODSystemError("Invalid function parameter => comparator:ODVersion")
if (this.primary < comparator.primary) return "lower"
else if (this.primary > comparator.primary) return "higher"
else {
if (this.secondary < comparator.secondary) return "lower"
else if (this.secondary > comparator.secondary) return "higher"
else {
if (this.tertiary < comparator.tertiary) return "lower"
else if (this.tertiary > comparator.tertiary) return "higher"
else return "equal"
}
}
}
/**Check if this version is included in the list
* @example
* const list = [
* new api.ODVersion(1,0,0),
* new api.ODVersion(1,0,1),
* new api.ODVersion(1,0,2)
* ]
* new api.ODVersion(1,0,0).compatible(list) //returns true
* new api.ODVersion(1,0,1).compatible(list) //returns true
* new api.ODVersion(1,0,3).compatible(list) //returns false
*/
compatible(list:ODVersion[]): boolean {
if (!Array.isArray(list)) throw new ODSystemError("Invalid function parameter => list:ODVersion[]")
if (!list.every((v) => (v instanceof ODVersion))) throw new ODSystemError("Invalid function parameter => list:ODVersion[]")
return list.some((v) => {
return (v.toString() === this.toString())
})
}
/**Check if this version is higher or equal to the provided `requirement`. */
min(requirement:string|ODVersion){
if (typeof requirement == "string") requirement = ODVersion.fromString("temp",requirement)
//skip when primary version is higher or lower than current one.
if (this.primary < requirement.primary) return false
else if (this.primary > requirement.primary) return true
//skip when secondary version is higher or lower than current one.
if (this.secondary < requirement.secondary) return false
else if (this.secondary > requirement.secondary) return true
//skip when tertiary version is higher or lower than current one.
if (this.tertiary < requirement.tertiary) return false
else if (this.tertiary > requirement.tertiary) return true
return true
}
/**Check if this version is lower or equal to the provided `requirement`. */
max(requirement:string|ODVersion){
if (typeof requirement == "string") requirement = ODVersion.fromString("temp",requirement)
//skip when primary version is higher or lower than current one.
if (this.primary < requirement.primary) return true
else if (this.primary > requirement.primary) return false
//skip when secondary version is higher or lower than current one.
if (this.secondary < requirement.secondary) return true
else if (this.secondary > requirement.secondary) return false
//skip when tertiary version is higher or lower than current one.
if (this.tertiary < requirement.tertiary) return true
else if (this.tertiary > requirement.tertiary) return false
return true
}
/**Check if this version is matches the major version (`vX.X`) of the provided `requirement`. */
major(requirement:string|ODVersion){
if (typeof requirement == "string") requirement = ODVersion.fromString("temp",requirement)
return (this.primary == requirement.primary && this.secondary == requirement.secondary)
}
/**Check if this version is matches the minor version (`vX.X.X`) of the provided `requirement`. */
minor(requirement:string|ODVersion){
if (typeof requirement == "string") requirement = ODVersion.fromString("temp",requirement)
return (this.primary == requirement.primary && this.secondary == requirement.secondary && this.tertiary == requirement.tertiary)
}
}
/**## ODHTTPGetRequest `class`
* This is a class that can help you with creating simple HTTP GET requests.
*
* It works using the native node.js fetch() method. You can configure all options in the constructor!
* @example
* const request = new api.ODHTTPGetRequest("https://www.example.com/abc.txt",false,{})
*
* const result = await request.run()
* result.body //the response body (string)
* result.status //the response code (number)
* result.response //the full response (object)
*/
export class ODHTTPGetRequest {
/**The url used in the request */
url: string
/**The request config for additional options */
config: RequestInit
/**Throw on error OR return http code 500 */
throwOnError: boolean
constructor(url:string,throwOnError:boolean,config?:RequestInit){
if (typeof url != "string") throw new ODSystemError("Invalid constructor parameter => url:string")
if (typeof throwOnError != "boolean") throw new ODSystemError("Invalid constructor parameter => throwOnError:boolean")
if (typeof config != "undefined" && typeof config != "object") throw new ODSystemError("Invalid constructor parameter => config?:RequestInit")
this.url = url
this.throwOnError = throwOnError
const newConfig = config ?? {}
newConfig.method = "GET"
if (newConfig.headers) Object.assign(newConfig.headers,{"User-Agent":"OpenDiscordBots-OpenTicket/4.1.3"})
else newConfig.headers = {"User-Agent":"OpenDiscordBots-OpenTicket/4.1.3"}
this.config = newConfig
}
/**Execute the GET request.*/
run(): Promise<{status:number, body:string, response?:Response}> {
return new Promise(async (resolve,reject) => {
try{
const response = await fetch(this.url,this.config)
resolve({
status:response.status,
body:(await response.text()),
response:response
})
}catch(err){
if (this.throwOnError) return reject("[OPENTICKET ERROR]: ODHTTPGetRequest => Unknown fetch() error: "+err)
else return resolve({
status:500,
body:"Open Ticket Error: Unknown fetch() error: "+err,
})
}
})
}
}
/**## ODHTTPPostRequest `class`
* This is a class that can help you with creating simple HTTP POST requests.
*
* It works using the native node.js fetch() method. You can configure all options in the constructor!
* @example
* const request = new api.ODHTTPPostRequest("https://www.example.com/abc.txt",false,{})
*
* const result = await request.run()
* result.body //the response body (string)
* result.status //the response code (number)
* result.response //the full response (object)
*/
export class ODHTTPPostRequest {
/**The url used in the request */
url: string
/**The request config for additional options */
config: RequestInit
/**Throw on error OR return http code 500 */
throwOnError: boolean
constructor(url:string,throwOnError:boolean,config?:RequestInit){
if (typeof url != "string") throw new ODSystemError("Invalid constructor parameter => url:string")
if (typeof throwOnError != "boolean") throw new ODSystemError("Invalid constructor parameter => throwOnError:boolean")
if (typeof config != "undefined" && typeof config != "object") throw new ODSystemError("Invalid constructor parameter => config?:RequestInit")
this.url = url
this.throwOnError = throwOnError
const newConfig = config ?? {}
newConfig.method = "POST"
if (newConfig.headers) Object.assign(newConfig.headers,{"User-Agent":"OpenDiscordBots-OpenTicket/4.1.3"})
else newConfig.headers = {"User-Agent":"OpenDiscordBots-OpenTicket/4.1.3"}
this.config = newConfig
}
/**Execute the POST request.*/
run(): Promise<{status:number, body:string, response?:Response}> {
return new Promise(async (resolve,reject) => {
try{
const response = await fetch(this.url,this.config)
resolve({
status:response.status,
body:(await response.text()),
response:response
})
}catch(err){
if (this.throwOnError) return reject("[OPENTICKET ERROR]: ODHTTPPostRequest => Unknown fetch() error: "+err)
else return resolve({
status:500,
body:"Open Ticket Error: Unknown fetch() error!",
})
}
})
}
}
/**## ODEnvHelper `class`
* This is a utility class that helps you with reading the ENV.
*
* It has support for the built-in `process.env` & `.env` file
* @example
* const envHelper = new api.ODEnvHelper()
*
* const variableA = envHelper.getVariable("value-a")
* const variableB = envHelper.getVariable("value-b","dotenv") //only get from .env
* const variableA = envHelper.getVariable("value-c","env") //only get from process.env
*/
export class ODEnvHelper {
/**All variables found in the `.env` file */
dotenv: object
/**All variables found in `process.env` */
env: object
constructor(customEnvPath?:string){
if (typeof customEnvPath != "undefined" && typeof customEnvPath != "string") throw new ODSystemError("Invalid constructor parameter => customEnvPath?:string")
const path = customEnvPath ? customEnvPath : ".env"
this.dotenv = fs.existsSync(path) ? this.#readDotEnv(fs.readFileSync(path)) : {}
this.env = process.env
}
/**Get a variable from the env */
getVariable(name:string,source?:"dotenv"|"env"): any|undefined {
if (typeof name != "string") throw new ODSystemError("Invalid function parameter => name:string")
if ((typeof source != "undefined" && typeof source != "string") || (source && !["env","dotenv"].includes(source))) throw new ODSystemError("Invalid function parameter => source:'dotenv'|'env'")
if (source == "dotenv"){
return this.dotenv[name]
}else if (source == "env"){
return this.env[name]
}else{
//when no source specified => .env has priority over process.env
if (this.dotenv[name]) return this.dotenv[name]
else return this.env[name]
}
}
//THIS CODE IS COPIED FROM THE DODENV-LIB
//Repo: https://github.com/motdotla/dotenv
//Source: https://github.com/motdotla/dotenv/blob/master/lib/main.js#L12
#readDotEnv(src:Buffer){
const LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg
const obj = {}
// Convert buffer to string
let lines = src.toString()
// Convert line breaks to same format
lines = lines.replace(/\r\n?/mg, '\n')
let match
while ((match = LINE.exec(lines)) != null) {
const key = match[1]
// Default undefined or null to empty string
let value = (match[2] || '')
// Remove whitespace
value = value.trim()
// Check if double quoted
const maybeQuote = value[0]
// Remove surrounding quotes
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, '$2')
// Expand newlines if double quoted
if (maybeQuote === '"') {
value = value.replace(/\\n/g, '\n')
value = value.replace(/\\r/g, '\r')
}
// Add to object
obj[key] = value
}
return obj
}
}
/**## ODSystemError `class`
* A wrapper for the node.js `Error` class that makes the error look better in the console!
*
* This wrapper is made for Open Ticket system errors! **It can only be used by Open Ticket itself!**
*/
export class ODSystemError extends Error {
/**This variable gets detected by the error handling system to know how to render it */
_ODErrorType = "system"
/**Create an `ODSystemError` directly from an `Error` class */
static fromError(err:Error){
err["_ODErrorType"] = "system"
return err as ODSystemError
}
}
/**## ODPluginError `class`
* A wrapper for the node.js `Error` class that makes the error look better in the console!
*
* This wrapper is made for Open Ticket plugin errors! **It can only be used by plugins!**
*/
export class ODPluginError extends Error {
/**This variable gets detected by the error handling system to know how to render it */
_ODErrorType = "plugin"
/**Create an `ODPluginError` directly from an `Error` class */
static fromError(err:Error){
err["_ODErrorType"] = "plugin"
return err as ODPluginError
}
}
/**Oh, what could this be `¯\_(ツ)_/¯` */
export interface ODEasterEggs {
creator:string,
translators:string[]
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-58
View File
@@ -1,58 +0,0 @@
///////////////////////////////////////
//CODE MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODDebugger } from "./console"
/**## ODCode `class`
* This is an Open Ticket code runner.
*
* Using this, you're able to execute a function just before the startup screen. (90% of the code is already loaded)
* You can also specify a priority to change the execution order.
* In Open Ticket, this is used for the following processes:
* - Autoclose/delete
* - Database syncronisation (with tickets, stats & used options)
* - Panel auto-update
* - Database Garbage Collection (removing tickets that don't exist anymore)
* - And more!
*/
export class ODCode extends ODManagerData {
/**The priority of this code */
priority: number
/**The main function of this code */
func: () => void|Promise<void>
constructor(id:ODValidId, priority:number, func:() => void|Promise<void>){
super(id)
this.priority = priority
this.func = func
}
}
/**## ODCodeManager `class`
* This is an Open Ticket code manager.
*
* It manages & executes `ODCode`'s in the correct order.
*
* Use this to register a function/code which executes just before the startup screen. (90% is already loaded)
*/
export class ODCodeManager extends ODManager<ODCode> {
constructor(debug:ODDebugger){
super(debug,"code")
}
/**Execute all `ODCode` functions in order of their priority (high to low). */
async execute(){
const derefArray = [...this.getAll()]
const workers = derefArray.sort((a,b) => b.priority-a.priority)
for (const worker of workers){
try {
await worker.func()
}catch(err){
process.emit("uncaughtException",err)
}
}
}
}
-159
View File
@@ -1,159 +0,0 @@
///////////////////////////////////////
//CONFIG MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODPromiseVoid, ODSystemError, ODValidId } from "./base"
import nodepath from "path"
import { ODDebugger } from "./console"
import fs from "fs"
import * as fjs from "formatted-json-stringify"
/**## ODConfigManager `class`
* This is an Open Ticket config manager.
*
* It manages all config files in the bot and allows plugins to access config files from Open Ticket & other plugins!
*
* You can use this class to get/change/add a config file (`ODConfig`) in your plugin!
*/
export class ODConfigManager extends ODManager<ODConfig> {
/**Alias to Open Ticket debugger. */
#debug: ODDebugger
constructor(debug:ODDebugger){
super(debug,"config")
this.#debug = debug
}
add(data:ODConfig|ODConfig[],overwrite?:boolean): boolean {
if (Array.isArray(data)) data.forEach((d) => d.useDebug(this.#debug))
else data.useDebug(this.#debug)
return super.add(data,overwrite)
}
/**Init all config files. */
async init(){
for (const config of this.getAll()){
try{
await config.init()
}catch(err){
process.emit("uncaughtException",new ODSystemError(err))
}
}
}
}
/**## ODConfig `class`
* This is an Open Ticket config helper.
* This class doesn't do anything at all, it just gives a template & basic methods for a config. Use `ODJsonConfig` instead!
*
* You can use this class if you want to create your own config implementation (e.g. `yml`, `xml`,...)!
*/
export class ODConfig extends ODManagerData {
/**The name of the file with extension. */
file: string = ""
/**The path to the file relative to the main directory. */
path: string = ""
/**An object/array of the entire config file! Variables inside it can be edited while the bot is running! */
data: any
/**Is this config already initiated? */
initiated: boolean = false
/**An array of listeners to run when the config gets reloaded. These are not executed on the initial loading. */
protected reloadListeners: Function[] = []
/**Alias to Open Ticket debugger. */
protected debug: ODDebugger|null = null
constructor(id:ODValidId, data:any){
super(id)
this.data = data
}
/**Use the Open Ticket debugger for logs. */
useDebug(debug:ODDebugger|null){
this.debug = debug
}
/**Init the config. */
init(): ODPromiseVoid {
this.initiated = true
if (this.debug) this.debug.debug("Initiated config '"+this.file+"' in ODConfigManager.",[{key:"id",value:this.id.value}])
//please implement this feature in your own config extension & extend this function.
}
/**Reload the config. Be aware that this doesn't update the config data everywhere in the bot! */
reload(): ODPromiseVoid {
if (this.debug) this.debug.debug("Reloaded config '"+this.file+"' in ODConfigManager.",[{key:"id",value:this.id.value}])
//please implement this feature in your own config extension & extend this function.
}
/**Save the edited config to the filesystem. This is used by the Interactive Setup CLI. It's not recommended to use this while the bot is running. */
save(): ODPromiseVoid {
if (this.debug) this.debug.debug("Saved config '"+this.file+"' in ODConfigManager.",[{key:"id",value:this.id.value}])
//please implement this feature in your own config extension & extend this function.
}
/**Listen for a reload of this JSON file! */
onReload(cb:Function){
this.reloadListeners.push(cb)
}
/**Remove all reload listeners. Not recommended! */
removeAllReloadListeners(){
this.reloadListeners = []
}
}
/**## ODJsonConfig `class`
* This is an Open Ticket JSON config.
* You can use this class to get & edit variables from the config files or to create your own JSON config!
* @example
* //create a config from: ./config/test.json with the id "some-config"
* const config = new api.ODJsonConfig("some-config","test.json")
*
* //create a config with custom dir: ./plugins/testplugin/test.json
* const config = new api.ODJsonConfig("plugin-config","test.json","./plugins/testplugin/")
*/
export class ODJsonConfig extends ODConfig {
formatter: fjs.custom.BaseFormatter
constructor(id:ODValidId, file:string, customPath?:string, formatter?:fjs.custom.BaseFormatter){
super(id,{})
this.file = (file.endsWith(".json")) ? file : file+".json"
this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./config/",this.file)
this.formatter = formatter ?? new fjs.DefaultFormatter(null,true," ")
}
/**Init the config. */
init(): ODPromiseVoid {
if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!")
try{
this.data = JSON.parse(fs.readFileSync(this.path).toString())
super.init()
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Unable to parse config \""+nodepath.join("./",this.path)+"\"!")
}
}
/**Reload the config. Be aware that this doesn't update the config data everywhere in the bot! */
reload(){
if (!this.initiated) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file hasn't been initiated yet!")
if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\", the file doesn't exist!")
try{
this.data = JSON.parse(fs.readFileSync(this.path).toString())
super.reload()
this.reloadListeners.forEach((cb) => {
try{
cb()
}catch(err){
process.emit("uncaughtException",err)
}
})
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Unable to reload config \""+nodepath.join("./",this.path)+"\"!")
}
}
/**Save the edited config to the filesystem. This is used by the Interactive Setup CLI. It's not recommended to use this while the bot is running. */
save(): ODPromiseVoid {
if (!this.initiated) throw new ODSystemError("Unable to save config \""+nodepath.join("./",this.path)+"\", the file hasn't been initiated yet!")
try{
const contents = this.formatter.stringify(this.data)
fs.writeFileSync(this.path,contents)
super.save()
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Unable to save config \""+nodepath.join("./",this.path)+"\"!")
}
}
}
-665
View File
@@ -1,665 +0,0 @@
///////////////////////////////////////
//CONSOLE MODULE
///////////////////////////////////////
import { ODHTTPGetRequest, ODVersion, ODSystemError, ODPluginError, ODManager, ODManagerData, ODValidId } from "./base"
import { ODMain } from "../main"
import nodepath from "path"
import fs from "fs"
import ansis from "ansis"
/**## ODValidConsoleColor `type`
* This is a collection of all the supported console colors within Open Ticket.
*/
export type ODValidConsoleColor = "white"|"red"|"yellow"|"green"|"blue"|"gray"|"cyan"|"magenta"
/**## ODConsoleMessageParam `type`
* This interface contains all data required for a console log parameter within Open Ticket.
*/
export interface ODConsoleMessageParam {
/**The key of this parameter. */
key:string,
/**The value of this parameter. */
value:string,
/**When enabled, this parameter will only be shown in the debug file. */
hidden?:boolean
}
/**## ODConsoleMessage `class`
* This is an Open Ticket console message.
*
* It is used to create beautiful & styled logs in the console with a prefix, message & parameters.
* It also has full color support using `ansis` and parameters are parsed for you!
*/
export class ODConsoleMessage {
/**The main message sent in the console */
message: string
/**An array of all the parameters in this message */
params: ODConsoleMessageParam[]
/**The prefix of this message (!uppercase recommended!) */
prefix: string
/**The color of the prefix of this message */
color: ODValidConsoleColor
constructor(message:string, prefix:string, color:ODValidConsoleColor, params?:ODConsoleMessageParam[]){
this.message = message
this.params = params ? params : []
this.prefix = prefix
if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){
this.color = color
}else{
this.color = "white"
}
}
/**Render this message to the console using `console.log`! Returns `false` when something went wrong. */
render(){
try {
const prefixcolor = ansis[this.color]
const paramsstring = " "+this.createParamsString("gray")
const message = prefixcolor("["+this.prefix+"] ")+this.message
console.log(message+paramsstring)
return true
}catch{
return false
}
}
/**Create a more-detailed, non-colored version of this message to store it in the `otdebug.txt` file! */
toDebugString(){
const pstrings: string[] = []
this.params.forEach((p) => {
pstrings.push(p.key+": "+p.value)
})
const pstring = (pstrings.length > 0) ? " ("+pstrings.join(", ")+")" : ""
const date = new Date()
const dstring = `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
return `[${dstring} ${this.prefix}] ${this.message}${pstring}`
}
/**Render the parameters of this message in a specific color. */
createParamsString(color:ODValidConsoleColor){
let validcolor: ODValidConsoleColor = "white"
if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){
validcolor = color
}
const pstrings: string[] = []
this.params.forEach((p) => {
if (!p.hidden) pstrings.push(p.key+": "+p.value)
})
return (pstrings.length > 0) ? ansis[validcolor](" ("+pstrings.join(", ")+")") : ""
}
/**Set the message */
setMessage(message:string){
this.message = message
return this
}
/**Set the params */
setParams(params:ODConsoleMessageParam[]){
this.params = params
return this
}
/**Set the prefix */
setPrefix(prefix:string){
this.prefix = prefix
return this
}
/**Set the prefix color */
setColor(color:ODValidConsoleColor){
if (["white","red","yellow","green","blue","gray","cyan","magenta"].includes(color)){
this.color = color
}else{
this.color = "white"
}
return this
}
}
/**## ODConsoleInfoMessage `class`
* This is an Open Ticket console info message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "INFO" messages!
*/
export class ODConsoleInfoMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"INFO","blue",params)
}
}
/**## ODConsoleSystemMessage `class`
* This is an Open Ticket console system message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "SYSTEM" messages!
*/
export class ODConsoleSystemMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"SYSTEM","green",params)
}
}
/**## ODConsolePluginMessage `class`
* This is an Open Ticket console plugin message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "PLUGIN" messages!
*/
export class ODConsolePluginMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"PLUGIN","magenta",params)
}
}
/**## ODConsoleDebugMessage `class`
* This is an Open Ticket console debug message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "DEBUG" messages!
*/
export class ODConsoleDebugMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"DEBUG","cyan",params)
}
}
/**## ODConsoleWarningMessage `class`
* This is an Open Ticket console warning message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "WARNING" messages!
*/
export class ODConsoleWarningMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"WARNING","yellow",params)
}
}
/**## ODConsoleErrorMessage `class`
* This is an Open Ticket console error message.
*
* It is the same as a normal `ODConsoleMessage`, but it has a predefined prefix & color scheme for the "ERROR" messages!
*/
export class ODConsoleErrorMessage extends ODConsoleMessage {
constructor(message:string,params?:ODConsoleMessageParam[]){
super(message,"ERROR","red",params)
}
}
/**## ODError `class`
* This is an Open Ticket error.
*
* It is used to render and log Node.js errors & crashes in a styled way to the console & `otdebug.txt` file!
*/
export class ODError {
/**The original error that this class wraps around */
error: Error|ODSystemError|ODPluginError
/**The origin of the original error */
origin: NodeJS.UncaughtExceptionOrigin
constructor(error:Error|ODSystemError|ODPluginError, origin:NodeJS.UncaughtExceptionOrigin){
this.error = error
this.origin = origin
}
/**Render this error to the console using `console.log`! Returns `false` when something went wrong. */
render(){
try {
let prefix = (this.error["_ODErrorType"] == "plugin") ? "PLUGIN ERROR" : ((this.error["_ODErrorType"] == "system") ? "OPENTICKET ERROR" : "UNKNOWN ERROR")
//title
console.log(ansis.red("["+prefix+"]: ")+this.error.message+" | origin: "+this.origin)
//stack trace
if (this.error.stack) console.log(ansis.gray(this.error.stack))
//additional message
if (this.error["_ODErrorType"] == "plugin") console.log(ansis.red.bold("\nPlease report this error to the plugin developer and help us create a more stable plugin!"))
else console.log(ansis.red.bold("\nPlease report this error to our discord server and help us create a more stable ticket bot!"))
console.log(ansis.red("Also send the "+ansis.cyan.bold("otdebug.txt")+" file! It would help a lot!\n"))
return true
}catch{
return false
}
}
/**Create a more-detailed, non-colored version of this error to store it in the `otdebug.txt` file! */
toDebugString(){
return "[UNKNOWN OD ERROR]: "+this.error.message+" | origin: "+this.origin+"\n"+this.error.stack
}
}
/**## ODConsoleMessageTypes `type`
* This is a collection of all the default console message types within Open Ticket.
*/
export type ODConsoleMessageTypes = "info"|"system"|"plugin"|"debug"|"warning"|"error"
/**## ODConsoleManager `class`
* This is the Open Ticket console manager.
*
* It handles the entire console system of Open Ticket. It's also the place where you need to log `ODConsoleMessage`'s.
* This manager keeps a short history of messages sent to the console which is configurable by plugins.
*
* The debug file (`otdebug.txt`) is handled in a sub-manager!
*/
export class ODConsoleManager {
/**The history of `ODConsoleMessage`'s and `ODError`'s since startup */
history: (ODConsoleMessage|ODError)[] = []
/**The max length of the history. The oldest messages will be removed when over the limit */
historylength = 100
/**An alias to the debugfile manager. (`otdebug.txt`) */
debugfile: ODDebugFileManager
/**Is silent mode enabled? */
silent: boolean = false
constructor(historylength:number, debugfile:ODDebugFileManager){
this.historylength = historylength
this.debugfile = debugfile
}
/**Log a message to the console ... But in the Open Ticket way :) */
log(message:ODConsoleMessage): void
log(message:ODError): void
log(message:string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]): void
log(message:ODConsoleMessage|ODError|string, type?:ODConsoleMessageTypes, params?:ODConsoleMessageParam[]){
if (message instanceof ODConsoleMessage){
if (!this.silent) message.render()
if (this.debugfile) this.debugfile.writeConsoleMessage(message)
this.history.push(message)
}else if (message instanceof ODError){
if (!this.silent) message.render()
if (this.debugfile) this.debugfile.writeErrorMessage(message)
this.history.push(message)
}else if (["string","number","boolean","object"].includes(typeof message)){
let newMessage: ODConsoleMessage
if (type == "info") newMessage = new ODConsoleInfoMessage(message,params)
else if (type == "system") newMessage = new ODConsoleSystemMessage(message,params)
else if (type == "plugin") newMessage = new ODConsolePluginMessage(message,params)
else if (type == "debug") newMessage = new ODConsoleDebugMessage(message,params)
else if (type == "warning") newMessage = new ODConsoleWarningMessage(message,params)
else if (type == "error") newMessage = new ODConsoleErrorMessage(message,params)
else newMessage = new ODConsoleSystemMessage(message,params)
if (!this.silent) newMessage.render()
if (this.debugfile) this.debugfile.writeConsoleMessage(newMessage)
this.history.push(newMessage)
}
this.#purgeHistory()
}
/**Shorten the history when it exceeds the max history length! */
#purgeHistory(){
if (this.history.length > this.historylength) this.history.shift()
}
}
/**## ODDebugFileManager `class`
* This is the Open Ticket debug file manager.
*
* It manages the Open Ticket debug file (`otdebug.txt`) which keeps a history of all system logs.
* There are even internal logs that aren't logged to the console which are available in this file!
*
* Using this class, you can change the max length of this file and some other cool things!
*/
export class ODDebugFileManager {
/**The path to the debugfile (`./otdebug.txt` by default) */
path: string
/**The filename of the debugfile (`otdebug.txt` by default) */
filename: string
/**The current version of the bot used in the debug file. */
version: ODVersion
/**The max length of the debug file. */
maxlines: number
constructor(path:string, filename:string, maxlines:number, version:ODVersion){
this.path = nodepath.join(path,filename)
this.filename = filename
this.version = version
this.maxlines = maxlines
this.#writeStartupStats()
}
/**Check if the debug file exists */
#existsDebugFile(){
return fs.existsSync(this.path)
}
/**Read from the debug file */
#readDebugFile(){
if (this.#existsDebugFile()){
try {
return fs.readFileSync(this.path).toString()
}catch{
return false
}
}else{
return false
}
}
/**Write to the debug file and shorten it when needed. */
#writeDebugFile(text:string){
const currenttext = this.#readDebugFile()
if (currenttext){
const splitted = currenttext.split("\n")
if (splitted.length+text.split("\n").length > this.maxlines){
splitted.splice(7,(text.split("\n").length))
}
splitted.push(text)
fs.writeFileSync(this.path,splitted.join("\n"))
}else{
//write new file:
const newtext = this.#createStatsText()+text
fs.writeFileSync(this.path,newtext)
}
}
/**Generate the stats/header of the debug file (containing the version) */
#createStatsText(){
const date = new Date()
const dstring = `${date.getDate()}/${date.getMonth()+1}/${date.getFullYear()} ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`
return [
"=========================",
"OPEN TICKET DEBUG FILE:",
"version: "+this.version.toString(),
"last startup: "+dstring,
"=========================\n\n"
].join("\n")
}
/**Write the stats/header to the debug file on startup */
#writeStartupStats(){
const currenttext = this.#readDebugFile()
if (currenttext){
//edit previous file:
const splitted = currenttext.split("\n")
splitted.splice(0,7)
if (splitted.length+11 > this.maxlines){
splitted.splice(0,((splitted.length+11) - this.maxlines))
}
splitted.unshift(this.#createStatsText())
splitted.push("\n---------------------------------------------------------------------\n---------------------------------------------------------------------\n")
fs.writeFileSync(this.path,splitted.join("\n"))
}else{
//write new file:
const newtext = this.#createStatsText()
fs.writeFileSync(this.path,newtext)
}
}
/**Write an `ODConsoleMessage` to the debug file */
writeConsoleMessage(message:ODConsoleMessage){
this.#writeDebugFile(message.toDebugString())
}
/**Write an `ODError` to the debug file */
writeErrorMessage(error:ODError){
this.#writeDebugFile(error.toDebugString())
}
/**Write custom text to the debug file */
writeText(text:string){
this.#writeDebugFile(text)
}
/**Write a custom note to the debug file (starting with `[NOTE]:`) */
writeNote(text:string){
this.#writeDebugFile("[NOTE]: "+text)
}
}
/**## ODDebugger `class`
* This is the Open Ticket debugger.
*
* It is a simple wrapper around the `ODConsoleManager` to handle debugging (primarily for `ODManagers`).
* Messages created using this debugger are only logged to the debug file unless specified otherwise.
*
* You will probably notice this class being used in the `ODManager` constructor.
*
* Using this system, all additions & removals inside a manager are logged to the debug file. This makes searching for errors a lot easier!
*/
export class ODDebugger {
/**An alias to the Open Ticket console manager. */
console: ODConsoleManager
/**When enabled, debug logs are also shown in the console. */
visible: boolean = false
constructor(console:ODConsoleManager){
this.console = console
}
/**Create a debug message. This will always be logged to `otdebug.txt` & sometimes to the console (when enabled). Returns `true` when visible */
debug(message:string, params?:{key:string,value:string}[]): boolean {
if (this.visible){
this.console.log(new ODConsoleDebugMessage(message,params))
return true
}else{
this.console.debugfile.writeConsoleMessage(new ODConsoleDebugMessage(message,params))
return false
}
}
}
/**## ODLivestatusColor `type`
* This is a collection of all the colors available within the LiveStatus system.
*/
export type ODLiveStatusColor = "normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan"
/**## ODLiveStatusSourceData `interface`
* This is an interface containing all raw data received from the LiveStatus system.
*/
export interface ODLiveStatusSourceData {
/**The message to display */
message:{
/**The title of the message to display */
title:string,
/**The title color of the message to display */
titleColor:ODLiveStatusColor,
/**The description of the message to display */
description:string,
/**The description color of the message to display */
descriptionColor:ODLiveStatusColor
},
/**The message will only be shown when the bot matches all statements */
active:{
/**A list of versions to match */
versions:string[],
/**A list of languages to match */
languages:string[],
/**All languages should match */
allLanguages:boolean,
/**Match when the bot is using plugins */
usingPlugins:boolean,
/**Match when the bot is not using plugins */
notUsingPlugins:boolean,
/**Match when the bot is using slash commands */
usingSlashCommands:boolean,
/**Match when the bot is not using slash commands */
notUsingSlashCommands:boolean,
/**Match when the bot is not using transcripts */
notUsingTranscripts:boolean,
/**Match when the bot is using text transcripts */
usingTextTranscripts:boolean,
/**Match when the bot is using html transcripts */
usingHtmlTranscripts:boolean
}
}
/**## ODLiveStatusSource `class`
* This is the Open Ticket livestatus source.
*
* It is an empty template for a livestatus source.
* By default, you should use `ODLiveStatusUrlSource` or `ODLiveStatusFileSource`,
* unless you want to create one on your own!
*
* This class doesn't do anything on it's own! It's just a template!
*/
export class ODLiveStatusSource extends ODManagerData {
/**The raw data of this source */
data: ODLiveStatusSourceData[]
constructor(id:ODValidId, data:ODLiveStatusSourceData[]){
super(id)
this.data = data
}
/**Change the current data using this method! */
setData(data:ODLiveStatusSourceData[]){
this.data = data
}
/**Get all messages relevant to the bot based on some parameters. */
async getMessages(main:ODMain): Promise<ODLiveStatusSourceData[]> {
const validMessages: ODLiveStatusSourceData[] = []
//parse data from ODMain
const currentVersion: string = main.versions.get("opendiscord:version").toString(true)
const usingSlashCommands: boolean = main.configs.get("opendiscord:general").data.slashCommands
const usingTranscripts: false|"text"|"html" = false as false|"text"|"html" //TODO
const currentLanguage: string = main.languages.getCurrentLanguageId()
const usingPlugins: boolean = (main.plugins.getLength() > 0)
//check data for each message
this.data.forEach((msg) => {
const {active} = msg
const correctVersion = active.versions.includes(currentVersion)
const correctSlashMode = (usingSlashCommands && active.usingSlashCommands) || (!usingSlashCommands && active.notUsingSlashCommands)
const correctTranscriptMode = (usingTranscripts == "text" && active.usingTextTranscripts) || (usingTranscripts == "html" && active.usingHtmlTranscripts) || (!usingTranscripts && active.notUsingTranscripts)
const correctLanguage = active.languages.includes(currentLanguage) || active.allLanguages
const correctPlugins = (usingPlugins && active.usingPlugins) || (!usingPlugins && active.notUsingPlugins)
if (correctVersion && correctLanguage && correctPlugins && correctSlashMode && correctTranscriptMode) validMessages.push(msg)
})
//return the valid messages
return validMessages
}
}
/**## ODLiveStatusFileSource `class`
* This is the Open Ticket livestatus file source.
*
* It is a LiveStatus source that will read the data from a local file.
*
* This can be used for testing/extending the LiveStatus system!
*/
export class ODLiveStatusFileSource extends ODLiveStatusSource {
/**The path to the source file */
path: string
constructor(id:ODValidId, path:string){
if (fs.existsSync(path)){
super(id,JSON.parse(fs.readFileSync(path).toString()))
}else throw new ODSystemError("LiveStatus source file doesn't exist!")
this.path = path
}
}
/**## ODLiveStatusUrlSource `class`
* This is the Open Ticket livestatus url source.
*
* It is a LiveStatus source that will read the data from a http URL (json file).
*
* This is the default way of receiving LiveStatus messages!
*/
export class ODLiveStatusUrlSource extends ODLiveStatusSource {
/**The url used in the request */
url: string
/**The `ODHTTPGetRequest` helper to fetch the url! */
request: ODHTTPGetRequest
constructor(id:ODValidId, url:string){
super(id,[])
this.url = url
this.request = new ODHTTPGetRequest(url,false)
}
async getMessages(main:ODMain): Promise<ODLiveStatusSourceData[]> {
//additional setup
this.request.url = this.url
const rawRes = await this.request.run()
if (rawRes.status != 200) throw new ODSystemError("ODLiveStatusUrlSource => Request Failed!")
try{
this.setData(JSON.parse(rawRes.body))
}catch{
throw new ODSystemError("ODLiveStatusUrlSource => Request Failed!")
}
//default
return super.getMessages(main)
}
}
/**## ODLiveStatusManager `class`
* This is the Open Ticket livestatus manager.
*
* It manages all LiveStatus sources and has the renderer for all LiveStatus messages.
*
* You can use this to customise or add stuff to the LiveStatus system.
* Access it in the global `opendiscord.startscreen.livestatus` variable!
*/
export class ODLiveStatusManager extends ODManager<ODLiveStatusSource> {
/**The class responsible for rendering the livestatus messages. */
renderer: ODLiveStatusRenderer
/**A reference to the ODMain or "openticket" global variable */
#main: ODMain
constructor(debug:ODDebugger, main:ODMain){
super(debug,"livestatus source")
this.renderer = new ODLiveStatusRenderer(main.console)
this.#main = main
}
/**Get the messages from all sources combined! */
async getAllMessages(): Promise<ODLiveStatusSourceData[]> {
const messages: ODLiveStatusSourceData[] = []
for (const source of this.getAll()){
try {
messages.push(...(await source.getMessages(this.#main)))
}catch{}
}
return messages
}
}
/**## ODLiveStatusRenderer `class`
* This is the Open Ticket livestatus renderer.
*
* It's responsible for rendering all LiveStatus messages to the console.
*/
export class ODLiveStatusRenderer {
/**A reference to the ODConsoleManager or "opendiscord.console" global variable */
#console: ODConsoleManager
constructor(console:ODConsoleManager){
this.#console = console
}
/**Render all messages */
render(messages:ODLiveStatusSourceData[]): string {
try {
//process data
const final: string[] = []
messages.forEach((msg) => {
const titleColor = msg.message.titleColor
const title = "["+msg.message.title+"] "
const descriptionColor = msg.message.descriptionColor
const description = msg.message.description.split("\n").map((text,row) => {
//first row row doesn't need prefix
if (row < 1) return text
//other rows do need a prefix
let text2 = text
for (const i of title){
text2 = " "+text2
}
return text2
}).join("\n")
if (!["red","yellow","green","blue","gray","magenta","cyan"].includes(titleColor)) var finalTitle = ansis.white(title)
else var finalTitle = ansis[titleColor](title)
if (!["red","yellow","green","blue","gray","magenta","cyan"].includes(descriptionColor)) var finalDescription = ansis.white(description)
else var finalDescription = ansis[descriptionColor](description)
final.push(finalTitle+finalDescription)
})
//return all messages
return final.join("\n")
}catch{
this.#console.log("Failed to render LiveStatus messages!","error")
return ""
}
}
}
-348
View File
@@ -1,348 +0,0 @@
///////////////////////////////////////
//COOLDOWN MODULE
///////////////////////////////////////
import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base"
import { ODDebugger } from "./console"
/**## ODCooldownManager `class`
* This is an Open Ticket cooldown manager.
*
* It is responsible for managing all cooldowns in Open Ticket. An example of this is the ticket creation cooldown.
*
* There are many types of cooldowns available, but you can also create your own!
*/
export class ODCooldownManager extends ODManager<ODCooldown<object>> {
constructor(debug:ODDebugger){
super(debug,"cooldown")
}
/**Initiate all cooldowns in this manager. */
async init(){
for (const cooldown of this.getAll()){
await cooldown.init()
}
}
}
/**## ODCooldownData `class`
* This is Open Ticket cooldown data.
*
* It contains the instance of an active cooldown (e.g. for a user). It is handled by the cooldown itself.
*/
export class ODCooldownData<Data extends object> extends ODManagerData {
/**Is this cooldown active? */
active: boolean
/**Additional data of this cooldown instance. (different for each cooldown type) */
data: Data
constructor(id:ODValidId,active:boolean,data:Data){
super(id)
this.active = active
this.data = data
}
}
/**## ODCooldown `class`
* This is an Open Ticket cooldown.
*
* It doesn't do anything on it's own, but it provides the methods that are used to interact with a cooldown.
* This class can be extended from to create a working cooldown.
*
* There are also premade cooldowns available in the bot!
*/
export class ODCooldown<Data extends object> extends ODManagerData {
data: ODManager<ODCooldownData<Data>> = new ODManager()
/**Is this cooldown already initialized? */
ready: boolean = false
constructor(id:ODValidId){
super(id)
}
/**Check this id and start cooldown when it exeeds the limit! Returns `true` when on cooldown! */
use(id:string): boolean {
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
/**Check this id without starting or updating the cooldown. Returns `true` when on cooldown! */
check(id:string): boolean {
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
/**Remove the cooldown for an id when available.*/
delete(id:string){
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
/**Initialize the internal systems of this cooldown. */
async init(){
throw new ODSystemError("Tried to use an unimplemented ODCooldown!")
}
}
/**## ODCounterCooldown `class`
* This is an Open Ticket counter cooldown.
*
* It is is a cooldown based on a counter. When the number exceeds the limit, the cooldown is activated.
* The number will automatically be decreased with a set amount & interval.
*/
export class ODCounterCooldown extends ODCooldown<{value:number}> {
/**The cooldown will activate when exceeding this limit. */
activeLimit: number
/**The cooldown will deactivate when below this limit. */
cancelLimit: number
/**The amount to increase the counter with everytime the cooldown is triggered/updated. */
increment: number
/**The amount to decrease the counter over time. */
decrement: number
/**The interval between decrements in milliseconds. */
invervalMs: number
constructor(id:ODValidId, activeLimit:number, cancelLimit:number, increment:number, decrement:number, intervalMs:number){
super(id)
this.activeLimit = activeLimit
this.cancelLimit = cancelLimit
this.increment = increment
this.decrement = decrement
this.invervalMs = intervalMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if (cooldown.active){
return true
}else if (cooldown.data.value < this.activeLimit){
cooldown.data.value = cooldown.data.value + this.increment
return false
}else{
cooldown.active = true
return false
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,(this.increment >= this.activeLimit),{
value:this.increment
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return cooldown.active
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
async init(){
if (this.ready) return
setInterval(async () => {
await this.data.loopAll((cooldown) => {
cooldown.data.value = cooldown.data.value - this.decrement
if (cooldown.data.value <= this.cancelLimit){
cooldown.active = false
}
if (cooldown.data.value <= 0){
this.data.remove(cooldown.id)
}
})
},this.invervalMs)
this.ready = true
}
}
/**## ODIncrementalCounterCooldown `class`
* This is an Open Ticket incremental counter cooldown.
*
* It is is a cooldown based on an incremental counter. It is exactly the same as the normal counter,
* with the only difference being that it still increments when the limit is already exeeded.
*/
export class ODIncrementalCounterCooldown extends ODCooldown<{value:number}> {
/**The cooldown will activate when exceeding this limit. */
activeLimit: number
/**The cooldown will deactivate when below this limit. */
cancelLimit: number
/**The amount to increase the counter with everytime the cooldown is triggered/updated. */
increment: number
/**The amount to decrease the counter over time. */
decrement: number
/**The interval between decrements in milliseconds. */
invervalMs: number
constructor(id:ODValidId, activeLimit:number, cancelLimit:number, increment:number, decrement:number, intervalMs:number){
super(id)
this.activeLimit = activeLimit
this.cancelLimit = cancelLimit
this.increment = increment
this.decrement = decrement
this.invervalMs = intervalMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if (cooldown.active){
cooldown.data.value = cooldown.data.value + this.increment
return true
}else if (cooldown.data.value < this.activeLimit){
cooldown.data.value = cooldown.data.value + this.increment
return false
}else{
cooldown.active = true
return false
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,(this.increment >= this.activeLimit),{
value:this.increment
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return cooldown.active
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
async init(){
if (this.ready) return
setInterval(async () => {
await this.data.loopAll((cooldown) => {
cooldown.data.value = cooldown.data.value - this.decrement
if (cooldown.data.value <= this.cancelLimit){
cooldown.active = false
}
if (cooldown.data.value <= 0){
this.data.remove(cooldown.id)
}
})
},this.invervalMs)
this.ready = true
}
}
/**## ODTimeoutCooldown `class`
* This is an Open Ticket timeout cooldown.
*
* It is a cooldown based on a timer. When triggered/updated, the cooldown is activated for the set amount of time.
* After the timer has timed out, the cooldown will be deleted.
*/
export class ODTimeoutCooldown extends ODCooldown<{date:number}> {
/**The amount of milliseconds before the cooldown times-out */
timeoutMs: number
constructor(id:ODValidId, timeoutMs:number){
super(id)
this.timeoutMs = timeoutMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if ((new Date().getTime() - cooldown.data.date) > this.timeoutMs){
this.data.remove(id)
return false
}else{
return true
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,true,{
date:new Date().getTime()
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return true
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
/**Get the remaining amount of milliseconds before the timeout stops. */
remaining(id:string): number|null {
const cooldown = this.data.get(id)
if (!cooldown) return null
const rawResult = this.timeoutMs - (new Date().getTime() - cooldown.data.date)
return (rawResult > 0) ? rawResult : 0
}
async init(){
if (this.ready) return
this.ready = true
}
}
/**## ODIncrementalTimeoutCooldown `class`
* This is an Open Ticket incremental timeout cooldown.
*
* It is is a cooldown based on an incremental timer. It is exactly the same as the normal timer,
* with the only difference being that it adds additional time when triggered/updated while the cooldown is already active.
*/
export class ODIncrementalTimeoutCooldown extends ODCooldown<{date:number}> {
/**The amount of milliseconds before the cooldown times-out */
timeoutMs: number
/**The amount of milliseconds to add when triggered/updated while the cooldown is already active. */
incrementMs: number
constructor(id:ODValidId, timeoutMs:number, incrementMs:number){
super(id)
this.timeoutMs = timeoutMs
this.incrementMs = incrementMs
}
use(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
if ((new Date().getTime() - cooldown.data.date) > this.timeoutMs){
this.data.remove(id)
return false
}else{
cooldown.data.date = cooldown.data.date + this.incrementMs
return true
}
}else{
//cooldown for this id doesn't exist
this.data.add(new ODCooldownData(id,true,{
date:new Date().getTime()
}))
return false
}
}
check(id:string): boolean {
const cooldown = this.data.get(id)
if (cooldown){
//cooldown for this id already exists
return true
}else return false
}
delete(id:string): void {
this.data.remove(id)
}
/**Get the remaining amount of milliseconds before the timeout stops. */
remaining(id:string): number|null {
const cooldown = this.data.get(id)
if (!cooldown) return null
const rawResult = this.timeoutMs - (new Date().getTime() - cooldown.data.date)
return (rawResult > 0) ? rawResult : 0
}
async init(){
if (this.ready) return
this.ready = true
}
}
-278
View File
@@ -1,278 +0,0 @@
///////////////////////////////////////
//DATABASE MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODOptionalPromise, ODPromiseVoid, ODSystemError, ODValidId, ODValidJsonType } from "./base"
import fs from "fs"
import nodepath from "path"
import { ODDebugger } from "./console"
import * as fjs from "formatted-json-stringify"
/**## ODDatabaseManager `class`
* This is an Open Ticket database manager.
*
* It manages all databases in the bot and allows to permanently store data from the bot!
*
* You can use this class to get/add a database (`ODDatabase`) in your plugin!
*/
export class ODDatabaseManager extends ODManager<ODDatabase> {
constructor(debug:ODDebugger){
super(debug,"database")
}
/**Init all database files. */
async init(){
for (const database of this.getAll()){
try{
await database.init()
}catch(err){
process.emit("uncaughtException",new ODSystemError(err))
}
}
}
}
/**## ODDatabase `class`
* This is an Open Ticket database template.
* This class doesn't do anything at all, it just gives a template & basic methods for a database. Use `ODJsonDatabase` instead!
*
* You can use this class if you want to create your own database implementation (e.g. `mongodb`, `mysql`,...)!
*/
export class ODDatabase extends ODManagerData {
/**The name of the file with extension. */
file: string = ""
/**The path to the file relative to the main directory. */
path: string = ""
/**Init the database. */
init(): ODPromiseVoid {
//nothing
}
/**Add/Overwrite a specific category & key in the database. Returns `true` when overwritten. */
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean> {
return false
}
/**Get a specific category & key in the database */
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined> {
return undefined
}
/**Delete a specific category & key in the database */
delete(category:string, key:string): ODOptionalPromise<boolean> {
return false
}
/**Check if a specific category & key exists in the database */
exists(category:string, key:string): ODOptionalPromise<boolean> {
return false
}
/**Get a specific category in the database */
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
return undefined
}
/**Get all values in the database */
getAll(): ODOptionalPromise<ODJsonDatabaseStructure> {
return []
}
}
/**## ODJsonDatabaseStructure `type`
* This is the structure of how a JSON database file!
*/
export type ODJsonDatabaseStructure = {category:string, key:string, value:ODValidJsonType}[]
/**## ODJsonDatabase `class`
* This is an Open Ticket JSON database.
* It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy.
* You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`!
*
* You can use this class if you want to add your own database or to use an existing one!
*/
export class ODJsonDatabase extends ODDatabase {
constructor(id:ODValidId, file:string, customPath?:string){
super(id)
this.file = (file.endsWith(".json")) ? file : file+".json"
this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./database/",this.file)
}
/**Init the database. */
init(): ODPromiseVoid {
this.#system.getData()
}
/**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten!
* @example
* const didOverwrite = database.setData("category","key","value") //value can be any of the valid types
* //You need an ODJsonDatabase class named "database" for this example to work!
*/
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean> {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
//overwrite when already present
if (currentData){
currentList[currentList.indexOf(currentData)].value = value
}else{
currentList.push({category,key,value})
}
this.#system.setData(currentList)
return currentData ? true : false
}
/**Get the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const data = database.getData("category","key") //data will be the value
* //You need an ODJsonDatabase class named "database" for this example to work!
*/
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined> {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? tempresult.value : undefined
}
/**Remove the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const didExist = database.deleteData("category","key") //delete this value
* //You need an ODJsonDatabase class named "database" for this example to work!
*/
delete(category:string, key:string): ODOptionalPromise<boolean> {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
if (currentData) currentList.splice(currentList.indexOf(currentData),1)
this.#system.setData(currentList)
return currentData ? true : false
}
/**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */
exists(category:string, key:string): ODOptionalPromise<boolean> {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? true : false
}
/**Get all values in `category`. Returns `undefined` when non-existent! */
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
const currentList = this.#system.getData()
const tempresult = currentList.filter((d) => (d.category === category))
return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined
}
/**Get all values in `category`. */
getAll(): ODOptionalPromise<ODJsonDatabaseStructure> {
return this.#system.getData()
}
#system = {
/**Read parsed data from the json file */
getData: (): ODJsonDatabaseStructure => {
if (fs.existsSync(this.path)){
try{
return JSON.parse(fs.readFileSync(this.path).toString())
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Unable to read database "+this.path+"! getData() read error. (see error above)")
}
}else{
fs.writeFileSync(this.path,"[]")
return []
}
},
/**Write parsed data to the json file */
setData: (data:ODJsonDatabaseStructure) => {
fs.writeFileSync(this.path,JSON.stringify(data,null,"\t"))
}
}
}
/**## ODFormattedJsonDatabase `class`
* This is an Open Ticket Formatted JSON database.
* It stores data in a `json` file as a large `Array` using the `category`, `key`, `value` strategy.
* You can store the following types: `string`, `number`, `boolean`, `array`, `object` & `null`!
*
* This one is exactly the same as `ODJsonDatabase`, but it has a formatter from the `formatted-json-stringify` package.
* This can help you organise it a little bit better!
*/
export class ODFormattedJsonDatabase extends ODDatabase {
/**The formatter to use on the database array */
formatter: fjs.ArrayFormatter
constructor(id:ODValidId, file:string, formatter:fjs.ArrayFormatter, customPath?:string){
super(id)
this.file = (file.endsWith(".json")) ? file : file+".json"
this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./database/",this.file)
this.formatter = formatter
}
/**Init the database. */
init(): ODPromiseVoid {
this.#system.getData()
}
/**Set/overwrite the value of `category` & `key`. Returns `true` when overwritten!
* @example
* const didOverwrite = database.setData("category","key","value") //value can be any of the valid types
* //You need an ODFormattedJsonDatabase class named "database" for this example to work!
*/
set(category:string, key:string, value:ODValidJsonType): ODOptionalPromise<boolean> {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
//overwrite when already present
if (currentData){
currentList[currentList.indexOf(currentData)].value = value
}else{
currentList.push({category,key,value})
}
this.#system.setData(currentList)
return currentData ? true : false
}
/**Get the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const data = database.getData("category","key") //data will be the value
* //You need an ODFormattedJsonDatabase class named "database" for this example to work!
*/
get(category:string, key:string): ODOptionalPromise<ODValidJsonType|undefined> {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? tempresult.value : undefined
}
/**Remove the value of `category` & `key`. Returns `undefined` when non-existent!
* @example
* const didExist = database.deleteData("category","key") //delete this value
* //You need an ODFormattedJsonDatabase class named "database" for this example to work!
*/
delete(category:string, key:string): ODOptionalPromise<boolean> {
const currentList = this.#system.getData()
const currentData = currentList.find((d) => (d.category === category) && (d.key === key))
if (currentData) currentList.splice(currentList.indexOf(currentData),1)
this.#system.setData(currentList)
return currentData ? true : false
}
/**Check if a value of `category` & `key` exists. Returns `false` when non-existent! */
exists(category:string, key:string): ODOptionalPromise<boolean> {
const currentList = this.#system.getData()
const tempresult = currentList.find((d) => (d.category === category) && (d.key === key))
return tempresult ? true : false
}
/**Get all values in `category`. Returns `undefined` when non-existent! */
getCategory(category:string): ODOptionalPromise<{key:string, value:ODValidJsonType}[]|undefined> {
const currentList = this.#system.getData()
const tempresult = currentList.filter((d) => (d.category === category))
return tempresult ? tempresult.map((data) => {return {key:data.key,value:data.value}}) : undefined
}
/**Get all values in `category`. */
getAll(): ODOptionalPromise<ODJsonDatabaseStructure> {
return this.#system.getData()
}
#system = {
/**Read parsed data from the json file */
getData: (): ODJsonDatabaseStructure => {
if (fs.existsSync(this.path)){
return JSON.parse(fs.readFileSync(this.path).toString())
}else{
fs.writeFileSync(this.path,"[]")
return []
}
},
/**Write parsed data to the json file */
setData: (data:ODJsonDatabaseStructure) => {
fs.writeFileSync(this.path,this.formatter.stringify(data))
}
}
}
-366
View File
@@ -1,366 +0,0 @@
///////////////////////////////////////
//DEFAULTS MODULE
///////////////////////////////////////
/**## ODDefaults `interface`
* This type is a list of all defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export interface ODDefaults {
/**Enable the default error handling system. */
errorHandling:boolean,
/**Crash when there is an unknown bot error. */
crashOnError:boolean,
/**Enable the system responsible for the `--debug` flag. */
debugLoading:boolean,
/**Enable the system responsible for the `--silent` flag. */
silentLoading:boolean,
/**When enabled, you're able to use the "!OPENTICKET:dump" command to send the OT debug file. This is only possible when you're the owner of the bot. */
allowDumpCommand:boolean,
/**Enable loading all Open Ticket plugins, sadly enough is only useful for the system :) */
pluginLoading:boolean,
/**Don't crash the bot when a plugin crashes! */
softPluginLoading:boolean,
/**Load the default Open Ticket plugin classes. */
pluginClassLoading:boolean,
/**Load the default Open Ticket flags. */
flagLoading:boolean,
/**Enable the default initializer for Open Ticket flags. */
flagInitiating:boolean,
/**Load the default Open Ticket progress bar renderers. */
progressBarRendererLoading:boolean,
/**Load the default Open Ticket progress bars. */
progressBarLoading:boolean,
/**Load the default Open Ticket configs. */
configLoading:boolean,
/**Enable the default initializer for Open Ticket config. */
configInitiating:boolean,
/**Load the default Open Ticket databases. */
databaseLoading:boolean,
/**Enable the default initializer for Open Ticket database. */
databaseInitiating:boolean,
/**Load the default Open Ticket sessions. */
sessionLoading:boolean,
/**Load the default Open Ticket languages. */
languageLoading:boolean,
/**Enable the default initializer for Open Ticket languages. */
languageInitiating:boolean,
/**Enable selecting the current language from `config/general.json`. */
languageSelection:boolean,
/**Set the backup language when the primary language is missing a property. */
backupLanguage:string,
/****[NOT FOR PLUGIN TRANSLATIONS]** The full list of available languages (used in the default config checker). */
languageList:string[],
/**Load the default Open Ticket config checker. */
checkerLoading:boolean,
/**Load the default Open Ticket config checker functions. */
checkerFunctionLoading:boolean,
/**Enable the default execution of the config checkers. */
checkerExecution:boolean,
/**Load the default Open Ticket config checker translations. */
checkerTranslationLoading:boolean,
/**Enable the default rendering of the config checkers. */
checkerRendering:boolean,
/**Enable the default quit action when there is an error in the config checker. */
checkerQuit:boolean,
/**Render the checker even when there are no errors & warnings. */
checkerRenderEmpty:boolean,
/**Load the default Open Ticket client configuration. */
clientLoading:boolean,
/**Load the default Open Ticket client initialization. */
clientInitiating:boolean,
/**Load the default Open Ticket client ready actions (status, commands, permissions, ...). */
clientReady:boolean,
/**Create a warning when the bot is present in multiple guilds. */
clientMultiGuildWarning:boolean,
/**Load the default Open Ticket client activity (from `config/general.json`). */
clientActivityLoading:boolean,
/**Load the default Open Ticket client activity initialization (& status refresh). */
clientActivityInitiating:boolean,
/**Load the default Open Ticket priority levels. */
priorityLoading:boolean,
/**Load the default Open Ticket slash commands. */
slashCommandLoading:boolean,
/**Load the default Open Ticket slash command registerer (register slash cmds in discord). */
slashCommandRegistering:boolean,
/**When enabled, the bot is forced to re-register all slash commands in the server. This can be used in case of a auto-update malfunction. */
forceSlashCommandRegistration:boolean,
/**When enabled, the bot is allowed to unregister all slash commands which aren't used in Open Ticket. Disable this if you don't want to use the Open Ticket `ODSlashCommand` classes. */
allowSlashCommandRemoval:boolean,
/**Load the default Open Ticket context menus. */
contextMenuLoading:boolean,
/**Load the default Open Ticket context menu registerer (register menus in discord). */
contextMenuRegistering:boolean,
/**When enabled, the bot is forced to re-register all context menus in the server. This can be used in case of a auto-update malfunction. */
forceContextMenuRegistration:boolean,
/**When enabled, the bot is allowed to unregister all context menus which aren't used in Open Ticket. Disable this if you don't want to use the Open Ticket `ODContextMenu` classes. */
allowContextMenuRemoval:boolean,
/**Load the default Open Ticket text commands. */
textCommandLoading:boolean,
/**Load the default Open Ticket questions (from `config/questions.json`) */
questionLoading:boolean,
/**Load the default Open Ticket options (from `config/options.json`) */
optionLoading:boolean,
/**Load the default Open Ticket panels (from `config/panels.json`) */
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`) */
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`) */
transcriptHistoryLoading:boolean,
/**Load the default Open Ticket button builders. */
buttonBuildersLoading:boolean,
/**Load the default Open Ticket dropdown builders. */
dropdownBuildersLoading:boolean,
/**Load the default Open Ticket file builders. */
fileBuildersLoading:boolean,
/**Load the default Open Ticket embed builders. */
embedBuildersLoading:boolean,
/**Load the default Open Ticket message builders. */
messageBuildersLoading:boolean,
/**Load the default Open Ticket modal builders. */
modalBuildersLoading:boolean,
/**Load the default Open Ticket command responders. */
commandRespondersLoading:boolean,
/**Load the default Open Ticket button responders. */
buttonRespondersLoading:boolean,
/**Load the default Open Ticket dropdown responders. */
dropdownRespondersLoading:boolean,
/**Load the default Open Ticket modal responders. */
modalRespondersLoading:boolean,
/**Load the default Open Ticket context menu responders. */
contextMenuRespondersLoading:boolean,
/**Load the default Open Ticket autocomplete responders. */
autocompleteRespondersLoading:boolean,
/**Set the time (in ms) before Open Ticket sends an error message when no reply is sent in a responder. */
responderTimeoutMs:number,
/**Load the default Open Ticket actions. */
actionsLoading:boolean,
/**Load the default Open Ticket verify bars. */
verifyBarsLoading:boolean,
/**Load the default Open Ticket permissions. */
permissionsLoading:boolean,
/**Load the default Open Ticket posts. */
postsLoading:boolean,
/**Initiate the default Open Ticket posts. */
postsInitiating:boolean,
/**Load the default Open Ticket cooldowns. */
cooldownsLoading:boolean,
/**Initiate the default Open Ticket cooldowns. */
cooldownsInitiating:boolean,
/**Load the default Open Ticket help menu categories. */
helpMenuCategoryLoading:boolean,
/**Load the default Open Ticket help menu components. */
helpMenuComponentLoading:boolean,
/**Load the default Open Ticket stat scopes. */
statScopesLoading:boolean,
/**Load the default Open Ticket stats. */
statLoading:boolean,
/**Initiate the default Open Ticket stats. */
statInitiating:boolean,
/**Load the default Open Ticket code/functions. */
codeLoading:boolean,
/**Execute the default Open Ticket code/functions. */
codeExecution:boolean,
/**Load the default Open Ticket livestatus. */
liveStatusLoading:boolean,
/**Load the default Open Ticket startscreen. */
startScreenLoading:boolean,
/**Render the default Open Ticket startscreen. */
startScreenRendering:boolean,
/**Load the emoji style from the Open Ticket general config. */
emojiTitleStyleLoading:boolean,
/**The emoji style to use in embed & message titles using `utilities.emoijTitle()` */
emojiTitleStyle:"disabled"|"before"|"after"|"double",
/**The emoji divider to use in embed & message titles using `utilities.emoijTitle()` */
emojiTitleDivider:string
/**The interval in milliseconds that are between autoclose timeout checkers. */
autocloseCheckInterval:number
/**The interval in milliseconds that are between autodelete timeout checkers. */
autodeleteCheckInterval:number
}
/**## ODDefaultsBooleans `type`
* This type is a list of boolean defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsBooleans = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends boolean ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsStrings `type`
* This type is a list of string defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsStrings = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends string ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsNumbers `type`
* This type is a list of number defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsNumbers = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends number ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsStringArray `type`
* This type is a list of string[] defaults available in the `ODDefaultsManager` class.
* It's used to generate typescript declarations for this class.
*/
export type ODDefaultsStringArray = {
[Key in keyof ODDefaults]: ODDefaults[Key] extends string[] ? Key : never
}[keyof ODDefaults]
/**## ODDefaultsManager `class`
* This is an Open Ticket defaults manager.
*
* It manages all settings in Open Ticket that are not meant to be in the config.
* Here you can disable certain default features to replace them or to specifically enable them!
*
* You are unable to add your own defaults, you can only edit Open Ticket defaults!
*/
export class ODDefaultsManager {
/**A list of all the defaults */
#defaults: ODDefaults
constructor(){
this.#defaults = {
errorHandling:true,
crashOnError:false,
debugLoading:true,
silentLoading:true,
allowDumpCommand:true,
pluginLoading:true,
softPluginLoading:false,
pluginClassLoading:true,
flagLoading:true,
flagInitiating:true,
progressBarRendererLoading:true,
progressBarLoading:true,
configLoading:true,
configInitiating:true,
databaseLoading:true,
databaseInitiating:true,
sessionLoading:true,
languageLoading:true,
languageInitiating:true,
languageSelection:true,
backupLanguage:"opendiscord:english",
languageList:[],
checkerLoading:true,
checkerFunctionLoading:true,
checkerExecution:true,
checkerTranslationLoading:true,
checkerRendering:true,
checkerQuit:true,
checkerRenderEmpty:false,
clientLoading:true,
clientInitiating:true,
clientReady:true,
clientMultiGuildWarning:true,
clientActivityLoading:true,
clientActivityInitiating:true,
priorityLoading:true,
slashCommandLoading:true,
slashCommandRegistering:true,
forceSlashCommandRegistration:false,
allowSlashCommandRemoval:true,
contextMenuLoading:true,
contextMenuRegistering:true,
forceContextMenuRegistration:false,
allowContextMenuRemoval:true,
textCommandLoading:true,
questionLoading:true,
optionLoading:true,
panelLoading:true,
ticketLoading:true,
roleLoading:true,
blacklistLoading:true,
transcriptCompilerLoading:true,
transcriptHistoryLoading:true,
buttonBuildersLoading:true,
dropdownBuildersLoading:true,
fileBuildersLoading:true,
embedBuildersLoading:true,
messageBuildersLoading:true,
modalBuildersLoading:true,
commandRespondersLoading:true,
buttonRespondersLoading:true,
dropdownRespondersLoading:true,
modalRespondersLoading:true,
contextMenuRespondersLoading:true,
autocompleteRespondersLoading:true,
responderTimeoutMs:2500,
actionsLoading:true,
verifyBarsLoading:true,
permissionsLoading:true,
postsLoading:true,
postsInitiating:true,
cooldownsLoading:true,
cooldownsInitiating:true,
helpMenuCategoryLoading:true,
helpMenuComponentLoading:true,
statScopesLoading:true,
statLoading:true,
statInitiating:true,
codeLoading:true,
codeExecution:true,
liveStatusLoading:true,
startScreenLoading:true,
startScreenRendering:true,
emojiTitleStyleLoading:true,
emojiTitleStyle:"before",
emojiTitleDivider:" ",
autocloseCheckInterval:300000, //5 minutes
autodeleteCheckInterval:300000 //5 minutes
}
}
/**Set a default to a specific value. Remember! All plugins can edit these values, so your value could be overwritten! */
setDefault<DefaultName extends keyof ODDefaults>(key:DefaultName, value:ODDefaults[DefaultName]): void {
this.#defaults[key] = value
}
/**Get a default. Remember! All plugins can edit these values, so this value could be overwritten! */
getDefault<DefaultName extends keyof ODDefaults>(key:DefaultName): ODDefaults[DefaultName] {
return this.#defaults[key]
}
}
-99
View File
@@ -1,99 +0,0 @@
///////////////////////////////////////
//EVENT MODULE
///////////////////////////////////////
import { ODManagerData, ODManager, ODValidId } from "./base"
import { ODConsoleWarningMessage, ODDebugger } from "./console"
/**## ODEvent `class`
* This is an Open Ticket event.
*
* This class is made to work with the `ODEventManager` to handle events.
* The function of this specific class is to manage all listeners for a specifc event!
*/
export class ODEvent extends ODManagerData {
/**Alias to Open Ticket debugger. */
#debug?: ODDebugger
/**The list of permanent listeners. */
listeners: Function[] = []
/**The list of one-time listeners. List is cleared every time the event is emitted. */
oncelisteners: Function[] = []
/**The max listener limit before a possible memory leak will be announced */
listenerLimit: number = 25
/**Use the Open Ticket debugger in this manager for logs*/
useDebug(debug:ODDebugger|null){
this.#debug = debug ?? undefined
}
/**Get a collection of listeners combined from both types. Also clears the one-time listeners array! */
#getCurrentListeners(){
const final: Function[] = []
this.oncelisteners.forEach((l) => final.push(l))
this.listeners.forEach((l) => final.push(l))
this.oncelisteners = []
return final
}
/**Edit the listener limit */
setListenerLimit(limit:number){
this.listenerLimit = limit
}
/**Add a permanent callback to this event. This will stay as long as the bot is running! */
listen(callback:Function){
this.listeners.push(callback)
if (this.listeners.length > this.listenerLimit){
if (this.#debug) this.#debug.console.log(new ODConsoleWarningMessage("Possible event memory leak detected!",[
{key:"event",value:this.id.value},
{key:"listeners",value:this.listeners.length.toString()}
]))
}
}
/**Add a one-time-only callback to this event. This will only trigger the callback once! */
listenOnce(callback:Function){
this.oncelisteners.push(callback)
}
/**Wait until this event is fired! Be carefull with it, because it could block the entire bot when wrongly used! */
async wait(): Promise<any[]> {
return new Promise((resolve,reject) => {
this.oncelisteners.push((...args:any) => {resolve(args)})
})
}
/**Emit this event to all listeners. You are required to provide all parameters of the event! */
async emit(params:any[]): Promise<void> {
for (const listener of this.#getCurrentListeners()){
try{
await listener(...params)
}catch(err){
process.emit("uncaughtException",err)
}
}
}
}
/**## ODEventManager `class`
* This is an Open Ticket event manager.
*
* This class is made to manage all events in the bot. You can compare it with the built-in node.js `EventEmitter`
*
* It's not recommended to create this class yourself. Plugin events should be registered in their `plugin.json` file instead.
* All events are available in the `opendiscord.events` global!
*/
export class ODEventManager extends ODManager<ODEvent> {
/**Reference to the Open Ticket debugger */
#debug: ODDebugger
constructor(debug:ODDebugger){
super(debug,"event")
this.#debug = debug
}
add(data:ODEvent, overwrite?:boolean): boolean {
data.useDebug(this.#debug)
return super.add(data,overwrite)
}
remove(id:ODValidId): ODEvent|null {
const data = super.remove(id)
if (data) data.useDebug(null)
return data
}
}
-73
View File
@@ -1,73 +0,0 @@
///////////////////////////////////////
//FLAG MODULE
///////////////////////////////////////
import { ODId, ODValidId, ODManager, ODManagerData } from "./base"
import { ODDebugger } from "./console"
/**## ODFlag `class`
* This is an Open Ticket flag.
*
* A flag is a boolean that can be specified by a parameter in the console.
* It's useful for small settings that are only required once in a while.
*
* Flags can also be enabled manually by plugins!
*/
export class ODFlag extends ODManagerData {
/**The method that has been used to set the value of this flag. (`null` when not set) */
method: "param"|"manual"|null = null
/**The name of this flag. Visible to the user. */
name: string
/**The description of this flag. Visible to the user. */
description: string
/**The name of the parameter in the console. (e.g. `--test`) */
param: string
/**A list of aliases for the parameter in the console. */
aliases: string[]
/**The value of this flag. */
value: boolean = false
constructor(id:ODValidId, name:string, description:string, param:string, aliases?:string[], initialValue?:boolean){
super(id)
this.name = name
this.description = description
this.param = param
this.aliases = aliases ?? []
this.value = initialValue ?? false
}
/**Set the value of this flag. */
setValue(value:boolean,method?:"param"|"manual"){
this.value = value
this.method = method ?? "manual"
}
/**Detect if the process contains the param or aliases & set the value. Use `force` to overwrite a manually set value. */
detectProcessParams(force?:boolean){
if (force){
const params = [this.param,...this.aliases]
this.setValue(params.some((p) => process.argv.includes(p)),"param")
}else if (this.method != "manual"){
const params = [this.param,...this.aliases]
this.setValue(params.some((p) => process.argv.includes(p)),"param")
}
}
}
/**## ODFlagManager `class`
* This is an Open Ticket flag manager.
*
* This class is responsible for managing & initiating all flags of the bot.
* It also contains a shortcut for initiating all flags.
*/
export class ODFlagManager extends ODManager<ODFlag> {
constructor(debug:ODDebugger){
super(debug,"flag")
}
/**Set all flags to their `process.argv` value. */
async init(){
await this.loopAll((flag) => {
flag.detectProcessParams(false)
})
}
}
-216
View File
@@ -1,216 +0,0 @@
///////////////////////////////////////
//HELP MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODDebugger } from "./console"
/**## ODHelpMenuComponentRenderer `type`
* This is the callback of the help menu component renderer. It also contains information about how & where it is rendered.
*/
export type ODHelpMenuComponentRenderer = (page:number, category:number, location:number, mode:"slash"|"text") => string|Promise<string>
/**## ODHelpMenuComponent `class`
* This is an Open Ticket help menu component.
*
* It can render something on the Open Ticket help menu.
*/
export class ODHelpMenuComponent extends ODManagerData {
/**The priority of this component. The higher, the earlier it will appear in the help menu. */
priority: number
/**The render function for this component. */
render: ODHelpMenuComponentRenderer
constructor(id:ODValidId, priority:number, render:ODHelpMenuComponentRenderer){
super(id)
this.priority = priority
this.render = render
}
}
/**## ODHelpMenuTextComponent `class`
* This is an Open Ticket help menu text component.
*
* It can render a static piece of text on the Open Ticket help menu.
*/
export class ODHelpMenuTextComponent extends ODHelpMenuComponent {
constructor(id:ODValidId, priority:number, text:string){
super(id,priority,() => {
return text
})
}
}
/**## ODHelpMenuCommandComponentOption `interface`
* This interface contains a command option for the `ODHelpMenuCommandComponent`.
*/
export interface ODHelpMenuCommandComponentOption {
/**The name of this option. */
name:string,
/**Is this option optional? */
optional:boolean
}
/**## ODHelpMenuCommandComponentSettings `interface`
* This interface contains the settings for the `ODHelpMenuCommandComponent`.
*/
export interface ODHelpMenuCommandComponentSettings {
/**The name of this text command. */
textName?:string,
/**The name of this slash command. */
slashName?:string,
/**Options available in the text command. */
textOptions?:ODHelpMenuCommandComponentOption[],
/**Options available in the slash command. */
slashOptions?:ODHelpMenuCommandComponentOption[],
/**The description for the text command. */
textDescription?:string,
/**The description for the slash command. */
slashDescription?:string
}
/**## ODHelpMenuCommandComponent `class`
* This is an Open Ticket help menu command component.
*
* It contains a useful helper to render a command in the Open Ticket help menu.
*/
export class ODHelpMenuCommandComponent extends ODHelpMenuComponent {
constructor(id:ODValidId, priority:number, settings:ODHelpMenuCommandComponentSettings){
super(id,priority,(page,category,location,mode) => {
if (mode == "slash" && settings.slashName){
return `\`${settings.slashName}${(settings.slashOptions) ? this.#renderOptions(settings.slashOptions) : ""}\` ➜ ${settings.slashDescription ?? ""}`
}else if (mode == "text" && settings.textName){
return `\`${settings.textName}${(settings.textOptions) ? this.#renderOptions(settings.textOptions) : ""}\` ➜ ${settings.textDescription ?? ""}`
}else return ""
})
}
/**Utility function to render all command options. */
#renderOptions(options:ODHelpMenuCommandComponentOption[]){
return " "+options.map((opt) => (opt.optional) ? `[${opt.name}]` : `<${opt.name}>`).join(" ")
}
}
/**## ODHelpMenuCategory `class`
* This is an Open Ticket help menu category.
*
* Every category in the help menu is an embed field by default.
* Try to limit the amount of components per category.
*/
export class ODHelpMenuCategory extends ODManager<ODHelpMenuComponent> {
/**The id of this category. */
id: ODId
/**The priority of this category. The higher, the earlier it will appear in the menu. */
priority: number
/**The name of this category. (can include emoji's) */
name: string
/**When enabled, it automatically starts this category on a new page. */
newPage: boolean
constructor(id:ODValidId, priority:number, name:string, newPage?:boolean){
super()
this.id = new ODId(id)
this.priority = priority
this.name = name
this.newPage = newPage ?? false
}
/**Render this category and it's components. */
async render(page:number, category:number, mode:"slash"|"text"){
//sort from high priority to low
const derefArray = [...this.getAll()]
derefArray.sort((a,b) => {
return b.priority-a.priority
})
const result: string[] = []
let i = 0
for (const component of derefArray){
try {
result.push(await component.render(page,category,i,mode))
}catch(err){
process.emit("uncaughtException",err)
}
i++
}
//only return the non-empty components
return result.filter((component) => component !== "").join("\n\n")
}
}
/**## ODHelpMenuRenderResult `type`
* This is the array returned when the help menu has been rendered successfully.
*
* It contains a list of pages, which contain categories by name & value (content).
*/
export type ODHelpMenuRenderResult = {name:string, value:string}[][]
/**## ODHelpMenuManager `class`
* This is an Open Ticket help menu manager.
*
* It is responsible for rendering the entire help menu content.
* You are also able to configure the amount of categories per page here.
*
* Fewer Categories == More Clean Menu
*/
export class ODHelpMenuManager extends ODManager<ODHelpMenuCategory> {
/**Alias to Open Ticket debugger. */
#debug: ODDebugger
/**The amount of categories per-page. */
categoriesPerPage: number = 3
constructor(debug:ODDebugger){
super(debug,"help menu category")
this.#debug = debug
}
add(data:ODHelpMenuCategory, overwrite?:boolean): boolean {
data.useDebug(this.#debug,"help menu component")
return super.add(data,overwrite)
}
/**Render this entire help menu & return a `ODHelpMenuRenderResult`. */
async render(mode:"slash"|"text"): Promise<ODHelpMenuRenderResult> {
//sort from high priority to low
const derefArray = [...this.getAll()]
derefArray.sort((a,b) => {
return b.priority-a.priority
})
const result: {name:string, value:string}[][] = []
let currentPage: {name:string, value:string}[] = []
for (const category of derefArray){
try {
const renderedCategory = await category.render(result.length,currentPage.length,mode)
if (renderedCategory !== ""){
//create new page when category wants to
if (currentPage.length > 0 && category.newPage){
result.push(currentPage)
currentPage = []
}
currentPage.push({
name:category.name,
value:renderedCategory
})
//create new page when page is full
if (currentPage.length >= this.categoriesPerPage){
result.push(currentPage)
currentPage = []
}
}
}catch(err){
process.emit("uncaughtException",err)
}
}
//push current page when not-empty
if (currentPage.length > 0) result.push(currentPage)
return result
}
}
-201
View File
@@ -1,201 +0,0 @@
///////////////////////////////////////
//LANGUAGE MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODPromiseVoid, ODSystemError, ODValidId } from "./base"
import nodepath from "path"
import { ODDebugger } from "./console"
import fs from "fs"
/**## ODLanguageMetadata `interface`
* This interface contains all metadata available in the language files.
*/
export interface ODLanguageMetadata {
/**The version of Open Ticket this translation is made for. */
otversion:string,
/**The name of the language in english (with capital letter). */
language:string,
/**A list of translators (discord/github username) who've contributed to this language. */
translators:string[],
/**The last date that this translation has been modified (format: DD/MM/YYYY) */
lastedited:string,
/**When `true`, the translator made use of some sort of automation while creating the translation. (e.g. ChatGPT, Google Translate, DeepL, ...) */
automated:boolean
}
/**## ODLanguageManager `class`
* This is an Open Ticket language manager.
*
* It manages all languages in the bot and manages translation for you!
* Get a translation via the `getTranslation()` or `getTranslationWithParams()` methods.
*
* Add new languages using the `ODlanguage` class in your plugin!
*/
export class ODLanguageManager extends ODManager<ODLanguage> {
/**The currently selected language. */
current: ODLanguage|null = null
/**The currently selected backup language. (used when translation missing in current language) */
backup: ODLanguage|null = null
/**An alias to Open Ticket debugger. */
#debug: ODDebugger
constructor(debug:ODDebugger, presets:boolean){
super(debug,"language")
if (presets) this.add(new ODLanguage("english","english.json"))
this.current = presets ? new ODLanguage("english","english.json") : null
this.backup = presets ? new ODLanguage("english","english.json") : null
this.#debug = debug
}
/**Set the current language by providing the ID of a language which is registered in this manager. */
setCurrentLanguage(id:ODValidId){
this.current = this.get(id)
const languageId = this.current?.id.value ?? "<unknown-id>"
const languageAutomated = this.current?.metadata?.automated.toString() ?? "<unknown-metadata>"
this.#debug.debug("Selected current language",[
{key:"id",value:languageId},
{key:"automated",value:languageAutomated},
])
}
/**Get the current language (same as `this.current`) */
getCurrentLanguage(){
return (this.current) ? this.current : null
}
/**Set the backup language by providing the ID of a language which is registered in this manager. */
setBackupLanguage(id:ODValidId){
this.backup = this.get(id)
const languageId = this.backup?.id.value ?? "<unknown-id>"
const languageAutomated = this.backup?.metadata?.automated.toString() ?? "<unknown-metadata>"
this.#debug.debug("Selected backup language",[
{key:"id",value:languageId},
{key:"automated",value:languageAutomated},
])
}
/**Get the backup language (same as `this.backup`) */
getBackupLanguage(){
return (this.backup) ? this.backup : null
}
/**Get the metadata of the current/backup language. */
getLanguageMetadata(frombackup?:boolean): ODLanguageMetadata|null {
if (frombackup) return (this.backup) ? this.backup.metadata : null
return (this.current) ? this.current.metadata : null
}
/**Get the ID (string) of the current language. (Not backup language) */
getCurrentLanguageId(){
return (this.current) ? this.current.id.value : ""
}
/**Get a translation string by JSON location. (e.g. `"checker.system.typeError"`) */
getTranslation(id:string): string|null {
if (!this.current) return this.#getBackupTranslation(id)
const splitted = id.split(".")
let currentObject = this.current.data
let result: string|false = false
splitted.forEach((id) => {
if (typeof currentObject[id] == "object"){
currentObject = currentObject[id]
}else if (typeof currentObject[id] == "string"){
result = currentObject[id]
}
})
if (typeof result == "string") return result
else return this.#getBackupTranslation(id)
}
/**Get a backup translation string by JSON location. (system only) */
#getBackupTranslation(id:string): string|null {
if (!this.backup) return null
const splitted = id.split(".")
let currentObject = this.backup.data
let result: string|false = false
splitted.forEach((id) => {
if (typeof currentObject[id] == "object"){
currentObject = currentObject[id]
}else if (typeof currentObject[id] == "string"){
result = currentObject[id]
}
})
if (typeof result == "string") return result
else return null
}
/**Get a backup translation string by JSON location and replace `{0}`,`{1}`,`{2}`,... with the provided parameters. */
getTranslationWithParams(id:string, params:string[]): string|null {
let translation = this.getTranslation(id)
if (!translation) return translation
params.forEach((value,index) => {
if (!translation) return
translation = translation.replace(`{${index}}`,value)
})
return translation
}
/**Init all language files. */
async init(){
for (const language of this.getAll()){
try{
await language.init()
}catch(err){
process.emit("uncaughtException",new ODSystemError(err))
}
}
}
}
/**## ODLanguage `class`
* This is an Open Ticket language file.
*
* It contains metadata and all translation strings available in this language.
* Register this class to an `ODLanguageManager` to use it!
*
* JSON languages should be created using the `ODJsonLanguage` class instead!
*/
export class ODLanguage extends ODManagerData {
/**The name of the file with extension. */
file: string = ""
/**The path to the file relative to the main directory. */
path: string = ""
/**The raw object data of the translation. */
data: any
/**The metadata of the language if available. */
metadata: ODLanguageMetadata|null = null
constructor(id:ODValidId, data:any){
super(id)
this.data = data
}
/**Init the language. */
init(): ODPromiseVoid {
//nothing
}
}
/**## ODJsonLanguage `class`
* This is an Open Ticket JSON language file.
*
* It contains metadata and all translation strings from a certain JSON file (in `./languages/`).
* Register this class to an `ODLanguageManager` to use it!
*
* Use the `ODLanguage` class to use translations from non-JSON files!
*/
export class ODJsonLanguage extends ODLanguage {
constructor(id:ODValidId, file:string, customPath?:string){
super(id,{})
this.file = (file.endsWith(".json")) ? file : file+".json"
this.path = customPath ? nodepath.join("./",customPath,this.file) : nodepath.join("./languages/",this.file)
}
/**Init the langauge. */
init(): ODPromiseVoid {
if (!fs.existsSync(this.path)) throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\", the file doesn't exist!")
try{
this.data = JSON.parse(fs.readFileSync(this.path).toString())
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("Unable to parse language \""+nodepath.join("./",this.path)+"\"!")
}
if (this.data["_TRANSLATION"]) this.metadata = this.data["_TRANSLATION"]
}
}
-340
View File
@@ -1,340 +0,0 @@
///////////////////////////////////////
//PERMISSION MODULE
///////////////////////////////////////
import { ODId, ODValidId, ODManager, ODSystemError, ODManagerData } from "./base"
import * as discord from "discord.js"
import { ODDebugger } from "./console"
import { ODClientManager } from "./client"
/**## ODPermissionType `type`
* All available permission types/levels. Can be used in the `ODPermission` class.
*/
export type ODPermissionType = "member"|"support"|"moderator"|"admin"|"owner"|"developer"
/**## ODPermissionScope `type`
* The scope in which a certain permission is active.
*/
export type ODPermissionScope = "global-user"|"channel-user"|"global-role"|"channel-role"
/**## ODPermissionResult `interface`
* The result returned by `ODPermissionManager.getPermissions()`.
*/
export interface ODPermissionResult {
/**The permission type. */
type:ODPermissionType
/**The permission scope. */
scope:ODPermissionScope|"default"
/**The highest level available for this scope. */
level:ODPermissionLevel,
/**The permission which returned this level. */
source:ODPermission|null
}
/**## ODPermissionLevel `enum`
* All available permission types/levels. But as `enum` instead of `type`. Used to calculate the level.
*/
export enum ODPermissionLevel {
/**A normal member. (Default for everyone) */
member,
/**Support team. Higher than a normal member. (Used for ticket-admins) */
support,
/**Moderator. Higher than the support team. (Unused) */
moderator,
/**Admin. Higher than a moderator. (Used for global-admins) */
admin,
/**Server owner. (Able to use all commands including `/stats reset`) */
owner,
/**Bot owner or all users from dev team. (Able to use all commands including `/stats reset`) */
developer
}
/**## ODPermission `class`
* This is an Open Ticket permission.
*
* It defines a single permission level for a specific scope (global/channel & user/role)
* These permissions only apply to commands & interactions.
* They are not related to channel permissions in the ticket system.
*
* Register this class to an `ODPermissionManager` to use it!
*/
export class ODPermission extends ODManagerData {
/**The scope of this permission. */
readonly scope: ODPermissionScope
/**The type/level of this permission. */
readonly permission: ODPermissionType
/**The user/role of this permission. */
readonly value: discord.Role|discord.User
/**The channel that this permission applies to. (`null` when global) */
readonly channel: discord.Channel|null
constructor(id:ODValidId, scope:"global-user", permission:ODPermissionType, value:discord.User)
constructor(id:ODValidId, scope:"global-role", permission:ODPermissionType, value:discord.Role)
constructor(id:ODValidId, scope:"channel-user", permission:ODPermissionType, value:discord.User, channel:discord.Channel)
constructor(id:ODValidId, scope:"channel-role", permission:ODPermissionType, value:discord.Role, channel:discord.Channel)
constructor(id:ODValidId, scope:ODPermissionScope, permission:ODPermissionType, value:discord.Role|discord.User, channel?:discord.Channel){
super(id)
this.scope = scope
this.permission = permission
this.value = value
this.channel = channel ?? null
}
}
/**## ODPermissionSettings `interface`
* Optional settings for the `getPermissions()` method in the `ODPermissionManager`.
*/
export interface ODPermissionSettings {
/**Include permissions from the global user scope. */
allowGlobalUserScope?:boolean,
/**Include permissions from the global role scope. */
allowGlobalRoleScope?:boolean,
/**Include permissions from the channel user scope. */
allowChannelUserScope?:boolean,
/**Include permissions from the channel role scope. */
allowChannelRoleScope?:boolean,
/**Only include permissions of which the id matches this regex. */
idRegex?:RegExp
}
/**## ODPermissionCalculationCallback `type`
* The callback of the permission calculation. (Used in `ODPermissionManager`)
*/
export type ODPermissionCalculationCallback = (user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null) => Promise<ODPermissionResult>
/**## ODPermissionCommandResult `type`
* The result of calculating permissions for a command.
*/
export type ODPermissionCommandResult = {
/**Returns `true` when the user has valid permissions. */
hasPerms:false,
reason:"no-perms"|"disabled"|"not-in-server"
}|{
/**Returns `true` when the user has valid permissions. */
hasPerms:true,
/**Is the user a server admin or a normal member? This does not decide if the user has permissions or not. */
isAdmin:boolean
}
/**## ODPermissionManager `class`
* This is an Open Ticket permission manager.
*
* It manages all permissions in the bot!
* Use the `getPermissions()` and `hasPermissions()` methods to get user perms.
*
* Add new permissions using the `ODPermission` class in your plugin!
*/
export class ODPermissionManager extends ODManager<ODPermission> {
/**Alias for Open Ticket debugger. */
#debug: ODDebugger
/**The function for calculating permissions in this manager. */
#calculation: ODPermissionCalculationCallback|null
/**An alias to the Open Discord client manager. */
#client: ODClientManager
/**The result which is returned when no other permissions match. (`member` by default) */
defaultResult: ODPermissionResult = {
level:ODPermissionLevel["member"],
scope:"default",
type:"member",
source:null
}
constructor(debug:ODDebugger, client:ODClientManager, useDefaultCalculation?:boolean){
super(debug,"permission")
this.#debug = debug
this.#calculation = useDefaultCalculation ? this.#defaultCalculation : null
this.#client = client
}
/**Edit the permission calculation function in this manager. */
setCalculation(calculation:ODPermissionCalculationCallback){
this.#calculation = calculation
}
/**Edit the result which is returned when no other permissions match. (`member` by default) */
setDefaultResult(result:ODPermissionResult){
this.defaultResult = result
}
/**Get an `ODPermissionResult` based on a few context factors. Use `hasPermissions()` to simplify the result. */
getPermissions(user:discord.User, channel?:discord.Channel|null, guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise<ODPermissionResult> {
try{
if (!this.#calculation) throw new ODSystemError("ODPermissionManager:getPermissions() => missing perms calculation")
return this.#calculation(user,channel,guild,settings)
}catch(err){
process.emit("uncaughtException",err)
throw new ODSystemError("ODPermissionManager:getPermissions() => failed perms calculation")
}
}
/**Simplifies the `ODPermissionResult` returned from `getPermissions()` and returns a boolean to check if the user matches the required permissions. */
hasPermissions(minimum:ODPermissionType, data:ODPermissionResult){
if (minimum == "member") return true
else if (minimum == "support") return (data.level >= ODPermissionLevel["support"])
else if (minimum == "moderator") return (data.level >= ODPermissionLevel["moderator"])
else if (minimum == "admin") return (data.level >= ODPermissionLevel["admin"])
else if (minimum == "owner") return (data.level >= ODPermissionLevel["owner"])
else if (minimum == "developer") return (data.level >= ODPermissionLevel["developer"])
else throw new ODSystemError("Invalid minimum permission type at ODPermissionManager.hasPermissions()")
}
/**Check for permissions. (default calculation) */
async #defaultCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise<ODPermissionResult> {
const globalCalc = await this.#defaultGlobalCalculation(user,channel,guild,settings)
const channelCalc = await this.#defaultChannelCalculation(user,channel,guild,settings)
if (globalCalc.level > channelCalc.level) return globalCalc
else return channelCalc
}
/**Check for global permissions. Result will be compared with the channel perms in `#defaultCalculation()`. */
async #defaultGlobalCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise<ODPermissionResult> {
const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null
const allowGlobalUserScope = (settings && typeof settings.allowGlobalUserScope != "undefined") ? settings.allowGlobalUserScope : true
const allowGlobalRoleScope = (settings && typeof settings.allowGlobalRoleScope != "undefined") ? settings.allowGlobalRoleScope : true
//check for global user permissions
if (allowGlobalUserScope){
const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "global-user" && (permission.value instanceof discord.User) && permission.value.id == user.id)
if (users.length > 0){
//sort all permisions from highest to lowest
users.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:users[0].permission,
scope:"global-user",
level:ODPermissionLevel[users[0].permission],
source:users[0] ?? null
}
}
}
//check for global role permissions
if (allowGlobalRoleScope){
if (guild){
const member = await this.#client.fetchGuildMember(guild,user.id)
if (member){
const memberRoles = member.roles.cache.map((role) => role.id)
const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "global-role" && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id)
if (roles.length > 0){
//sort all permisions from highest to lowest
roles.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:roles[0].permission,
scope:"global-role",
level:ODPermissionLevel[roles[0].permission],
source:roles[0] ?? null
}
}
}
}
}
//spread result to prevent accidental referencing
return {...this.defaultResult}
}
/**Check for channel permissions. Result will be compared with the global perms in `#defaultCalculation()`. */
async #defaultChannelCalculation(user:discord.User,channel?:discord.Channel|null,guild?:discord.Guild|null, settings?:ODPermissionSettings|null): Promise<ODPermissionResult> {
const idRegex = (settings && typeof settings.idRegex != "undefined") ? settings.idRegex : null
const allowChannelUserScope = (settings && typeof settings.allowChannelUserScope != "undefined") ? settings.allowChannelUserScope : true
const allowChannelRoleScope = (settings && typeof settings.allowChannelRoleScope != "undefined") ? settings.allowChannelRoleScope : true
if (guild && channel && !channel.isDMBased()){
//check for channel user permissions
if (allowChannelUserScope){
const users = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-user" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.User) && permission.value.id == user.id)
if (users.length > 0){
//sort all permisions from highest to lowest
users.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:users[0].permission,
scope:"channel-user",
level:ODPermissionLevel[users[0].permission],
source:users[0] ?? null
}
}
}
//check for channel role permissions
if (allowChannelRoleScope){
const member = await this.#client.fetchGuildMember(guild,user.id)
if (member){
const memberRoles = member.roles.cache.map((role) => role.id)
const roles = this.getFiltered((permission) => (!idRegex || (idRegex && idRegex.test(permission.id.value))) && permission.scope == "channel-role" && permission.channel && (permission.channel.id == channel.id) && (permission.value instanceof discord.Role) && memberRoles.includes(permission.value.id) && permission.value.guild.id == guild.id)
if (roles.length > 0){
//sort all permisions from highest to lowest
roles.sort((a,b) => {
const levelA = ODPermissionLevel[a.permission]
const levelB = ODPermissionLevel[b.permission]
if (levelB > levelA) return 1
else if (levelA > levelB) return -1
else return 0
})
return {
type:roles[0].permission,
scope:"channel-role",
level:ODPermissionLevel[roles[0].permission],
source:roles[0] ?? null
}
}
}
}
}
//spread result to prevent accidental modification because of referencing
return {...this.defaultResult}
}
/**Check the permissions for a certain command of the bot. */
async checkCommandPerms(permissionMode:string,requiredLevel:ODPermissionType,user:discord.User,member?:discord.GuildMember|null,channel?:discord.Channel|null,guild?:discord.Guild|null,settings?:ODPermissionSettings): Promise<ODPermissionCommandResult> {
if (permissionMode === "none"){
return {hasPerms:false,reason:"disabled"}
}else if (permissionMode === "everyone"){
const isAdmin = this.hasPermissions(requiredLevel,await this.getPermissions(user,channel,guild,settings))
return {hasPerms:true,isAdmin}
}else if (permissionMode === "admin"){
const isAdmin = this.hasPermissions(requiredLevel,await this.getPermissions(user,channel,guild,settings))
if (!isAdmin) return {hasPerms:false,reason:"no-perms"}
else return {hasPerms:true,isAdmin}
}else{
if (!guild || !member){
this.#debug.debug("ODPermissionManager.checkCommandPerms(): Permission Error, Not in server! (#1)")
return {hasPerms:false,reason:"not-in-server"}
}
const role = await this.#client.fetchGuildRole(guild,permissionMode)
if (!role){
this.#debug.debug("ODPermissionManager.checkCommandPerms(): Permission Error, Not in server! (#2)")
return {hasPerms:false,reason:"not-in-server"}
}
if (!role.members.has(member.id)) return {hasPerms:false,reason:"no-perms"}
const isAdmin = this.hasPermissions(requiredLevel,await this.getPermissions(user,channel,guild,settings))
return {hasPerms:true,isAdmin}
}
}
}
-242
View File
@@ -1,242 +0,0 @@
///////////////////////////////////////
//PLUGIN MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODSystemError, ODValidId, ODVersion } from "./base"
import nodepath from "path"
import { ODConsolePluginMessage, ODConsoleWarningMessage, ODDebugger } from "./console"
/**## ODUnknownCrashedPlugin `interface`
* Basic details for a plugin that crashed while loading the `plugin.json` file.
*/
export interface ODUnknownCrashedPlugin {
/**The name of the plugin. (path when plugin crashed before `name` was loaded) */
name:string,
/**The description of the plugin. (when found before crashing) */
description:string
}
/**## ODPluginManager `class`
* This is an Open Ticket plugin manager.
*
* It manages all active plugins in the bot!
* It also contains all "plugin classes" which are managers registered by plugins.
* These are accessible via the `opendiscord.plugins.classes` global.
*
* Use `isPluginLoaded()` to check if a plugin has been loaded.
*/
export class ODPluginManager extends ODManager<ODPlugin> {
/**A manager for all custom managers registered by plugins. */
classes: ODPluginClassManager
/**A list of basic details from all plugins that crashed while loading the `plugin.json` file. */
unknownCrashedPlugins: ODUnknownCrashedPlugin[] = []
constructor(debug:ODDebugger){
super(debug,"plugin")
this.classes = new ODPluginClassManager(debug)
}
/**Check if a plugin has been loaded successfully and is available for usage.*/
isPluginLoaded(id:ODValidId): boolean {
const newId = new ODId(id)
const plugin = this.get(newId)
return (plugin !== null && plugin.executed)
}
}
/**## ODPluginData `interface`
* Parsed data from the `plugin.json` file in a plugin.
*/
export interface ODPluginData {
/**The name of this plugin (shown on startup) */
name:string,
/**The id of this plugin. (Must be identical to directory name) */
id:string,
/**The version of this plugin. */
version:string,
/**The location of the start file of the plugin relative to the rootDir of the plugin */
startFile:string,
/**A list of compatible versions. (e.g. `["OTv4.0.x", "OMv1.x.x"]`) (optional, will be required in future version)
* - `OT` --> Open Ticket support
* - `OM` --> Open Moderation support
*/
supportedVersions?:string[],
/**Is this plugin enabled? */
enabled:boolean,
/**The priority of this plugin. Higher priority will load before lower priority. */
priority:number,
/**A list of events to register to the `opendiscord.events` global before loading any plugins. This way, plugins with a higher priority are able to use events from this plugin as well! */
events:string[]
/**Npm dependencies which are required for this plugin to work. */
npmDependencies:string[],
/**Plugins which are required for this plugin to work. */
requiredPlugins:string[],
/**Plugins which are incompatible with this plugin. */
incompatiblePlugins:string[],
/**Additional details about this plugin. */
details:ODPluginDetails
}
/**## ODPluginDetails `interface`
* Additional details in the `plugin.json` file from a plugin.
*/
export interface ODPluginDetails {
/**The main author of the plugin. Additional contributors can be specified in `contributors`. */
author:string,
/**A list of plugin contributors. (optional, will be required in future version) */
contributors?:string[],
/**A short description of this plugin. */
shortDescription:string,
/**A large description of this plugin. */
longDescription:string,
/**A URL to a cover image of this plugin. (currently unused) */
imageUrl:string,
/**A URL to the website/project page of this plugin. (currently unused) */
projectUrl:string,
/**A list of tags/categories that this plugin affects. */
tags:string[]
}
/**## ODPlugin `class`
* This is an Open Ticket plugin.
*
* It represents a single plugin in the `./plugins/` directory.
* All plugins are accessible via the `opendiscord.plugins` global.
*
* Don't re-execute plugins which are already enabled! It might break the bot or plugin.
*/
export class ODPlugin extends ODManagerData {
/**The name of the directory of this plugin. (same as id) */
dir: string
/**All plugin data found in the `plugin.json` file. */
data: ODPluginData
/**The name of this plugin. */
name: string
/**The priority of this plugin. */
priority: number
/**The version of this plugin. */
version: ODVersion
/**The additional details of this plugin. */
details: ODPluginDetails
/**Is this plugin enabled? */
enabled: boolean
/**Did this plugin execute successfully?. */
executed: boolean
/**Did this plugin crash? (A reason is available in the `crashReason`) */
crashed: boolean
/**The reason which caused this plugin to crash. */
crashReason: null|"incompatible.plugin"|"missing.plugin"|"missing.dependency"|"incompatible.version"|"executed" = null
constructor(dir:string, jsondata:ODPluginData){
super(jsondata.id)
this.dir = dir
this.data = jsondata
this.name = jsondata.name
this.priority = jsondata.priority
this.version = ODVersion.fromString("plugin",jsondata.version)
this.details = jsondata.details
this.enabled = jsondata.enabled
this.executed = false
this.crashed = false
}
/**Get the startfile location relative to the `./plugins/` directory. (`./dist/plugins/`) when compiled) */
getStartFile(){
const newFile = this.data.startFile.replace(/\.ts$/,".js")
return nodepath.join(this.dir,newFile)
}
/**Execute this plugin. Returns `false` on crash. */
async execute(debug:ODDebugger,force?:boolean): Promise<boolean> {
if ((this.enabled && !this.crashed) || force){
try{
//import relative plugin directory path (works on windows & unix based systems)
const pluginPath = nodepath.join("../../../../plugins/",this.getStartFile()).replaceAll("\\","/")
await import(pluginPath)
debug.console.log("Plugin \""+this.id.value+"\" loaded successfully!","plugin")
this.executed = true
return true
}catch(error){
this.crashed = true
this.crashReason = "executed"
debug.console.log(error.message+", canceling plugin execution...","plugin",[
{key:"path",value:"./plugins/"+this.dir}
])
debug.console.log("You can see more about this error in the ./otdebug.txt file!","info")
debug.console.debugfile.writeText(error.stack)
return false
}
}else return true
}
/**Check if a npm dependency exists. */
#checkDependency(id:string){
try{
require.resolve(id)
return true
}catch{
return false
}
}
/**Get a list of all missing npm dependencies that are required for this plugin. */
dependenciesInstalled(){
const missing: string[] = []
this.data.npmDependencies.forEach((d) => {
if (!this.#checkDependency(d)){
missing.push(d)
}
})
return missing
}
/**Get a list of all missing plugins that are required for this plugin. */
pluginsInstalled(manager:ODPluginManager){
const missing: string[] = []
this.data.requiredPlugins.forEach((p) => {
const plugin = manager.get(p)
if (!plugin || !plugin.enabled){
missing.push(p)
}
})
return missing
}
/**Get a list of all enabled incompatible plugins that interfere with this plugin. */
pluginsIncompatible(manager:ODPluginManager){
const incompatible: string[] = []
this.data.incompatiblePlugins.forEach((p) => {
const plugin = manager.get(p)
if (plugin && plugin.enabled){
incompatible.push(p)
}
})
return incompatible
}
/**Get a list of all authors & contributors of this plugin. */
getAuthors(): string[] {
return [this.details.author,...(this.details.contributors ?? [])]
}
}
/**## ODPluginClassManager `class`
* This is an Open Ticket plugin class manager.
*
* It manages all managers registered by plugins!
* Plugins are able to register their own managers, handlers, functions, classes, ... here.
* By doing this, other plugins are also able to make use of it.
* This can be useful for plugins that want to extend other plugins.
*
* Use `isPluginLoaded()` to check if a plugin has been loaded before trying to access the manager.
*/
export class ODPluginClassManager extends ODManager<ODManagerData> {
constructor(debug:ODDebugger){
super(debug,"plugin class")
}
}
-90
View File
@@ -1,90 +0,0 @@
///////////////////////////////////////
//POST MODULE
///////////////////////////////////////
import { ODId, ODManager, ODManagerData, ODValidId } from "./base"
import { ODMessageBuildResult, ODMessageBuildSentResult } from "./builder"
import { ODDebugger } from "./console"
import * as discord from "discord.js"
/**## ODPostManager `class`
* This is an Open Ticket post manager.
*
* It manages `ODPosts`'s for you.
*
* You can use this to get the logs channel of the bot (or some other static channel/category).
*/
export class ODPostManager extends ODManager<ODPost<discord.GuildBasedChannel>> {
/**A reference to the main server of the bot */
#guild: discord.Guild|null = null
constructor(debug:ODDebugger){
super(debug,"post")
}
add(data:ODPost<discord.GuildBasedChannel>, overwrite?:boolean): boolean {
if (this.#guild) data.useGuild(this.#guild)
return super.add(data,overwrite)
}
/**Initialize the post manager & all posts. */
async init(guild:discord.Guild){
this.#guild = guild
for (const post of this.getAll()){
post.useGuild(guild)
await post.init()
}
}
}
/**## ODPost `class`
* This is an Open Ticket post class.
*
* A post is just a shortcut to a static discord channel or category.
* This can be used to get a specific channel over and over again!
*
* This class also contains utilities for sending messages via the Open Ticket builders.
*/
export class ODPost<ChannelType extends discord.GuildBasedChannel> extends ODManagerData {
/**A reference to the main server of the bot */
#guild: discord.Guild|null = null
/**Is this post already initialized? */
ready: boolean = false
/**The discord.js channel */
channel: ChannelType|null = null
/**The discord channel id */
channelId: string
constructor(id:ODValidId, channelId:string){
super(id)
this.channelId = channelId
}
/**Use a specific guild in this class for fetching the channel*/
useGuild(guild:discord.Guild|null){
this.#guild = guild
}
/**Change the channel id to another channel! */
setChannelId(id:string){
this.channelId = id
}
/**Initialize the discord.js channel of this post. */
async init(){
if (this.ready) return
if (!this.#guild) return this.channel = null
try{
this.channel = await this.#guild.channels.fetch(this.channelId) as ChannelType
}catch{
this.channel = null
}
this.ready = true
}
/**Send a message to this channel using the Open Ticket builder system */
async send(msg:ODMessageBuildResult): Promise<ODMessageBuildSentResult<true>> {
if (!this.channel || !this.channel.isTextBased()) return {success:false,message:null}
try{
const sent = await this.channel.send(msg.message)
return {success:true,message:sent}
}catch{
return {success:false,message:null}
}
}
}
-232
View File
@@ -1,232 +0,0 @@
///////////////////////////////////////
//PROGRESS BAR MODULE
///////////////////////////////////////
import { ODSystemError, ODManager, ODManagerData, ODValidId } from "./base"
import { ODDebugger } from "./console"
import readline from "readline"
/**## ODProgressBarRendererManager `class`
* This is an Open Ticket progress bar renderer manager.
*
* It is responsible for managing all console progress bar renderers in Open Ticket.
*
* A renderer is a function which will try to visualize the progress bar in the console.
*/
export class ODProgressBarRendererManager extends ODManager<ODProgressBarRenderer<{}>> {
constructor(debug:ODDebugger){
super(debug,"progress bar renderer")
}
}
/**## ODProgressBarManager `class`
* This is an Open Ticket progress bar manager.
*
* It is responsible for managing all console progress bars in Open Ticket. An example of this is the slash command registration progress bar.
*
* There are many types of progress bars available, but you can also create your own!
*/
export class ODProgressBarManager extends ODManager<ODProgressBar> {
renderers: ODProgressBarRendererManager
constructor(debug:ODDebugger){
super(debug,"progress bar")
this.renderers = new ODProgressBarRendererManager(debug)
}
}
/**## ODProgressBarRenderFunc `type`
* This is the render function for an Open Ticket console progress bar.
*/
export type ODProgressBarRenderFunc<Settings extends {}> = (settings:Settings,min:number,max:number,value:number,prefix:string|null,suffix:string|null) => string
/**## ODProgressBarRenderer `class`
* This is an Open Ticket console progress bar renderer.
*
* It is used to render a progress bar in the console of the bot.
*
* There are already a lot of default options available if you just want an easy progress bar!
*/
export class ODProgressBarRenderer<Settings extends {}> extends ODManagerData {
settings: Settings
#render: ODProgressBarRenderFunc<Settings>
constructor(id:ODValidId,render:ODProgressBarRenderFunc<Settings>,settings:Settings){
super(id)
this.#render = render
this.settings = settings
}
/**Render a progress bar using this renderer. */
render(min:number,max:number,value:number,prefix:string|null,suffix:string|null){
try {
return this.#render(this.settings,min,max,value,prefix,suffix)
}catch(err){
process.emit("uncaughtException",err)
return "<PROGRESS-BAR-ERROR>"
}
}
withAdditionalSettings(settings:Partial<Settings>): ODProgressBarRenderer<Settings> {
const newSettings: Settings = {...this.settings}
for (const key of Object.keys(settings)){
if (typeof settings[key] != "undefined") newSettings[key] = settings[key]
}
return new ODProgressBarRenderer(this.id,this.#render,newSettings)
}
}
/**## ODProgressBar `class`
* This is an Open Ticket console progress bar.
*
* It is used to create a simple or advanced progress bar in the console of the bot.
* These progress bars are not visible in the `otdebug.txt` file and should only be used as extra visuals.
*
* Use other classes as existing templates or create your own progress bar from scratch using this class.
*/
export class ODProgressBar extends ODManagerData {
/**The renderer of this progress bar. */
renderer: ODProgressBarRenderer<{}>
/**Is this progress bar currently active? */
#active: boolean = false
/**A list of listeners when the progress bar stops. */
#stopListeners: Function[] = []
/**The current value of the progress bar. */
protected value: number
/**The minimum value of the progress bar. */
min: number
/**The maximum value of the progress bar. */
max: number
/**The initial value of the progress bar. */
initialValue: number
/**The prefix displayed in the progress bar. */
prefix:string|null
/**The prefix displayed in the progress bar. */
suffix:string|null
/**Enable automatic stopping when reaching `min` or `max`. */
autoStop: null|"min"|"max"
constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,min:number,max:number,value:number,autoStop:null|"min"|"max",prefix:string|null,suffix:string|null){
super(id)
this.renderer = renderer
this.min = min
this.max = max
this.initialValue = this.#parseValue(value)
this.value = this.#parseValue(value)
this.autoStop = autoStop
this.prefix = prefix
this.suffix = suffix
}
/**Parse a value in such a way that it doesn't go below/above the min/max limits. */
#parseValue(value:number){
if (value > this.max) return this.max
else if (value < this.min) return this.min
else return value
}
/**Render progress bar to the console. */
#renderStdout(){
if (!this.#active) return
readline.clearLine(process.stdout,0)
readline.cursorTo(process.stdout,0)
process.stdout.write(this.renderer.render(this.min,this.max,this.value,this.prefix,this.suffix))
}
/**Start showing this progress bar in the console. */
start(): boolean {
if (this.#active) return false
this.value = this.#parseValue(this.initialValue)
this.#active = true
this.#renderStdout()
return true
}
/**Update this progress bar while active. (will automatically update the progress bar in the console) */
protected update(value:number,stop?:boolean): boolean {
if (!this.#active) return false
this.value = this.#parseValue(value)
this.#renderStdout()
if (stop || (this.autoStop == "max" && this.value == this.max) || (this.autoStop == "min" && this.value == this.min)){
process.stdout.write("\n")
this.#active = false
this.#stopListeners.forEach((cb) => cb())
this.#stopListeners = []
}
return true
}
/**Wait for the progress bar to finish. */
finished(): Promise<void> {
return new Promise((resolve) => {
this.#stopListeners.push(resolve)
})
}
}
/**## ODTimedProgressBar `class`
* This is an Open Ticket timed console progress bar.
*
* It is used to create a simple timed progress bar in the console.
* You can set a fixed duration (milliseconds) in the constructor.
*/
export class ODTimedProgressBar extends ODProgressBar {
/**The time in milliseconds. */
time: number
/**The mode of the timer. */
mode: "increasing"|"decreasing"
constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,time:number,mode:"increasing"|"decreasing",prefix:string|null,suffix:string|null){
super(id,renderer,0,time,0,(mode == "increasing") ? "max" : "min",prefix,suffix)
this.time = time
this.mode = mode
}
/**The timer which is used. */
async #timer(ms:number): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
resolve()
},ms)
})
}
/**Run the timed progress bar. */
async #execute(){
let i = 0
const fragment = this.time/100
while (i < 100){
await this.#timer(fragment)
i++
super.update((this.mode == "increasing") ? (i*fragment) : this.time-(i*fragment))
}
}
start(){
const res = super.start()
if (!res) return false
this.#execute()
return true
}
}
/**## ODManualProgressBar `class`
* This is an Open Ticket manual console progress bar.
*
* It is used to create a simple manual progress bar in the console.
* You can update the progress manually using `update()`.
*/
export class ODManualProgressBar extends ODProgressBar {
constructor(id:ODValidId,renderer:ODProgressBarRenderer<{}>,amount:number,autoStop:null|"min"|"max",prefix:string|null,suffix:string|null){
super(id,renderer,0,amount,0,autoStop,prefix,suffix)
}
/**Set the value of the progress bar. */
set(value:number,stop?:boolean){
super.update(value,stop)
}
/**Get the current value of the progress bar. */
get(){
return this.value
}
/**Increase the value of the progress bar. */
increase(amount:number,stop?:boolean){
super.update(this.value+amount,stop)
}
/**Decrease the value of the progress bar. */
decrease(amount:number,stop?:boolean){
super.update(this.value-amount,stop)
}
}

Some files were not shown because too many files have changed in this diff Show More