diff --git a/package.json b/package.json index 759cc3a..0b18f84 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "license": "GPL-3.0-only", "dependencies": { "@discordjs/rest": "^2.6.1", - "@open-discord-bots/framework": "^0.2.8", + "@open-discord-bots/framework": "^0.2.11", "@types/node": "^22.5.0", "@types/terminal-kit": "^2.5.7", "ansis": "^4.2.0", @@ -46,7 +46,7 @@ "homepage": "https://openticket.dj-dj.be", "imports": { "#opendiscord": "./dist/src/index.js", - "#opendiscord-types": "./dist/src/core/api/api.js" + "#opendiscord-types": "./dist/src/core/api.js" }, "funding": { "type": "individual", diff --git a/plugins/example-plugin/index.ts b/plugins/example-plugin/index.ts index 97b70ba..68b5b6a 100644 --- a/plugins/example-plugin/index.ts +++ b/plugins/example-plugin/index.ts @@ -10,11 +10,11 @@ if (opendiscord.project != "openticket") throw new api.ODPluginError("This plugi //Add Typescript autocomplete support for plugin data. (!!!OPTIONAL!!!) declare module "#opendiscord-types" { - export interface ODPluginManagerIds_Default { + export interface ODPluginManagerIdMappings { "example-plugin":api.ODPlugin } - export interface ODConfigManagerIds_Default { - "example-plugin:config":api.ODJsonConfig + export interface ODConfigManagerIdMappings { + "example-plugin:config":api.ODJsonConfig<{testVariable1:boolean,testVariable2:number,testVariable3:string}> } } @@ -30,7 +30,7 @@ opendiscord.events.get("onConfigLoad").listen((configManager) => { //Let's also log it to the console to let us know it worked! const ourConfig = configManager.get("example-plugin:config") opendiscord.log("The example config loaded successfully!","plugin",[ - {key:"var-1",value:ourConfig.data.testVariable1}, + {key:"var-1",value:ourConfig.data.testVariable1.toString()}, {key:"var-2",value:ourConfig.data.testVariable2.toString()}, {key:"var-3",value:ourConfig.data.testVariable3.toString()} ]) diff --git a/src/actions/createTicket.ts b/src/actions/createTicket.ts index 8760aa2..a097aba 100644 --- a/src/actions/createTicket.ts +++ b/src/actions/createTicket.ts @@ -229,6 +229,8 @@ export const registerActions = async () => { 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){ const logChannel = opendiscord.posts.get("opendiscord:logs") diff --git a/src/actions/createTranscript.ts b/src/actions/createTranscript.ts index 546c391..9eb1c4c 100644 --- a/src/actions/createTranscript.ts +++ b/src/actions/createTranscript.ts @@ -33,6 +33,11 @@ export const registerActions = async () => { 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]) @@ -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]) @@ -94,14 +104,30 @@ 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) => { + 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{ @@ -162,7 +188,7 @@ export const registerActions = async () => { {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:"compiler",value:instance.compiler?.id.value ?? ""}, ]) }) ]) diff --git a/src/actions/handleTranscriptErrors.ts b/src/actions/handleTranscriptErrors.ts index bc0cf9a..790525d 100644 --- a/src/actions/handleTranscriptErrors.ts +++ b/src/actions/handleTranscriptErrors.ts @@ -9,47 +9,25 @@ export const registerButtonResponders = async () => { //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"] + const {guild,channel,user,member} = instance + const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIdMappings["opendiscord:delete-ticket"]["source"] + //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})) @@ -121,7 +99,7 @@ export const registerButtonResponders = async () => { }), 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"] + const originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIdMappings["opendiscord:delete-ticket"]["source"] if (!guild){ instance.reply(await opendiscord.builders.messages.getSafe("opendiscord:error-not-in-guild").build("button",{channel,user})) diff --git a/src/commands/claim.ts b/src/commands/claim.ts index 72c2b6c..123533e 100644 --- a/src/commands/claim.ts +++ b/src/commands/claim.ts @@ -70,7 +70,7 @@ export const registerButtonResponders = async () => { 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 + const originalSource = instance.interaction.customId.split("_")[1] as Exclude 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) @@ -97,7 +97,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as Exclude + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //claim with reason diff --git a/src/commands/clear.ts b/src/commands/clear.ts index 1de6e25..0ef581b 100644 --- a/src/commands/clear.ts +++ b/src/commands/clear.ts @@ -68,7 +68,7 @@ export const registerButtonResponders = async () => { 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 originalSource = instance.interaction.customId.split("_")[1] as api.ODActionManagerIdMappings["opendiscord:clear-tickets"]["source"] const filter = instance.interaction.customId.split("_")[2] as api.ODTicketClearFilter //start ticket clear diff --git a/src/commands/close.ts b/src/commands/close.ts index 8f2c01b..a4cfc65 100644 --- a/src/commands/close.ts +++ b/src/commands/close.ts @@ -82,7 +82,7 @@ export const registerButtonResponders = async () => { 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 + const originalSource = instance.interaction.customId.split("_")[1] as Exclude 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) @@ -109,7 +109,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as Exclude + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //close with reason diff --git a/src/commands/delete.ts b/src/commands/delete.ts index ebe4c32..97b8181 100644 --- a/src/commands/delete.ts +++ b/src/commands/delete.ts @@ -86,7 +86,7 @@ export const registerButtonResponders = async () => { 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 + const originalSource = instance.interaction.customId.split("_")[1] as Exclude 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) @@ -115,7 +115,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as Exclude + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //delete with reason diff --git a/src/commands/pin.ts b/src/commands/pin.ts index f1a8499..45ed82e 100644 --- a/src/commands/pin.ts +++ b/src/commands/pin.ts @@ -102,7 +102,7 @@ export const registerButtonResponders = async () => { 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 + const originalSource = instance.interaction.customId.split("_")[1] as Exclude 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) @@ -129,7 +129,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as Exclude + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //pin with reason diff --git a/src/commands/reopen.ts b/src/commands/reopen.ts index fb86a30..748f974 100644 --- a/src/commands/reopen.ts +++ b/src/commands/reopen.ts @@ -69,7 +69,7 @@ export const registerButtonResponders = async () => { 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 + const originalSource = instance.interaction.customId.split("_")[1] as Exclude 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) @@ -97,7 +97,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as Exclude + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //reopen with reason diff --git a/src/commands/ticket.ts b/src/commands/ticket.ts index ce26854..88126a4 100644 --- a/src/commands/ticket.ts +++ b/src/commands/ticket.ts @@ -7,7 +7,7 @@ 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,source:api.ODActionManagerIdMappings["opendiscord:create-ticket-permissions"]["source"],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}) if (!permsRes.valid && instance.channel){ diff --git a/src/commands/unclaim.ts b/src/commands/unclaim.ts index 73cb608..f7a75f0 100644 --- a/src/commands/unclaim.ts +++ b/src/commands/unclaim.ts @@ -69,7 +69,7 @@ export const registerButtonResponders = async () => { 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 + const originalSource = instance.interaction.customId.split("_")[1] as Exclude 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) @@ -96,7 +96,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as Exclude + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //unclaim with reason diff --git a/src/commands/unpin.ts b/src/commands/unpin.ts index 30a9579..e077143 100644 --- a/src/commands/unpin.ts +++ b/src/commands/unpin.ts @@ -69,7 +69,7 @@ export const registerButtonResponders = async () => { 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 + const originalSource = instance.interaction.customId.split("_")[1] as Exclude 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) @@ -96,7 +96,7 @@ export const registerModalResponders = async () => { return } - const originalSource = instance.interaction.customId.split("_")[2] as Exclude + const originalSource = instance.interaction.customId.split("_")[2] as Exclude const reason = instance.values.getTextField("reason",true) //unpin with reason diff --git a/src/core/mappings/plugin.ts b/src/core/mappings/plugin.ts index e67e05d..ff61099 100644 --- a/src/core/mappings/plugin.ts +++ b/src/core/mappings/plugin.ts @@ -22,7 +22,7 @@ export interface ODPluginClassManagerIdMappings extends api.ODPluginClassManager /**## ODMappedPluginManager `class * A special class with types for the Open Ticket `ODPluginManager` class. */ -export class ODMappedPluginManager extends api.ODPluginManager {} +export class ODMappedPluginManager extends api.ODPluginManager {} /**## ODMappedPluginClassManager `class * A special class with types for the Open Ticket `ODPluginClassManager` class.