diff --git a/README.md b/README.md index c66c5c6..fad8a54 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ Open Ticket -[![discord](https://img.shields.io/badge/discord-join%20our%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-3.2.2-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v3.2.2) [![discord.js](https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm)]() [![license](https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) [![stars](https://img.shields.io/github/stars/djj123dj/open-ticket?color=yellow&label=stars&logo=github&style=flat-square)](https://docs.openticket.dj-dj.be) +[![discord](https://img.shields.io/badge/discord-join%20our%20server-5865F2.svg?style=flat-square&logo=discord)](https://discord.com/invite/26vT9wt3n3) [![version](https://img.shields.io/badge/version-3.3.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v3.3.0) [![discord.js](https://img.shields.io/badge/discord.js-v14-CB3837.svg?style=flat-square&logo=npm)]() [![license](https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) [![stars](https://img.shields.io/github/stars/djj123dj/open-ticket?color=yellow&label=stars&logo=github&style=flat-square)](https://docs.openticket.dj-dj.be) ### Open Ticket Open Ticket is of the most customisable discord ticket bots of all time! @@ -13,7 +13,7 @@ Take a look at all the features and discover the possibilities! ## Features - **🎉 NEW! html transcripts!** - 🔒 close, ❌ delete & ✅ re-open tickets -- 🇬🇧 translation in 12 different languages +- 🇬🇧 translation in 14 different languages - 📄 very advanced customisation - 🆗 buttons or 🔽 dropdowns! - 🆒 plugins @@ -57,9 +57,11 @@ Translators |Danish |the_gamer#5095 | |Portuguese |QuirAddon#9778 | |Russian |Apexo#0723 | +|Turkish |Hydrâelčhâvø#1575 | +|Polish |MKevas#8311 | ## links -current version: _v3.2.2_ +current version: _v3.3.0_
changelog: [click here](https://docs.openticket.dj-dj.be/other/changelog)
documentation: [click here](https://docs.openticket.dj-dj.be/quick-start) diff --git a/commands/add.js b/commands/add.js index f88c28a..0092579 100644 --- a/commands/add.js +++ b/commands/add.js @@ -44,7 +44,7 @@ module.exports = () => { }) - if (!DISABLE.commands.slash.add) client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.add) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "add") return const user = interaction.options.getUser("user") @@ -55,14 +55,16 @@ module.exports = () => { return } + await interaction.deferReply() + interaction.channel.messages.fetchPinned().then(msglist => { var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value interaction.channel.permissionOverwrites.create(user.id, { ViewChannel:true, AddReactions:true,AttachFiles:true, EmbedLinks:true, SendMessages:true}) - interaction.reply({embeds:[bot.embeds.commands.addEmbed(user,interaction.user)]}) + interaction.editReply({embeds:[bot.embeds.commands.addEmbed(user,interaction.user)]}) var loguser = user log("command","someone used the 'add' command",[{key:"user",value:interaction.user.tag}]) diff --git a/commands/change.js b/commands/change.js index 5400e05..2ce1f36 100644 --- a/commands/change.js +++ b/commands/change.js @@ -27,13 +27,14 @@ module.exports = () => { const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - var newtype = msg.content.split(config.prefix+"change")[1].substring(1) - if (!newtype) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) - - const newTicket = require("../core/utils/configParser").getTicketById(newtype) const list = [] config.options.forEach((o) => list.push(o.id)) - if (!newTicket) return bot.errorLog.invalidIdChooseFromList(list) + + var newtype = msg.content.split(config.prefix+"change")[1].substring(1) + if (!newtype) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(list,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) + + const newTicket = require("../core/utils/configParser").getTicketById(newtype) + if (!newTicket) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(list,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) /**@type {String} */ var chName = msg.channel.name @@ -55,7 +56,7 @@ module.exports = () => { }) }) - if (!DISABLE.commands.slash.change) client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.change) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "change") return @@ -65,21 +66,26 @@ module.exports = () => { return } - //interaction.deferReply() - interaction.channel.messages.fetchPinned().then(async msglist => { + await interaction.deferReply() + interaction.channel.messages.fetchPinned().then(async (msglist) => { + /**@type {discord.Message} */ var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - var newtype = interaction.options.getString("type",true) - if (!newtype) return interaction.reply({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) - - const newTicket = require("../core/utils/configParser").getTicketById(newtype,true) const list = [] config.options.forEach((o) => list.push(o.id)) - if (!newTicket) return bot.errorLog.invalidIdChooseFromList(list) + var newtype = interaction.options.getString("type",true) + const newTicket = require("../core/utils/configParser").getTicketById(newtype,true) + + if (!newTicket) return interaction.editReply({embeds:[bot.errorLog.invalidIdChooseFromList(list,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"change `")]}) + + /**@type {discord.PermissionOverwriteManager} */ + const prePermsManager = interaction.channel.permissionOverwrites + const prePerms = prePermsManager.cache + /**@type {String} */ var chName = interaction.channel.name const splitted = chName.split("-") @@ -91,8 +97,25 @@ module.exports = () => { if (parent && parent.type == discord.ChannelType.GuildCategory) interaction.channel.setParent(parent) } + await prePermsManager.set(prePerms) interaction.channel.setName(newTicket.channelprefix+name) - interaction.reply({embeds:[bot.embeds.commands.changeEmbed(interaction.user,newtype)]}) + + var newHiddendata = hiddendata.data + newHiddendata.find((value,index) => { + if (value.key == "type"){ + newHiddendata[index] = {key:"type",value:newtype} + } + }) + + const prevDescription = bot.hiddenData.removeHiddenData(firstmsg.embeds[0].description).description + const newData = bot.hiddenData.writeHiddenData("ticketdata",newHiddendata) + const newDescription = prevDescription+newData + const newEmbed = new discord.EmbedBuilder(firstmsg.embeds[0].data) + .setDescription(newDescription) + + firstmsg.edit({embeds:[newEmbed]}) + + interaction.editReply({embeds:[bot.embeds.commands.changeEmbed(interaction.user,newtype)]}) log("command","someone used the 'change' command",[{key:"user",value:interaction.user.tag}]) log("system","ticket type changed",[{key:"user",value:interaction.user.tag},{key:"ticket",value:name},{key:"newtype",value:newtype}]) diff --git a/commands/claim.js b/commands/claim.js index ff17fc2..a608d39 100644 --- a/commands/claim.js +++ b/commands/claim.js @@ -5,6 +5,8 @@ const config = bot.config const log = bot.errorLog.log const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") +const embed = discord.EmbedBuilder +const storage = bot.storage const APIEvents = require("../core/api/modules/events") const DISABLE = require("../core/api/api.json").disable @@ -25,27 +27,39 @@ module.exports = () => { } msg.channel.messages.fetchPinned().then(msglist => { + /**@type {discord.Message} */ var firstmsg = msglist.last() if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) + const hdraw = bot.hiddenData.removeHiddenData(firstmsg.embeds[0].description) + const hiddendata = hdraw.hiddenData const ticketId = hiddendata.data.find(d => d.key == "type").value + hiddendata.data.push({key:"claimedby",value:interaction.user.id}) + storage.set("claimData",interaction.channel.id,interaction.user.id) - //msg.channel.send({embeds:[bot.embeds.commands.claimEmbed(claimingUser,msg.author)]}) - msg.channel.send({embeds:[bot.errorLog.warning("Coming soon!","This feature isn't ready yet!\nIt will become active in the next update!")]}) + const newEmbed = new embed(firstmsg.embeds[0].data) + .setFooter({text:"claimed by: "+interaction.user.tag,iconURL:interaction.user.displayAvatarURL()}) + .setDescription(hdraw.description+bot.hiddenData.writeHiddenData(hiddendata.type,hiddendata.data)) + + if (!firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim],embeds:[newEmbed]}) + + }else if (firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim],embeds:[newEmbed]}) + } + + msg.channel.send({embeds:[bot.embeds.commands.claimEmbed(claimingUser,msg.author)]}) - var loguser = claimingUser log("command","someone used the 'claim' command",[{key:"user",value:msg.author.tag}]) log("system","user claimed to ticket",[{key:"user",value:msg.author.tag},{key:"ticket",value:msg.channel.name},{key:"claimed_user",value:claimingUser.tag}]) const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - //APIEvents.onTicketAdd(msg.author,loguser,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) - //APIEvents.onCommand("add",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date()) - }) - + APIEvents.onTicketClaim(msg.author,loguser,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) + APIEvents.onCommand("claim",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date()) + }) }) - if (!DISABLE.commands.slash.claim) client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.claim) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "claim") return const user = interaction.options.getUser("user",false) ? interaction.options.getUser("user",true) : interaction.user @@ -56,25 +70,38 @@ module.exports = () => { return } + await interaction.deferReply() + interaction.channel.messages.fetchPinned().then(msglist => { + /**@type {discord.Message} */ var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) + const hdraw = bot.hiddenData.removeHiddenData(firstmsg.embeds[0].description) + const hiddendata = hdraw.hiddenData const ticketId = hiddendata.data.find(d => d.key == "type").value - //interaction.reply({embeds:[bot.embeds.commands.claimEmbed(user,interaction.user)]}) - interaction.reply({embeds:[bot.errorLog.warning("Coming soon!","This feature isn't ready yet!\nIt will become active in the next update!")]}) + hiddendata.data.push({key:"claimedby",value:interaction.user.id}) + storage.set("claimData",interaction.channel.id,interaction.user.id) + + const newEmbed = new embed(firstmsg.embeds[0].data) + .setFooter({text:"claimed by: "+user.tag,iconURL:user.displayAvatarURL()}) + .setDescription(hdraw.description+bot.hiddenData.writeHiddenData(hiddendata.type,hiddendata.data)) + + if (!firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim],embeds:[newEmbed]}) + + }else if (firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim],embeds:[newEmbed]}) + } + + interaction.editReply({embeds:[bot.embeds.commands.claimEmbed(user,interaction.user)]}) - var loguser = user log("command","someone used the 'claim' command",[{key:"user",value:interaction.user.tag}]) - log("system","user claimed to ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name},{key:"claimed_user",value:loguser.tag}]) + log("system","user claimed to ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name},{key:"claimed_user",value:user.tag}]) const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - //APIEvents.onTicketAdd(interaction.user,loguser,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) - //APIEvents.onCommand("add",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date()) - + APIEvents.onTicketClaim(interaction.user,user,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) + APIEvents.onCommand("claim",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date()) }) - - }) } \ No newline at end of file diff --git a/commands/close.js b/commands/close.js index 15d36f9..5c8d43a 100644 --- a/commands/close.js +++ b/commands/close.js @@ -44,7 +44,7 @@ module.exports = () => { } }) - require("../core/ticketActions/ticketCloser").NEWcloseTicket(msg.member,msg.channel,prefix,"close",reason,true) + require("../core/ticketActions/ticketCloser").closeManager(msg.member,msg.channel,prefix,"close",reason,true) log("command","someone used the 'close' command",[{key:"user",value:msg.author.tag}]) APIEvents.onCommand("close",true,msg.author,msg.channel,msg.guild,new Date()) @@ -54,7 +54,7 @@ module.exports = () => { }) - if (!DISABLE.commands.slash.close) client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.close) client.on("interactionCreate",async(interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "close") return @@ -62,16 +62,18 @@ module.exports = () => { const reason = interaction.options.getString("reason") ? interaction.options.getString("reason") : false + await interaction.deferReply() + interaction.channel.messages.fetchPinned().then(msglist => { var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - if (hiddendata.data.find(h => h.key == "pendingdelete")) return interaction.reply({embeds:[bot.errorLog.warning("Warning!","You can't close a ticket while it's being deleted!")]}) + if (hiddendata.data.find(h => h.key == "pendingdelete")) return interaction.editReply({embeds:[bot.errorLog.warning("Warning!","You can't close a ticket while it's being deleted!")]}) const descriptionReason = reason ? "**"+l.messages.reason+":** "+reason : false - interaction.reply({embeds:[bot.embeds.commands.closeEmbed(interaction.user,descriptionReason)],components:[bot.buttons.close.closeCommandRow]}) + interaction.editReply({embeds:[bot.embeds.commands.closeEmbed(interaction.user,descriptionReason)],components:[bot.buttons.close.closeCommandRow]}) var name = interaction.channel.name var prefix = "" @@ -82,7 +84,7 @@ module.exports = () => { } }) - require("../core/ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close",false,true) + require("../core/ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"close",false,true) log("command","someone used the 'close' command",[{key:"user",value:interaction.user.tag}]) APIEvents.onCommand("close",true,interaction.user,interaction.channel,interaction.guild,new Date()) diff --git a/commands/delete.js b/commands/delete.js index 4b5f5b1..018b69a 100644 --- a/commands/delete.js +++ b/commands/delete.js @@ -38,7 +38,7 @@ module.exports = () => { } }) - require("../core/ticketActions/ticketCloser").NEWcloseTicket(msg.member,msg.channel,prefix,"delete",false,true) + require("../core/ticketActions/ticketCloser").closeManager(msg.member,msg.channel,prefix,"delete",false,true) log("command","someone used the 'delete' command",[{key:"user",value:msg.author.tag}]) APIEvents.onCommand("delete",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date()) @@ -47,25 +47,25 @@ module.exports = () => { }) - if (!DISABLE.commands.slash.delete) client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.delete) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "delete") return - //interaction.deferReply() - if (!interaction.guild) return if (!permsChecker.command(interaction.user.id,interaction.guild.id)){ permsChecker.sendUserNoPerms(interaction.user) return interaction.reply({embeds:[bot.errorLog.noPermsDelete(interaction.user)]}) } + await interaction.deferReply() + interaction.channel.messages.fetchPinned().then(msglist => { var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - interaction.reply({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) + interaction.editReply({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) var name = interaction.channel.name var prefix = "" @@ -76,7 +76,7 @@ module.exports = () => { } }) - require("../core/ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true) + require("../core/ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"delete",false,true) log("command","someone used the 'delete' command",[{key:"user",value:interaction.user.tag}]) APIEvents.onCommand("delete",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date()) diff --git a/commands/help.js b/commands/help.js index ad78252..cf31a32 100644 --- a/commands/help.js +++ b/commands/help.js @@ -15,11 +15,14 @@ module.exports = () => { const prefix = config.system.showSlashcmdsInHelp ? "/" : config.prefix const helpEmbed = new discord.EmbedBuilder() - .setColor(config.main_color) + .setColor(config.color) .setTitle("❔ "+l.helpMenu.title) - const header = config.system.ticket_channel ? l.helpMenu.header1.replace("{0}","<#"+config.system.ticket_channel+">") : l.helpMenu.header2 - helpEmbed.setDescription(header+"`"+prefix+msgName+" ` ➜ _"+l.helpMenu.msgCmd+"_\n\n`"+prefix+"rename ` ➜ _"+l.helpMenu.renameCmd+"_\n`"+prefix+"close` ➜ _"+l.helpMenu.closeCmd+"_\n`"+prefix+"delete` ➜ _"+l.helpMenu.deleteCmd+"_\n`"+prefix+"reopen` ➜ _"+l.helpMenu.reopenCmd+"_\n\n`"+prefix+"add ` ➜ _"+l.helpMenu.addCmd+"_\n`"+prefix+"remove ` ➜ _"+l.helpMenu.removeCmd+"_\n\n`"+prefix+"change ` ➜ _Change ticket type._") + const header = l.helpMenu.header2 + helpEmbed.setDescription(header+"`"+prefix+msgName+" ` ➜ _"+l.helpMenu.msgCmd+"_\n\n`"+prefix+"rename ` ➜ _"+l.helpMenu.renameCmd+"_\n`"+prefix+"close [reason]` ➜ _"+l.helpMenu.closeCmd+"_\n`"+prefix+"delete` ➜ _"+l.helpMenu.deleteCmd+"_\n`"+prefix+"reopen` ➜ _"+l.helpMenu.reopenCmd+"_\n\n`"+prefix+"add ` ➜ _"+l.helpMenu.addCmd+"_\n`"+prefix+"remove ` ➜ _"+l.helpMenu.removeCmd+"_\n\n`"+prefix+"change ` ➜ _"+l.helpMenu.changeCmd+"_\n`"+prefix+"claim [user]` ➜ _"+l.helpMenu.claimCmd+"_\n`"+prefix+"unclaim` ➜ _"+l.helpMenu.unclaimCmd+"_") + helpEmbed.addFields([ + {name:"Autoclose",value:l.helpMenu.autocloseCmd+"\n`"+prefix+"autoclose enable `\n`"+prefix+"autoclose disable`"} + ]) var otherprefix = prefix.endsWith(" ") ? prefix.substring(0,prefix.length-1) : prefix diff --git a/commands/remove.js b/commands/remove.js index e5f8a4a..8ef5667 100644 --- a/commands/remove.js +++ b/commands/remove.js @@ -55,14 +55,16 @@ module.exports = () => { return } + await interaction.deferReply() + await interaction.channel.messages.fetchPinned().then(msglist => { var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value interaction.channel.permissionOverwrites.delete(user.id) - interaction.reply({embeds:[bot.embeds.commands.removeEmbed(user,interaction.user)]}) + interaction.editReply({embeds:[bot.embeds.commands.removeEmbed(user,interaction.user)]}) var loguser = user diff --git a/commands/rename.js b/commands/rename.js index 6741658..4d35f36 100644 --- a/commands/rename.js +++ b/commands/rename.js @@ -53,7 +53,7 @@ module.exports = () => { }) - if (!DISABLE.commands.slash.rename) client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.rename) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "rename") return @@ -63,11 +63,11 @@ module.exports = () => { return } - //interaction.deferReply() + await interaction.deferReply() interaction.channel.messages.fetchPinned().then(msglist => { var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value @@ -84,7 +84,7 @@ module.exports = () => { if (!prefix) prefix = "noprefix-" interaction.channel.setName(prefix+newname) - interaction.reply({embeds:[bot.embeds.commands.renameEmbed(interaction.user,prefix+newname)]}) + interaction.editReply({embeds:[bot.embeds.commands.renameEmbed(interaction.user,prefix+newname)]}) log("command","someone used the 'rename' command",[{key:"user",value:interaction.user.tag}]) log("system","ticket renamed",[{key:"user",value:interaction.user.tag},{key:"ticket",value:name},{key:"newname",value:newname}]) diff --git a/commands/reopen.js b/commands/reopen.js index 3c86a0f..52793fd 100644 --- a/commands/reopen.js +++ b/commands/reopen.js @@ -37,17 +37,17 @@ module.exports = () => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "reopen") return - //interaction.deferReply() + await interaction.deferReply() interaction.channel.messages.fetchPinned().then(async msglist => { var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - if (hiddendata.data.find(h => h.key == "pendingdelete")) return interaction.reply({embeds:[bot.errorLog.warning("Warning!","You can't re-open a ticket while it's being deleted!")]}) + if (hiddendata.data.find(h => h.key == "pendingdelete")) return interaction.editReply({embeds:[bot.errorLog.warning("Warning!","You can't re-open a ticket while it's being deleted!")]}) - await interaction.reply({embeds:[bot.embeds.commands.reopenEmbed(interaction.user)],components:[bot.buttons.close.openRowNormal]}) + await interaction.editReply({embeds:[bot.embeds.commands.reopenEmbed(interaction.user)],components:[bot.buttons.close.openRowNormal]}) require("../core/ticketActions/ticketReopener").reopenTicket(interaction.guild,interaction.channel,interaction.user) diff --git a/commands/ticket.js b/commands/ticket.js index 5f8e2bc..dc9b57b 100644 --- a/commands/ticket.js +++ b/commands/ticket.js @@ -30,8 +30,8 @@ module.exports = () => { const id = msg.content.split(config.prefix+"msg")[1].substring(1) ? msg.content.split(config.prefix+"msg")[1].substring(1) : false - if (!id) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"msg `")]}) - if (!msgIds.includes(id)) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds)]}) + if (!id) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"msg `")]}) + if (!msgIds.includes(id)) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds,l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"msg `")]}) const {embed,componentRows} = require("../core/utils/getEmbed").createEmbed(id) diff --git a/commands/unclaim.js b/commands/unclaim.js index be01a4d..e6821ea 100644 --- a/commands/unclaim.js +++ b/commands/unclaim.js @@ -5,6 +5,8 @@ const config = bot.config const log = bot.errorLog.log const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") +const embed = discord.EmbedBuilder +const storage = bot.storage const APIEvents = require("../core/api/modules/events") const DISABLE = require("../core/api/api.json").disable @@ -21,31 +23,52 @@ module.exports = () => { return } + const unclaimuser = storage.get("claimData",msg.channel.id) + if (!unclaimuser || unclaimuser == "false") return msg.channel.send({embeds:[bot.errorLog.serverError("This ticket isn't claimed yet!")]}) + msg.channel.messages.fetchPinned().then(msglist => { + /**@type {discord.Message} */ var firstmsg = msglist.last() if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) - const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) + const hdraw = bot.hiddenData.removeHiddenData(firstmsg.embeds[0].description) + const hiddendata = hdraw.hiddenData const ticketId = hiddendata.data.find(d => d.key == "type").value + hiddendata.data.push({key:"claimedby",value:"false"}) + storage.set("claimData",interaction.channel.id,"false") - //msg.channel.send({embeds:[bot.embeds.commands.unclaimEmbed(msg.author)]}) - msg.channel.send({embeds:[bot.errorLog.warning("Coming soon!","This feature isn't ready yet!\nIt will become active in the next update!")]}) - - var loguser = msg.author - log("command","someone used the 'unclaim' command",[{key:"user",value:msg.author.tag}]) - log("system","user unclaimed from ticket",[{key:"user",value:msg.author.tag},{key:"ticket",value:msg.channel.name},{key:"unclaimed_user",value:msg.author.tag}]) + const newEmbed = new embed(firstmsg.embeds[0].data) + .setDescription(hdraw.description+bot.hiddenData.writeHiddenData(hiddendata.type,hiddendata.data)) const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - //APIEvents.onTicketAdd(msg.author,loguser,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) - //APIEvents.onCommand("add",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date()) - }) - + if (ticketData && ticketData.autoclose.enable){ + const footerText = l.commands.autocloseTitle.replace("{0}",ticketData.autoclose.inactiveHours+"h") + newEmbed.setFooter({text:footerText}) + }else{ + newEmbed.setFooter(null) + } + + if (!firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal],embeds:[newEmbed]}) + + }else if (firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabled],embeds:[newEmbed]}) + } + + msg.channel.send({embeds:[bot.embeds.commands.unclaimEmbed(msg.author)]}) + + log("command","someone used the 'unclaim' command",[{key:"user",value:msg.author.tag}]) + log("system","user unclaimed from ticket",[{key:"user",value:msg.author.tag},{key:"ticket",value:msg.channel.name},{key:"unclaimed_user",value:unclaimuser}]) + + + APIEvents.onTicketUnclaim(msg.author,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) + APIEvents.onCommand("unclaim",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date()) + }) }) - if (!DISABLE.commands.slash.unclaim) client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.unclaim) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "unclaim") return - const user = interaction.user if (!interaction.guild) return if (!permsChecker.command(interaction.user.id,interaction.guild.id)){ @@ -53,25 +76,48 @@ module.exports = () => { return } + await interaction.deferReply() + + const unclaimuser = storage.get("claimData",interaction.channel.id) + if (!unclaimuser || unclaimuser == "false") return interaction.editReply({embeds:[bot.errorLog.serverError("This ticket isn't claimed yet!")]}) + + interaction.channel.messages.fetchPinned().then(msglist => { + /**@type {discord.Message} */ var firstmsg = msglist.last() - if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.reply({embeds:[bot.errorLog.notInATicket]}) - const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) + const hdraw = bot.hiddenData.removeHiddenData(firstmsg.embeds[0].description) + const hiddendata = hdraw.hiddenData const ticketId = hiddendata.data.find(d => d.key == "type").value - //interaction.reply({embeds:[bot.embeds.commands.unclaimEmbed(interaction.user)]}) - interaction.reply({embeds:[bot.errorLog.warning("Coming soon!","This feature isn't ready yet!\nIt will become active in the next update!")]}) - - var loguser = user - log("command","someone used the 'unclaim' command",[{key:"user",value:interaction.user.tag}]) - log("system","user unclaimed from ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name},{key:"unclaimed_user",value:loguser.tag}]) + hiddendata.data.push({key:"claimedby",value:"false"}) + storage.set("claimData",interaction.channel.id,"false") + + const newEmbed = new embed(firstmsg.embeds[0].data) + .setDescription(hdraw.description+bot.hiddenData.writeHiddenData(hiddendata.type,hiddendata.data)) const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) - //APIEvents.onTicketAdd(interaction.user,loguser,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) - //APIEvents.onCommand("add",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date()) - - }) + if (ticketData && ticketData.autoclose.enable){ + const footerText = l.commands.autocloseTitle.replace("{0}",ticketData.autoclose.inactiveHours+"h") + newEmbed.setFooter({text:footerText}) + }else{ + newEmbed.setFooter(null) + } - + if (!firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal],embeds:[newEmbed]}) + + }else if (firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabled],embeds:[newEmbed]}) + } + + interaction.editReply({embeds:[bot.embeds.commands.unclaimEmbed(interaction.user)]}) + + log("command","someone used the 'unclaim' command",[{key:"user",value:interaction.user.tag}]) + log("system","user unclaimed from ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name},{key:"unclaimed_user",value:unclaimuser}]) + + APIEvents.onTicketUnclaim(interaction.user,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) + APIEvents.onCommand("unclaim",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date()) + }) }) } \ No newline at end of file diff --git a/config.json b/config.json index 756b3e4..a2ec616 100644 --- a/config.json +++ b/config.json @@ -1,10 +1,13 @@ { - "main_color":"#ffffff", - "server_id":"server id (for slash cmds)", - "auth_token":"auth token", - "main_adminroles":["discord role id"], + "color":"#ffffff", + "serverId":"server id (for slash cmds)", + "token":{ + "value":"insert your bot token here", + "fromENV":false + }, + "adminRoles":["discord role id"], "prefix":"!ticket ", - "languagefile":"english", + "languageFile":"english", "status":{ "enabled":true, @@ -13,13 +16,11 @@ }, "system":{ - "ticket_channel":"channel id", - "max_allowed_tickets":3, - "enable_DM_Messages":true, + "maxAmountOfTickets":3, + "dmMessages":false, - "has@everyoneaccess":false, - "member_role":"member role (this role doesn't have access to tickets)", - "closeMode":"adminonly or normal (select one of the 2)", + "memberRole":"member role (leave empty if you have no member role)", + "closeMode":"adminonly OR normal (select one!)", "transcripts":"!!!! ALL SETTINGS FOR TRANSCRIPTS ARE LOCATED IN: transcriptconfig.json !!!!", @@ -57,6 +58,11 @@ "closedCategory":{ "enable":false, "id":"category id" + }, + + "autoclose":{ + "enable":false, + "inactiveHours":24 } }, @@ -95,7 +101,7 @@ "dropdown":false, "enableFooter":false, - "footer":"Open Ticket v3.2.2 - I'm a footer!", + "footer":"Open Ticket v3.3.0 - I'm a footer!", "enableThumbnail":false, "thumbnail":"https://www.example.com/catmemes/cat.png", diff --git a/core/api/modules/base.js b/core/api/modules/base.js deleted file mode 100644 index 8d4921e..0000000 --- a/core/api/modules/base.js +++ /dev/null @@ -1,8 +0,0 @@ -/** FOR DEVELOPERS ONLY!! - * Don't change anything in this file before reading the documentation! - * visit the api documentation at https://docs.openticket.dj-dj.be - */ - - -exports.embeddedMode = false -exports.clientLocation = require("../../../index").client \ No newline at end of file diff --git a/core/checker.js b/core/checker.js index e1c30b7..23f48be 100644 --- a/core/checker.js +++ b/core/checker.js @@ -53,9 +53,9 @@ exports.checker = async () => { /**@param {String} value */ const checkToken = (value) => { if (value.length < 40){ - createError("'auth_token' | your token is invalid") + createError("'token/value' | your token is invalid") } - if (value.includes(" ")) createError("'auth_token' | your token includes spaces!") + if (value.includes(" ")) createError("'token/value' | your token includes spaces!") } /**@param {String} value @param {String} path */ @@ -119,24 +119,29 @@ exports.checker = async () => { if (type == "boolean"){ if (typeof value != "boolean"){ createError("'"+path+"' | invalid type, this must be a boolean!") - } + return true + }else return false }else if (type == "number"){ if (typeof value != "number"){ createError("'"+path+"' | invalid type, this must be a number!") - } + return true + }else return false }else if (type == "string"){ if (typeof value != "string"){ createError("'"+path+"' | invalid type, this must be a string!") - } + return true + }else return false }else if (type == "array"){ if (!Array.isArray(value)){ createError("'"+path+"' | invalid type, this must be an array!") - } + return true + }else return false }else if (type == "object"){ if (typeof value != "object"){ createError("'"+path+"' | invalid type, this must be an object!") - } - } + return true + }else return false + }else return false } const checkButtonColor = (value,path) => { @@ -256,6 +261,14 @@ exports.checker = async () => { createError("'"+path+"/closedCategory' | there is no closedCategory object!") } + //autoclose + if (option.autoclose){ + checkType(option.autoclose.enable,"boolean",path/"/autoclose/enable") + checkType(option.autoclose.inactiveHours,"number",path/"/autoclose/id") + }else{ + createError("'"+path+"/autoclose' | there is no autoclose object!") + } + }else if (type == "website"){ //url checkType(option.url,"string",path+"/url") @@ -337,17 +350,19 @@ exports.checker = async () => { } //OPTIONS!!! - var counter = 0 - input.options.forEach((option) => {if (!configParser.optionExists(option)){counter++}}) + if (checkType(input.options,"array",path+"/options")){ + var counter = 0 + input.options.forEach((option) => {if (!configParser.optionExists(option)){counter++}}) - if (counter == input.options.length){ - createWarn("'"+path+"/options' | insert the option ids here!") - }else{ - input.options.forEach((option,index) => { - if (!configParser.optionExists(option)){ - createWarn("'"+path+"/options:"+index+"' | this option doesnt exist!") - } - }) + if (counter == input.options.length){ + createWarn("'"+path+"/options' | insert the option ids here!") + }else{ + input.options.forEach((option,index) => { + if (!configParser.optionExists(option)){ + createWarn("'"+path+"/options:"+index+"' | this option doesnt exist!") + } + }) + } } //other @@ -393,26 +408,26 @@ exports.checker = async () => { //--------------------------| //--------------------------| - var configArray = ["main_color","server_id","auth_token","main_adminroles","prefix","languagefile","status","system","options","messages"] + var configArray = ["color","serverId","token","adminRoles","prefix","languageFile","status","system","options","messages"] configArray.forEach((item) => { if (config[item] == undefined){ throw new Error("\n\nMAIN ERROR: the item '"+item+"' doesn't exist in config.json") } }) - checkHexColor(config.main_color,"main_color") - checkDiscord("serverid",config.server_id,"server_id") + checkHexColor(config.color,"main_color") + checkDiscord("serverid",config.serverId,"server_id") - if (!require("./api/api.json").disable.checkerjs.token) checkToken(config.auth_token) + if (!require("./api/api.json").disable.checkerjs.token && !config.token.fromENV) checkToken(config.token.value) - checkType(config.main_adminroles,"array","/main_adminroles") - checkDiscordArray("roleid",config.main_adminroles,"main_adminroles") + checkType(config.adminRoles,"array","/main_adminroles") + checkDiscordArray("roleid",config.adminRoles,"main_adminroles") checkString(config.prefix,1,15,"prefix","prefix") //languagefile - checkType(config.languagefile,"string","languagefile") - const lf = config.languagefile + checkType(config.languageFile,"string","languagefile") + const lf = config.languageFile - if (!lf.startsWith("custom") && !lf.startsWith("english") && !lf.startsWith("dutch") && !lf.startsWith("romanian") && !lf.startsWith("german") && !lf.startsWith("arabic") && !lf.startsWith("spanish") && !lf.startsWith("portuguese") && !lf.startsWith("french") && !lf.startsWith("italian") && !lf.startsWith("czech") && !lf.startsWith("danish") && !lf.startsWith("russian")){ + if (!lf.startsWith("custom") && !lf.startsWith("english") && !lf.startsWith("dutch") && !lf.startsWith("romanian") && !lf.startsWith("german") && !lf.startsWith("arabic") && !lf.startsWith("spanish") && !lf.startsWith("portuguese") && !lf.startsWith("french") && !lf.startsWith("italian") && !lf.startsWith("czech") && !lf.startsWith("danish") && !lf.startsWith("russian") && !lf.startsWith("turkish") && !lf.startsWith("polish")){ createError("'languagefile' | invalid language, more info in the wiki") } @@ -430,28 +445,18 @@ exports.checker = async () => { //system: - //ticket channel - if (config.system.ticket_channel){ - if (config.system.ticket_channel.length < 16 || config.system.ticket_channel.length > 20 || !/^\d+$/.test(config.system.ticket_channel)){ - createError("'system/ticket_channel' | this channel id is invalid") - } - }else createWarn("'"+path+"' | you have no ticket channel selected!") - //max tickets - checkType(config.system.max_allowed_tickets,"number","system/max_allowed_tickets") + checkType(config.system.maxAmountOfTickets,"number","system/maxAmountOfTickets") //enableDMmessages - checkType(config.system.enable_DM_Messages,"boolean","system/enable_DM_Messages") + checkType(config.system.dmMessages,"boolean","system/dmMessages") - //has@everyoneaccess - checkType(config.system["has@everyoneaccess"],"boolean","system/has@everyoneaccess") - - //member_role - checkType(config.system.member_role,"string","system/member_role") - if (config.system.member_role != "" && config.system.member_role != " " && config.system.member_role != "false" && config.system.member_role != "null" && config.system.member_role != "0"){ - checkDiscord("roleid",config.system.member_role,"system/member_role") + //memberRole + checkType(config.system.memberRole,"string","system/memberRole") + if (config.system.memberRole && ![" ","0","false","null","undefined"].includes(config.system.memberRole)){ + checkDiscord("roleid",config.system.memberRole,"system/memberRole") }else{ - createWarn("'system/member_role' | You don't have a member role, but it's recommended!") + createWarn("'system/memberRole' | You don't have a member role, but it's recommended!") } //closemode diff --git a/core/dynamicdatabase/dynamicfiles/database.js b/core/dynamicdatabase/dynamicfiles/database.js index d0b167a..866ef67 100644 --- a/core/dynamicdatabase/dynamicfiles/database.js +++ b/core/dynamicdatabase/dynamicfiles/database.js @@ -47,6 +47,17 @@ exports.get = (category,key) => { const result = tempresult ? tempresult.value : false return result } + +/** + * @param {String} category + * @returns {[{key:String,value:String}]|false} + */ +exports.getCategory = (category) => { + const currentData = getData() + const result = currentData.filter((v) => v.category == category) + return result +} + /** * @param {String} category * @param {String} key diff --git a/core/dynamicdatabase/storage.js b/core/dynamicdatabase/storage.js index dcc4060..9d150be 100644 --- a/core/dynamicdatabase/storage.js +++ b/core/dynamicdatabase/storage.js @@ -1,3 +1,13 @@ +/** +================================================================== +ALL DATABASE FILES NEED TO EXPORT THE FOLLOWING FUNCTIONS: +- get(category:String,key:String) => String (value) +- set(category:String,key:String,value:String) => Boolean (success) +- delete(category:String,key:String) => Boolean (success) +- getCategory(category:String) => Array[{key:String,value:String}] (key,value) +================================================================== + */ + try { var db = require("./dynamicfiles/database") }catch(err){ diff --git a/core/errorLogSystem.js b/core/errorLogSystem.js index 71755ae..d224156 100644 --- a/core/errorLogSystem.js +++ b/core/errorLogSystem.js @@ -48,12 +48,13 @@ exports.serverError = (message) => { return x } -/**@param {String[]} list */ -exports.invalidIdChooseFromList = (list) => { +/**@param {String[]} list @param {String|undefined} message */ +exports.invalidIdChooseFromList = (list,message) => { + const beforemsg = message ? message+"\n\n" : "" var x = new embed() .setColor(c.Red) .setTitle(":x: "+l.errors.chooseFromListTitle) - .setDescription(l.errors.chooseFromListDescription+"\n`"+list.join("`\n`")+"`") + .setDescription(beforemsg+l.errors.chooseFromListDescription+"\n`"+list.join("`\n`")+"`") return x } @@ -66,7 +67,7 @@ exports.notInATicket = new embed() /**@param {String} message @param {String} title */ exports.success = (title,message) => { var x = new embed() - .setColor(config.main_color) + .setColor(config.color) .setTitle(":white_check_mark: "+title) .setDescription(message) diff --git a/core/interactionHandlers/buttons/close.js b/core/interactionHandlers/buttons/close.js index 4f8bdbf..a476070 100644 --- a/core/interactionHandlers/buttons/close.js +++ b/core/interactionHandlers/buttons/close.js @@ -7,7 +7,7 @@ const log = bot.errorLog.log const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder diff --git a/core/interactionHandlers/buttons/firstmsg.js b/core/interactionHandlers/buttons/firstmsg.js index fbbc910..37200e8 100644 --- a/core/interactionHandlers/buttons/firstmsg.js +++ b/core/interactionHandlers/buttons/firstmsg.js @@ -7,7 +7,7 @@ const log = bot.errorLog.log const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder @@ -15,6 +15,13 @@ const bs = discord.ButtonStyle exports.firstmsgRowNormal = new arb() + .addComponents( + new button() + .setCustomId("OTclaimTicket") + .setDisabled(false) + .setStyle(bs.Success) + .setLabel("Claim Ticket") + ) .addComponents( new button() .setCustomId("OTcloseTicket") @@ -33,6 +40,63 @@ exports.firstmsgRowNormal = new arb() ) exports.firstmsgRowDisabled = new arb() + .addComponents( + new button() + .setCustomId("OTclaimTicket") + .setDisabled(false) + .setStyle(bs.Success) + .setLabel("Claim Ticket") + ) + .addComponents( + new button() + .setCustomId("OTcloseTicket") + .setDisabled(true) + .setStyle(bs.Secondary) + .setLabel(l.buttons.close) + .setEmoji("🔒") + ) + .addComponents( + new button() + .setCustomId("OTdeleteTicket") + .setDisabled(true) + .setStyle(bs.Danger) + .setLabel(l.buttons.delete) + .setEmoji("✖️") + ) + +exports.firstmsgRowNormalNoClaim = new arb() + .addComponents( + new button() + .setCustomId("OTclaimTicket") + .setDisabled(true) + .setStyle(bs.Secondary) + .setLabel("Claim Ticket") + ) + .addComponents( + new button() + .setCustomId("OTcloseTicket") + .setDisabled(false) + .setStyle(bs.Secondary) + .setLabel(l.buttons.close) + .setEmoji("🔒") + ) + .addComponents( + new button() + .setCustomId("OTdeleteTicket") + .setDisabled(false) + .setStyle(bs.Danger) + .setLabel(l.buttons.delete) + .setEmoji("✖️") + ) + +exports.firstmsgRowDisabledNoClaim = new arb() + .addComponents( + new button() + .setCustomId("OTclaimTicket") + .setDisabled(true) + .setStyle(bs.Secondary) + .setLabel("Claim Ticket") + ) .addComponents( new button() .setCustomId("OTcloseTicket") diff --git a/core/interactionHandlers/buttons/verifyBars.js b/core/interactionHandlers/buttons/verifyBars.js index cbd8453..fdd911c 100644 --- a/core/interactionHandlers/buttons/verifyBars.js +++ b/core/interactionHandlers/buttons/verifyBars.js @@ -8,7 +8,7 @@ const log = bot.errorLog.log const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder diff --git a/core/interactionHandlers/embeds/commands.js b/core/interactionHandlers/embeds/commands.js index 6a01609..9b8c5ec 100644 --- a/core/interactionHandlers/embeds/commands.js +++ b/core/interactionHandlers/embeds/commands.js @@ -7,7 +7,7 @@ const log = bot.errorLog.log const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color /** * @@ -53,6 +53,21 @@ exports.closeEmbed = (closer,description) => { return embd } +/** + * + * @param {discord.User} closer + * @param {Number} time + * @returns {discord.EmbedBuilder} + */ +exports.autocloseSignalEmbed = (closer,time) => { + const embd = new embed() + .setTitle("⏰ This ticket got closed by Autoclose!") + .setColor(mc) + .setFooter({text:closer.tag,iconURL:closer.displayAvatarURL()}) + .setDescription("This ticket has been inactive for `"+time+"h`!") + return embd +} + /** * * @param {discord.User} deleter diff --git a/core/interactionHandlers/handlers/accepted/claiming.js b/core/interactionHandlers/handlers/accepted/claiming.js new file mode 100644 index 0000000..6f7f1cb --- /dev/null +++ b/core/interactionHandlers/handlers/accepted/claiming.js @@ -0,0 +1,51 @@ +const discord = require('discord.js') +const bot = require('../../../../index') +const client = bot.client +const config = bot.config +const l = bot.language +const log = bot.errorLog.log + +const permissionChecker = require("../../../utils/permisssionChecker") +const storage = bot.storage +const hiddendata = bot.hiddenData +const embed = discord.EmbedBuilder +const mc = config.color + +const button = discord.ButtonBuilder +const arb = discord.ActionRowBuilder +const bs = discord.ButtonStyle + +module.exports = () => { + //CLAIM + client.on("interactionCreate",async interaction => { + if (!interaction.isButton()) return + if (interaction.customId != "OTclaimTicket") return + + try { + interaction.deferUpdate() + }catch{} + + interaction.channel.messages.fetchPinned().then(msglist => { + /**@type {discord.Message} */ + var firstmsg = msglist.last() + if (firstmsg == undefined || firstmsg.author.id != client.user.id) return interaction.editReply({embeds:[bot.errorLog.notInATicket]}) + const hdraw = bot.hiddenData.removeHiddenData(firstmsg.embeds[0].description) + const hiddendata = hdraw.hiddenData + const ticketId = hiddendata.data.find(d => d.key == "type").value + + hiddendata.data.push({key:"claimedby",value:interaction.user.id}) + storage.set("claimData",interaction.channel.id,interaction.user.id) + + const newEmbed = new embed(firstmsg.embeds[0].data) + .setFooter({text:"claimed by: "+interaction.user.tag,iconURL:interaction.user.displayAvatarURL()}) + .setDescription(hdraw.description+bot.hiddenData.writeHiddenData(hiddendata.type,hiddendata.data)) + + if (!firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim],embeds:[newEmbed]}) + + }else if (firstmsg.components[0].components[1].disabled){ + firstmsg.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim],embeds:[newEmbed]}) + } + }) + }) +} \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/closing.js b/core/interactionHandlers/handlers/accepted/closing.js index 17776aa..ba5bddc 100644 --- a/core/interactionHandlers/handlers/accepted/closing.js +++ b/core/interactionHandlers/handlers/accepted/closing.js @@ -9,7 +9,7 @@ const permissionChecker = require("../../../utils/permisssionChecker") const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder @@ -41,8 +41,17 @@ module.exports = () => { return } } + if (interaction.message.pinned && interaction.message.author.id == client.user.id){ + const claimdata = storage.get("claimData",interaction.channel.id) + if (claimdata && claimdata != "false"){ + interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabledNoClaim]}) + }else{ + interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowDisabled]}) + } + }else{ + interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) + } - interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) /** * @type {String} @@ -57,7 +66,7 @@ module.exports = () => { }) interaction.channel.send({embeds:[bot.embeds.commands.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) - await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close",false,true) + await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"close",false,true) closeTicketButtonChecker = false }) } \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/closingReason.js b/core/interactionHandlers/handlers/accepted/closingReason.js index bae9523..5aa3bdd 100644 --- a/core/interactionHandlers/handlers/accepted/closingReason.js +++ b/core/interactionHandlers/handlers/accepted/closingReason.js @@ -9,7 +9,7 @@ const permissionChecker = require("../../../utils/permisssionChecker") const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder @@ -93,7 +93,7 @@ module.exports = () => { }) //interaction.channel.send({embeds:[bot.embeds.commands.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) - await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close",reason,true) + await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"close",reason,true) closeTicketButtonChecker = false }) } \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/deleting.js b/core/interactionHandlers/handlers/accepted/deleting.js index 091d36c..2cfdbc0 100644 --- a/core/interactionHandlers/handlers/accepted/deleting.js +++ b/core/interactionHandlers/handlers/accepted/deleting.js @@ -9,7 +9,7 @@ const permissionChecker = require("../../../utils/permisssionChecker") const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder @@ -52,7 +52,7 @@ module.exports = () => { await interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) await interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) - await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true) + await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"delete",false,true) deleteTicketButtonChecker = false }) @@ -92,7 +92,7 @@ module.exports = () => { await interaction.message.edit({components:[bot.buttons.close.closeCommandRowDisabled]}) await interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) - await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true) + await require("../../../ticketActions/ticketCloser").closeManager(interaction.member,interaction.channel,prefix,"delete",false,true) deleteTicketButtonChecker1 = false }) diff --git a/core/interactionHandlers/handlers/accepted/reopening.js b/core/interactionHandlers/handlers/accepted/reopening.js index 2cbc080..d810770 100644 --- a/core/interactionHandlers/handlers/accepted/reopening.js +++ b/core/interactionHandlers/handlers/accepted/reopening.js @@ -9,7 +9,7 @@ const permissionChecker = require("../../../utils/permisssionChecker") const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder diff --git a/core/interactionHandlers/handlers/firstmsg.js b/core/interactionHandlers/handlers/firstmsg.js index cd8c748..2235f4a 100644 --- a/core/interactionHandlers/handlers/firstmsg.js +++ b/core/interactionHandlers/handlers/firstmsg.js @@ -8,7 +8,7 @@ const log = bot.errorLog.log const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder diff --git a/core/interactionHandlers/handlers/handlers.js b/core/interactionHandlers/handlers/handlers.js index c2c015b..da7dc3c 100644 --- a/core/interactionHandlers/handlers/handlers.js +++ b/core/interactionHandlers/handlers/handlers.js @@ -7,4 +7,5 @@ module.exports = () => { require("./accepted/reopening")() require("./accepted/deleting")() require("./accepted/closingReason")() + require("./accepted/claiming")() } \ No newline at end of file diff --git a/core/interactionHandlers/handlers/verifyBars.js b/core/interactionHandlers/handlers/verifyBars.js index bb2ae74..d02dc9d 100644 --- a/core/interactionHandlers/handlers/verifyBars.js +++ b/core/interactionHandlers/handlers/verifyBars.js @@ -8,7 +8,7 @@ const log = bot.errorLog.log const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder -const mc = config.main_color +const mc = config.color const button = discord.ButtonBuilder const arb = discord.ActionRowBuilder @@ -33,7 +33,17 @@ module.exports = () => { try { interaction.deferUpdate() } catch{} - interaction.message.edit({components:[bot.buttons.close.openRowNormal]}) + + if (interaction.message.pinned && interaction.message.author.id == client.user.id){ + const claimdata = storage.get("claimData",interaction.channel.id) + if (claimdata && claimdata != "false"){ + interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim]}) + }else{ + interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal]}) + } + }else{ + interaction.message.edit({components:[bot.buttons.close.openRowNormal]}) + } }) //DELETE @@ -54,7 +64,17 @@ module.exports = () => { try { interaction.deferUpdate() } catch{} - interaction.message.edit({components:[bot.buttons.close.openRowNormal]}) + + if (interaction.message.pinned && interaction.message.author.id == client.user.id){ + const claimdata = storage.get("claimData",interaction.channel.id) + if (claimdata && claimdata != "false"){ + interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormalNoClaim]}) + }else{ + interaction.message.edit({components:[bot.buttons.firstmsg.firstmsgRowNormal]}) + } + }else{ + interaction.message.edit({components:[bot.buttons.close.openRowNormal]}) + } }) //DELETE NO TRANSCRIPT diff --git a/core/languageManager.js b/core/languageManager.js index 198533f..77d5e4f 100644 --- a/core/languageManager.js +++ b/core/languageManager.js @@ -4,11 +4,10 @@ if (index.developerConfig){ var config = require("../devconfig.json") }else{var config = require("../config.json")} - var localLanguage = require("../language/english.json") const fs = require("fs") -const lfexists = fs.existsSync("./language/"+config.languagefile+".json") -if (lfexists) localLanguage = require("../language/"+config.languagefile+".json") +const lfexists = fs.existsSync("./language/"+config.languageFile+".json") +if (lfexists) localLanguage = require("../language/"+config.languageFile+".json") const errorLog = async () => { const chalk = await (await import("chalk")).default @@ -20,6 +19,12 @@ const successLog = async (language) => { const chalk = await (await import("chalk")).default require("./startscreen").headerDataLanguage("sucessfully loaded language "+language,false) + index.actionRecorder.push({ + category:"ot.managers.language", + file:"./core/languageManager.js", + time:new Date().getTime(), + type:"language.success" + }) } if (!localLanguage){ @@ -30,5 +35,5 @@ if (!localLanguage){ runError() }else{ exports.language = localLanguage - successLog(config.languagefile) + successLog(config.languageFile) } \ No newline at end of file diff --git a/core/reactionRoles.js b/core/reactionRoles.js index fc8317a..6ce63b5 100644 --- a/core/reactionRoles.js +++ b/core/reactionRoles.js @@ -16,8 +16,12 @@ module.exports = async () => { if (interaction.isButton() && !interaction.customId.startsWith("newR")) return if (interaction.isStringSelectMenu() && !(interaction.customId == "OTdropdownMenu")) return - - + bot.actionRecorder.push({ + category:"ot.managers.reactionroles", + file:"./core/reactionRoles.js", + time:new Date().getTime(), + type:"reactionRoles.interactionCreated" + }) const optionidRaw = interaction.isStringSelectMenu() ? interaction.values[0] : interaction.customId @@ -40,6 +44,12 @@ module.exports = async () => { const user = interaction.member if (mode == "add"){ + bot.actionRecorder.push({ + category:"ot.managers.reactionroles", + file:"./core/reactionRoles.js", + time:new Date().getTime(), + type:"reactionRoles.type.add" + }) option.roles.forEach((role) => { interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role) @@ -49,6 +59,12 @@ module.exports = async () => { }) }else if (mode == "remove"){ + bot.actionRecorder.push({ + category:"ot.managers.reactionroles", + file:"./core/reactionRoles.js", + time:new Date().getTime(), + type:"reactionRoles.type.remove" + }) option.roles.forEach((role) => { interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role) @@ -58,6 +74,12 @@ module.exports = async () => { }) }else if (mode == "add&remove"){ + bot.actionRecorder.push({ + category:"ot.managers.reactionroles", + file:"./core/reactionRoles.js", + time:new Date().getTime(), + type:"reactionRoles.type.add&remove" + }) option.roles.forEach((role) => { if (!interaction.guild.members.cache.find(u => u.id == user.id).roles.cache.has(role)){ interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role) diff --git a/core/slashSystem/autoSlashUpdate.js b/core/slashSystem/autoSlashUpdate.js index ba610aa..27614b7 100644 --- a/core/slashSystem/autoSlashUpdate.js +++ b/core/slashSystem/autoSlashUpdate.js @@ -8,7 +8,7 @@ const act = discord.ApplicationCommandType const acot = discord.ApplicationCommandOptionType module.exports = async () => { - const sid = config.server_id + const sid = config.serverId const ids = configParser.getTicketValuesArray("id") /**@type {[{name:String,value:String}]} */ diff --git a/core/slashSystem/slashEnable.js b/core/slashSystem/slashEnable.js index b587f7b..85ab3c4 100644 --- a/core/slashSystem/slashEnable.js +++ b/core/slashSystem/slashEnable.js @@ -7,9 +7,10 @@ const configParser = require("../utils/configParser") const act = discord.ApplicationCommandType const acot = discord.ApplicationCommandOptionType -module.exports = async () => { +/**@param {Boolean|undefined} invisible*/ +module.exports = async (invisible) => { const chalk = (await import("chalk")).default - const sid = config.server_id + const sid = config.serverId const ids = configParser.getTicketValuesArray("id") /**@type {[{name:String,value:String}]} */ @@ -30,17 +31,20 @@ module.exports = async () => { var readystats = 0 //process.stdout.write("[status] there are "+chalk.blue("0 out of 10")+" commands ready! (this can take up to 40 seconds)") - setInterval(() => { - process.stdout.cursorTo(0) - process.stdout.write("[status] there are "+chalk.blue(readystats+" out of 13")+" commands ready! (this can take up to 40 seconds)") - if (readystats >= 13){ - const fs = require("fs") - fs.writeFileSync("./storage/slashcmdEnabled.txt","true") - console.log(chalk.green("\nready!")) - console.log(chalk.blue("you can now start the bot with "+chalk.bgBlue("'npm start'")+"!")) - process.exit(1) - } - },100) + if (!invisible){ + setInterval(() => { + process.stdout.cursorTo(0) + process.stdout.write("[status] there are "+chalk.blue(readystats+" out of 13")+" commands ready! (this can take up to 40 seconds)") + if (readystats >= 13){ + console.log(chalk.green("\nready!")) + console.log(chalk.blue("you can now start the bot with "+chalk.bgBlue("'npm start'")+"!")) + process.exit(1) + } + },100) + } + + const fs = require("fs") + fs.writeFileSync("./storage/slashcmdEnabled.txt",require("../../package.json").version) //slashtranslation const ST = require("../../language/slashcmds/slash.json").data diff --git a/core/startscreen.js b/core/startscreen.js index 7c8159b..710aac9 100644 --- a/core/startscreen.js +++ b/core/startscreen.js @@ -14,6 +14,9 @@ const showFlags = async (chalk) => { if (process.argv.some((v) => v == "--nochecker")) console.log(chalk.blue("[FLAGS] => disabled checker.js")); isFlag = true if (process.argv.some((v) => v == "--tsoffline")) console.log(chalk.blue("[FLAGS] => offline check for html transcripts disabled!")); isFlag = true if (process.argv.some((v) => v == "--debug")) console.log(chalk.blue("[FLAGS] => enabled DEBUG mode")); isFlag = true + if (process.argv.some((v) => v == "--noslash")) console.log(chalk.blue("[FLAGS] => slash commands disabled")); isFlag = true + if (process.argv.some((v) => v == "--localstatus")) console.log(chalk.blue("[FLAGS] => using local livestatus.json")); isFlag = true + if (process.argv.some((v) => v == "--noerrorupload")) console.log(chalk.blue("[FLAGS] => not uploading errors to liveStatus")); isFlag = true if (!isFlag) console.log(chalk.blue("no flags!")) } @@ -22,7 +25,7 @@ exports.run = async () => { const chalk = await (await import("chalk")).default console.log(chalk.hex("f8ba00")(logo)) const version = require("../package.json").version - var headertext = "v"+version+" - Support: https://discord.dj-dj.be - Language: "+config.languagefile + var headertext = "v"+version+" - Support: https://discord.dj-dj.be - Language: "+config.languageFile const spaceamount = (84-headertext.length)/2 var i = 0 while (i < spaceamount){ @@ -48,7 +51,7 @@ exports.headerDataReady = (chalk,status,updatingslash,slashmode) => { console.log("\n\n"+chalk.red(chalk.underline("STARTING IN SLASH CMD CONFIGURATION MODE!"))) return } - console.log(chalk.hex("f8ba00")("updating slash cmds: ")+chalk.bold(slashmode)) + console.log(chalk.hex("f8ba00")("updating slash cmds: ")+chalk.bold(updatingslash)) } var languageMSG = "" @@ -62,14 +65,15 @@ exports.headerDataLanguage = async (message,err) => { languageErr = err } -/** - * @param {{total:Number,error:Number,success:Number}} plugins -*/ +/**@param {{total:Number,error:Number,success:Number}} plugins*/ exports.headerDataPlugins = async (plugins) => { const chalk = await (await import("chalk")).default const lmsg = languageErr ? chalk.red(languageMSG) : languageMSG console.log(chalk.hex("f8ba00")("language: ")+lmsg) console.log(chalk.hex("f8ba00")("plugins loaded: ")+chalk.bold(plugins.total+" total ")+"("+plugins.success+"✅ "+plugins.error+"❌)") + console.log("\n"+chalk.bold(chalk.underline("LIVESTATUS:"))) + await require("./utils/liveStatus").run(plugins) + console.log("\n"+chalk.bold(chalk.underline("LOGS:"))) } \ No newline at end of file diff --git a/core/ticketActions/ticketAutoclose.js b/core/ticketActions/ticketAutoclose.js new file mode 100644 index 0000000..62e6e4f --- /dev/null +++ b/core/ticketActions/ticketAutoclose.js @@ -0,0 +1,48 @@ +const discord = require('discord.js') +const bot = require('../../index') +const client = bot.client +const config = bot.config +const log = bot.errorLog.log +const l = bot.language +const storage = bot.storage + +module.exports = () => { + setInterval(async () => { + const tickets = storage.getCategory("autocloseTickets") + if (!tickets) return + tickets.forEach(async (t) => { + if (t.value == "false" || t.value == 0 || typeof t.value != "number") return + const channel = await client.channels.fetch(t.key,{cache:true}) + if (!channel || !channel.isTextBased()) return + + const message = (await channel.messages.fetch({limit:10})).first() + if (!message) return + + const secondsSLM = Math.round((new Date().getTime() - message.createdTimestamp)/1000) + const hoursSLM = secondsSLM/3600 + + if (hoursSLM > t.value){ + /**@type {discord.Guild|false} */ + const guild = client.guilds.cache.find((g) => g.id == channel.guild.id) + if (!guild) return + const clientMember = guild.members.cache.find((m) => m.id == client.user.id) + if (!clientMember) return + + var name = channel.name + var prefix = "" + const tickets = config.options + tickets.forEach((ticket) => { + if (name.startsWith(ticket.channelprefix)){ + prefix = ticket.channelprefix + } + }) + + require("./ticketCloser").closeManager(clientMember,channel,prefix,"close","OTautoclose",true) + storage.delete("autocloseTickets",channel.id) + + channel.send({embeds:[bot.embeds.commands.autocloseSignalEmbed(client.user,t.value)],components:[bot.buttons.close.closeCommandRow]}) + } + }) + + },2000) +} \ No newline at end of file diff --git a/core/ticketActions/ticketCloser.js b/core/ticketActions/ticketCloser.js index 9dab369..ffeddef 100755 --- a/core/ticketActions/ticketCloser.js +++ b/core/ticketActions/ticketCloser.js @@ -18,7 +18,7 @@ const pendingDelete = [] * @param {Boolean} nomessage * @param {String} reason only when closing, not when deleting! */ -exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => { +exports.closeManager = async (member,channel,prefix,mode,reason,nomessage) => { const guild = channel.guild const user = member.user const chalk = await (await import("chalk")).default @@ -35,7 +35,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => const ticketOpenerChannelName = channelname.split(prefix)[1] //get user that opened the ticket - var getuserID = storage.get("userTicketStorage",channel.id) + var getuserID = storage.get("userFromChannel",channel.id) try { var ticketOpener = client.users.cache.find(u => u.id === getuserID) var isDatabaseError = false @@ -66,7 +66,11 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => log("system","deleted a ticket",[{key:"user",value:user.tag},{key:"ticket",value:channel.name}]) pendingDelete.push(channel.id) - if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1) + if (!isDatabaseError) storage.set("amountOfUserTickets",getuserID,Number(storage.get("amountOfUserTickets",getuserID)) - 1) + storage.delete("userFromChannel",channel.id) + storage.delete("claimData",channel.id) + storage.delete("autocloseTickets",channel.id) + if (Number(storage.get("amountOfUserTickets",getuserID)) < 0) storage.set("amountOfUserTickets",getuserID,0) //getID & send DM & send api event await channel.messages.fetchPinned().then(async msglist => { @@ -119,7 +123,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => }) //add main adminroles - config.main_adminroles.forEach((role,index) => { + config.adminRoles.forEach((role,index) => { try { const adminrole = guild.roles.cache.find(r => r.id == role) if (!adminrole) return @@ -170,7 +174,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => */ const ticketadmin = ticketData.adminroles ticketadmin.forEach((role,index) => { - if (!config.main_adminroles.includes(role)){ + if (!config.adminRoles.includes(role)){ try { const adminrole = guild.roles.cache.find(r => r.id == role) if (!adminrole) return @@ -191,30 +195,12 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => channel.permissionOverwrites.set(permissionArray) if (!nomessage){ - //message - var closeButtonRow = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("OTdeleteTicket1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("OTreopenTicket") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Success) - .setLabel(l.buttons.reopen) - .setEmoji("✔") - ) - + //message const embed = new discord.EmbedBuilder() - .setColor(config.main_color) - .setTitle(":lock: "+l.messages.closedTitle+" :lock:") + .setColor(config.color) + .setTitle(":lock: "+l.commands.closeTitle+" :lock:") .setDescription(l.messages.closedDescription) - channel.send({embeds:[embed],components:[closeButtonRow]}) + channel.send({embeds:[embed],components:[bot.buttons.close.closeCommandRow]}) } log("system","closed a ticket",[{key:"user",value:user.tag},{key:"ticket",value:channel.name}]) diff --git a/core/ticketActions/ticketOpener.js b/core/ticketActions/ticketOpener.js index 5ac4f90..80910af 100755 --- a/core/ticketActions/ticketOpener.js +++ b/core/ticketActions/ticketOpener.js @@ -53,20 +53,20 @@ module.exports = () => { if (interaction.isButton()){ try { - if (config.system.answerInEphemeralOnOpen) interaction.deferReply({ephemeral:true}) + if (config.system.answerInEphemeralOnOpen) await interaction.deferReply({ephemeral:true}) } catch{} }else if (interaction.isChatInputCommand()){ - interaction.deferReply({ephemeral:config.system.answerInEphemeralOnOpen}) + await interaction.deferReply({ephemeral:config.system.answerInEphemeralOnOpen}) }else if (interaction.isStringSelectMenu()){ try { - interaction.deferUpdate() + await interaction.deferUpdate() } catch{} } - if (storage.get("ticketStorage",interaction.member.id) == null || storage.get("ticketStorage",interaction.member.id) == "false"|| Number(storage.get("ticketStorage",interaction.member.id)) < config.system.max_allowed_tickets){ + if (storage.get("amountOfUserTickets",interaction.member.id) == null || storage.get("amountOfUserTickets",interaction.member.id) == "false"|| Number(storage.get("amountOfUserTickets",interaction.member.id)) < config.system.maxAmountOfTickets){ //update storage - storage.set("ticketStorage",interaction.member.id,Number(storage.get("ticketStorage",interaction.member.id))+1) + storage.set("amountOfUserTickets",interaction.member.id,Number(storage.get("amountOfUserTickets",interaction.member.id))+1) var ticketNumber = interaction.member.user.username //set ticketName @@ -84,19 +84,12 @@ module.exports = () => { const pfb = discord.PermissionFlagsBits const guild = client.guilds.cache.find(g => g.id == interaction.guild.id) - //set everyone allowed - if (config.system['has@everyoneaccess']){ - var everyoneAllowPerms = [pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel] - var everyoneDenyPerms = [] - }else{ - var everyoneAllowPerms = [] - var everyoneDenyPerms = [pfb.ViewChannel] - } + //set @everyone no ticket access permissionsArray.push({ id:interaction.guild.roles.everyone, type:"role", - allow:everyoneAllowPerms, - deny:everyoneDenyPerms + allow:[], + deny:[pfb.ViewChannel] }) //add the user that created the ticket @@ -107,7 +100,7 @@ module.exports = () => { }) //add main adminroles - config.main_adminroles.forEach((role,index) => { + config.adminRoles.forEach((role,index) => { try { const adminrole = guild.roles.cache.find(r => r.id == role) if (!adminrole) return @@ -128,7 +121,7 @@ module.exports = () => { */ const ticketadmin = currentTicketOptions.adminroles ticketadmin.forEach((role,index) => { - if (!config.main_adminroles.includes(role)){ + if (!config.adminRoles.includes(role)){ try { const adminrole = guild.roles.cache.find(r => r.id == role) if (!adminrole) return @@ -145,9 +138,9 @@ module.exports = () => { }) //add member role - if (config.system.member_role != "" && config.system.member_role != " " && config.system.member_role != "false" && config.system.member_role != "null" && config.system.member_role != "0"){ + if (config.system.memberRole && ![" ","0","false","null","undefined"].includes(config.system.memberRole)){ try { - const userrole = guild.roles.cache.find(r => r.id == config.system.member_role) + const userrole = guild.roles.cache.find(r => r.id == config.system.memberRole) if (userrole){ permissionsArray.push({ id:userrole, @@ -156,7 +149,7 @@ module.exports = () => { }) } }catch{ - log("system","invalid role! At 'config.json => system/member_role") + log("system","invalid role! At 'config.json => system/memberRole") } } @@ -169,15 +162,21 @@ module.exports = () => { permissionOverwrites:permissionsArray }).then((ticketChannel) => { - storage.set("userTicketStorage",ticketChannel.id,interaction.member.id) + storage.set("userFromChannel",ticketChannel.id,interaction.member.id) + if (currentTicketOptions.autoclose.enable) storage.set("autocloseTickets",ticketChannel.id,currentTicketOptions.autoclose.inactiveHours) const hiddendata = bot.hiddenData.writeHiddenData("ticketdata",[{key:"type",value:currentTicketOptions.id},{key:"openerid",value:interaction.user.id},{key:"createdms",value:new Date().getTime()}]) var ticketEmbed = new discord.EmbedBuilder() //.setAuthor({name:interaction.user.id}) - .setColor(config.main_color) + .setColor(config.color) .setTitle(currentTicketOptions.name) //.setFooter({text:"Ticket Type: "+currentTicketOptions.id}) + if (currentTicketOptions.autoclose.enable){ + const footerText = l.commands.autocloseTitle.replace("{0}",currentTicketOptions.autoclose.inactiveHours+"h") + ticketEmbed.setFooter({text:footerText}) + } + if (currentTicketOptions.ticketmessage.length > 0){ ticketEmbed.setDescription(currentTicketOptions.ticketmessage+hiddendata) }else{ @@ -205,12 +204,12 @@ module.exports = () => { .setStyle(discord.ButtonStyle.Link) .setDisabled(false) .setEmoji("🎫") - .setLabel("go to ticket") + .setLabel(l.commands.goToTicket) .setURL(ticketChannel.url) ]) try{ - if (currentTicketOptions.enableDmOnOpen) interaction.member.send({embeds:[bot.errorLog.custom(l.messages.newTicketDmTitle,currentTicketOptions.message,":ticket:",config.main_color)],components:[channelbutton]}) + if (currentTicketOptions.enableDmOnOpen) interaction.member.send({embeds:[bot.errorLog.custom(l.messages.newTicketDmTitle,currentTicketOptions.message,":ticket:",config.color)],components:[channelbutton]}) } catch{log("system","failed to send DM")} @@ -219,7 +218,7 @@ module.exports = () => { }) }else{ try { - if (config.system.enable_DM_Messages){ + if (config.system.dmMessages){ interaction.member.send({embeds:[bot.errorLog.warning(l.errors.maxAmountTitle,l.errors.maxAmountDescription)]}) } } diff --git a/core/ticketActions/ticketReopener.js b/core/ticketActions/ticketReopener.js index 10ecdf7..76453f3 100755 --- a/core/ticketActions/ticketReopener.js +++ b/core/ticketActions/ticketReopener.js @@ -19,19 +19,12 @@ const reopenTicket = (guild,channel,user) => { var permissionsArray = [] - //set everyone allowed - if (config.system['has@everyoneaccess']){ - var everyoneAllowPerms = [pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel] - var everyoneDenyPerms = [] - }else{ - var everyoneAllowPerms = [] - var everyoneDenyPerms = [pfb.ViewChannel] - } + //set @everyone no ticket access permissionsArray.push({ id:guild.roles.everyone, type:"role", - allow:everyoneAllowPerms, - deny:everyoneDenyPerms + allow:[], + deny:[pfb.ViewChannel] }) channel.permissionOverwrites.cache.forEach((p) => { diff --git a/core/transcriptSystem/communication/template.json b/core/transcriptSystem/communication/template.json index 01870b7..8c0bf35 100644 --- a/core/transcriptSystem/communication/template.json +++ b/core/transcriptSystem/communication/template.json @@ -1,6 +1,6 @@ { "version":"1.0.0", - "otversion":"3.2.2", + "otversion":"3.3.0", "style":{ "enableCustomBackground":false, "backgroundModus":"color OR image", diff --git a/core/transcriptSystem/embeds.js b/core/transcriptSystem/embeds.js index 4b08efc..02e15ec 100644 --- a/core/transcriptSystem/embeds.js +++ b/core/transcriptSystem/embeds.js @@ -22,7 +22,7 @@ exports.beingprocessed = (name,id,rawprocesstime,user) => { const embed = new discord.EmbedBuilder() .setTitle("🧾 "+l.transcripts.title) - .setColor(config.main_color) + .setColor(config.color) .setAuthor({name:user.tag,iconURL:user.displayAvatarURL()}) .setFooter({text:name}) @@ -42,7 +42,7 @@ exports.beingprocessed = (name,id,rawprocesstime,user) => { exports.tsready = (name,id,url,user) => { const embed = new discord.EmbedBuilder() .setTitle("🧾 "+l.transcripts.title) - .setColor(config.main_color) + .setColor(config.color) .setAuthor({name:user.tag,iconURL:user.displayAvatarURL()}) .setFooter({text:name}) diff --git a/core/transcriptSystem/oldTranscript.js b/core/transcriptSystem/oldTranscript.js index c33e6d0..1d1861e 100755 --- a/core/transcriptSystem/oldTranscript.js +++ b/core/transcriptSystem/oldTranscript.js @@ -26,7 +26,20 @@ exports.createTranscript = async (messagecollection,channel,backup) => { messagecollection.forEach((msg) => { const timestamp = new Date(msg.createdTimestamp) - if (msg.content){var content = msg.content}else{var content = "*empty message*"} + //empty message handling + if (msg.content){ + var content = msg.content + }else if (msg.embeds.length > 0 && msg.attachments.length > 0){ + var content = "*this message only has embeds & files*" + }else if (msg.embeds.length > 0){ + var content = "*this message only has embeds*" + }else if (msg.attachments.length > 0){ + var content = "*this message only has files*" + }else{ + var content = "*empty message*" + } + + const fileurls = [] const rawfiles = Array.from(msg.attachments) rawfiles.forEach((file) => { diff --git a/core/utils/configParser.js b/core/utils/configParser.js index dd9b4bd..9e68d31 100644 --- a/core/utils/configParser.js +++ b/core/utils/configParser.js @@ -6,7 +6,7 @@ const l = bot.language //================== //OTTicketOptions -/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color: "red"|"green"|"blue"|"gray",adminroles: String[],channelprefix: String,category: String,message: String,enableDmOnOpen: Boolean,ticketmessage: String, thumbnail:{enable:Boolean,url:String}, image:{enable:Boolean,url:String}, closedCategory:{enable:Boolean,id:String}}} OTTicketOptions */ +/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color: "red"|"green"|"blue"|"gray",adminroles: String[],channelprefix: String,category: String,message: String,enableDmOnOpen: Boolean,ticketmessage: String, thumbnail:{enable:Boolean,url:String}, image:{enable:Boolean,url:String}, closedCategory:{enable:Boolean,id:String}, autoclose:{enable:Boolean,inactiveHours:Number} }} OTTicketOptions */ //OTRoleOptions /**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color:"red"|"green"|"blue"|"gray"|"none",roles:String[],mode:"add&remove"|"remove"|"add",enableDmOnOpen:Boolean}} OTRoleOptions */ @@ -19,7 +19,7 @@ const l = bot.language /**@typedef {{id: string, name: string, description: string, dropdown: boolean, enableFooter: boolean, footer: string, enableThumbnail: boolean, thumbnail: string, enableCustomColor: boolean, color: string, options: string[], other:{enableTicketExplaination: boolean, enableMaxTicketsWarning: boolean, customDropdownPlaceholder:{enable:Boolean,text:String}, customCategoryText:{enable:Boolean,text:String}, embedTitleURL:{enable:Boolean,url:String} } }} OTConfigMessage*/ //OTAllOptions -/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color:"red"|"green"|"blue"|"gray"|"none",roles:String[],mode:"add&remove"|"remove"|"add",adminroles: String[],channelprefix: String,category: String,message: String,enableDmOnOpen: Boolean,ticketmessage: String, thumbnail:{enable:Boolean,url:String}, image:{enable:Boolean,url:String}, url:String, closedCategory:{enable:Boolean,id:String}}} OTAllOptions */ +/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",color:"red"|"green"|"blue"|"gray"|"none",roles:String[],mode:"add&remove"|"remove"|"add",adminroles: String[],channelprefix: String,category: String,message: String,enableDmOnOpen: Boolean,ticketmessage: String, thumbnail:{enable:Boolean,url:String}, image:{enable:Boolean,url:String}, url:String, closedCategory:{enable:Boolean,id:String}, autoclose:{enable:Boolean,inactiveHours:Number}}} OTAllOptions */ //StringOptions /**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDmOnOpen"|"ticketmessage"|"thumbnail"|"image"|"closedCategory"} OTTicketStringOptions */ diff --git a/core/utils/getButton.js b/core/utils/getButton.js index 86db8dc..36348a5 100644 --- a/core/utils/getButton.js +++ b/core/utils/getButton.js @@ -32,6 +32,12 @@ exports.getOption = getOption * @returns {discord.ButtonBuilder|false} */ exports.getButton = (id) => { + bot.actionRecorder.push({ + category:"ot.managers.utils", + file:"./core/utils/getButton.js", + time:new Date().getTime(), + type:"getbutton" + }) const option = getOption(id) if (!option) return false if (option.type == "ticket"){ @@ -67,28 +73,4 @@ exports.getButton = (id) => { } return button -} - - -exports.rawButtonData = class { - constructor() { - this.id = "" - this.name = "" - this.description = "" - this.icon = "" - this.label = "" - this.type = "" - - this.color = "" - this.enableDmOnOpen = true - this.url = "" - this.roles = ["",""] - this.mode = "" - this.adminroles = ["",""] - this.channelprefix = "" - this.category = "" - this.message = "" - this.ticketmessage = "" - - } } \ No newline at end of file diff --git a/core/utils/getDropdown.js b/core/utils/getDropdown.js index 5b21d00..04545dd 100644 --- a/core/utils/getDropdown.js +++ b/core/utils/getDropdown.js @@ -11,6 +11,12 @@ const configParser = require("./configParser") * @returns {discord.StringSelectMenuBuilder|false} */ exports.getDropdown = (ids,placeholder) => { + bot.actionRecorder.push({ + category:"ot.managers.utils", + file:"./core/utils/getDropdown.js", + time:new Date().getTime(), + type:"getdropdown" + }) const dropdown = new discord.StringSelectMenuBuilder() .setCustomId("OTdropdownMenu") .setDisabled(false) @@ -18,7 +24,7 @@ exports.getDropdown = (ids,placeholder) => { .setMinValues(1) .setPlaceholder(placeholder || l.messages.chooseATicket) .addOptions( - new discord.SelectMenuOptionBuilder() + new discord.StringSelectMenuBuilder() .setDefault(true) .setLabel(placeholder || l.messages.chooseATicket) .setValue("OTChooseTicket") @@ -28,7 +34,7 @@ exports.getDropdown = (ids,placeholder) => { const option = configParser.getTicketById(id,true) const roleoption = configParser.getRoleById(id,true) if (option){ - const selectComponent = new discord.SelectMenuOptionBuilder() + const selectComponent = new discord.StringSelectMenuOptionBuilder() .setDefault(false) .setValue("OTnewT"+option.id) @@ -37,12 +43,13 @@ exports.getDropdown = (ids,placeholder) => { }else{ if (option.label) selectComponent.setLabel(option.label) if (option.icon) selectComponent.setEmoji(option.icon) + if (option.description) selectComponent.setDescription(option.description) } dropdown.addOptions(selectComponent) }else if (roleoption){ - const selectComponent = new discord.SelectMenuOptionBuilder() + const selectComponent = new discord.StringSelectMenuOptionBuilder() .setDefault(false) .setValue("OTnewR"+roleoption.id) diff --git a/core/utils/getEmbed.js b/core/utils/getEmbed.js index 2b22e7f..f6a0f02 100644 --- a/core/utils/getEmbed.js +++ b/core/utils/getEmbed.js @@ -14,12 +14,18 @@ const l = bot.language exports.createEmbed = (id) => { + bot.actionRecorder.push({ + category:"ot.managers.utils", + file:"./core/utils/getEmbed.js", + time:new Date().getTime(), + type:"getembed" + }) //----------------------------------- //general importing const data = require("./configParser").getConfigMessage(id) /**@type {discord.ButtonBuilder[]}*/ var buttons = [] - /**@type {getButton.rawButtonData[]} */ + /**@type {import('./configParser').OTAllOptions[]} */ var buttonData = [] data.options.forEach((option) => { @@ -43,14 +49,14 @@ exports.createEmbed = (id) => { if (data.enableCustomColor){ embed.setColor(data.color) }else{ - embed.setColor(config.main_color) + embed.setColor(config.color) } if (data.other.embedTitleURL.enable) embed.setURL(data.other.embedTitleURL.url) var description = data.description if (data.other.enableTicketExplaination){ - const chooseCategoryMSG = data.other.customCategoryText.enable ? data.other.customCategoryText.text : l.messages.chooseCategory + const chooseCategoryMSG = data.other.customCategoryText.enable ? data.other.customCategoryText.text : l.messages.chooseATicket description = description+"\n\n__"+chooseCategoryMSG+"__\n" var ticketExplainations = [] @@ -63,7 +69,7 @@ exports.createEmbed = (id) => { } if (data.other.enableMaxTicketsWarning){ - description = description+"\n\n"+l.commands.maxTicketWarning.replace("{0}",config.system.max_allowed_tickets) + description = description+"\n\n"+l.commands.maxTicketWarning.replace("{0}",config.system.maxAmountOfTickets) } if (description) embed.setDescription(description) diff --git a/core/utils/liveStatus.js b/core/utils/liveStatus.js index e5e57db..711a2e7 100644 --- a/core/utils/liveStatus.js +++ b/core/utils/liveStatus.js @@ -3,13 +3,194 @@ const bot = require('../../index') const client = bot.client const config = bot.config const log = bot.errorLog.log +const axios = require("axios").default +const fs = require("fs") const loadChalk = async () => { return await (await import("chalk")).default } -module.exports = async () => { +//OTLiveStatus +/**@typedef {[{style:[{title:String,titleColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan",description:String,descriptionColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan"}],active:{versions:String[],languages:String[],usingPlugins:["yes"|"no"|"both"],usingSlashCommands:["yes"|"no"|"both"],transcripts:["html"|"text"|"both"]}}]} OTLiveStatus */ + +//OTLiveStatusError +/**@typedef {{bot:{id:String,pfp:String,name:String}, openticket:{version:String,language:String, slashcmds:Boolean,transcripts:false|"text"|"html",config:{system:{},options:{},messages:{},transcripts:{}},plugins:String[],pluginload:{success:Number,error:Number,total:Number}}, details:{actions:[{type:String,category:String,file:String,time:Number}],errortime:Number}, error:String}} OTLiveStatusError */ + +/**@type {[{type:String, category:String, file:String, time:Number}]} */ +exports.actionRecorder = [] + +//================================================================ +//=========================FUNCTIONS============================== +//================================================================ + +const getSlashEnabled = () => { + if (!fs.existsSync("./storage/slashcmdEnabled.txt")) return false + if (fs.readFileSync("./storage/slashcmdEnabled.txt").toString() == require("../../package.json").version){ + return true + }else return false +} + +/** + * @param {Boolean} [local=false] + * @returns {Promise} +*/ +const getLivestatus = (local) => { + return new Promise((resolve,reject) => { + if (local){ + try { + const livestatus = require("../../livestatus.json") + if (!livestatus) return resolve(false) + resolve(livestatus) + }catch{ + return resolve(false) + } + }else{ + try { + axios.get("https://livestatus.dj-dj.be/openticket.json").then((res) => { + const livestatus = res.data + if (!Array.isArray(livestatus)) return resolve(false) + if (!livestatus) return resolve(false) + resolve(livestatus) + }) + }catch{ + return resolve(false) + } + } + }) +} + +var globalPluginData = {total:0,error:0,success:0} + +//announcer +/**@param {{total:Number,error:Number,success:Number}} pluginData*/ +exports.run = async (pluginData) => { const chalk = await loadChalk() - - //LIVESTATUS SOON + globalPluginData = pluginData + const res = await getLivestatus(process.argv.some((v) => v == "--localstatus")) + if (!res) return false + if (res.length == 0) return + + /**@type {[{title:String,titleColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan",description:String,descriptionColor:"normal"|"red"|"green"|"blue"|"yellow"|"white"|"gray"|"magenta"|"cyan"}]} */ + const activeStyles = [] + res.forEach((announcement) => { + const a = announcement.active + + const isLanguage = a.languages.includes(config.languageFile) || a.languages.includes("all") + const isVersion = a.versions.includes(require("../../package.json").version) + + var tsenabled = (bot.tsconfig.sendTranscripts.enableChannel || bot.tsconfig.sendTranscripts.enableDM) + var tsmode = bot.tsconfig.sendTranscripts.useHTMLtranscripts ? "html" : "text" + const isTranscript = (a.transcripts.includes("html") && tsmode == "html" && tsenabled) || (a.transcripts.includes("text") && tsmode == "text" && tsenabled) || (a.transcripts.includes("both") && tsenabled) + const isPlugins = (a.usingPlugins.includes("yes") && pluginData.total > 0) || (a.usingPlugins.includes("no") && pluginData.total == 0) || (a.usingPlugins.includes("both")) + const isSlashCMD = (a.usingSlashCommands.includes("yes") && getSlashEnabled()) || (a.usingSlashCommands.includes("no") && !getSlashEnabled()) || (a.usingSlashCommands.includes("both")) + + if (!isLanguage || !isVersion || !isTranscript || !isPlugins || !isSlashCMD) return + announcement.style.forEach((s) => activeStyles.push(s)) + }) + const final = [] + activeStyles.forEach((style) => { + const dc = style.descriptionColor + const tempd = style.description.split("\n") + const tc = style.titleColor + const t = "["+style.title+"]" + const tempd2 = [] + tempd.forEach((tmpd,i) => { + if (i > 0){ + var newtext = tmpd + var i2 = 0 + while(i2 < t.length+1){ + newtext = " "+newtext + i2++ + } + tempd2.push(newtext) + }else{ + tempd2.push(tmpd) + } + }) + const d = tempd2.join("\n") + + + var fd = d + if (dc == "normal" || dc == "white") fd = chalk.white(d) + if (dc == "red") fd = chalk.red(d) + if (dc == "yellow") fd = chalk.yellow(d) + if (dc == "green") fd = chalk.green(d) + if (dc == "blue") fd = chalk.blue(d) + if (dc == "gray") fd = chalk.gray(d) + if (dc == "magenta") fd = chalk.magenta(d) + if (dc == "cyan") fd = chalk.cyan(d) + + var ft = t + if (tc == "normal" || tc == "white") ft = chalk.white(t) + if (tc == "red") ft = chalk.red(t) + if (tc == "yellow") ft = chalk.yellow(t) + if (tc == "green") ft = chalk.green(t) + if (tc == "blue") ft = chalk.blue(t) + if (tc == "gray") ft = chalk.gray(t) + if (tc == "magenta") ft = chalk.magenta(t) + if (tc == "cyan") ft = chalk.cyan(t) + + final.push(ft+" "+fd) + }) + + console.log(final.join("\n\n")) +} + +/**@param {OTLiveStatusError} options @returns {Promise} */ +const uploadLiveStatus = (options) => { + return new Promise((resolve,reject) => { + if (process.argv.some((v) => v == "--noerrorupload")) return resolve(true) + try { + var data = encodeURIComponent(JSON.stringify(options)) + axios.get("https://livestatus.dj-dj.be/openticket?auth=openticketLIVESTATUS1234&data="+data).then((res) => { + if (res.status == 200) resolve(true) + else resolve(false) + }) + }catch{ + resolve(false) + } + }) +} + +/**@param {String} err @returns {Promise}*/ +exports.liveStatusUploadManager = async (err) => { + return new Promise(async (resolve) => { + + if (process.argv.some((v) => v == "--noerrorupload")) return resolve(true) + else{ + var tsenabled = (bot.tsconfig.sendTranscripts.enableChannel || bot.tsconfig.sendTranscripts.enableDM) + var tsmode = bot.tsconfig.sendTranscripts.useHTMLtranscripts ? "html" : "text" + const transcriptMode = tsenabled ? tsmode : false + const slashMode = getSlashEnabled() + + try { + resolve(await uploadLiveStatus({ + bot:{ + id:client.user.id, + name:client.user.tag, + pfp:client.user.displayAvatarURL() + }, + error:err, + openticket:{ + config:{ + messages:config.messages, + options:config.options, + transcripts:bot.tsconfig, + system:config.system + }, + language:config.languageFile, + version:require("../../package.json").version, + slashcmds:slashMode, + transcripts:transcriptMode, + plugins:fs.readdirSync("./plugins"), + pluginload:globalPluginData + }, + details:{ + errortime:new Date().getTime(), + actions:this.actionRecorder + } + })) + }catch{resolve(false)} + } + }) } \ No newline at end of file diff --git a/core/utils/permisssionChecker.js b/core/utils/permisssionChecker.js index 8ca662c..ab318fc 100644 --- a/core/utils/permisssionChecker.js +++ b/core/utils/permisssionChecker.js @@ -13,8 +13,14 @@ const storage = bot.storage * @returns {Boolean} has permissions? */ exports.command = (memberid,guildid) => { + bot.actionRecorder.push({ + category:"ot.managers.permissionChecker", + file:"./core/permissionChecker.js", + time:new Date().getTime(), + type:"command" + }) const permsmember = client.guilds.cache.find(g => g.id == guildid).members.cache.find(m => m.id == memberid) - if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ + if (config.adminRoles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ return false }else {return true} } @@ -25,6 +31,12 @@ exports.command = (memberid,guildid) => { * @returns {Boolean} */ exports.sendUserNoPerms = (user) => { + bot.actionRecorder.push({ + category:"ot.managers.permissionChecker", + file:"./core/permissionChecker.js", + time:new Date().getTime(), + type:"sendusernoperms" + }) try { user.send({embeds:[bot.errorLog.noPermsMessage(user)]}) return true @@ -39,6 +51,12 @@ exports.sendUserNoPerms = (user) => { * @returns {Boolean} */ exports.sendUserNoTicket = (user) => { + bot.actionRecorder.push({ + category:"ot.managers.permissionChecker", + file:"./core/permissionChecker.js", + time:new Date().getTime(), + type:"sendusernoticket" + }) try { user.send({embeds:[bot.errorLog.notInATicket]}) return true @@ -53,6 +71,12 @@ exports.sendUserNoPerms = (user) => { * @returns {Boolean} */ exports.sendUserNoDelete = (user) => { + bot.actionRecorder.push({ + category:"ot.managers.permissionChecker", + file:"./core/permissionChecker.js", + time:new Date().getTime(), + type:"sendusernodelete" + }) try { user.send({embeds:[bot.errorLog.noPermsDelete(user)]}) return true @@ -68,6 +92,12 @@ exports.sendUserNoPerms = (user) => { * @returns {Boolean} */ exports.sendChannelNoPerms = (channel,user) => { + bot.actionRecorder.push({ + category:"ot.managers.permissionChecker", + file:"./core/permissionChecker.js", + time:new Date().getTime(), + type:"sendchannelnoperms" + }) try { channel.send({embeds:[bot.errorLog.noPermsMessage(user)]}) return true @@ -83,6 +113,12 @@ exports.sendUserNoPerms = (user) => { * @returns {Boolean} */ exports.sendChannelNoTicket = (channel,user) => { + bot.actionRecorder.push({ + category:"ot.managers.permissionChecker", + file:"./core/permissionChecker.js", + time:new Date().getTime(), + type:"sendchannelnoticket" + }) try { channel.send({embeds:[bot.errorLog.notInATicket]}) return true @@ -98,6 +134,12 @@ exports.sendUserNoPerms = (user) => { * @returns {Boolean} */ exports.sendChannelNoDelete = (channel,user) => { + bot.actionRecorder.push({ + category:"ot.managers.permissionChecker", + file:"./core/permissionChecker.js", + time:new Date().getTime(), + type:"sendchannelnodelete" + }) try { channel.send({embeds:[bot.errorLog.noPermsDelete(user)]}) return true diff --git a/index.js b/index.js index 5701f37..ccc8472 100644 --- a/index.js +++ b/index.js @@ -28,7 +28,7 @@ INFORMATION: ============ - Open Ticket v3.2.2 - © DJdj Development + Open Ticket v3.3.0 - © DJdj Development discord: https://discord.dj-dj.be website: https://www.dj-dj.be @@ -45,24 +45,17 @@ const discord = require("discord.js") const fs = require('fs') const {GatewayIntentBits,Partials} = discord -const APIBase = require("./core/api/modules/base") -if (APIBase.embeddedMode){ - var tempClient = APIBase.clientLocation -}else{ - var tempClient = new discord.Client({ - intents:[ - GatewayIntentBits.DirectMessages, - GatewayIntentBits.GuildInvites, - GatewayIntentBits.GuildMembers, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.Guilds, - GatewayIntentBits.MessageContent - ], - partials:[Partials.Channel,Partials.Message] - }) -} -/**@type {discord.Client} */ -const client = tempClient +const client = new discord.Client({ + intents:[ + GatewayIntentBits.DirectMessages, + GatewayIntentBits.GuildInvites, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.Guilds, + GatewayIntentBits.MessageContent + ], + partials:[Partials.Channel,Partials.Message] +}) exports.client = client client.setMaxListeners(50) if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","created client") @@ -82,10 +75,6 @@ if (process.argv.some((v) => v == "--devconfig")){ if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded flags") exports.developerConfig = isDevConfig -const language = require("./core/languageManager").language -exports.language = language -if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded language") - const config = tempconfig exports.config = config @@ -93,16 +82,21 @@ exports.config = config const tsconfig = isDevConfig ? require("./devtsconfig.json") : require("./transcriptconfig.json") exports.tsconfig = tsconfig +const language = require("./core/languageManager").language +exports.language = language +if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded language") + if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded config") exports.storage = require('./core/dynamicdatabase/storage') if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","loaded storage") exports.errorLog = require("./core/errorLogSystem") -const log = this.errorLog.log if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","LOADED LOGGING SYSTEM") if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","switching to new logs") this.errorLog.log("debug","loaded new logs") +exports.actionRecorder = require("./core/utils/liveStatus").actionRecorder + exports.hiddenData = require("./core/utils/hiddendata") this.errorLog.log("debug","loaded hiddendataTM") @@ -118,6 +112,12 @@ this.errorLog.log("debug","loaded buttons & embeds") client.on('ready',async () => { this.errorLog.log("debug","client logged in") + this.actionRecorder.push({ + category:"ot.managers.djs", + file:"index.js", + time:new Date().getTime(), + type:"client.loggedin.success" + }) var statusSet = false const setStatus = (type,text) => { if (statusSet == true) return @@ -131,40 +131,94 @@ client.on('ready',async () => { statusSet = true } this.errorLog.log("debug","bot status loaded") + this.actionRecorder.push({ + category:"ot.managers.djs", + file:"index.js", + time:new Date().getTime(), + type:"client.setstatus.success" + }) const chalk = await (await import("chalk")).default require("./core/startscreen").run() + this.actionRecorder.push({ + category:"ot.managers.main", + file:"index.js", + time:new Date().getTime(), + type:"startscreen.success" + }) + if (!process.argv[2] || (process.argv[2] && !process.argv[2].startsWith("slash"))){ + //normal start this.errorLog.log("debug","loaded console interface") - - require("./core/utils/liveStatus")() if (config.status.enabled){ setStatus(config.status.type,config.status.text) } + this.actionRecorder.push({ + category:"ot.managers.main", + file:"index.js", + time:new Date().getTime(), + type:"startmode.normal" + }) + var updatingSlash = false if (fs.existsSync("./storage/slashcmdEnabled.txt")){ - /**@type {"true"|"false"} */ + /**@type {"true"|"false"|String} */ const data = fs.readFileSync("./storage/slashcmdEnabled.txt").toString() - if (data === "true"){require("./core/slashSystem/autoSlashUpdate")(); updatingSlash = true} - }else{fs.writeFileSync("./storage/slashcmdEnabled.txt","false")} + if (data === require("./package.json").version){ + require("./core/slashSystem/autoSlashUpdate")() + updatingSlash = true + + }else if ((data != require("./package.json").version) && (data != "false")){ + require("./core/slashSystem/slashEnable")(true) + updatingSlash = true + } + }else{ + if (process.argv.some((v) => v == "--noslash")){ + fs.writeFileSync("./storage/slashcmdEnabled.txt","false") + }else{ + fs.writeFileSync("./storage/slashcmdEnabled.txt",require("./package.json").version) + require("./core/slashSystem/slashEnable")(true) + updatingSlash = true + } + } + this.actionRecorder.push({ + category:"ot.managers.main", + file:"index.js", + time:new Date().getTime(), + type:"slashcmd.autoupdate.success" + }) try { - await client.guilds.cache.find((g) => g.id == config.server_id).members.fetch() + await client.guilds.cache.find((g) => g.id == config.serverId).members.fetch() }catch{ this.errorLog.log("info","tried to cache user information, failed!") } require("./core/startscreen").headerDataReady(chalk,config.status,updatingSlash,false) + }else{ + //slash command activation using node index.js slash (enable|disable) require("./core/startscreen").headerDataReady(chalk,config.status,updatingSlash,true) this.errorLog.log("debug","slashmode activated") if (process.argv[3] == "enable"){ console.log(chalk.green("switching to slashEnable.js")) + this.actionRecorder.push({ + category:"ot.managers.main", + file:"index.js", + time:new Date().getTime(), + type:"startmode.slash.enable" + }) require("./core/slashSystem/slashEnable")() }else if (process.argv[3] == "disable"){ console.log(chalk.green("switching to slashDisable.js")) + this.actionRecorder.push({ + category:"ot.managers.main", + file:"index.js", + time:new Date().getTime(), + type:"startmode.slash.disable" + }) require("./core/slashSystem/slashDisable")() }else{ console.log(chalk.bgRed("[SLASH CMD MANAGER]: unknown slash command action!")) @@ -173,17 +227,49 @@ client.on('ready',async () => { } //load plugins + this.actionRecorder.push({ + category:"ot.managers.plugins", + file:"./core/api/pluginlauncher.js", + time:new Date().getTime(), + type:"plugins.loading" + }) require("./core/api/pluginlauncher")() + this.actionRecorder.push({ + category:"ot.managers.plugins", + file:"./core/api/pluginlauncher.js", + time:new Date().getTime(), + type:"plugins.success" + }) this.errorLog.log("debug","loading plugins") }) -if (!require("./core/api/api.json").disable.checkerjs.all) require("./core/checker").checker() +if (!require("./core/api/api.json").disable.checkerjs.all){ + this.actionRecorder.push({ + category:"ot.managers.main", + file:"./core/checker.js", + time:new Date().getTime(), + type:"checker.loading" + }) + require("./core/checker").checker() this.errorLog.log("debug","loading checker.js") this.errorLog.log("debug","checking config...") + this.actionRecorder.push({ + category:"ot.managers.main", + file:"./core/checker.js", + time:new Date().getTime(), + type:"checker.success" + }) +} if (process.argv[2] && process.argv[2].startsWith("slash")){ //do nothing }else{ + this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"commands.loading" + }) this.errorLog.log("debug","LOADING COMMANDS") //commands require('./commands/ticket')() @@ -197,23 +283,61 @@ if (process.argv[2] && process.argv[2].startsWith("slash")){ require("./commands/claim")() require("./commands/unclaim")() require("./commands/change")() + this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"commands.success" + }) + this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"core.loading" + }) this.errorLog.log("debug","LOADING CORE") //core require('./core/ticketActions/ticketOpener')() require("./core/reactionRoles")() + require("./core/ticketActions/ticketAutoclose")() this.errorLog.log("debug","LOADING INTERACTION HANDLERS") //InteractionHandlers require("./core/interactionHandlers/handlers/handlers")() - //require("./test")() + this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"core.success" + }) } +this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"api.loading" +}) this.errorLog.log("debug","loading api") const APIEvents = require("./core/api/modules/events") const APIConfig = require("./core/api/api.json") +this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"api.success" +}) + +this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"debugsystem.loading" +}) + const debugLog = (debugString) => { if (!APIConfig.disable.debug.all && !APIConfig.disable.debug.debuglogs){ const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n\n==========================" @@ -244,7 +368,18 @@ process.on("uncaughtException",async (error,origin) => { errorLog(error.name+": "+error.message+" | origin: "+origin,error.stack) APIEvents.onError(error.name+": "+error.message,new Date()) + + //TEMPORARY INTEGRATION FOR LIVESTATUS ERROR UPLOADER: + await require("./core/utils/liveStatus").liveStatusUploadManager(error.name+": "+error.message+" | origin: "+origin+"\n"+error.stack) }) -if (!APIBase.embeddedMode) client.login(config.auth_token) +this.actionRecorder.push({ + category:"ot.managers.loader", + file:"./index.js", + time:new Date().getTime(), + type:"debugsystem.success" +}) + +const token = config.token.fromENV ? process.env.TOKEN : config.token.value +client.login(token) this.errorLog.log("debug","login with token") \ No newline at end of file diff --git a/language/arabic.json b/language/arabic.json index fdc8443..57f9b40 100644 --- a/language/arabic.json +++ b/language/arabic.json @@ -1,79 +1,90 @@ { - "errors": { - "missingArgsTitle": "قيمة غير صالحة!", - "missingArgsDescription": "قيمة مفقودة", - "noPermsTitle": "ليس لديك برمشنات !", - "noPermsDescription": "أنت بحاجة الى برمشن `ADMINISTRATOR` او أن تكون في قائمة المسموح بهم!", - "noPermsDelete": "فقط الإداريين يمكنهم حذف التكت!", - "chooseFromListTitle": "Invalid ID", - "chooseFromListDescription": "قم بأختيار أحد من الأيديات من الأسفل:", - "boterror": "خلل في البوت !", - "notInTicketTitle": "انت لست في تكت!", - "notInTicketDescription": "هذا الأمر لا يعمل خارج التكت!", - "ticketDoesntExist": "هذا التكت لم يعد فعال!", - "roleDoesntExist": "خطاً ,لم تعد الرتبة موجوده!", - "anotherOption": "هذا الخيار ليس التكت و لكنه شيء أخر!", - "maxAmountTitle": "خطأ , تم الوصول الى الحد الأقصى!", - "maxAmountDescription": "لقد وصلت الى الحد الأقصى لعدد التكتات المسموحة بها!\nSo لا يمكنك فتح واحدة أخرى!", - "somethingWentWrong": "**هناك خطاً!**\nأعد المحاولة لاحقاً!" - }, - "commands": { - "userAddedTitle": "تم أضافة {0} من المستخدمين في التكت!", - "userRemovedTitle": "تم أزالة {0} من المستخدمين من التكت!", - "renameTitle": "تم تغيير أسم التكت الى {0}!", - "closeTitle": "تم أغلاق التكت!", - "deleteTitle": " جاري حذف التكت...", - "reopenTitle": "إعادة فتح التكت!", - "claimTitle":"This ticket is now claimed to {0}", - "unclaimTitle":"This ticket isn't claimed anymore!", - "changeTitle":"Changed ticket type to {0}!", + "errors": { + "missingArgsTitle": "قيمة غير صالحة!", + "missingArgsDescription": "قيمة مفقودة", + "noPermsTitle": "ليس لديك برمشنات !", + "noPermsDescription": "أنت بحاجة الى برمشن `ADMINISTRATOR` او أن تكون في قائمة المسموح بهم!", + "noPermsDelete": "فقط الإداريين يمكنهم حذف التكت!", + "chooseFromListTitle": "Invalid ID", + "chooseFromListDescription": "قم بأختيار أحد من الأيديات من الأسفل:", + "boterror": "خلل في البوت !", + "notInTicketTitle": "انت لست في تكت!", + "notInTicketDescription": "هذا الأمر لا يعمل خارج التكت!", + "ticketDoesntExist": "هذا التكت لم يعد فعال!", + "roleDoesntExist": "خطاً ,لم تعد الرتبة موجوده!", + "anotherOption": "هذا الخيار ليس التكت و لكنه شيء أخر!", + "maxAmountTitle": "خطأ , تم الوصول الى الحد الأقصى!", + "maxAmountDescription": "لقد وصلت الى الحد الأقصى لعدد التكتات المسموحة بها!\nSo لا يمكنك فتح واحدة أخرى!", + "somethingWentWrong": "**هناك خطاً!**\nأعد المحاولة لاحقاً!" + }, + "commands": { + "userAddedTitle": "تم أضافة {0} من المستخدمين في التكت!", + "userRemovedTitle": "تم أزالة {0} من المستخدمين من التكت!", + "renameTitle": "تم تغيير أسم التكت الى {0}!", + "closeTitle": "تم أغلاق التكت!", + "deleteTitle": " جاري حذف التكت...", + "reopenTitle": "إعادة فتح التكت!", + + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", + "changeTitle":"Changed ticket type to {0}!", - "ticketWarning": "هذا الأمبد موجود بالفعل في الرسالة بالأسفل!", - "maxTicketWarning": "**تحذير:** _يمكنك فقط فتح {0} تكت في الوقت!_" - }, - "helpMenu": { - "title": "الأوامر المتاحة:", - "header1": "**أذهب الى {0} لإنشاء تذكرة!**\n\n", - "header2": "**قم بكتابة أمر `/new` او `/ticket` لفتح تكت!**\n\n", + "statsTitle":"Here are the stats for {0}!", + "autocloseTitle":"This ticket will be closed automatically after {0}!", + "autocloseRejectTitle":"This ticket will no longer be closed automatically!", + "autocloseWarn":"This only affects inactive tickets!", - "msgCmd": "أنشاء أيمبد مع الأزرار. (الأداريين فقط)", - "renameCmd": "إعادة تسمية التكت. (بدون مسافات)", - "closeCmd": "أغلاق التكت.", - "deleteCmd": "حذف التكت.", - "addCmd": "إضافة مستخدم الى التكت.", - "removeCmd": "إزالة مستخدم من التكت.", - "reopenCmd": "إعادة فتح تكت بعد إغلاقة." - }, - "buttons": { - "close": "إغلاق التكت", - "delete": "حذف التكت", - "reopen": "إعادة فتح التكت", - "closeWithReason":"close with reason" - }, - "messages": { - "reopenTitle": "تم إعادة فتح التكت بنجاح!", - "reopenDescription": "لا تتردد في فتح التكت مرة أخرى , حظاً موفقاً!", - "closedTitle": "تم إغلاق التكت!", - "closedDescription": "فقط الأداريين يمكنهم التحدث في هذا التكت الأن!\n\n*أضغط على الزر بالأسفل لحذف التكت او إعادة فتحة مجدداً!*", - "createdTitle": "تم إنشاء تكت!", - "createdDescription": "تم أنشاء تكت , قم بأنتظار الدعم في الطريق!", + "goToTicket":"go to ticket", + "ticketWarning": "هذا الأمبد موجود بالفعل في الرسالة بالأسفل!", + "maxTicketWarning": "**تحذير:** _يمكنك فقط فتح {0} تكت في الوقت!_" + }, + "helpMenu": { + "title": "الأوامر المتاحة:", + "header1": "**أذهب الى {0} لإنشاء تذكرة!**\n\n", + "header2": "**قم بكتابة أمر `/new` او `/ticket` لفتح تكت!**\n\n", - "newTicketDmTitle": "تكت جديد!", - "closedTicketDmTitle": "تم إغلاق التكت!", - "deletedTicketDmTitle": "تم حذف التكت!", - "closedTicketDmDescription": "تم أغلاق تذكرتك من قبل إداري", - "deletedTicketDmDescription": "تم حذف تذكرتك من قبل إداري!", - "reopenTicketDmTitle": "تم إعادة فتح تذكرتك!", - "reopenTicketDmDescription": "تم إعادة فتح التكت!", - - "chooseCategory": "أختر الكتقاجوري:", - "gettingdeleted": "يتم حذف التكت...", + "msgCmd": "أنشاء أيمبد مع الأزرار. (الأداريين فقط)", + "renameCmd": "إعادة تسمية التكت. (بدون مسافات)", + "closeCmd": "أغلاق التكت.", + "deleteCmd": "حذف التكت.", + "addCmd": "إضافة مستخدم الى التكت.", + "removeCmd": "إزالة مستخدم من التكت.", + "reopenCmd": "إعادة فتح تكت بعد إغلاقة.", + "changeCmd":"Change ticket type.", + "claimCmd":"Claim a ticket.", + "unclaimCmd":"Unclaim a ticket.", + "statsCmd":"View ticket stats.", + "autocloseCmd":"Set timer to automatically close ticket" + }, + "buttons": { + "close": "إغلاق التكت", + "delete": "حذف التكت", + "reopen": "إعادة فتح التكت", + "closeWithReason":"close with reason" + }, + "messages": { + "closedDescription": "فقط الأداريين يمكنهم التحدث في هذا التكت الأن!\n\n*أضغط على الزر بالأسفل لحذف التكت او إعادة فتحة مجدداً!*", + "createdTitle": "تم إنشاء تكت!", + "createdDescription": "تم أنشاء تكت , قم بأنتظار الدعم في الطريق!", - "none": "لا يوجد", - "reason": "سبب", + "newTicketDmTitle": "تكت جديد!", + "closedTicketDmTitle": "تم إغلاق التكت!", + "deletedTicketDmTitle": "تم حذف التكت!", + "closedTicketDmDescription": "تم أغلاق تذكرتك من قبل إداري", + "deletedTicketDmDescription": "تم حذف تذكرتك من قبل إداري!", + "reopenTicketDmTitle": "تم إعادة فتح تذكرتك!", + "reopenTicketDmDescription": "تم إعادة فتح التكت!", + + "chooseCategory": "أختر الكتقاجوري:", + "gettingdeleted": "يتم حذف التكت...", - "deletedby":"deleted by", + "none": "لا يوجد", + "reason": "سبب", + "createdat":"created at", + "openedby":"opened by", + "deletedby":"deleted by", "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", "chooseATicket": "Choose a ticket" }, diff --git a/language/custom.json b/language/custom.json index b2020fe..ef296d2 100644 --- a/language/custom.json +++ b/language/custom.json @@ -24,10 +24,17 @@ "closeTitle":"Closed this ticket!", "deleteTitle":"Deleting this ticket...", "reopenTitle":"Re-Opened this ticket!", - "claimTitle":"This ticket is now claimed to {0}", + + "claimTitle":"This ticket is claimed to {0}", "unclaimTitle":"This ticket isn't claimed anymore!", "changeTitle":"Changed ticket type to {0}!", + "statsTitle":"Here are the stats for {0}!", + "autocloseTitle":"This ticket will be closed automatically after {0}!", + "autocloseRejectTitle":"This ticket will no longer be closed automatically!", + "autocloseWarn":"This only affects inactive tickets!", + + "goToTicket":"go to ticket", "ticketWarning":"The embed is in the message below!", "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Delete a ticket.", "addCmd":"Add a user to the ticket.", "removeCmd":"Remove a user from the ticket.", - "reopenCmd":"Re-Open a ticket after it was closed." + "reopenCmd":"Re-Open a ticket after it was closed.", + "changeCmd":"Change ticket type.", + "claimCmd":"Claim a ticket.", + "unclaimCmd":"Unclaim a ticket.", + "statsCmd":"View ticket stats.", + "autocloseCmd":"Set timer to automatically close ticket" }, "buttons":{ "close":"Close Ticket", @@ -51,9 +63,6 @@ "closeWithReason":"close with reason" }, "messages":{ - "reopenTitle":"Re-Opened this ticket!", - "reopenDescription":"Feel free to talk again!", - "closedTitle":"Closed this ticket!", "closedDescription":"Only admins can talk in this ticket now!\n\n*Click on the button below to delete or to re-open this ticket!*", "createdTitle":"Ticket Created!", "createdDescription":"Your ticket is created, you can detect it by a ping!", @@ -71,9 +80,11 @@ "none":"none", "reason":"reason", - + "createdat":"created at", + "openedby":"opened by", "deletedby":"deleted by", "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", "chooseATicket": "Choose a ticket" }, diff --git a/language/czech.json b/language/czech.json index 4965fb1..f3d23d9 100644 --- a/language/czech.json +++ b/language/czech.json @@ -24,10 +24,17 @@ "closeTitle":"Zavři tenhle ticket!", "deleteTitle":"Mažu ticket...", "reopenTitle":"Znovu otevíram ticket", - "claimTitle":"Nyní jsi převzal ticket {0}", - "unclaimTitle":"Tento ticketu už je převzatý!", - "changeTitle":"Změnil jsi typ ticketu na {0}!", + + "claimTitle":"Ticket nyní převzal {0}", + "unclaimTitle":"Ticket už není převzaný", + "changeTitle":"Změněn typ ticketu {0}!", + "statsTitle":"Tady je info o ticketu {0}!", + "autocloseTitle":"Tento ticketu bude automaticky uzavřen za {0}!", + "autocloseRejectTitle":"Tento ticketu už nebude automaticky uzavřen!", + "autocloseWarn":"Toto zavře pouze neaktivní tickety!", + + "goToTicket":"běž do ticketu", "ticketWarning":"The embed is in the message below!", "maxTicketWarning":"**Warning:** _Můžeš vytvořit pouze {0} v tuhle chvíli!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Odstranit ticket.", "addCmd":"Pridat uživatele do ticketu.", "removeCmd":"Odebrat uživatele z ticketu.", - "reopenCmd":"Re-Open a ticket after it was closed." + "reopenCmd":"Re-Open a ticket after it was closed.", + "changeCmd":"Změnit typ ticketu.", + "claimCmd":"Převzi ticket.", + "unclaimCmd":"Uvolnit ticket.", + "statsCmd":"Zobrazit info o ticketu.", + "autocloseCmd":"Nastavit automatické uzavření ticketu" }, "buttons":{ "close":"Zavřit ticket", @@ -51,9 +63,6 @@ "closeWithReason":"zavřít s důvodem" }, "messages":{ - "reopenTitle":"Znovu otevřit ticket!", - "reopenDescription":"Klidně napiš znova!", - "closedTitle":"Zavřít tenhle ticket!", "closedDescription":"Pouze admini muzou zde psát ted!\n\n*Klikni na tlačítko níže pro smazání nebo pro znovu otevření tohohle ticketu!*", "createdTitle":"Ticket otevřen!", "createdDescription":"Tvůj ticket je vytvořem, můžeš si ho všimnout pomocí pingu!", @@ -71,9 +80,11 @@ "none":"žádný", "reason":"důvod", - + "createdat":"otevřeno v", + "openedby":"otevřel", "deletedby":"smazano uzivatelem", "closedby":"zavreno uzivatelem", + "modalreason":"Jakž byl důvod k zavření toho ticketu?", "chooseATicket": "Vyber ticket" }, diff --git a/language/danish.json b/language/danish.json index b0c448a..4988ef8 100644 --- a/language/danish.json +++ b/language/danish.json @@ -24,10 +24,17 @@ "closeTitle": "Lukket denne ticket!", "deleteTitle": "Sletter denne ticket...", "reopenTitle": "Genåbnede denne ticket!", - "claimTitle": "Denne ticket er nu krævet til {0}", - "unclaimTitle": "Der gøres ikke krav på denne ticket længere!", - "changeTitle": "Ændrede ticket type til {0}!", + + "claimTitle": "Denne ticket bliver nu håndteret af {0}", + "unclaimTitle": "Denne ticket bliver ikke håndteret længere!", + "changeTitle": "Ændrede ticket-type til {0}!", + "statsTitle": "Her er statestikerne til {0}!", + "autocloseTitle": "Denne ticket lukker automatisk om {0}!", + "autocloseRejectTitle": "Denne ticket lukker ikke længere automatisk!", + "autocloseWarn": "Dette har kun effekt på inaktive tickets!", + + "goToTicket": "gå til ticket", "ticketWarning": "Embedet er i meddelelsen nedenfor!", "maxTicketWarning": "**Warning:** _Du kan kun oprette {0} ticket(s) ad gangen!_" }, @@ -42,7 +49,12 @@ "deleteCmd": "Slet en ticket.", "addCmd": "Tilføj en bruger til ticketen.", "removeCmd": "Fjern en bruger fra ticketen.", - "reopenCmd": "Genåbn en ticket, efter at den var lukket." + "reopenCmd": "Genåbn en ticket, efter at den var lukket.", + "changeCmd": "Skift ticket type.", + "claimCmd": "Håndter en ticket.", + "unclaimCmd": "Afhåndter en ticket.", + "statsCmd": "Se ticket statestiker.", + "autocloseCmd": "Angiv tiden til automatisk at lukke en ticket" }, "buttons": { "close": "Luk Ticket", @@ -51,9 +63,6 @@ "closeWithReason": "Luk med grundlag" }, "messages": { - "reopenTitle": "Genåbnede denne ticket!", - "reopenDescription": "Snak gerne igen!", - "closedTitle": "Lukket denne ticket!", "closedDescription": "Kun administratorer kan tale i denne billet nu!\n\n*Klik på knappen nedenfor for at slette eller genåbne denne billet!", "createdTitle": "Ticket Oprettet!", "createdDescription": "Din ticket er oprettet, du kan registrere den ved et ping!", @@ -71,9 +80,11 @@ "none": "intet", "reason": "grundlag", - + "createdat": "lavet af", + "openedby": "åbnet af", "deletedby": "slettet af", "closedby": "lukket af", + "modalreason": "Hvad er grunden til at lukke denne ticket?", "chooseATicket": "Vælg en ticket" }, diff --git a/language/dutch.json b/language/dutch.json index d067cd5..fb9dca4 100644 --- a/language/dutch.json +++ b/language/dutch.json @@ -24,10 +24,17 @@ "closeTitle":"Ticket gesloten!", "deleteTitle":"Ticket aan het verwijderen...", "reopenTitle":"Ticket heropend!", + "claimTitle":"Dit ticket is geclaimed door {0}", "unclaimTitle":"Dit ticket is niet meer geclaimed!", "changeTitle":"Ticket type veranderd naar {0}!", + "statsTitle":"Hier zijn de stats voor {0}!", + "autocloseTitle":"Dit ticket wordt automatisch gesloten na {0}!", + "autocloseRejectTitle":"Dit ticket wordt niet langer automatisch gesloten!", + "autocloseWarn":"Dit geldt alleen voor inactieve tickets!", + + "goToTicket":"ga naar ticket", "ticketWarning":"De embed is in het bericht hier onder!", "maxTicketWarning":"**Waarschuwing:** _Je kan maar {0} ticket(s) tegelijkertijd maken!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Verijder een ticket.", "addCmd":"Voeg een user aan een ticket.", "removeCmd":"Verwijder een user van een ticket.", - "reopenCmd":"Heropen een ticket nadat het gesloten is." + "reopenCmd":"Heropen een ticket nadat het gesloten is.", + "changeCmd":"Verander ticket type.", + "claimCmd":"Claim een ticket.", + "unclaimCmd":"Unclaim een ticket.", + "statsCmd":"Bekijk ticket stats.", + "autocloseCmd":"Zet een timer om het ticket automatisch te sluiten" }, "buttons":{ "close":"Sluit Ticket", @@ -51,9 +63,6 @@ "closeWithReason":"sluit met reden" }, "messages":{ - "reopenTitle":"Ticket heropend!", - "reopenDescription":"Voel vrij om weer te praten!", - "closedTitle":"Ticket gesloten!", "closedDescription":"Alleen admins kunnen nog praten.\n\n*Klik op de knoppen hieronder voor meer acties!*", "createdTitle":"Ticket Aangemaakt!", "createdDescription":"U ticket is gemaakt, je kan het detecteren bij een ping!", @@ -71,9 +80,11 @@ "none":"geen", "reason":"reden", - + "createdat":"gecreëerd op", + "openedby":"geopend door", "deletedby":"verwijderd door", "closedby":"gesloten door", + "modalreason":"Wat is de reden om dit ticket te sluiten?", "chooseATicket": "Kies een ticket" }, diff --git a/language/english.json b/language/english.json index b2020fe..9dcfa45 100644 --- a/language/english.json +++ b/language/english.json @@ -24,10 +24,17 @@ "closeTitle":"Closed this ticket!", "deleteTitle":"Deleting this ticket...", "reopenTitle":"Re-Opened this ticket!", - "claimTitle":"This ticket is now claimed to {0}", + + "claimTitle":"This ticket is claimed to {0}", "unclaimTitle":"This ticket isn't claimed anymore!", "changeTitle":"Changed ticket type to {0}!", + "statsTitle":"Here are the stats for {0}!", + "autocloseTitle":"This ticket will be closed automatically after {0}!", + "autocloseRejectTitle":"This ticket will no longer be closed automatically!", + "autocloseWarn":"This only affects inactive tickets!", + + "goToTicket":"go to ticket", "ticketWarning":"The embed is in the message below!", "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Delete a ticket.", "addCmd":"Add a user to the ticket.", "removeCmd":"Remove a user from the ticket.", - "reopenCmd":"Re-Open a ticket after it was closed." + "reopenCmd":"Re-Open a ticket after it was closed.", + "changeCmd":"Change ticket type.", + "claimCmd":"Claim a ticket.", + "unclaimCmd":"Unclaim a ticket.", + "statsCmd":"View ticket stats.", + "autocloseCmd":"Set timer to automatically close ticket" }, "buttons":{ "close":"Close Ticket", @@ -51,9 +63,6 @@ "closeWithReason":"close with reason" }, "messages":{ - "reopenTitle":"Re-Opened this ticket!", - "reopenDescription":"Feel free to talk again!", - "closedTitle":"Closed this ticket!", "closedDescription":"Only admins can talk in this ticket now!\n\n*Click on the button below to delete or to re-open this ticket!*", "createdTitle":"Ticket Created!", "createdDescription":"Your ticket is created, you can detect it by a ping!", @@ -71,9 +80,11 @@ "none":"none", "reason":"reason", - + "createdat":"created at", + "openedby":"opened by", "deletedby":"deleted by", "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", "chooseATicket": "Choose a ticket" }, diff --git a/language/french.json b/language/french.json index cbbd52b..6b7c3e8 100644 --- a/language/french.json +++ b/language/french.json @@ -24,10 +24,17 @@ "closeTitle":"Fermé ce ticket!", "deleteTitle":"Suppression de ce ticket...", "reopenTitle":"A rouvert ce ticket!", - "claimTitle":"This ticket is now claimed to {0}", - "unclaimTitle":"This ticket isn't claimed anymore!", - "changeTitle":"Changed ticket type to {0}!", + + "claimTitle":"Ce ticket est maintenant réclamé à {0}", + "unclaimTitle":"Ce ticket n'est pas réclamé!", + "changeTitle":"Modification du type de ticket en {0}!", + "statsTitle":"Voici les statistiques pour {0}!", + "autocloseTitle":"Ce ticket sera automatiquement clôturé après {0}!", + "autocloseRejectTitle":"Ce ticket ne sera plus clôturé automatiquement!", + "autocloseWarn":"Cela n'affecte que les tickets inactifs!", + + "goToTicket":"Aller au ticket", "ticketWarning":"L'intégration est dans le message ci-dessous!", "maxTicketWarning":"**Attention :** _Vous ne pouvez créer que {0} ticket(s) à la fois !_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Supprimer un billet.", "addCmd":"Ajouter un utilisateur au ticket.", "removeCmd":"Supprimer un utilisateur du ticket.", - "reopenCmd":"Rouvrir un ticket après sa clôture." + "reopenCmd":"Rouvrir un ticket après sa clôture.", + "changeCmd":"Changer le type de ticket.", + "claimCmd":"Réclamer un billet", + "unclaimCmd":"Annuler la réclamation d'un ticket.", + "statsCmd":"Afficher les statistiques des tickets.", + "autocloseCmd":"Définir une minuterie pour fermer automatiquement le ticket" }, "buttons":{ "close":"Fermer le ticket", @@ -51,9 +63,6 @@ "closeWithReason":"fermer avec une raison" }, "messages":{ - "reopenTitle":"A rouvert ce ticket!", - "reopenDescription":"N'hésitez pas à reparler!", - "closedTitle":"Fermé ce ticket!", "closedDescription":"Seuls les administrateurs peuvent parler dans ce ticket maintenant !\n\n*Cliquez sur le bouton ci-dessous pour supprimer ou rouvrir ce ticket !*", "createdTitle":"Ticket créé !", "createdDescription":"Votre ticket est créé, vous pouvez le détecter par un ping !", @@ -71,9 +80,11 @@ "none":"rien", "reason":"raison", - + "createdat":"Créé à", + "openedby":"Ouvert par", "deletedby":"supprimé par", "closedby":"fermé par", + "modalreason":"Qu’elle est la raison pour fermer ce ticket?", "chooseATicket": "Choisir un ticket" }, diff --git a/language/german.json b/language/german.json index 91e324f..d8e1d12 100644 --- a/language/german.json +++ b/language/german.json @@ -24,10 +24,17 @@ "closeTitle":"Dieses Ticket schließen!", "deleteTitle":"Löschen Sie dieses Ticket!", "reopenTitle":"Öffne dieses Ticket erneut!", - "claimTitle":"Das Ticket wurde beansprucht von {0}", - "unclaimTitle":"Das Ticket wrid nicht mehr beansprucht", - "changeTitle":"Ticket Typ wurde geändert auf {0}!", + + "claimTitle":"Dieses Ticket wurde beansprucht von {0}", + "unclaimTitle":"Dieses Ticket wird nichtmehr beansprucht.", + "changeTitle":"Ticket Typ wurde geändert zu {0}!", + "statsTitle":"Hier sind die Stats für {0}!", + "autocloseTitle":"Dieses Ticket wird automatisch geschlossen in {0}!", + "autocloseRejectTitle":"Dieses Ticket wird nichtmehr automatisch geschlossen", + "autocloseWarn":"Dies betrifft nur inaktive Tickets!", + + "goToTicket":"Geh zu deinem Ticket", "ticketWarning":"Die Einbettung befindet sich in der Nachricht unten!", "maxTicketWarning":"**Warnung:** _Sie können nur {0} ticket(s) erstellen zu einer Zeit!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Ein Ticket löschen.", "addCmd":"Fügen Sie dem Ticket einen Benutzer hinzu.", "removeCmd":"Entfernen eines Benutzers aus dem Ticket.", - "reopenCmd":"Öffnen Sie ein Ticket erneut, nachdem es geschlossen wurde." + "reopenCmd":"Öffnen Sie ein Ticket erneut, nachdem es geschlossen wurde.", + "changeCmd":"Ticket Typ ändern", + "claimCmd":"Ticket beanspruchen", + "unclaimCmd":"Ticket nicht mehr beanspruchen.", + "statsCmd":"Ticket Stats", + "autocloseCmd":"Timer wurde gesetzt auf automatisches schließen des Tickets" }, "buttons":{ "close":"Ticket schließen", @@ -51,9 +63,6 @@ "closeWithReason":"Geschlossen mit dem Grund" }, "messages":{ - "reopenTitle":"Dieses Ticket wiedereröffnet!", - "reopenDescription":"Sie können gerne weiterreden!", - "closedTitle":"Dieses Ticket geschlossen!", "closedDescription":"Nur Admins können jetzt in diesem Ticket sprechen!\n\n*Klicken Sie auf die Schaltfläche unten, um dieses Ticket zu löschen oder erneut zu öffnen!*", "createdTitle":"Ticket erstellt!", "createdDescription":"Ihr Ticket ist erstellt, Sie können es durch einen Ping erkennen!", @@ -71,9 +80,11 @@ "none":"none", "reason":"Grund", - + "createdat":"Erstellt um", + "openedby":"Geöffnet um", "deletedby":"Gelöscht von", "closedby":"Geschlossen von", + "modalreason":"Was ist der Grund?", "chooseATicket": "Wähle ein passendes Thema!" }, diff --git a/language/italian.json b/language/italian.json index 243ba05..8a9624e 100644 --- a/language/italian.json +++ b/language/italian.json @@ -24,10 +24,17 @@ "closeTitle":"Ticket chiuso!", "deleteTitle":"Eliminando questo ticket...", "reopenTitle":"Ri-aperto questo ticket!", - "claimTitle":"Questo ticket è ora gestito da {0}", + + "claimTitle":"Questo ticket adesso è gestito da {0}", "unclaimTitle":"Questo ticket non è più gestito!", - "changeTitle":"Cambiato il tipo di ticket in {0}!", + "changeTitle":"Ticket cambiato in {0}!", + "statsTitle":"Queste sono le stats per {0}!", + "autocloseTitle":"Questo ticket sarà eliminato direttamente dopo {0}!", + "autocloseRejectTitle":"Questo ticket non sarà più chiuso automaticamente!", + "autocloseWarn":"Questo vale solo per i ticket inattivi!", + + "goToTicket":"vai al ticket", "ticketWarning":"L'embed è nel messaggio sotto!", "maxTicketWarning":"*Attenzione:* Tu puoi creare solo {0} ticket alla volta!" }, @@ -42,7 +49,12 @@ "deleteCmd":"Elimina un ticket.", "addCmd":"Aggiungi un utente al ticket.", "removeCmd":"Rimuovi un utente da un ticket.", - "reopenCmd":"Ri-apri un ticket dopo averlo chiuso." + "reopenCmd":"Ri-apri un ticket dopo averlo chiuso.", + "changeCmd":"Cambia tipo di ticket.", + "claimCmd":"Gestisci un ticket.", + "unclaimCmd":"Lascia la gestione del ticket.", + "statsCmd":"Vedi le statistiche dei ticket.", + "autocloseCmd":"Imposta il timer dell'autochiusura dei ticket" }, "buttons":{ "close":"Chiudi", @@ -51,9 +63,6 @@ "closeWithReason":"chiudi con motivo" }, "messages":{ - "reopenTitle":"Ticket ri-aperto!", - "reopenDescription":"Sentiti libero di parlare nuovamente!", - "closedTitle":"Ticket chiuso!", "closedDescription":"Solo gli amministratori possono parlare in questo ticket ora!\n\n*Clicca sul pulsante sotto per eliminare o ri-aprire questo ticket!*", "createdTitle":"Ticket creato!", "createdDescription":"Il tuo ticket è stato creato, puoi capirlo dal ping!", @@ -71,9 +80,11 @@ "none":"nessuno", "reason":"motivo", - + "createdat":"creato il", + "openedby":"aperto da", "deletedby":"eliminato da", "closedby":"chiuso da", + "modalreason":"Quale è il motivo per chiudere questo ticket?", "chooseATicket": "Scegli un ticket" }, diff --git a/language/polish.json b/language/polish.json new file mode 100644 index 0000000..97f9728 --- /dev/null +++ b/language/polish.json @@ -0,0 +1,98 @@ +{ + "errors":{ + "missingArgsTitle":"Nieprawidłowe argumenty!", + "missingArgsDescription":"Brakujący argument", + "noPermsTitle":"Brak permisji!", + "noPermsDescription":"Musisz mieć uprawnienia `ADMINISTRATOR` lub być na liście dozwolonych ról!", + "noPermsDelete":"Tylko administratorzy mogą usunąć zgłoszenie!", + "chooseFromListTitle":"Błędne ID", + "chooseFromListDescription":"Wybierz jeden z poniższych identyfikatorów:", + "boterror":"Błąd bota!", + "notInTicketTitle":"Nie jesteś w tickecie!", + "notInTicketDescription":"To polecenie nie działa poza ticketami!", + "ticketDoesntExist":"Ten ticket już nie istnieje!", + "roleDoesntExist":"Ta rola już nie istnieje!", + "anotherOption":"Ta opcja nie jest ticketem, ale innym typem!", + "maxAmountTitle":"Maksymalna liczba osiągnięta!", + "maxAmountDescription":"Osiągnąłeś maksymalną dozwoloną liczbę ticketów!\nWięc nie możesz stworzyć nowego!", + "somethingWentWrong":"**Coś poszło nie tak!**\nSpróbuj ponownie innym razem!" + }, + "commands":{ + "userAddedTitle":"Dodano {0} do tego ticketa!", + "userRemovedTitle":"Usunięto {0} z tego ticketa!", + "renameTitle":"Zmieniono nazwę na {0}!", + "closeTitle":"Zamknięto ten ticket!", + "deleteTitle":"Usuwanie tego zgłoszenia..", + "reopenTitle":"Ponownie otwarto ten ticket!", + + "claimTitle":"Ten ticket został odebrany przez {0}", + "unclaimTitle":"Nie można już odebrać tego biletu!", + "changeTitle":"Changed ticket type to {0}!", + + "statsTitle":"Oto statystyki dotyczące {0}!", + "autocloseTitle":"Ten ticket zostanie automatycznie zamknięty po {0}!", + "autocloseRejectTitle":"Ten ticket nie będzie już automatycznie zamykany!", + "autocloseWarn":"Dotyczy to tylko nieaktywnych biletów!", + + "goToTicket":"Przejdź do ticketa", + "ticketWarning":"Osadzenie znajduje się w wiadomości poniżej!", + "maxTicketWarning":"**Ostrzeżenie:** _Możesz utworzyć tylko {0} bilet(ów) na raz!_" + }, + "helpMenu":{ + "title":"Dostępne polecenia:", + "header1":"**Przejdź do {0}, aby utworzyć zgłoszenie!**\n\n", + "header2":"**Uruchom polecenie `/new` lub `/ticket`, aby utworzyć zgłoszenie!**\n\n", + + "msgCmd":"Odradzaj osadzanie za pomocą przycisków. (tylko administratorzy)", + "renameCmd":"Zmień nazwę zgłoszenia. (bez spacji)", + "closeCmd":"Zamknij ticket.", + "deleteCmd":"Skasuj ticket.", + "addCmd":"Dodaj użytkownika do zgłoszenia.", + "removeCmd":"Usuń użytkownika ze zgłoszenia.", + "reopenCmd":"Otwórz ponownie ticket po jego zamknięciu.", + "changeCmd":"Zmień typ ticketa.", + "claimCmd":"Odbierz ticket.", + "unclaimCmd":"Zrezygnuj z ticketa.", + "statsCmd":"Pokaż statystyki zgłoszenia.", + "autocloseCmd":"Ustaw timer, aby automatycznie zamykał ticket." + }, + "buttons":{ + "close":"Zamknij", + "delete":"Skasuj", + "reopen":"Otworz ponownie", + "closeWithReason":"Zamknij z powodem" + }, + "messages":{ + "closedDescription":"Tylko admini mogą teraz rozmawiać w tym zgłoszeniu!\n\n*Kliknij przycisk poniżej, aby usunąć lub ponownie otworzyć ten ticket!*", + "createdTitle":"Ticket Created!", + "createdDescription":"Twój ticket został utworzony, możesz go wykryć za pomocą pingu!", + + "newTicketDmTitle":"Nowy Ticket!", + "closedTicketDmTitle":"Ticket Zamknięty!", + "deletedTicketDmTitle":"Ticket Skasowany!", + "closedTicketDmDescription":"Twój ticket jest zamknięty!", + "deletedTicketDmDescription":"Twój ticket został skasowany!", + "reopenTicketDmTitle":"Ticket otwarty!", + "reopenTicketDmDescription":"Twój ticket został ponownie otwarty!", + + "chooseCategory":"Wybierz kategorię:", + "gettingdeleted":"Ticket jest usuwany..", + + "none":"brak", + "reason":"powód", + "createdat":"utworzony", + "openedby":"otwarte przez", + "deletedby":"skasowane przez", + "closedby":"zamknięte przez", + + "modalreason":"Jaki jest powód zamknięcia tego zgłoszenia?", + "chooseATicket": "Wybierz zgłoszenie" + }, + "transcripts":{ + "title":"Transkrypcja", + "processed":"Ta transkrypcja jest przetwarzana", + "wait":"Proszę czekać!", + "estimated":"Szacowany czas", + "available":"Transkrypcja jest dostępna tutaj" + } +} \ No newline at end of file diff --git a/language/portuguese.json b/language/portuguese.json index 8a696ff..b06c2c4 100644 --- a/language/portuguese.json +++ b/language/portuguese.json @@ -24,10 +24,17 @@ "closeTitle":"Fechado este ticket!", "deleteTitle":"Excluindo este ticket...", "reopenTitle":"Reabriu este ticket!", - "claimTitle":"This ticket is now claimed to {0}", - "unclaimTitle":"This ticket isn't claimed anymore!", - "changeTitle":"Changed ticket type to {0}!", + + "claimTitle":"Esse ticket foi reinvidicado {0}", + "unclaimTitle":"Esse ticket não foi reinvidicado!", + "changeTitle":"Tipo de ticket alterado para {0}!", + "statsTitle":"Aqui estão as estatísticas para {0}!", + "autocloseTitle":"Este ticket vai fechar altomaticamente após {0}!", + "autocloseRejectTitle":"Este ticket não será mais fechado automaticamente!", + "autocloseWarn":"Isso apenas afeta tickets inativos!", + + "goToTicket":"ir para ticket", "ticketWarning":"A incorporação está na mensagem abaixo!", "maxTicketWarning":"**Cuidado:** _Você só pode criar {0} ticket(s) de cada vez!!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Excluir um ticket.", "addCmd":"Adicionar um usuário ao ticket.", "removeCmd":"Remover um usuário do ticket.", - "reopenCmd":"Reabra um ticket depois que ele foi fechado." + "reopenCmd":"Reabra um ticket depois que ele foi fechado.", + "changeCmd":"Mudar tipo de ticket", + "claimCmd":"Resgatar Ticket", + "unclaimCmd":"Desresgatar Ticket", + "statsCmd":"Olhar status do ticket", + "autocloseCmd":"Definir tempo para fechar ticket automaticamente." }, "buttons":{ "close":"Fechar Ticket", @@ -51,9 +63,6 @@ "closeWithReason":"fechado com motivo" }, "messages":{ - "reopenTitle":"Reabriu este ticket!", - "reopenDescription":"Sinta-se à vontade para falar novamente!", - "closedTitle":"Fechado este ticket!", "closedDescription":"Somente administradores podem falar neste ticket agora!\n\n*Clique no botão abaixo para excluir ou reabrir este ticket!*", "createdTitle":"Ticket criado!", "createdDescription":"Seu ticket foi criado, você pode detectá-lo com um ping!", @@ -71,11 +80,12 @@ "none":"vazio", "reason":"motivo", - + "createdat":"Criado por:", + "openedby":"Aberto por:", "deletedby":"deletado por", "closedby":"fechado por", + "modalreason":"Qual o motivo de fechar o ticket?", - "chooseATicket": "Fechar Ticket" }, "transcripts":{ diff --git a/language/romanian.json b/language/romanian.json index a41b65d..c38ecd1 100644 --- a/language/romanian.json +++ b/language/romanian.json @@ -24,10 +24,17 @@ "closeTitle":"Ticket inchis!", "deleteTitle":"Se sterge ticket-ul...", "reopenTitle":"Ticket Re-deschis!", - "claimTitle":"This ticket is now claimed to {0}", - "unclaimTitle":"This ticket isn't claimed anymore!", - "changeTitle":"Changed ticket type to {0}!", + "claimTitle":"Acest ticket a primit claim de la {0}", + "unclaimTitle":"Acest ticket nu mai este detinut!", + "changeTitle":"A fost schimbat tipul ticket-ului la {0}!", + + "statsTitle":"Acestea sunt informatiile pentru {0}!", + "autocloseTitle":"Acest ticket va fi inchis automat dupa {0}!", + "autocloseRejectTitle":"Acest ticket nu va mai fi inchis automat!", + "autocloseWarn":"Aceasta optiune afecteaza numai ticketele inactive!", + + "goToTicket":"Mergi la ticket", "ticketWarning":"Embed-ul se afla in mesajul de mai jos!", "maxTicketWarning":"**Avertizare:** _Poti creea doar {0} tickete active!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Sterge un ticket.", "addCmd":"Adauga un utilizator in ticket.", "removeCmd":"Sterge un utilizator din ticket.", - "reopenCmd":"Re-deschide un ticket dupa ce a fost deschis." + "reopenCmd":"Re-deschide un ticket dupa ce a fost deschis.", + "changeCmd":"Schimba categoria ticket-ului.", + "claimCmd":"Revendica un ticket", + "unclaimCmd":"Anuleaza revendicarea unui ticket.", + "statsCmd":"Afiseasa informatiile ticket-ului.", + "autocloseCmd":"Seteaza un cronometru pentru inchiderea ticket-ului." }, "buttons":{ "close":"Inchide ticket-ul", @@ -51,9 +63,6 @@ "closeWithReason":"Inchide cu motiv" }, "messages":{ - "reopenTitle":"Ticket Re-deschis!", - "reopenDescription":"Poti vorbi din nou!", - "closedTitle":"Ticket inchis!", "closedDescription":"Doar adminii pot vorbi in acest ticket acum!\n\n*Apasa pe butonul de mai jos pentru a re-deschide ori sterge ticket-ul!*", "createdTitle":"Ticket Creat!", "createdDescription":"Ticket-ul tau a fost creat, poti sa il vezi in canalul pe care ai fost mentionat!", @@ -71,9 +80,11 @@ "none":"niciunul", "reason":"Motiv", - + "createdat":"Creat la", + "openedby":"Deschis de", "deletedby":"Sters de", "closedby":"Inchis de", + "modalreason":"Care este motivul pentru inchiderea acestui ticket?", "chooseATicket": "Alege un ticket" }, diff --git a/language/russian.json b/language/russian.json index 640ffcb..d64d275 100644 --- a/language/russian.json +++ b/language/russian.json @@ -24,10 +24,17 @@ "closeTitle":"Закрыл этот тикет!", "deleteTitle":"Удаляем этот тикет...", "reopenTitle":"Открываем заново этот тикет!", + "claimTitle":"Этот тикет теперь взят {0}", "unclaimTitle":"Этот тикет никем не взят!", "changeTitle":"Изменён тип тикета на {0}!", + "statsTitle":"Here are the stats for {0}!", + "autocloseTitle":"This ticket will be closed automatically after {0}!", + "autocloseRejectTitle":"This ticket will no longer be closed automatically!", + "autocloseWarn":"This only affects inactive tickets!", + + "goToTicket":"go to ticket", "ticketWarning":"embed ниже сообщения!", "maxTicketWarning":"**Предупреждение:** _Вы можете создать только {0} тикет(а/ов) в этот раз!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Удалить тикет.", "addCmd":"Добавить пользователя в тикет.", "removeCmd":"Удалить пользователя из тикета.", - "reopenCmd":"Открыть заново тикет после того, как он был закрыт." + "reopenCmd":"Открыть заново тикет после того, как он был закрыт.", + "changeCmd":"Change ticket type.", + "claimCmd":"Claim a ticket.", + "unclaimCmd":"Unclaim a ticket.", + "statsCmd":"View ticket stats.", + "autocloseCmd":"Set timer to automatically close ticket" }, "buttons":{ "close":"Закрыть тикет", @@ -51,9 +63,6 @@ "closeWithReason":"закрыть с причиной" }, "messages":{ - "reopenTitle":"Открыл заново этот тикет!", - "reopenDescription":"Не стесняйтесь обращаться снова!", - "closedTitle":"Закрыл этот тикет!", "closedDescription":"Только админы теперь могут писать в этом тикете!\n\n*Нажмите на кнопку ниже, чтобы удалить или заново окрыть тикет!*", "createdTitle":"Тикет создан!", "createdDescription":"Ваш тикет создан, вы можете обнаружить его по пингу!", @@ -71,9 +80,11 @@ "none":"отсутствует", "reason":"причина", - + "createdat":"created at", + "openedby":"opened by", "deletedby":"удалён", "closedby":"закрыт", + "modalreason":"Какая причина закрытия этого тикета?", "chooseATicket": "Выберите тикет" }, diff --git a/language/spanish.json b/language/spanish.json index 3eb617f..44b9901 100644 --- a/language/spanish.json +++ b/language/spanish.json @@ -24,10 +24,17 @@ "closeTitle":"Cerró este ticket!", "deleteTitle":"Eliminando este ticket...", "reopenTitle":"Re-abrió este boleto!", - "claimTitle":"Este ticket será atendido por {0}", - "unclaimTitle":"¡Este ticket ya no está reservado!", - "changeTitle":"¡Cambiando el tipo de ticket a {0}!", + + "claimTitle":"Este ticket fué reclamado por {0}", + "unclaimTitle":"¡Este ticket se encuentra desatendido!", + "changeTitle":"¡Cambiado el tipo de ticket a {0}!", + "statsTitle":"¡Aquí están las estadísticas para {0}!", + "autocloseTitle":"¡Este ticket será cerrado después de {0}!", + "autocloseRejectTitle":"¡Cierre automático del ticket desactivado!", + "autocloseWarn":"¡Esto solo afecta tickets inactivos!", + + "goToTicket":"ir al ticket", "ticketWarning":"La inserción está en el mensaje a continuación!", "maxTicketWarning":"**Advertencia:** _Solo puedes crear {0} ticket(s) a la vez!_" }, @@ -42,7 +49,12 @@ "deleteCmd":"Eliminar un ticket.", "addCmd":"Agregar un usuario al ticket.", "removeCmd":"Eliminar un usuario del ticket.", - "reopenCmd":"Re-Abre un ticket después de que este se vea cerrado." + "reopenCmd":"Re-Abre un ticket después de que este se vea cerrado.", + "changeCmd":"Cambia el tipo de ticket.", + "claimCmd":"Reclama un ticket.", + "unclaimCmd":"Desatiende un ticket.", + "statsCmd":"Mira las estadísticas de los tickets.", + "autocloseCmd":"Establece un temporizador para cerrar el ticket." }, "buttons":{ "close":"Cerrar ticket.", @@ -51,9 +63,6 @@ "closeWithReason":"cerrar con razón" }, "messages":{ - "reopenTitle":"¡Ticket Re-Abierto!", - "reopenDescription":"¡Siéntete libre de hablar de nuevo!", - "closedTitle":"¡Ticket cerrado!", "closedDescription":"¡Solo admins pueden hablar ahora en este ticket!\n\n*¡Presiona en el botón de abajo para eliminar o re-abrir el ticket!*", "createdTitle":"¡Ticket creado!", "createdDescription":"¡Ticket creado, también te he mencionado en él!", @@ -71,9 +80,11 @@ "none":"Ninguna.", "reason":"Razón", - + "createdat":"creado el", + "openedby":"abierto por", "deletedby":"eliminado por", "closedby":"cerrado por", + "modalreason":"Cúal es la razón para cerrar este ticket?", "chooseATicket": "Elije un ticket" }, diff --git a/language/turkish.json b/language/turkish.json new file mode 100644 index 0000000..e09a912 --- /dev/null +++ b/language/turkish.json @@ -0,0 +1,98 @@ +{ + "errors":{ + "missingArgsTitle":"Geçersiz argümanlar!", + "missingArgsDescription":"Eksik argüman!", + "noPermsTitle":"Bunun için yetkin yok!", + "noPermsDescription":"Bunu yapmak için 'ADMİNİSTRAR'rolüne ihtiyacınız var, veya izin verilen roller listesinde olun!", + "noPermsDelete":"Sadece adminler bileti silebilir!", + "chooseFromListTitle":"Geçersiz Kimlik", + "chooseFromListDescription":"Aşağıdaki kimliklerden birini seçin:", + "boterror":"Bot Hatası!", + "notInTicketTitle":"Bir biletin yok!", + "notInTicketDescription":"Bu komut bilet dışında kullanılamaz!", + "ticketDoesntExist":"Bu bilet artık yok!", + "roleDoesntExist":"Bu rol artık yok!", + "anotherOption":"Bu seçenek bir bilet değil, başka bir türdür!", + "maxAmountTitle":"Ulaşabileceğin maksimum tutara ulaştın!", + "maxAmountDescription":"İzin verilen maksimum bilet sayısına ulaştınız!\nHhayır yeni bir tane oluşturamazsın!", + "somethingWentWrong":"**Bir şeyler ters gitti!**\n lütfen başka bir zaman tekrar deneyin!" + }, + "commands":{ + "userAddedTitle":"Bilete {0} adlı kullanıcı eklendi!", + "userRemovedTitle":"Biletten {0} adlı kullanıcı çıkarıldı !", + "renameTitle":"Bilet ismi {0} olarak değştirildi!", + "closeTitle":"Bilet Kapatıldı!", + "deleteTitle":"Bilet siliniyor...", + "reopenTitle":"Bilet Yeniden Açıldı!", + + "claimTitle":"Bu bilet artık talep edildi. {0}", + "unclaimTitle":"Tu bilet artık talep edilmiyor!", + "changeTitle":"Bu bilet türü {0} olarak değiştirildi!", + + "statsTitle":"Here are the stats for {0}!", + "autocloseTitle":"This ticket will be closed automatically after {0}!", + "autocloseRejectTitle":"This ticket will no longer be closed automatically!", + "autocloseWarn":"This only affects inactive tickets!", + + "goToTicket":"go to ticket", + "ticketWarning":"Gömme aşağıdaki mesajda yer almaktadır!", + "maxTicketWarning":"**Uyarı:** _You can only create {0} ticket(s) at a time!_" + }, + "helpMenu":{ + "title":"Kullanılabilir Komutlar:", + "header1":"**Bilet oluşturmak için {0} kanalını kullan!**\n\n", + "header2":"**Bilet oluşturmak için `/new` veya `/ticket' komutunu çalıştırın!**\n\n", + + "msgCmd":"Gömülü bilet mesajı gönderir. (sadece yöneticiler)", + "renameCmd":"Bilet adını değiştirir. (boşluk olmadan)", + "closeCmd":"Bileti kapatır.", + "deleteCmd":"Bileti siler.", + "addCmd":"Bilete kullanıcı ekler.", + "removeCmd":"Biletten kullanıcı çıkarır.", + "reopenCmd":"Bilet kapandıktan sonra tekrar açar.", + "changeCmd":"Change ticket type.", + "claimCmd":"Claim a ticket.", + "unclaimCmd":"Unclaim a ticket.", + "statsCmd":"View ticket stats.", + "autocloseCmd":"Set timer to automatically close ticket" + }, + "buttons":{ + "close":"Bileti Kapat", + "delete":"Bileti Sil", + "reopen":"Bileti Yeniden Aç", + "closeWithReason":"Bu bileti neden kapatıyorsun ?" + }, + "messages":{ + "closedDescription":"Bu bilette artık sadece yöneticiler konuşabilir!\n\n* Bu bileti silmek veya yeniden açmak için aşağıdaki butona tıklayın!*", + "createdTitle":"Talep Oluşturuldu!", + "createdDescription":"Your ticket is created, you can detect it by a ping!", + + "newTicketDmTitle":"Yeni Bilet!", + "closedTicketDmTitle":"Bilet Kapatıldı!", + "deletedTicketDmTitle":"Bilet Silindi!", + "closedTicketDmDescription":"Senin biletin kapatıldı!", + "deletedTicketDmDescription":"Senin biletin silindi!", + "reopenTicketDmTitle":"Bilet yeniden açıldı!", + "reopenTicketDmDescription":"Senin biletin yeniden açıldı!", + + "chooseCategory":"Bir kategori seç:", + "gettingdeleted":"Bu bilet siliniyor...", + + "none":"yok", + "reason":"sebep", + "createdat":"created at", + "openedby":"opened by", + "deletedby":"Silen kişi", + "closedby":"Kapatan kişi", + + "modalreason":"Bu biletin kapanmasının sebebi nedir?", + "chooseATicket": "Bir bilet seçin" + }, + "transcripts":{ + "title":"Transkript", + "processed":"Bu transkript işleniyor", + "wait":"Lütfen Bekleyiniz!", + "estimated":"Tahmini Süre", + "available":"Transkript burada mevcuttur" + } +} \ No newline at end of file diff --git a/package.json b/package.json index af73f54..1c321a9 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "open-ticket", - "version": "3.2.2", + "version": "3.3.0", "description": "This is an open-source discord ticket bot, you can configure it and it comes with cool features like a transcript.", "main": "index.js", "scripts": { "start": "node index.js", - "test": "node index.js d", + "test": "node index.js --devconfig", "slashEnable": "node index.js slash enable", "slashDisable": "node index.js slash disable", "cleardata": "node ./core/dynamicdatabase/cleardata.js" @@ -15,7 +15,7 @@ "dependencies": { "axios": "^0.27.2", "chalk": "^5.0.1", - "discord.js": "^14.7.1", + "discord.js": "^14.8.0", "node": "^16.10.0" }, "repository": { diff --git a/transcriptconfig.json b/transcriptconfig.json index c7c536b..a5c003c 100644 --- a/transcriptconfig.json +++ b/transcriptconfig.json @@ -1,10 +1,10 @@ { "sendTranscripts":{ "enableChannel":false, + "enableDM":false, + "channel":"transcript channel id", - "useHTMLtranscripts":true, - - "enableDM":false + "useHTMLtranscripts":true }, "style":{ "titleColor":"#F8BA00",