(v4.1) Added +/-10 Minor Features & Improvements

This commit is contained in:
DJj123dj
2025-11-04 19:39:52 +01:00
parent c7b44232c4
commit e55438cc67
14 changed files with 223 additions and 55 deletions
+24
View File
@@ -222,6 +222,18 @@ export const registerVerifyBars = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
//start closing ticket
if (params.data == "reason"){
@@ -309,6 +321,18 @@ export const registerVerifyBars = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
//start closing ticket
if (params.data == "reason"){
+3
View File
@@ -209,6 +209,9 @@ export const registerActions = async () => {
const msg = await channel.send((await opendiscord.builders.messages.getSafe("opendiscord:ticket-message").build(source,{guild,channel,user,ticket})).message)
ticket.get("opendiscord:ticket-message").value = msg.id
//pin ticket message (if required)
if (generalConfig.data.system.pinFirstTicketMessage && msg.pinnable) await msg.pin("Ticket Message")
//manage stats
await opendiscord.stats.get("opendiscord:ticket").setStat("opendiscord:messages-sent",ticket.id.value,1,"increase")
+80
View File
@@ -121,6 +121,14 @@ export const registerVerifyBars = async () => {
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.delete
//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()
}
}
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:[]}))
@@ -167,6 +175,18 @@ export const registerVerifyBars = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
@@ -206,6 +226,14 @@ export const registerVerifyBars = async () => {
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.delete
//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()
}
}
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:[]}))
@@ -252,6 +280,18 @@ export const registerVerifyBars = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
@@ -295,6 +335,14 @@ export const registerVerifyBars = async () => {
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.delete
//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()
}
}
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:[]}))
@@ -341,6 +389,18 @@ export const registerVerifyBars = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
@@ -384,6 +444,14 @@ export const registerVerifyBars = async () => {
new api.ODWorker("opendiscord:permissions",1,async (instance,params,source,cancel) => {
const permissionMode = generalConfig.data.system.permissions.delete
//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()
}
}
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:[]}))
@@ -430,6 +498,18 @@ export const registerVerifyBars = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
//start deleting ticket
if (params.data == "reason"){
+2 -2
View File
@@ -277,7 +277,7 @@ const ticketButtons = () => {
instance.setMode("button")
instance.setCustomId("od:pin-ticket_"+source)
instance.setColor("gray")
instance.setEmoji("📌")
instance.setEmoji(generalConfig.data.system.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.pin"))
})
)
@@ -291,7 +291,7 @@ const ticketButtons = () => {
instance.setMode("button")
instance.setCustomId("od:unpin-ticket_"+source)
instance.setColor("gray")
instance.setEmoji("📌")
instance.setEmoji(generalConfig.data.system.pinEmoji)
instance.setLabel(lang.getTranslation("actions.buttons.unpin"))
})
)
+34 -31
View File
@@ -596,8 +596,11 @@ const ticketEmbeds = () => {
if (embedOptions.image) instance.setImage(embedOptions.image)
if (embedOptions.timestamp) instance.setTimestamp(new Date())
if (embedOptions.description) instance.setDescription(embedOptions.description)
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)
const answers = ticket.get("opendiscord:answers").value
answers.forEach((answer) => {
if (!answer.value || answer.value.length == 0) return
@@ -629,7 +632,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔒",lang.getTranslation("actions.titles.close")))
instance.setDescription(lang.getTranslation("actions.descriptions.close"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -643,7 +646,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔓",lang.getTranslation("actions.titles.reopen")))
instance.setDescription(lang.getTranslation("actions.descriptions.reopen"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -657,7 +660,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🗑️",lang.getTranslation("actions.titles.delete")))
instance.setDescription(lang.getTranslation("actions.descriptions.delete"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -671,7 +674,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👋",lang.getTranslation("actions.titles.claim")))
instance.setDescription(lang.getTranslation("actions.descriptions.claim"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -685,7 +688,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("↩️",lang.getTranslation("actions.titles.unclaim")))
instance.setDescription(lang.getTranslation("actions.descriptions.unclaim"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -697,9 +700,9 @@ const ticketEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.pin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslation("actions.descriptions.pin"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -711,9 +714,9 @@ const ticketEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.unpin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.unpin")))
instance.setDescription(lang.getTranslation("actions.descriptions.unpin"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -727,7 +730,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔄",lang.getTranslation("actions.titles.rename")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.rename",["`#"+data+"`"]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -741,7 +744,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🔀",lang.getTranslation("actions.titles.move")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.move",["`"+data.get("opendiscord:name").value+"`"]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -755,7 +758,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.add")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.add",[discord.userMention(data.id)]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -769,7 +772,7 @@ const ticketEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("👤",lang.getTranslation("actions.titles.remove")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.remove",[discord.userMention(data.id)]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -801,10 +804,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("📌",lang.getTranslation("actions.titles.pin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.pinEmoji,lang.getTranslation("actions.titles.pin")))
instance.setDescription(lang.getTranslation("actions.logs.pinDm"))
}else if (mode == "unpin"){
instance.setTitle(utilities.emojiTitle("📌",lang.getTranslation("actions.titles.unpin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.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")))
@@ -838,7 +841,7 @@ const ticketEmbeds = () => {
//TODO TRANSLATION!!!
{name:"Option"+":",value:"```"+(ticket.option.get("opendiscord:name").value)+"```",inline:false},
)
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false})
if (reason || generalConfig.data.system.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")))
@@ -856,10 +859,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("📌",lang.getTranslation("actions.titles.pin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.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("📌",lang.getTranslation("actions.titles.unpin")))
instance.setTitle(utilities.emojiTitle(generalConfig.data.system.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")))
@@ -912,7 +915,7 @@ const blacklistEmbeds = () => {
if (blacklist){
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistGetSuccess",[discord.userMention(data.id)]))
if (blacklist.reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+blacklist.reason+"```"})
if (blacklist.reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(blacklist.reason ?? "/")+"```"})
}else instance.setDescription("*"+lang.getTranslationWithParams("actions.descriptions.blacklistGetEmpty",[discord.userMention(data.id)])+"*")
})
@@ -928,7 +931,7 @@ const blacklistEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🚫",lang.getTranslation("actions.titles.blacklistAdd")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistAdd",[discord.userMention(data.id)]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -942,7 +945,7 @@ const blacklistEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("🆓",lang.getTranslation("actions.titles.blacklistRemove")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.blacklistRemove",[discord.userMention(data.id)]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -959,7 +962,7 @@ const blacklistEmbeds = () => {
instance.setTitle(utilities.emojiTitle((mode == "add") ? "🚫" : "🆓",title))
instance.setTimestamp(new Date())
instance.setDescription(text)
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -978,7 +981,7 @@ const blacklistEmbeds = () => {
instance.setAuthor(user.displayName,user.displayAvatarURL())
instance.setTimestamp(new Date())
instance.setDescription(text)
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
@@ -1082,7 +1085,7 @@ const transcriptEmbeds = () => {
instance.setTimestamp(new Date())
instance.setDescription(lang.getTranslation("transcripts.errors.error"))
instance.setFooter(lang.getTranslation("errors.descriptions.askForInfo"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```",inline:false})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
@@ -1265,7 +1268,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseEnabled")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autocloseEnabled",[time.toString()]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1279,7 +1282,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteEnabled")))
instance.setDescription(lang.getTranslationWithParams("actions.descriptions.autodeleteEnabled",[time.toString()]))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1293,7 +1296,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autocloseDisabled")))
instance.setDescription(lang.getTranslation("actions.descriptions.autocloseDisabled"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1307,7 +1310,7 @@ const autoEmbeds = () => {
instance.setColor(generalConfig.data.mainColor)
instance.setTitle(utilities.emojiTitle("⏱️",lang.getTranslation("actions.titles.autodeleteDisabled")))
instance.setDescription(lang.getTranslation("actions.descriptions.autodeleteDisabled"))
if (reason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+reason+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
@@ -1337,7 +1340,7 @@ const extraEmbeds = () => {
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+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
@@ -1364,7 +1367,7 @@ const extraEmbeds = () => {
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+"```"})
if (reason || generalConfig.data.system.alwaysShowReason) instance.addFields({name:lang.getTranslation("params.uppercase.reason")+":",value:"```"+(reason ?? "/")+"```"})
})
)
}
+12
View File
@@ -64,6 +64,18 @@ export const registerCommandResponders = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
const reason = instance.options.getString("reason",false)
+20
View File
@@ -59,10 +59,30 @@ export const registerCommandResponders = async () => {
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 (!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:"This ticket cannot be closed/deleted before a message has been sent by a user.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
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:"This ticket cannot be closed/deleted before a message has been sent by a ticket admin or support member.",customTitle:opendiscord.languages.getTranslation("errors.titles.noPermissions")})) //TODO TRANSLATION!!!
return cancel()
}
}
const reason = instance.options.getString("reason",false)
const withoutTranscript = instance.options.getBoolean("notranscript",false) ?? false
//don't allow deleteWithoutTranscript to non-global-admins when enabled
if (withoutTranscript && 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()
}
}
//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}))
+2 -2
View File
@@ -4,7 +4,7 @@
import { ODValidButtonColor, ODValidId } from "../modules/base"
import * as discord from "discord.js"
import { ODConfigManager, ODConfig, ODJsonConfig } from "../modules/config"
import { ODClientActivityStatus, ODClientActivityType } from "../modules/client"
import { ODClientActivityMode, ODClientActivityType } from "../modules/client"
import { ODRoleUpdateMode } from "../openticket/role"
/** (CONTRIBUTOR GUIDE) HOW TO ADD NEW CONFIG VARIABLES?
@@ -77,7 +77,7 @@ export interface ODJsonConfig_DefaultStatusType {
/**The type of status (e.g. playing, listening, custom, ...) */
type:Exclude<ODClientActivityType,false>,
/**The mode/status of the bot (e.g. online, invisible, idle, do not disturb) */
mode:ODClientActivityStatus
mode:ODClientActivityMode
/**The text for the status. */
text:string,
/**Additional text for the status. (visible below 'text') */
+1 -1
View File
@@ -176,7 +176,7 @@ export class ODMain {
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.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)
}
+11 -8
View File
@@ -335,10 +335,10 @@ export class ODClientManager {
* Possible activity types for the bot.
*/
export type ODClientActivityType = ("playing"|"listening"|"watching"|"custom"|false)
/**## ODClientPermissions `type`
/**## ODClientActivityMode `type`
* Possible activity statuses for the bot.
*/
export type ODClientActivityStatus = ("online"|"invisible"|"idle"|"dnd")
export type ODClientActivityMode = ("online"|"invisible"|"idle"|"dnd")
/**## ODClientActivityManager `class`
@@ -358,8 +358,10 @@ export class ODClientActivityManager {
type: ODClientActivityType = false
/**The current status text */
text: string = ""
/**The current status status */
status: ODClientActivityStatus = "online"
/**The current status mode */
mode: ODClientActivityMode = "online"
/**Additional state text */
state: string = ""
/**The timer responsible for refreshing the status. Stop it using `clearInterval(interval)` */
interval?: NodeJS.Timeout
@@ -374,10 +376,11 @@ export class ODClientActivityManager {
}
/**Update the status. When already initiated, it can take up to 10min to see the updated status in discord. */
setStatus(type:ODClientActivityType, text:string, status:ODClientActivityStatus, forceUpdate?:boolean){
setStatus(type:ODClientActivityType, text:string, mode:ODClientActivityMode, state:string, forceUpdate?:boolean){
this.type = type
this.text = text
this.status = status
this.mode = mode
this.state = state
if (forceUpdate) this.#updateClientActivity(this.type,this.text)
}
@@ -404,10 +407,10 @@ export class ODClientActivityManager {
this.manager.client.user.setPresence({
activities:[{
type:this.#getStatusTypeEnum(type),
state:undefined,
state:this.state ? this.state : undefined,
name:text,
}],
status:this.status
status:this.mode
})
}
/**Get the enum that links to the correct type */
+31 -8
View File
@@ -7,6 +7,7 @@ import { ODTicket, ODTicketManager } from "./ticket"
import { ODMessageBuildResult } from "../modules/builder"
import { ODClientManager } from "../modules/client"
import * as discord from "discord.js"
import { ODPermissionManager_Default } from "#opendiscord-types"
/**## ODTranscriptManager `class`
* This is an Open Ticket transcript manager.
@@ -21,10 +22,10 @@ export class ODTranscriptManager extends ODManager<ODTranscriptCompiler<any,null
/**Alias for the client manager. */
#client: ODClientManager
constructor(debug:ODDebugger, tickets:ODTicketManager, client:ODClientManager){
constructor(debug:ODDebugger, tickets:ODTicketManager, client:ODClientManager, permissions:ODPermissionManager_Default){
super(debug,"transcript compiler")
this.#client = client
this.collector = new ODTranscriptCollector(tickets,client)
this.collector = new ODTranscriptCollector(tickets,client,permissions)
}
}
@@ -166,10 +167,13 @@ export class ODTranscriptCollector {
#tickets: ODTicketManager
/**Alias for the client manager. */
#client: ODClientManager
/**Alias for the permissions manager. */
#permissions: ODPermissionManager_Default
constructor(tickets:ODTicketManager,client:ODClientManager){
constructor(tickets:ODTicketManager,client:ODClientManager,permissions:ODPermissionManager_Default){
this.#tickets = tickets
this.#client = client
this.#permissions = permissions
}
/**Collect all messages from a given ticket channel. It may not include all messages depending on the ratelimit. */
@@ -386,11 +390,11 @@ export class ODTranscriptCollector {
}
/**Calculate a human-readable file size. Used in transcripts. */
calculateFileSize(bytes:number): {size:number, unit:"B"|"KB"|"MB"|"GB"|"TB"} {
if (bytes >= 1000000000000) return {size:(Math.round((bytes/1000000000000)*100)/100),unit:"TB"}
if (bytes >= 1000000000) return {size:(Math.round((bytes/1000000000)*100)/100),unit:"GB"}
else if (bytes >= 1000000) return {size:(Math.round((bytes/1000000)*100)/100),unit:"MB"}
else if (bytes >= 1000) return {size:(Math.round((bytes/1000)*100)/100),unit:"KB"}
else return {size:bytes,unit:"B"}
if (bytes < 1024) return {size:Math.round(bytes),unit:"B"}
else if (bytes < 1024*1024) return {size:Math.round(bytes/1024),unit:"KB"}
else if (bytes < 1024*1024*1024) return {size:Math.round(bytes/(1024*1024)),unit:"MB"}
else if (bytes < 1024*1024*1024*1024) return {size:Math.round(bytes/(1024*1024*1024)),unit:"GB"}
else return {size:Math.round(bytes/(1024*1024*1024*1024)),unit:"TB"}
}
/**Get the `ODTranscriptEmojiData` from a discord.js component emoji. */
#handleComponentEmoji(message:discord.Message<true>, rawEmoji:discord.APIMessageComponentEmoji|null): ODTranscriptEmojiData|null {
@@ -439,6 +443,25 @@ export class ODTranscriptCollector {
return userData
}
/**Analyse the ticket for the amount of messages users & admins have sent in the ticket. */
async ticketUserMessagesAnalysis(ticket:ODTicket,guild:discord.Guild,channel:discord.GuildTextBasedChannel){
const messages = await this.collectAllMessages(ticket,{bots:true,client:true,users:true})
if (!messages) return null
const parsedMessages = await this.convertMessagesToTranscriptData(messages)
let userMessages = 0
let adminMessages = 0
for (const msg of parsedMessages){
if (msg.author.tag || msg.author.id == this.#client.client.user.id) continue
const user = await this.#client.fetchUser(msg.author.id)
if (!user) continue
const isAdmin = this.#permissions.hasPermissions("support",await this.#permissions.getPermissions(user,channel,guild))
if (isAdmin) adminMessages++
else userMessages++
}
return {userMessages,adminMessages,totalMessages:userMessages+adminMessages}
}
}
/**## ODTranscriptCollectorIncludeSettings `interface`
+1 -1
View File
@@ -226,7 +226,7 @@ async function quickSetupLogin(token:string): Promise<api.ODClientManager|null>
return new Promise(async (resolve) => {
try{
client.readyListener = async () => {
client.activity.setStatus("custom","Configuring Open Ticket...","idle",true)
client.activity.setStatus("custom","Configuring Open Ticket...","idle","",true)
resolve(client)
}
const success = await client.login(true)
+1 -1
View File
@@ -31,7 +31,7 @@ export const loadAllStartScreenComponents = async () => {
//STATS
opendiscord.startscreen.add(new api.ODStartScreenPropertiesCategoryComponent("opendiscord:stats",2,"startup info",[
{key:"status",value:ansis.bold(opendiscord.client.activity.getStatusType())+opendiscord.client.activity.text+" ("+opendiscord.client.activity.status+")"},
{key:"status",value:ansis.bold(opendiscord.client.activity.getStatusType())+opendiscord.client.activity.text+" ("+opendiscord.client.activity.mode+")"},
{key:"options",value:"loaded "+ansis.bold(opendiscord.options.getLength().toString())+" options!"},
{key:"panels",value:"loaded "+ansis.bold(opendiscord.panels.getLength().toString())+" panels!"},
{key:"tickets",value:"loaded "+ansis.bold(opendiscord.tickets.getLength().toString())+" tickets!"},
+1 -1
View File
@@ -412,7 +412,7 @@ const main = async () => {
opendiscord.log("Loading client activity...","system")
if (opendiscord.defaults.getDefault("clientActivityLoading")){
//load config status
if (generalConfig.data.status && generalConfig.data.status.enabled) opendiscord.client.activity.setStatus(generalConfig.data.status.type,generalConfig.data.status.text,generalConfig.data.status.mode)
if (generalConfig.data.status && generalConfig.data.status.enabled) opendiscord.client.activity.setStatus(generalConfig.data.status.type,generalConfig.data.status.text,generalConfig.data.status.mode,generalConfig.data.status.state)
}
await opendiscord.events.get("onClientActivityLoad").emit([opendiscord.client.activity,opendiscord.client])
await opendiscord.events.get("afterClientActivityLoaded").emit([opendiscord.client.activity,opendiscord.client])