Added transfer command (/transfer) + new stats

With this command you're able to transfer the ticket ownership to another person in the server.
This commit is contained in:
DJj123dj
2025-11-02 20:09:38 +01:00
parent 68a8170570
commit c7b44232c4
14 changed files with 345 additions and 21 deletions
+154
View File
@@ -0,0 +1,154 @@
///////////////////////////////////////
//TICKET TRANSFER SYSTEM
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerActions = async () => {
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) => {
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!")
const oldCreator = await opendiscord.tickets.getTicketUser(ticket,"creator") ?? opendiscord.client.client.user
await opendiscord.events.get("onTicketTransfer").emit([ticket,user,channel,oldCreator,newCreator,reason])
//update ticket
const oldCreatorId = ticket.get("opendiscord:opened-by").value
if (oldCreatorId){
ticket.get("opendiscord:previous-creators").value.push(oldCreatorId)
ticket.get("opendiscord:previous-creators").refreshDatabase()
}
if (!ticket.get("opendiscord:participants").value.find((p) => p.type == "user" && p.id == newCreator.id)){
ticket.get("opendiscord:participants").value.push({type:"user",id:newCreator.id})
ticket.get("opendiscord:participants").refreshDatabase()
}
ticket.get("opendiscord:opened-by").value = newCreator.id
if (["user-name","user-nickname","user-id"].includes(ticket.option.get("opendiscord:channel-suffix").value)){
const newSuffix = await opendiscord.options.suffix.getSuffixFromOption(ticket.option,newCreator,guild)
if (newSuffix) ticket.get("opendiscord:channel-suffix").value = newSuffix
}
//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
//handle permissions
const permissions: discord.OverwriteResolvable[] = [{
type:discord.OverwriteType.Role,
id:guild.roles.everyone.id,
allow:[],
deny:["ViewChannel","SendMessages","ReadMessageHistory"]
}]
const globalAdmins = opendiscord.configs.get("opendiscord:general").data.globalAdmins
const optionAdmins = ticket.option.get("opendiscord:admins").value
const readonlyAdmins = ticket.option.get("opendiscord:admins-readonly").value
globalAdmins.forEach((admin) => {
permissions.push({
type:discord.OverwriteType.Role,
id:admin,
allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"],
deny:[]
})
})
optionAdmins.forEach((admin) => {
if (globalAdmins.includes(admin)) return
permissions.push({
type:discord.OverwriteType.Role,
id:admin,
allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory","ManageMessages"],
deny:[]
})
})
readonlyAdmins.forEach((admin) => {
if (globalAdmins.includes(admin)) return
if (optionAdmins.includes(admin)) return
permissions.push({
type:discord.OverwriteType.Role,
id:admin,
allow:["ViewChannel","ReadMessageHistory"],
deny:["SendMessages","AddReactions","AttachFiles","SendPolls"]
})
})
//transfer all old user-participants over to the new ticket (creator & participants)
ticket.get("opendiscord:participants").value.forEach((p) => {
if (p.type == "user") permissions.push({
type:discord.OverwriteType.Member,
id:p.id,
allow:["ViewChannel","SendMessages","AddReactions","AttachFiles","SendPolls","ReadMessageHistory"],
deny:[]
})
})
try{
await channel.permissionOverwrites.set(permissions)
}catch{
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){
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}
])
opendiscord.debugfile.writeErrorMessage(new api.ODError(e,"uncaughtException"))
}
}
//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)
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) => {
const {guild,channel,user,ticket,newCreator,reason} = params
}),
new api.ODWorker("opendiscord:logs",0,(instance,params,source,cancel) => {
const {guild,channel,user,ticket,newCreator} = params
opendiscord.log(user.displayName+" transferred a ticket to '"+newCreator.displayName+"'!","info",[
{key:"user",value:user.username},
{key:"userid",value:user.id,hidden:true},
{key:"channel",value:"#"+channel.name},
{key:"channelid",value:channel.id,hidden:true},
{key:"reason",value:params.reason ?? "/"},
{key:"method",value:source}
])
})
])
opendiscord.actions.get("opendiscord:transfer-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
})
}
+15 -1
View File
@@ -330,7 +330,7 @@ const errorEmbeds = () => {
new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,source) => { new api.ODWorker("opendiscord:error-channel-rename",0,async (instance,params,source) => {
const {channel,user,originalName,newName} = params const {channel,user,originalName,newName} = params
const method = (source == "ticket-move" || source == "ticket-pin" || source == "ticket-rename" || source == "ticket-unpin" || source == "ticket-priority") ? source : getMethodFromSource(source) const method = (source == "ticket-move" || source == "ticket-pin" || source == "ticket-rename" || source == "ticket-unpin" || source == "ticket-priority" || source == "ticket-transfer") ? source : getMethodFromSource(source)
instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor) instance.setColor(generalConfig.data.system.useRedErrorEmbeds ? "Red" : generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.channelRename"))) instance.setTitle(utilities.emojiTitle("❌",lang.getTranslation("errors.titles.channelRename")))
@@ -1353,4 +1353,18 @@ const extraEmbeds = () => {
instance.setDescription("The current priority of this ticket is **"+priority.renderDisplayName()+"**!") //TODO TRANSLATION!!! instance.setDescription("The current priority of this ticket is **"+priority.renderDisplayName()+"**!") //TODO TRANSLATION!!!
}) })
) )
//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) => {
const {user,oldCreator,newCreator,reason} = params
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔀","Ticket Transferred")) //TODO TRANSLATION!!!
instance.setDescription("The ticket ownership has been transferred from "+discord.userMention(oldCreator.id)+" to "+discord.userMention(newCreator.id)+" by "+discord.userMention(user.id)+" successfully!") //TODO TRANSLATION!!!
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
})
)
} }
+9
View File
@@ -1102,4 +1102,13 @@ const extraMessages = () => {
instance.addEmbed(await embeds.getSafe("opendiscord:priority-get").build(source,{guild,channel,user,ticket,priority})) instance.addEmbed(await embeds.getSafe("opendiscord:priority-get").build(source,{guild,channel,user,ticket,priority}))
}) })
) )
//TRANSFER MESSAGE
messages.add(new api.ODMessage("opendiscord:transfer-message"))
messages.get("opendiscord:transfer-message").workers.add(
new api.ODWorker("opendiscord:transfer-message",0,async (instance,params,source) => {
const {guild,channel,user,ticket,oldCreator,newCreator,reason} = params
instance.addEmbed(await embeds.getSafe("opendiscord:transfer-message").build(source,{guild,channel,user,ticket,oldCreator,newCreator,reason}))
})
)
} }
+81
View File
@@ -0,0 +1,81 @@
///////////////////////////////////////
//TRANSFER COMMAND
///////////////////////////////////////
import {opendiscord, api, utilities} from "../index"
import * as discord from "discord.js"
const generalConfig = opendiscord.configs.get("opendiscord:general")
export const registerCommandResponders = async () => {
//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:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.transfer
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:transfer",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 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 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}))
}),
new api.ODWorker("opendiscord:logs",-1,(instance,params,source,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}
])
})
])
}
+6
View File
@@ -125,6 +125,12 @@ export interface ODActionManagerIds_Default {
result:{}, result:{},
workers:"opendiscord:update-ticket-priority"|"opendiscord:discord-logs"|"opendiscord:logs" workers:"opendiscord:update-ticket-priority"|"opendiscord:discord-logs"|"opendiscord:logs"
}, },
"opendiscord:transfer-ticket":{
source:"slash"|"text"|"other",
params:{guild:discord.Guild,channel:discord.GuildTextBasedChannel,user:discord.User,ticket:ODTicket,newCreator:discord.User,reason:string|null,sendMessage:boolean},
result:{},
workers:"opendiscord:transfer-ticket"|"opendiscord:discord-logs"|"opendiscord:logs"
},
} }
/**## ODActionManager_Default `default_class` /**## ODActionManager_Default `default_class`
+4 -2
View File
@@ -239,7 +239,7 @@ export interface ODEmbedManagerIds_Default {
"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-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-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-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"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"opendiscord:error-channel-rename"}, "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: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:help-menu":{source:"text"|"slash"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu"},
@@ -299,6 +299,7 @@ export interface ODEmbedManagerIds_Default {
"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: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-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: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` /**## ODEmbedManager_Default `default_class`
@@ -375,7 +376,7 @@ export interface ODMessageManagerIds_Default {
"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-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-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-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"|"other",params:{guild:discord.Guild|null,channel:discord.TextBasedChannel,user:discord.User,originalName:string,newName:string},workers:"opendiscord:error-channel-rename"}, "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: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:help-menu":{source:"slash"|"text"|"button"|"other",params:{mode:"slash"|"text",page:number},workers:"opendiscord:help-menu"},
@@ -437,6 +438,7 @@ export interface ODMessageManagerIds_Default {
"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: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-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: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` /**## ODMessageManager_Default `default_class`
+2
View File
@@ -52,6 +52,7 @@ export interface ODSlashCommandManagerIds_Default {
"opendiscord:autodelete":ODSlashCommand, "opendiscord:autodelete":ODSlashCommand,
"opendiscord:topic":ODSlashCommand, "opendiscord:topic":ODSlashCommand,
"opendiscord:priority":ODSlashCommand, "opendiscord:priority":ODSlashCommand,
"opendiscord:transfer":ODSlashCommand,
} }
/**## ODSlashCommandManager_Default `default_class` /**## ODSlashCommandManager_Default `default_class`
@@ -125,6 +126,7 @@ export interface ODTextCommandManagerIds_Default {
"opendiscord:topic-set":ODTextCommand, "opendiscord:topic-set":ODTextCommand,
"opendiscord:priority-set":ODTextCommand, "opendiscord:priority-set":ODTextCommand,
"opendiscord:priority-get":ODTextCommand, "opendiscord:priority-get":ODTextCommand,
"opendiscord:transfer":ODTextCommand,
} }
/**## ODTextCommandManager_Default `default_class` /**## ODTextCommandManager_Default `default_class`
+4 -2
View File
@@ -204,8 +204,10 @@ export interface ODEventIds_Default {
"afterTicketsCleared": 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> "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> "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) => 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) => 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 //roles
"onRoleLoad": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid> "onRoleLoad": ODEvent_Default<(roles:ODRoleManager) => ODPromiseVoid>
+1
View File
@@ -46,6 +46,7 @@ export interface ODCommandResponderManagerIds_Default {
"opendiscord:clear":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:clear"|"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: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: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: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"}, "opendiscord:autodelete":{source:"slash"|"text",params:{},workers:"opendiscord:permissions"|"opendiscord:autodelete"|"opendiscord:logs"},
+2
View File
@@ -60,6 +60,7 @@ export interface ODStatGlobalScopeIds_DefaultGlobal {
"opendiscord:tickets-claimed":ODBasicStat, "opendiscord:tickets-claimed":ODBasicStat,
"opendiscord:tickets-pinned":ODBasicStat, "opendiscord:tickets-pinned":ODBasicStat,
"opendiscord:tickets-moved":ODBasicStat, "opendiscord:tickets-moved":ODBasicStat,
"opendiscord:tickets-transferred":ODBasicStat,
"opendiscord:users-blacklisted":ODBasicStat, "opendiscord:users-blacklisted":ODBasicStat,
"opendiscord:transcripts-created":ODBasicStat, "opendiscord:transcripts-created":ODBasicStat,
"opendiscord:ticket-volume":ODDynamicStat, "opendiscord:ticket-volume":ODDynamicStat,
@@ -204,6 +205,7 @@ export interface ODStatScopeIds_DefaultUser {
"opendiscord:tickets-claimed":ODBasicStat, "opendiscord:tickets-claimed":ODBasicStat,
"opendiscord:tickets-pinned":ODBasicStat, "opendiscord:tickets-pinned":ODBasicStat,
"opendiscord:tickets-moved":ODBasicStat, "opendiscord:tickets-moved":ODBasicStat,
"opendiscord:tickets-transferred":ODBasicStat,
"opendiscord:users-blacklisted":ODBasicStat, "opendiscord:users-blacklisted":ODBasicStat,
"opendiscord:transcripts-created":ODBasicStat, "opendiscord:transcripts-created":ODBasicStat,
"opendiscord:current-tickets":ODDynamicStat, "opendiscord:current-tickets":ODDynamicStat,
+45
View File
@@ -617,6 +617,29 @@ export const loadAllSlashCommands = async () => {
//TODO: list (v4.2) //TODO: list (v4.2)
] ]
})) }))
//TRANSFER
if (allowedCommands.includes("transfer")) commands.add(new api.ODSlashCommand("opendiscord:transfer",{
type:act.ChatInput,
name:"transfer",
description:"Transfer the ticket ownership from one user to another.", //TODO TRANSLATION!!!
contexts:[discord.InteractionContextType.Guild],
integrationTypes:[discord.ApplicationIntegrationType.GuildInstall],
options:[
{
name:"user",
description:"The user to transfer to.", //TODO TRANSLATION!!!
type:acot.User,
required:true
},
{
name:"reason",
description:lang.getTranslation("commands.reason"),
type:acot.String,
required:false
}
]
}))
} }
export const loadAllTextCommands = async () => { export const loadAllTextCommands = async () => {
@@ -1169,6 +1192,28 @@ export const loadAllTextCommands = async () => {
guildPermission:true, guildPermission:true,
allowBots:false, allowBots:false,
})) }))
//TRANSFER
if (allowedCommands.includes("transfer")) commands.add(new api.ODTextCommand("opendiscord:transfer",{
name:"transfer",
prefix,
dmPermission:false,
guildPermission:true,
allowBots:false,
options:[
{
name:"user",
type:"user",
required:true
},
{
name:"reason",
type:"string",
required:false,
allowSpaces:true
}
]
}))
} }
export const loadAllContextMenus = async () => { export const loadAllContextMenus = async () => {
+2
View File
@@ -159,6 +159,8 @@ export const loadAllEvents = () => {
"afterTicketTopicChanged", "afterTicketTopicChanged",
"onTicketPriorityChange", "onTicketPriorityChange",
"afterTicketPriorityChanged", "afterTicketPriorityChanged",
"onTicketTransfer",
"afterTicketTransferred",
//roles //roles
"onRoleLoad", "onRoleLoad",
+18 -16
View File
@@ -19,15 +19,16 @@ export const loadAllStats = async () => {
const global = stats.get("opendiscord:global") const global = stats.get("opendiscord:global")
if (global){ if (global){
global.add(new api.ODBasicStat("opendiscord:tickets-created",12,lang.getTranslation("stats.properties.ticketsCreated"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-created",13,lang.getTranslation("stats.properties.ticketsCreated"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-closed",11,lang.getTranslation("stats.properties.ticketsClosed"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-closed",12,lang.getTranslation("stats.properties.ticketsClosed"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-deleted",10,lang.getTranslation("stats.properties.ticketsDeleted"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-deleted",11,lang.getTranslation("stats.properties.ticketsDeleted"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-reopened",9,lang.getTranslation("stats.properties.ticketsReopened"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-reopened",10,lang.getTranslation("stats.properties.ticketsReopened"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-autoclosed",8,lang.getTranslation("stats.properties.ticketsAutoclosed"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-autoclosed",9,lang.getTranslation("stats.properties.ticketsAutoclosed"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-autodeleted",7,"Tickets Autodeleted",0)) //TODO TRANSLATION!!! global.add(new api.ODBasicStat("opendiscord:tickets-autodeleted",8,"Tickets Autodeleted",0)) //TODO TRANSLATION!!!
global.add(new api.ODBasicStat("opendiscord:tickets-claimed",6,lang.getTranslation("stats.properties.ticketsClaimed"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-claimed",7,lang.getTranslation("stats.properties.ticketsClaimed"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-pinned",5,lang.getTranslation("stats.properties.ticketsPinned"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-pinned",6,lang.getTranslation("stats.properties.ticketsPinned"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-moved",4,lang.getTranslation("stats.properties.ticketsMoved"),0)) global.add(new api.ODBasicStat("opendiscord:tickets-moved",5,lang.getTranslation("stats.properties.ticketsMoved"),0))
global.add(new api.ODBasicStat("opendiscord:tickets-transferred",4,"Tickets Transferred",0)) //TODO TRANSLATION!!!
global.add(new api.ODBasicStat("opendiscord:users-blacklisted",3,lang.getTranslation("stats.properties.usersBlacklisted"),0)) global.add(new api.ODBasicStat("opendiscord:users-blacklisted",3,lang.getTranslation("stats.properties.usersBlacklisted"),0))
global.add(new api.ODBasicStat("opendiscord:transcripts-created",2,lang.getTranslation("stats.properties.transcriptsCreated"),0)) global.add(new api.ODBasicStat("opendiscord:transcripts-created",2,lang.getTranslation("stats.properties.transcriptsCreated"),0))
global.add(new api.ODDynamicStat("opendiscord:ticket-volume",1,() => { global.add(new api.ODDynamicStat("opendiscord:ticket-volume",1,() => {
@@ -71,13 +72,14 @@ export const loadAllStats = async () => {
if (permissions.type == "support") return lang.getTranslation("params.uppercase.role")+": 💬 `Support Team`" //TODO TRANSLATION!!! if (permissions.type == "support") return lang.getTranslation("params.uppercase.role")+": 💬 `Support Team`" //TODO TRANSLATION!!!
else return lang.getTranslation("params.uppercase.role")+": 👤 `Member`" //TODO TRANSLATION!!! else return lang.getTranslation("params.uppercase.role")+": 👤 `Member`" //TODO TRANSLATION!!!
})) }))
user.add(new api.ODBasicStat("opendiscord:tickets-created",9,lang.getTranslation("stats.properties.ticketsCreated"),0)) user.add(new api.ODBasicStat("opendiscord:tickets-created",10,lang.getTranslation("stats.properties.ticketsCreated"),0))
user.add(new api.ODBasicStat("opendiscord:tickets-closed",8,lang.getTranslation("stats.properties.ticketsClosed"),0)) user.add(new api.ODBasicStat("opendiscord:tickets-closed",9,lang.getTranslation("stats.properties.ticketsClosed"),0))
user.add(new api.ODBasicStat("opendiscord:tickets-deleted",7,lang.getTranslation("stats.properties.ticketsDeleted"),0)) user.add(new api.ODBasicStat("opendiscord:tickets-deleted",8,lang.getTranslation("stats.properties.ticketsDeleted"),0))
user.add(new api.ODBasicStat("opendiscord:tickets-reopened",6,lang.getTranslation("stats.properties.ticketsReopened"),0)) user.add(new api.ODBasicStat("opendiscord:tickets-reopened",7,lang.getTranslation("stats.properties.ticketsReopened"),0))
user.add(new api.ODBasicStat("opendiscord:tickets-claimed",5,lang.getTranslation("stats.properties.ticketsClaimed"),0)) user.add(new api.ODBasicStat("opendiscord:tickets-claimed",6,lang.getTranslation("stats.properties.ticketsClaimed"),0))
user.add(new api.ODBasicStat("opendiscord:tickets-pinned",4,lang.getTranslation("stats.properties.ticketsPinned"),0)) user.add(new api.ODBasicStat("opendiscord:tickets-pinned",5,lang.getTranslation("stats.properties.ticketsPinned"),0))
user.add(new api.ODBasicStat("opendiscord:tickets-moved",3,lang.getTranslation("stats.properties.ticketsMoved"),0)) user.add(new api.ODBasicStat("opendiscord:tickets-moved",4,lang.getTranslation("stats.properties.ticketsMoved"),0))
user.add(new api.ODBasicStat("opendiscord:tickets-transferred",3,"Tickets Transferred",0)) //TODO TRANSLATION!!!
user.add(new api.ODBasicStat("opendiscord:users-blacklisted",2,lang.getTranslation("stats.properties.usersBlacklisted"),0)) user.add(new api.ODBasicStat("opendiscord:users-blacklisted",2,lang.getTranslation("stats.properties.usersBlacklisted"),0))
user.add(new api.ODBasicStat("opendiscord:transcripts-created",1,lang.getTranslation("stats.properties.transcriptsCreated"),0)) user.add(new api.ODBasicStat("opendiscord:transcripts-created",1,lang.getTranslation("stats.properties.transcriptsCreated"),0))
user.add(new api.ODDynamicStat("opendiscord:current-tickets",0,async (scopeId,guild,channel,user) => { user.add(new api.ODDynamicStat("opendiscord:current-tickets",0,async (scopeId,guild,channel,user) => {
+2
View File
@@ -673,6 +673,7 @@ const main = async () => {
await (await import("./commands/autodelete.js")).registerCommandResponders() await (await import("./commands/autodelete.js")).registerCommandResponders()
await (await import("./commands/topic.js")).registerCommandResponders() await (await import("./commands/topic.js")).registerCommandResponders()
await (await import("./commands/priority.js")).registerCommandResponders() await (await import("./commands/priority.js")).registerCommandResponders()
await (await import("./commands/transfer.js")).registerCommandResponders()
} }
await opendiscord.events.get("onCommandResponderLoad").emit([opendiscord.responders.commands,opendiscord.responders,opendiscord.actions]) await opendiscord.events.get("onCommandResponderLoad").emit([opendiscord.responders.commands,opendiscord.responders,opendiscord.actions])
await opendiscord.events.get("afterCommandRespondersLoaded").emit([opendiscord.responders.commands,opendiscord.responders,opendiscord.actions]) await opendiscord.events.get("afterCommandRespondersLoaded").emit([opendiscord.responders.commands,opendiscord.responders,opendiscord.actions])
@@ -761,6 +762,7 @@ const main = async () => {
await (await import("./actions/clearTickets.js")).registerActions() await (await import("./actions/clearTickets.js")).registerActions()
await (await import("./actions/updateTicketTopic.js")).registerActions() await (await import("./actions/updateTicketTopic.js")).registerActions()
await (await import("./actions/updateTicketPriority.js")).registerActions() await (await import("./actions/updateTicketPriority.js")).registerActions()
await (await import("./actions/transferTicket.js")).registerActions()
} }
await opendiscord.events.get("onActionLoad").emit([opendiscord.actions]) await opendiscord.events.get("onActionLoad").emit([opendiscord.actions])
await opendiscord.events.get("afterActionsLoaded").emit([opendiscord.actions]) await opendiscord.events.get("afterActionsLoaded").emit([opendiscord.actions])