From 415330be2190e31ea0b89555625e071133f89870 Mon Sep 17 00:00:00 2001 From: DJj123dj <80536295+DJj123dj@users.noreply.github.com> Date: Sun, 14 Sep 2025 22:04:11 +0200 Subject: [PATCH] Added priority system (Part 1, Incomplete) --- src/builders/embeds.ts | 32 +++++++- src/core/api/api.ts | 3 +- src/core/api/defaults/builder.ts | 5 ++ src/core/api/defaults/client.ts | 5 +- src/core/api/defaults/event.ts | 5 ++ src/core/api/main.ts | 4 + src/core/api/modules/defaults.ts | 5 ++ src/core/api/openticket/priority.ts | 101 ++++++++++++++++++++++++++ src/data/framework/commandLoader.ts | 67 +++++++++++++++++ src/data/framework/eventLoader.ts | 4 + src/data/framework/helpMenuLoader.ts | 8 ++ src/data/openticket/priorityLoader.ts | 11 +++ src/index.ts | 8 ++ 13 files changed, 254 insertions(+), 4 deletions(-) create mode 100644 src/core/api/openticket/priority.ts create mode 100644 src/data/openticket/priorityLoader.ts diff --git a/src/builders/embeds.ts b/src/builders/embeds.ts index 050c670..a145298 100644 --- a/src/builders/embeds.ts +++ b/src/builders/embeds.ts @@ -20,6 +20,7 @@ export const registerAllEmbeds = async () => { roleEmbeds() clearEmbeds() autoEmbeds() + extraEmbeds() } /**Utility function to get the translated "method" from the source. Mostly used in error embeds. */ @@ -1166,8 +1167,6 @@ const roleEmbeds = () => { ) } -export default roleEmbeds - const clearEmbeds = () => { //CLEAR VERIFY MESSAGE embeds.add(new api.ODEmbed("opendiscord:clear-verify-message")) @@ -1311,4 +1310,33 @@ const autoEmbeds = () => { if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"}) }) ) +} + +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) => { + const {user,priority,reason} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🚨","Priority Changed")) //TODO TRANSLATION!!! + instance.setDescription("The ticket priority has been changed to **"+priority.renderDisplayName()+"** by "+discord.userMention(user.id)+" successfully!") //TODO TRANSLATION!!! + if (reason) 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) => { + const {user,priority} = params + + instance.setAuthor(user.displayName,user.displayAvatarURL()) + instance.setColor(generalConfig.data.mainColor) + instance.setTitle(utilities.emojiTitle("🚨","Priority Changed")) //TODO TRANSLATION!!! + instance.setDescription("The current priority of this ticket is **"+priority.renderDisplayName()+"**!") //TODO TRANSLATION!!! + }) + ) } \ No newline at end of file diff --git a/src/core/api/api.ts b/src/core/api/api.ts index 10e7906..7286d8f 100644 --- a/src/core/api/api.ts +++ b/src/core/api/api.ts @@ -60,4 +60,5 @@ export * from "./openticket/panel" export * from "./openticket/ticket" export * from "./openticket/blacklist" export * from "./openticket/transcript" -export * from "./openticket/role" \ No newline at end of file +export * from "./openticket/role" +export * from "./openticket/priority" \ No newline at end of file diff --git a/src/core/api/defaults/builder.ts b/src/core/api/defaults/builder.ts index 34bf3d9..7d8ff2a 100644 --- a/src/core/api/defaults/builder.ts +++ b/src/core/api/defaults/builder.ts @@ -13,6 +13,7 @@ import { ODVerifyBar } from "../modules/verifybar" import * as discord from "discord.js" import { ODTranscriptCompiler, ODTranscriptCompilerCompileResult } from "../openticket/transcript" import { ODRole, ODRoleUpdateResult } from "../openticket/role" +import { ODPriority } from "../openticket/priority" /**## ODBuilderManager_Default `default_class` * This is a special class that adds type definitions & typescript to the ODBuilderManager class. @@ -294,6 +295,8 @@ export interface ODEmbedManagerIds_Default { "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:priority-set":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriority,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:ODPriority},workers:"opendiscord:priority-get"}, } /**## ODEmbedManager_Default `default_class` @@ -428,6 +431,8 @@ export interface ODMessageManagerIds_Default { "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:priority-set":{source:"slash"|"text"|"other",params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,priority:ODPriority,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:ODPriority},workers:"opendiscord:priority-get"}, } /**## ODMessageManager_Default `default_class` diff --git a/src/core/api/defaults/client.ts b/src/core/api/defaults/client.ts index 0859c14..c191d09 100644 --- a/src/core/api/defaults/client.ts +++ b/src/core/api/defaults/client.ts @@ -50,6 +50,7 @@ export interface ODSlashCommandManagerIds_Default { "opendiscord:clear":ODSlashCommand, "opendiscord:autoclose":ODSlashCommand, "opendiscord:autodelete":ODSlashCommand, + "opendiscord:priority":ODSlashCommand, } /**## ODSlashCommandManager_Default `default_class` @@ -119,7 +120,9 @@ export interface ODTextCommandManagerIds_Default { "opendiscord:autoclose-disable":ODTextCommand, "opendiscord:autoclose-enable":ODTextCommand, "opendiscord:autodelete-disable":ODTextCommand, - "opendiscord:autodelete-enable":ODTextCommand + "opendiscord:autodelete-enable":ODTextCommand, + "opendiscord:priority-set":ODTextCommand, + "opendiscord:priority-get":ODTextCommand, } /**## ODTextCommandManager_Default `default_class` diff --git a/src/core/api/defaults/event.ts b/src/core/api/defaults/event.ts index f4f6d05..169c757 100644 --- a/src/core/api/defaults/event.ts +++ b/src/core/api/defaults/event.ts @@ -42,6 +42,7 @@ import { ODQuestionManager } from "../openticket/question" import { ODBlacklistManager } from "../openticket/blacklist" import { ODTranscriptManager_Default } from "../openticket/transcript" import { ODRole, ODRoleManager } from "../openticket/role" +import { ODPriorityManager_Default } from "../openticket/priority" /**## ODEventIds_Default `interface` * This interface is a list of ids available in the `ODEvent_Default` class. @@ -122,6 +123,10 @@ export interface ODEventIds_Default { "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> diff --git a/src/core/api/main.ts b/src/core/api/main.ts index cec0b11..4738986 100644 --- a/src/core/api/main.ts +++ b/src/core/api/main.ts @@ -37,6 +37,7 @@ 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. @@ -127,6 +128,8 @@ export class ODMain { 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() @@ -175,6 +178,7 @@ export class ODMain { this.blacklist = new ODBlacklistManager(this.debug) this.transcripts = new ODTranscriptManager_Default(this.debug,this.tickets,this.client) 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 :) */ diff --git a/src/core/api/modules/defaults.ts b/src/core/api/modules/defaults.ts index 4b366ff..c0b4491 100644 --- a/src/core/api/modules/defaults.ts +++ b/src/core/api/modules/defaults.ts @@ -83,6 +83,9 @@ export interface ODDefaults { /**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). */ @@ -284,6 +287,8 @@ export class ODDefaultsManager { clientMultiGuildWarning:true, clientActivityLoading:true, clientActivityInitiating:true, + + priorityLoading:true, slashCommandLoading:true, slashCommandRegistering:true, diff --git a/src/core/api/openticket/priority.ts b/src/core/api/openticket/priority.ts new file mode 100644 index 0000000..085cba8 --- /dev/null +++ b/src/core/api/openticket/priority.ts @@ -0,0 +1,101 @@ +/////////////////////////////////////// +//OPENTICKET PRIORITY MODULE +/////////////////////////////////////// +import { ODId, ODManager, ODValidJsonType, ODValidId, ODVersion, ODManagerData } from "../modules/base" +import { ODDebugger } from "../modules/console" +import * as discord from "discord.js" + +/**## ODPriorityManager `class` + * This is an Open Ticket priority manager. + * + * This class manages all registered priority levels in the bot. + * + * Priorities levels can be changed/updated/translated by plugins to allow for more customisability. + */ +export class ODPriorityManager extends ODManager { + /**A reference to the Open Ticket debugger. */ + #debug: ODDebugger + + constructor(debug:ODDebugger){ + super(debug,"priority") + this.#debug = debug + } +} + +/**## ODPriorityIds `type` + * This interface is a list of ids available in the `ODPriorityManager` class. + * It's used to generate typescript declarations for this class. + */ +export interface ODPriorityIds { + "opendiscord:urgent":ODPriority, + "opendiscord:very-high":ODPriority, + "opendiscord:high":ODPriority, + "opendiscord:normal":ODPriority, + "opendiscord:low":ODPriority, + "opendiscord:very-low":ODPriority, + "opendiscord:none":ODPriority, +} + +/**## ODPriorityManager_Default `default_class` + * This is a special class that adds type definitions & typescript to the ODPriorityManager class. + * It doesn't add any extra features! + * + * This default class is made for the global variable `opendiscord.priorities`! + */ +export class ODPriorityManager_Default extends ODPriorityManager { + get(id:PriorityId): ODPriorityIds[PriorityId] + get(id:ODValidId): ODPriority|null + + get(id:ODValidId): ODPriority|null { + return super.get(id) + } + + remove(id:PriorityId): ODPriorityIds[PriorityId] + remove(id:ODValidId): ODPriority|null + + remove(id:ODValidId): ODPriority|null { + return super.remove(id) + } + + exists(id:keyof ODPriorityIds): boolean + exists(id:ODValidId): boolean + + exists(id:ODValidId): boolean { + return super.exists(id) + } +} + +/**## ODPriority `class` + * This is an Open Ticket priority level. + * + * Using this class, you can register or edit a priority level for the ticket priority system. + * + * Priority levels should be registered in `opendiscord.priorities`. + * + * #### 🚨 Negative priorities are treated as `disabled/no-priority`! + */ +export class ODPriority extends ODManagerData { + /**The priority level itself. A negative number (e.g. `-1`) is treated as `disabled/no-priority`. */ + priority:number + /**The raw name of the level (used in text/slash command inputs). */ + rawName:string + /**The display name of the level (used in embeds & messages). */ + displayName:string + /**The display emoji of the level (used in embeds & messages). */ + displayEmoji:string|null + /**The emoji added to the channel name when the level is applied to a ticket. */ + channelEmoji:string|null + + constructor(id:ODValidId,priority:number,rawName:string,displayName:string,displayEmoji:string|null,channelEmoji:string|null){ + super(id) + this.priority = priority + this.rawName = rawName + this.displayName = displayName + this.displayEmoji = displayEmoji + this.channelEmoji = channelEmoji + } + /**Get the display name + emoji for rendering this priority in the UI/embeds. */ + renderDisplayName(){ + return (this.displayEmoji ? this.displayEmoji+" " : "")+this.displayName + } +} \ No newline at end of file diff --git a/src/data/framework/commandLoader.ts b/src/data/framework/commandLoader.ts index 4e10510..08133e7 100644 --- a/src/data/framework/commandLoader.ts +++ b/src/data/framework/commandLoader.ts @@ -555,6 +555,42 @@ export const loadAllSlashCommands = async () => { } ] })) + //PRIORITY + if (allowedCommands.includes("priority")) commands.add(new api.ODSlashCommand("opendiscord:priority",{ + type:act.ChatInput, + name:"priority", + description:"Set the priority of the ticket.", //TODO TRANSLATION!!! + contexts:[discord.InteractionContextType.Guild], + integrationTypes:[discord.ApplicationIntegrationType.GuildInstall], + options:[ + { + name:"set", + description:"Set the priority of the ticket.", //TODO TRANSLATION!!! + type:acot.Subcommand, + options:[ + { + name:"priority", + description:"The priority of the channel.", + type:acot.String, + required:true, + choices:opendiscord.priorities.getAll().sort((a,b) => b.priority-a.priority).map((prio) => ({value:prio.rawName,name:prio.renderDisplayName()})) + }, + { + name:"reason", + description:lang.getTranslation("commands.reason"), + type:acot.String, + required:false + } + ] + }, + { + name:"get", + description:"Get the priority of the ticket.", //TODO TRANSLATION!!! + type:acot.Subcommand + }, + //TODO: list (v4.2) + ] + })) } export const loadAllTextCommands = async () => { @@ -1057,6 +1093,37 @@ export const loadAllTextCommands = async () => { } ] })) + //PRIORITY + //TODO: priority list (v4.2) + if (allowedCommands.includes("priority")) commands.add(new api.ODTextCommand("opendiscord:priority-set",{ + name:"priority set", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + options:[ + { + name:"priority", + type:"string", + required:true, + allowSpaces:false, + choices:opendiscord.priorities.getAll().sort((a,b) => b.priority-a.priority).map((prio) => prio.rawName) + }, + { + name:"reason", + type:"string", + required:false, + allowSpaces:true + } + ] + })) + if (allowedCommands.includes("priority")) commands.add(new api.ODTextCommand("opendiscord:priority-get",{ + name:"priority get", + prefix, + dmPermission:false, + guildPermission:true, + allowBots:false, + })) } export const loadAllContextMenus = async () => { diff --git a/src/data/framework/eventLoader.ts b/src/data/framework/eventLoader.ts index aeda57d..c7c0dd6 100644 --- a/src/data/framework/eventLoader.ts +++ b/src/data/framework/eventLoader.ts @@ -75,6 +75,10 @@ export const loadAllEvents = () => { "afterClientActivityLoaded", "onClientActivityInit", "afterClientActivityInitiated", + + //priority levels + "onPriorityLoad", + "afterPrioritiesLoaded", //client slash commands "onSlashCommandLoad", diff --git a/src/data/framework/helpMenuLoader.ts b/src/data/framework/helpMenuLoader.ts index 0c23297..9f301b1 100644 --- a/src/data/framework/helpMenuLoader.ts +++ b/src/data/framework/helpMenuLoader.ts @@ -269,5 +269,13 @@ export const loadAllHelpMenuComponents = async () => { textOptions:[{name:"time",optional:false},{name:"reason",optional:true}], slashOptions:[{name:"time",optional:false},{name:"reason",optional:true}] })) + if (allowedCommands.includes("priority")) advanced.add(new api.ODHelpMenuCommandComponent("opendiscord:priority-set",0,{ + textName:prefix+"priority set", + textDescription:"Set the priority of the ticket channel.", //TODO TRANSLATION!!! + slashName:"/priority set", + slashDescription:"Set the priority of the ticket channel.", //TODO TRANSLATION!!! + textOptions:[{name:"priority",optional:false}], + slashOptions:[{name:"priority",optional:false}] + })) } } \ No newline at end of file diff --git a/src/data/openticket/priorityLoader.ts b/src/data/openticket/priorityLoader.ts new file mode 100644 index 0000000..e9abdd7 --- /dev/null +++ b/src/data/openticket/priorityLoader.ts @@ -0,0 +1,11 @@ +import {opendiscord, api, utilities} from "../../index" + +export const loadAllPriorities = async () => { + opendiscord.priorities.add(new api.ODPriority("opendiscord:urgent",5,"urgent","Urgent","🔴","🔴")) //TODO TRANSLATION!!! + opendiscord.priorities.add(new api.ODPriority("opendiscord:very-high",4,"very-high","Very High","🟠","🟠")) //TODO TRANSLATION!!! + opendiscord.priorities.add(new api.ODPriority("opendiscord:high",3,"high","High","🟡","🟡")) //TODO TRANSLATION!!! + opendiscord.priorities.add(new api.ODPriority("opendiscord:normal",2,"normal","Normal","🟢","🟢")) //TODO TRANSLATION!!! + opendiscord.priorities.add(new api.ODPriority("opendiscord:low",1,"low","Low","🔵","🔵")) //TODO TRANSLATION!!! + opendiscord.priorities.add(new api.ODPriority("opendiscord:very-low",0,"very-low","Very Low","⚪","⚪")) //TODO TRANSLATION!!! + opendiscord.priorities.add(new api.ODPriority("opendiscord:none",-1,"none","None",null,null)) //TODO TRANSLATION!!! +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 9963ce9..7cd2146 100644 --- a/src/index.ts +++ b/src/index.ts @@ -424,6 +424,14 @@ const main = async () => { await opendiscord.events.get("afterClientActivityInitiated").emit([opendiscord.client.activity,opendiscord.client]) } + //load priority levels + opendiscord.log("Loading prioritiy levels...","system") + if (opendiscord.defaults.getDefault("priorityLoading")){ + await (await import("./data/openticket/priorityLoader.js")).loadAllPriorities() + } + await opendiscord.events.get("onPriorityLoad").emit([opendiscord.priorities]) + await opendiscord.events.get("afterPrioritiesLoaded").emit([opendiscord.priorities]) + //load slash commands opendiscord.log("Loading slash commands...","system") if (opendiscord.defaults.getDefault("slashCommandLoading")){