diff --git a/.gitignore b/.gitignore index e485366..a45912f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ openticketdebug.txt developerChangelog.md storage/dynamicDB/ storage/.DS_Store -.vscode/ \ No newline at end of file +.vscode/ +livestatus.json +test.js \ No newline at end of file diff --git a/README.md b/README.md index 525c76a..930c163 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,10 @@ -## We need translators! -If you know a language that isn't already in open ticket and you can write json, -then is this the job for you! +# 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.0.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v3.0.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) [![documentation](https://img.shields.io/badge/documentation-Click%20Here-yellow.svg?style=flat-square)](https://docs.openticket.dj-dj.be) -make a ticket in our server to start! +Open ticket is the most configurable open-source ticket bot for discord! Made with the newest technologies. Like: Slash commands, transcripts, multiple ticket types, buttons & dropdowns! +Start using it now, you can do anything! -*if you translate, you will come in the credits* - -# 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-2.5.0-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v2.5.0) [![npm](https://img.shields.io/badge/npm-external%20libraries%20needed-CB3837.svg?style=flat-square&logo=npm)](#packages) [![license](https://img.shields.io/badge/license-GPL%203.0-important.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/blob/main/LICENSE) - -This is an open-source discord ticket bot, you can configure it and it comes with cool features like transcripts & custom options! +*We love to hear suggestions for more features!* Open Ticket logo @@ -20,68 +15,45 @@ This is an open-source discord ticket bot, you can configure it and it comes wit - Sanke: for translation & new ideas - Everyone that reported a bug #### And our translators! -- ExothDE: for translation -- 1x1: for translation -- R0JO: for translation -- t0miiis for translation +- ExothDE +- 1x1 +- Redactado +- t0miiis +- josuens14 +- M4 +- David. +- Maurizio ## features - discord interaction buttons - slash & text commands - close, delete & re-open tickets -- translation in 8 different languages -- dynamic database system +- translation in 10 different languages - transcripts - add/remove users from a ticket -- custom colors & name for embeds -- customise your ticket -- create url buttons for websites -- create reaction roles -- build with discord.js v14 -- configure everything per ticket -- remove credits if you want :( +- a lot of customisation options. +- tickets, reaction roles & links are all possible! +- choose between buttons or dropdowns! +- discord.js v14 +- everyting is configurable +- custom API + plugins - unlimited tickets spread over multiple messages - -*comming soon:* -- dashboard -- view transcripts in dashboard -- share transcripts - close with reason -- more translation -## installation -**You need `node.js 16` to run this project!** +*comming soon* +- share transcripts +- view transcripts in html -### packages -- chalk => version `latest` -- discord.js => version `latest` -- express => version `latest` -- node-localstorage => version `latest` -- axios => version `latest` +## quick start +[Click here to start your adventure!](https://docs.openticket.dj-dj.be/quick-start) -You can install all of them by running `npm install` - -## running -you can run `node index.js` but i would recommend you to use `npm start` - -if there are any errors, you can open an **issue on github** or **contact me in our discord server**. - -### config -Our config documentation is moved to another file: -[click here to view](https://www.github.com/DJj123dj/open-ticket/wiki/config-v2.5.0) - -### intents & permissions -In the discord developer portal in the "bot" panel you will find 3 switches under the title "Gateaway Intents". The following switches should always be turned on -- `SERVER MEMBERS INTENT` -- `MESSAGE CONTENT INTENT` - -To work the best, the bot needs `ADMINISTRATOR` permissions. -You can also configure your own permissions +## documentation +[Official Documentation](https://docs.openticket.dj-dj.be) ## information -_v2.5.0 stable_ +_v3.0.0_ -changelog: [click here](https://www.github.com/DJj123dj/open-ticket/wiki/Changelog) +changelog: [click here](https://docs.openticket.dj-dj.be/other/changelog) © 2022 - DJdj Development | [website](https://www.dj-dj.be) | [discord](https://discord.dj-dj.be) | [terms of service](https://www.dj-dj.be/terms) \ No newline at end of file diff --git a/commands/add.js b/commands/add.js index 337670a..f88c28a 100644 --- a/commands/add.js +++ b/commands/add.js @@ -7,9 +7,12 @@ const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { - client.on("messageCreate",msg => { + bot.errorLog.log("debug","COMMANDS: loaded add.js") + + if (!DISABLE.commands.text.add) client.on("messageCreate",msg => { if (!msg.content.startsWith(config.prefix+"add")) return var user = msg.mentions.users.first() if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"add `")]}) @@ -27,13 +30,13 @@ module.exports = () => { const ticketId = hiddendata.data.find(d => d.key == "type").value msg.channel.permissionOverwrites.create(user.id, { ViewChannel:true, AddReactions:true,AttachFiles:true, EmbedLinks:true, SendMessages:true}) - msg.channel.send({embeds:[bot.embeds.commands.addEmbed(user)]}) + msg.channel.send({embeds:[bot.embeds.commands.addEmbed(user,msg.author)]}) var loguser = msg.mentions.users.first() log("command","someone used the 'add' command",[{key:"user",value:msg.author.tag}]) log("system","user added to ticket",[{key:"user",value:msg.author.tag},{key:"ticket",value:msg.channel.name},{key:"added_user",value:loguser.tag}]) - const ticketData = require("../core/getoptions").getOptionsById("OTnewT"+ticketId) + 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()) @@ -41,7 +44,7 @@ module.exports = () => { }) - client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.add) client.on("interactionCreate",(interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "add") return const user = interaction.options.getUser("user") @@ -59,13 +62,13 @@ module.exports = () => { 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.reply({embeds:[bot.embeds.commands.addEmbed(user,interaction.user)]}) var loguser = user log("command","someone used the 'add' command",[{key:"user",value:interaction.user.tag}]) log("system","user added to ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name},{key:"added_user",value:loguser.tag}]) - const ticketData = require("../core/getoptions").getOptionsById("OTnewT"+ticketId) + 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()) diff --git a/commands/claim.js b/commands/claim.js new file mode 100644 index 0000000..ff17fc2 --- /dev/null +++ b/commands/claim.js @@ -0,0 +1,80 @@ +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 permsChecker = require("../core/utils/permisssionChecker") + +const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable + +module.exports = () => { + bot.errorLog.log("debug","COMMANDS: loaded claim.js") + + if (!DISABLE.commands.text.claim) client.on("messageCreate",msg => { + if (!msg.content.startsWith(config.prefix+"claim")) return + var user = msg.mentions.users.first() + + const claimingUser = user ? user : msg.author + + if (!msg.guild) return + if (!permsChecker.command(msg.author.id,msg.guild.id)){ + permsChecker.sendUserNoPerms(msg.author) + return + } + + msg.channel.messages.fetchPinned().then(msglist => { + 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 ticketId = hiddendata.data.find(d => d.key == "type").value + + + //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!")]}) + + 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()) + }) + + }) + + if (!DISABLE.commands.slash.claim) client.on("interactionCreate",(interaction) => { + if (!interaction.isChatInputCommand()) return + if (interaction.commandName != "claim") return + const user = interaction.options.getUser("user",false) ? interaction.options.getUser("user",true) : interaction.user + + if (!interaction.guild) return + if (!permsChecker.command(interaction.user.id,interaction.guild.id)){ + permsChecker.sendUserNoPerms(interaction.user) + return + } + + 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]}) + 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.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!")]}) + + 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}]) + + 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()) + + }) + + + }) +} \ No newline at end of file diff --git a/commands/close.js b/commands/close.js index 2c05d85..15d36f9 100644 --- a/commands/close.js +++ b/commands/close.js @@ -7,11 +7,22 @@ const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { - client.on("messageCreate",msg => { + bot.errorLog.log("debug","COMMANDS: loaded close.js") + + if (!DISABLE.commands.text.close) client.on("messageCreate",msg => { if (!msg.content.startsWith(config.prefix+"close")) return + const args = msg.content.substring((config.prefix+"close").length).split(" ") + args.shift() + /**@type {String|false} */ + var tempreason = args.join(" ") + if (!tempreason || tempreason == " " || tempreason == " "){ + tempreason = false + } + const reason = tempreason msg.channel.messages.fetchPinned().then(msglist => { var firstmsg = msglist.last() @@ -19,7 +30,10 @@ module.exports = () => { const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - msg.channel.send({embeds:[bot.embeds.commands.closeEmbed(msg.author)],components:[bot.buttons.close.closeCommandRow]}) + if (hiddendata.data.find(h => h.key == "pendingdelete")) return msg.channel.send({embeds:[bot.errorLog.warning("Warning!","You can't close a ticket while it's being deleted!")]}) + + const descriptionReason = reason ? "**"+l.messages.reason+":** "+reason : false + msg.channel.send({embeds:[bot.embeds.commands.closeEmbed(msg.author,descriptionReason)],components:[bot.buttons.close.closeCommandRow]}) var name = msg.channel.name var prefix = "" @@ -30,7 +44,7 @@ module.exports = () => { } }) - require("../core/ticketCloser").NEWcloseTicket(msg.member,msg.channel,prefix,"close",false,true) + require("../core/ticketActions/ticketCloser").NEWcloseTicket(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()) @@ -40,19 +54,24 @@ module.exports = () => { }) - client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.close) client.on("interactionCreate",(interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "close") return //interaction.deferReply() + const reason = interaction.options.getString("reason") ? interaction.options.getString("reason") : false + 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]}) 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.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) + 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!")]}) + + const descriptionReason = reason ? "**"+l.messages.reason+":** "+reason : false + interaction.reply({embeds:[bot.embeds.commands.closeEmbed(interaction.user,descriptionReason)],components:[bot.buttons.close.closeCommandRow]}) var name = interaction.channel.name var prefix = "" @@ -63,7 +82,7 @@ module.exports = () => { } }) - require("../core/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close",false,true) + require("../core/ticketActions/ticketCloser").NEWcloseTicket(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 5e2a6f1..4b5f5b1 100644 --- a/commands/delete.js +++ b/commands/delete.js @@ -7,9 +7,12 @@ const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { - client.on("messageCreate",msg => { + bot.errorLog.log("debug","COMMANDS: loaded delete.js") + + if (!DISABLE.commands.text.delete) client.on("messageCreate",msg => { if (!msg.content.startsWith(config.prefix+"delete")) return if (!msg.guild) return @@ -35,7 +38,7 @@ module.exports = () => { } }) - require("../core/ticketCloser").NEWcloseTicket(msg.member,msg.channel,prefix,"delete",false,true) + require("../core/ticketActions/ticketCloser").NEWcloseTicket(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()) @@ -44,7 +47,7 @@ module.exports = () => { }) - client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.delete) client.on("interactionCreate",(interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "delete") return @@ -53,7 +56,7 @@ module.exports = () => { if (!interaction.guild) return if (!permsChecker.command(interaction.user.id,interaction.guild.id)){ permsChecker.sendUserNoPerms(interaction.user) - return interaction.reply({embeds:[bot.errorLog.noPermsDelete]}) + return interaction.reply({embeds:[bot.errorLog.noPermsDelete(interaction.user)]}) } interaction.channel.messages.fetchPinned().then(msglist => { @@ -73,7 +76,7 @@ module.exports = () => { } }) - require("../core/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true) + require("../core/ticketActions/ticketCloser").NEWcloseTicket(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 cfdeaee..9c19abc 100644 --- a/commands/help.js +++ b/commands/help.js @@ -6,21 +6,26 @@ const log = bot.errorLog.log const l = bot.language const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { + bot.errorLog.log("debug","COMMANDS: loaded help.js") + + const msgName = config.system.showSlashcmdsInHelp ? "message" : "msg" + const prefix = config.system.showSlashcmdsInHelp ? "/" : config.prefix + const helpEmbed = new discord.EmbedBuilder() .setColor(config.main_color) .setTitle("❔ "+l.helpMenu.title) - const prefix = config.prefix const header = config.system.ticket_channel ? l.helpMenu.header1.replace("{0}","<#"+config.system.ticket_channel+">") : l.helpMenu.header2 - helpEmbed.setDescription(header+"`"+prefix+"msg ` ➜ _"+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+"_`") + 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+"_") if (config.credits) helpEmbed.setFooter({text:"Open-Ticket by DJdj Development | view on github for source code",iconURL:"https://raw.githubusercontent.com/DJj123dj/open-ticket/main/logo.png"}) var otherprefix = prefix.endsWith(" ") ? prefix.substring(0,prefix.length-1) : prefix - client.on("messageCreate",msg => { + if (!DISABLE.commands.text.help) client.on("messageCreate",msg => { if (!msg.content.startsWith(config.prefix)) return var args = msg.content.split(config.prefix) @@ -40,7 +45,7 @@ module.exports = () => { } }) - client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.help) client.on("interactionCreate",(interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "help") return diff --git a/commands/remove.js b/commands/remove.js index cc6e6c0..e5f8a4a 100644 --- a/commands/remove.js +++ b/commands/remove.js @@ -7,9 +7,12 @@ const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { - client.on("messageCreate",msg => { + bot.errorLog.log("debug","COMMANDS: loaded remove.js") + + if (!DISABLE.commands.text.remove) client.on("messageCreate",msg => { if (!msg.content.startsWith(config.prefix+"remove")) return var user = msg.mentions.users.first() if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" ``:\n`"+config.prefix+"remove `")]}) @@ -27,21 +30,21 @@ module.exports = () => { const ticketId = hiddendata.data.find(d => d.key == "type").value msg.channel.permissionOverwrites.delete(user.id) - msg.channel.send({embeds:[bot.embeds.commands.removeEmbed(user)]}) + msg.channel.send({embeds:[bot.embeds.commands.removeEmbed(user,msg.author)]}) var loguser = msg.mentions.users.first() log("command","someone used the 'remove' command",[{key:"user",value:msg.author.tag}]) log("system","user removed from ticket",[{key:"user",value:msg.author.tag},{key:"ticket",value:msg.channel.name},{key:"removed_user",value:loguser.tag}]) - const ticketData = require("../core/getoptions").getOptionsById("OTnewT"+ticketId) + const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) APIEvents.onTicketRemove(msg.author,loguser,msg.channel,msg.guild,new Date(),{status:"open",name:msg.channel.name,ticketOptions:ticketData}) APIEvents.onCommand("remove",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date()) }) }) - client.on("interactionCreate",async (interaction) => { + if (!DISABLE.commands.slash.remove) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "remove") return const user = interaction.options.getUser("user") @@ -59,14 +62,14 @@ module.exports = () => { 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.reply({embeds:[bot.embeds.commands.removeEmbed(user,interaction.user)]}) var loguser = user log("command","someone used the 'remove' command",[{key:"user",value:interaction.user.tag}]) log("system","user removed from ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name},{key:"removed_user",value:loguser.tag}]) - const ticketData = require("../core/getoptions").getOptionsById("OTnewT"+ticketId) + const ticketData = require("../core/utils/configParser").getTicketById(ticketId,true) APIEvents.onTicketRemove(interaction.user,loguser,interaction.channel,interaction.guild,new Date(),{status:"open",name:interaction.channel.name,ticketOptions:ticketData}) APIEvents.onCommand("remove",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date()) }) diff --git a/commands/rename.js b/commands/rename.js index 1f8a032..6741658 100644 --- a/commands/rename.js +++ b/commands/rename.js @@ -7,9 +7,12 @@ const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { - client.on("messageCreate",msg => { + bot.errorLog.log("debug","COMMANDS: loaded rename.js") + + if (!DISABLE.commands.text.rename) client.on("messageCreate",msg => { if (!msg.content.startsWith(config.prefix+"rename")) return if (!msg.guild) return @@ -50,7 +53,7 @@ module.exports = () => { }) - client.on("interactionCreate",(interaction) => { + if (!DISABLE.commands.slash.rename) client.on("interactionCreate",(interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "rename") return diff --git a/commands/reopen.js b/commands/reopen.js index c12b991..3c86a0f 100644 --- a/commands/reopen.js +++ b/commands/reopen.js @@ -7,9 +7,12 @@ const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { - client.on("messageCreate",msg => { + bot.errorLog.log("debug","COMMANDS: loaded reopen.js") + + if (!DISABLE.commands.text.reopen) client.on("messageCreate",msg => { if (!msg.content.startsWith(config.prefix+"reopen")) return msg.channel.messages.fetchPinned().then(msglist => { @@ -18,9 +21,11 @@ module.exports = () => { 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 msg.channel.send({embeds:[bot.errorLog.warning("Warning!","You can't re-open a ticket while it's being deleted!")]}) + msg.channel.send({embeds:[bot.embeds.commands.reopenEmbed(msg.author)],components:[bot.buttons.close.openRowNormal]}) - require("../core/ticketReopener").reopenTicket(msg.guild,msg.channel,msg.author) + require("../core/ticketActions/ticketReopener").reopenTicket(msg.guild,msg.channel,msg.author) log("command","someone used the 'reopen' command",[{key:"user",value:msg.author.tag}]) APIEvents.onCommand("reopen",true,msg.author,msg.channel,msg.guild,new Date()) @@ -28,7 +33,7 @@ module.exports = () => { }) - client.on("interactionCreate",async (interaction) => { + if (!DISABLE.commands.slash.reopen) client.on("interactionCreate",async (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "reopen") return @@ -40,9 +45,11 @@ module.exports = () => { 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!")]}) + await interaction.reply({embeds:[bot.embeds.commands.reopenEmbed(interaction.user)],components:[bot.buttons.close.openRowNormal]}) - require("../core/ticketReopener").reopenTicket(interaction.guild,interaction.channel,interaction.user) + require("../core/ticketActions/ticketReopener").reopenTicket(interaction.guild,interaction.channel,interaction.user) log("command","someone used the 'reopen' command",[{key:"user",value:interaction.user.tag}]) APIEvents.onCommand("reopen",true,interaction.user,interaction.channel,interaction.guild,new Date()) diff --git a/commands/ticket.js b/commands/ticket.js index d64d7c4..5f8e2bc 100644 --- a/commands/ticket.js +++ b/commands/ticket.js @@ -7,8 +7,11 @@ const l = bot.language const permsChecker = require("../core/utils/permisssionChecker") const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable module.exports = () => { + bot.errorLog.log("debug","COMMANDS: loaded ticket.js") + /**@type {String[]} */ var msgIds = [] config.messages.forEach((msg) => { @@ -16,7 +19,7 @@ module.exports = () => { }) - client.on("messageCreate", msg => { + if (!DISABLE.commands.text.msg) client.on("messageCreate", msg => { if (msg.content.startsWith(config.prefix+"msg"||config.prefix+"message")){ if (!msg.guild) return @@ -31,7 +34,7 @@ module.exports = () => { if (!msgIds.includes(id)) return msg.channel.send({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds)]}) - const {embed,componentRows} = require("../core/ticketMessageEmbed").createEmbed(id) + const {embed,componentRows} = require("../core/utils/getEmbed").createEmbed(id) msg.channel.send({embeds:[embed],components:componentRows}) @@ -40,7 +43,7 @@ module.exports = () => { } }) - client.on("interactionCreate", (interaction) => { + if (!DISABLE.commands.slash.msg) client.on("interactionCreate", (interaction) => { if (!interaction.isChatInputCommand()) return if (interaction.commandName != "message") return @@ -54,7 +57,7 @@ module.exports = () => { if (!msgIds.includes(id)) return interaction.reply({embeds:[bot.errorLog.invalidIdChooseFromList(msgIds)]}) - const {embed,componentRows} = require("../core/ticketMessageEmbed").createEmbed(id) + const {embed,componentRows} = require("../core/utils/getEmbed").createEmbed(id) interaction.reply({content:l.commands.ticketWarning}) interaction.channel.send({embeds:[embed],components:componentRows}) diff --git a/commands/unclaim.js b/commands/unclaim.js new file mode 100644 index 0000000..be01a4d --- /dev/null +++ b/commands/unclaim.js @@ -0,0 +1,77 @@ +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 permsChecker = require("../core/utils/permisssionChecker") + +const APIEvents = require("../core/api/modules/events") +const DISABLE = require("../core/api/api.json").disable + +module.exports = () => { + bot.errorLog.log("debug","COMMANDS: loaded unclaim.js") + + if (!DISABLE.commands.text.unclaim) client.on("messageCreate",msg => { + if (!msg.content.startsWith(config.prefix+"unclaim")) return + + if (!msg.guild) return + if (!permsChecker.command(msg.author.id,msg.guild.id)){ + permsChecker.sendUserNoPerms(msg.author) + return + } + + msg.channel.messages.fetchPinned().then(msglist => { + 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 ticketId = hiddendata.data.find(d => d.key == "type").value + + + //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 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 (!DISABLE.commands.slash.unclaim) client.on("interactionCreate",(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)){ + permsChecker.sendUserNoPerms(interaction.user) + return + } + + 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]}) + 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.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}]) + + 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()) + + }) + + + }) +} \ No newline at end of file diff --git a/config.json b/config.json index d09e42b..729f66c 100644 --- a/config.json +++ b/config.json @@ -24,7 +24,9 @@ "enable_transcript":false, "enable_DM_transcript":false, - "transcript_channel":"channel id" + "transcript_channel":"channel id", + + "showSlashcmdsInHelp":false }, "options":[ @@ -41,8 +43,18 @@ "channelprefix":"question-", "category":"category id", "message":"You created a ticket!", - "enableDMMessage":true, - "ticketmessage":"The staff will help you soon!\n\n*Click on the button below to close the ticket!*" + "enableDmOnOpen":true, + "ticketmessage":"The staff will help you soon!\n\n*Click on the button below to close the ticket!*", + + "thumbnail":{ + "enable":false, + "url":"https://www.example.com/catmemes/cat.png" + }, + + "closedCategory":{ + "enable":false, + "id":"category id" + } }, { @@ -67,7 +79,7 @@ "color":"red", "roles":["discord role id"], "mode":"add&remove|remove|add", - "enableDMMessage":true + "enableDmOnOpen":true } ], @@ -77,9 +89,10 @@ "id":"1", "name":"Choose Your Ticket", "description":"You can click one of the buttons below!", + "dropdown":false, "enableFooter":false, - "footer":"Open Ticket v2.5.0 - I'm a footer!", + "footer":"Open Ticket v3.0.0 - I'm a footer!", "enableThumbnail":false, "thumbnail":"https://www.example.com/catmemes/cat.png", diff --git a/core/api/api.json b/core/api/api.json index 03dd942..6832775 100644 --- a/core/api/api.json +++ b/core/api/api.json @@ -1,10 +1,13 @@ { "version":"1.0.0", + "enableAPIdebug":false, + "enableAPIconsolelogs":false, - - "disclaimer":"DISABLE doesn't work yet! Below this message!", + "info":"If you turn these switches to true, then the feature will be turned OFF!", + "info2":"You can use this to disable some features you don't want!", "disable":{ "messages":{ + "DISCLAIMER":"the messages part doesn't work yet!", "ticketCreated":false, "ticketClosed":false, "ticketDeleted":false, @@ -24,7 +27,9 @@ "new":false, "add":false, "remove":false, - "rename":false + "rename":false, + "claim":false, + "unclaim":false }, "slash":{ "help":false, @@ -35,12 +40,18 @@ "new":false, "add":false, "remove":false, - "rename":false + "rename":false, + "claim":false, + "unclaim":false } }, "checkerjs":{ "token":false, "all":false + }, + "debug":{ + "all":false, + "debuglogs":false } } } \ No newline at end of file diff --git a/core/api/modules/base.js b/core/api/modules/base.js index 1f96c22..8d4921e 100644 --- a/core/api/modules/base.js +++ b/core/api/modules/base.js @@ -1,28 +1,8 @@ -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 - /** FOR DEVELOPERS ONLY!! - * Don't change anything in this file, read the api documentation first! - * look into "api docs.md" for the docs! + * Don't change anything in this file before reading the documentation! + * visit the api documentation at https://docs.openticket.dj-dj.be */ -//used when creating plugins! -exports.enableApiLogs = false - -//DOESN'T WORK YET -//this is used when embedding open ticket into another bot exports.embeddedMode = false -exports.clientLocation = require("../../../index").client - -/** !! WARNING !! - * Only edit or extend the code when you know what you are doing! - * If open ticket crashes while you change the code, then we can't help you! - * - * DO IT ON YOUR OWN RISK! - */ \ No newline at end of file +exports.clientLocation = require("../../../index").client \ No newline at end of file diff --git a/core/api/pluginlauncher.js b/core/api/pluginlauncher.js index 3c5a34d..3c6877e 100644 --- a/core/api/pluginlauncher.js +++ b/core/api/pluginlauncher.js @@ -4,7 +4,7 @@ const log = bot.errorLog.log module.exports = () => { const files = fs.readdirSync("./plugins") - + const api = require("./api.json") var totalcount = 0 var successcount = 0 var failcount = 0 @@ -15,7 +15,14 @@ module.exports = () => { successcount++ totalcount++ - }catch{ + }catch(err){ + /**@type {Error} */ + const theError = err + if (api.enableAPIdebug){ + const data = fs.readFileSync("./apiDebug.txt") + const newData = data ? data.toString() : "" + fs.writeFileSync("./apiDebug.txt",newData+"ERROR: "+theError.name+": "+theError.message+"\n"+theError.stack+"\n\n") + } failcount++ totalcount++ } diff --git a/core/checker.js b/core/checker.js index c86a9cf..db98bca 100644 --- a/core/checker.js +++ b/core/checker.js @@ -1,6 +1,17 @@ exports.checker = async () => { const chalk = await (await import("chalk")).default - const config = require("../config.json") + + if (process.argv.some((v) => v == "--nochecker")) return + if (process.argv.some((v) => v == "--devconfig")){ + //console.log(chalk.blue("=> used dev config instead of normal config")) + try{ + var tempconfig = require("../devConfig.json") + }catch(err){console.log(err);var tempconfig = require("../config.json")} + }else{ + var tempconfig = require("../config.json") + } + + const config = tempconfig var errorList = [] var isError = false var warnList = [] @@ -41,9 +52,10 @@ exports.checker = async () => { } /**@param {String} value */ const checkToken = (value) => { - if (value.includes(" ") || value.length < 40){ + if (value.length < 40){ createError("'auth_token' | your token is invalid") } + if (value.includes(" ")) createError("'auth_token' | your token includes spaces!") } /**@param {String} value @param {String} path */ @@ -122,8 +134,12 @@ exports.checker = async () => { } } - const getButtonClass = require("./utils/getButton").rawButtonData - /**@param {getButtonClass} option */ + const configParser = require("./utils/configParser") + /** + * @param {configParser.OTAllOptions} option + * @param {String} path + */ + const checkOption = (option,path) => { //id @@ -195,12 +211,23 @@ exports.checker = async () => { //message checkType(option.message,"string",path+"/message") - //enableDMmessage - checkType(option.enableDMMessage,"boolean",path+"/enableDMMessage") + //enableDmOnOpen + checkType(option.enableDmOnOpen,"boolean",path+"/enableDmOnOpen") //ticketmessage checkType(option.ticketmessage,"string",path+"/ticketmessage") + //thumbnail + checkType(option.thumbnail.enable,"boolean",path/"/thumbnail/enable") + checkType(option.thumbnail.url,"string",path/"/thumbnail/url") + + //closedCategory + checkType(option.closedCategory.enable,"boolean",path/"/closedCategory/enable") + checkType(option.closedCategory.id,"string",path/"/closedCategory/id") + if (option.closedCategory.enable){ + checkDiscord("roleid",option.closedCategory.id,path+"/closedCategory/id") + } + }else if (type == "website"){ //url checkType(option.url,"string",path+"/url") @@ -208,13 +235,13 @@ exports.checker = async () => { createWarn("'"+path+"/url' | a url can't contain spaces") } if (option.url.length < 1){ - createError("'"+path+"/url' | you have no url in this button") + createError("'"+path+"/url' | there is no url!") } if (!option.url.startsWith("https://") && !option.url.startsWith("http://") && !option.url.startsWith("discord://")){ createWarn("'"+path+"/url' | your url doesn't start with https or http!") } if (option.url.startsWith("http://")){ - createWarn("'"+path+"/url' | your url is not a HTTPS link! discord maybe blocks this url!") + createWarn("'"+path+"/url' | your url is not a HTTPS link! discord can block this url!") } }else if (type == "role"){ //color @@ -230,13 +257,74 @@ exports.checker = async () => { createError("'"+path+"/mode' | mode must be one of these: add, remove, add&remove") } - //enableDMmessage - checkType(option.enableDMMessage,"boolean",path+"/enableDMMessage") + //enableDmOnOpen + checkType(option.enableDmOnOpen,"boolean",path+"/enableDmOnOpen") } } + /** + * + * @param {configParser.OTConfigMessage} input + * @param {String} path + */ const checkMessage = (input,path) => { + //id + if (!input.id) createError("'"+path+"/id' | this embed doesn't have an id!") + if (input.id.length > 50) createError("'"+path+"/id' | the id can't be longer than 50") + if (input.id.includes(" ") || input.id.includes("\n")) createError("'"+path+"/id' | the id can't contain spaces!") + //name + if (input.name.length < 1){ + createWarn("'"+path+"/name' | this embed has no name!") + }else if (input.name.length > 99) { + createError("'"+path+"/name' | the name can't be longer than 100") + } + + //description + if (input.description.length < 0){ + createWarn("'"+path+"/description' | this embed doesn't have a description!") + } + + //dropdown + checkType(input.dropdown,"boolean",path+"/dropdown") + + //footer + checkType(input.enableFooter,"boolean",path+"/enableFooter") + if (input.enableFooter){ + if (input.footer.length < 1) createError("'"+path+"/footer' | no footer!") + if (input.footer.length > 200) createError("'"+path+"/footer' | footer length can't be more than 200!") + } + + //thumbnail + checkType(input.enableThumbnail,"boolean",path+"/enableThumbnail") + if (input.enableThumbnail){ + if (input.thumbnail.length < 1) createError("'"+path+"/thumbnail' | no thumbnail url!") + } + + //customColor + checkType(input.enableCustomColor,"boolean",path+"/enableCustomColor") + if (input.enableCustomColor){ + if (input.color.length < 1) createError("'"+path+"/color' | no color!") + checkHexColor(input.color,path+"/color") + } + + //ticket explaination & max tickets warning + checkType(input.enableTicketExplaination,"boolean",path+"/enableTicketExplaination") + checkType(input.enableMaxTicketsWarning,"boolean",path+"/enableMaxTicketsWarning") + + //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!") + } + }) + } } //--------------------------| @@ -254,27 +342,30 @@ exports.checker = async () => { checkHexColor(config.main_color,"main_color") checkDiscord("serverid",config.server_id,"server_id") - checkToken(config.auth_token) + + if (!require("./api/api.json").disable.checkerjs.token) checkToken(config.auth_token) + checkDiscordArray("roleid",config.main_adminroles,"main_adminroles") checkString(config.prefix,1,15,"prefix","prefix") //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")){ + + 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")){ createError("'languagefile' | invalid language, more info in the wiki") } - checkType(config.credits,"boolean","credits") //status: checkType(config.status.enabled,"boolean","status/enabled") if (config.status.enabled){ if (config.status.type != "PLAYING" && config.status.type != "LISTENING" && config.status.type != "WATCHING"){ - createError("'status/type' | not a valid status type!") + createError("'status/type' | not a valid status type! (LISTENING,WATCHING,PLAYING)") } - if (config.status.text.length < 1 || config.status.text.length > 40){ - createError("'status/text' | text too long or short!") + if (config.status.text.length < 1){ + createError("'status/text' | there is no status text!") } + if (config.status.text.length > 50) createError("'status/text' | text too long!") } @@ -302,6 +393,7 @@ exports.checker = async () => { if (config.system.enable_transcript){ checkDiscord("channelid",config.system.transcript_channel,"system/transcript_channel") } + checkType(config.system.showSlashcmdsInHelp,"boolean","system/showSlashcmdsInHelp") //options @@ -309,6 +401,11 @@ exports.checker = async () => { checkOption(option,"options/"+index) }) + //messages + config.messages.forEach((message,index) => { + checkMessage(message,"messages/"+index) + }) + //discord check /** diff --git a/core/closebuttons.js b/core/closebuttons.js deleted file mode 100644 index 03e1d7c..0000000 --- a/core/closebuttons.js +++ /dev/null @@ -1,331 +0,0 @@ -const discord = require('discord.js') -const bot = require('../index') -const client = bot.client -const config = bot.config -const l = bot.language - - -module.exports = () => { - //closebar - var closeBar = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("closeTicketTrue") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("✅") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("closeTicketFalse") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("❌") - ) - var deleteBar = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicketTrue") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("✅") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicketFalse") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("❌") - ) - var deleteBar1 = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicketTrue1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("✅") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicketFalse1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("❌") - ) - //closebutton - var closeRowNormal = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("closeTicket") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicket") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - var closeRowClosed = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicket1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("sendTranscript") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setLabel(l.buttons.sendTranscript) - .setEmoji("📄") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("reopenTicket") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Success) - .setLabel(l.buttons.reopen) - .setEmoji("✔") - ) - - var closeRowDisabled = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("closeTicket") - .setDisabled(true) - .setStyle(discord.ButtonStyle.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicket") - .setDisabled(true) - .setStyle(discord.ButtonStyle.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - - - //NORMAL CLOSE - client.on("interactionCreate",interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "closeTicket") return - - interaction.deferUpdate() - interaction.message.edit({components:[closeBar]}) - - }) - client.on("interactionCreate",interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "closeTicketFalse") return - - interaction.deferUpdate() - interaction.message.edit({components:[closeRowNormal]}) - }) - - var closeTicketButtonChecker = false - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "closeTicketTrue") return - - interaction.deferUpdate() - - if (closeTicketButtonChecker == true) return - closeTicketButtonChecker = true - - if (config.system.closeMode == "adminonly"){ - const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) - if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ - try { - return msg.member.send({embeds:[bot.errorLog.noPermsMessage]}) - }catch{ - return msg.channel.send({embeds:[bot.errorLog.noPermsMessage]}) - } - } - } - - interaction.message.edit({components:[closeRowDisabled]}) - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close") - closeTicketButtonChecker = false - }) - - var closeTicket1ButtonChecker = false - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "closeTicketTrue1") return - - interaction.deferUpdate() - - if (closeTicket1ButtonChecker == true) return - closeTicket1ButtonChecker = true - - if (config.system.closeMode == "adminonly"){ - const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) - if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ - try { - return interaction.member.send({embeds:[bot.errorLog.noPermsMessage]}) - }catch{ - return interaction.channel.send({embeds:[bot.errorLog.noPermsMessage]}) - } - } - } - - const closedButtonDisabled = new discord.ActionRowBuilder() - .addComponents([ - new discord.ButtonBuilder() - .setCustomId("closeTicketTrue1") - .setDisabled(true) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("🔒") - ]) - interaction.message.edit({components:[closedButtonDisabled]}) - - interaction.channel.messages.fetchPinned().then((messages) => { - messages.first().edit({components:[closeRowDisabled]}) - }) - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close") - closeTicket1ButtonChecker = false - }) - - - //NORMAL DELETE - client.on("interactionCreate",interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "deleteTicket") return - - interaction.deferUpdate() - interaction.message.edit({components:[deleteBar]}) - - }) - client.on("interactionCreate",interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "deleteTicketFalse") return - - interaction.deferUpdate() - interaction.message.edit({components:[closeRowNormal]}) - }) - var deleteTicketButtonChecker = false - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "deleteTicketTrue") return - - interaction.deferUpdate() - - if (deleteTicketButtonChecker == true) return - deleteTicketButtonChecker = true - - const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) - if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ - try { - return interaction.member.send({embeds:[bot.errorLog.noPermsMessage]}) - }catch{ - return interaction.channel.send({embeds:[bot.errorLog.noPermsMessage]}) - } - } - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete") - deleteTicketButtonChecker = false - }) - - - - - //CLOSED DELETE - client.on("interactionCreate",interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "deleteTicket1") return - - interaction.deferUpdate() - interaction.message.edit({components:[deleteBar1]}) - - }) - client.on("interactionCreate",interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "deleteTicketFalse1") return - - interaction.deferUpdate() - interaction.message.edit({components:[closeRowClosed]}) - }) - - var deleteTicket1ButtonChecker = false - client.on("interactionCreate",async interaction => { - if (!interaction.isButton()) return - if (interaction.customId != "deleteTicketTrue1") return - - interaction.deferUpdate() - - if (deleteTicket1ButtonChecker == true) return - deleteTicket1ButtonChecker = true - - const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) - if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ - try { - return interaction.member.send({embeds:[bot.errorLog.noPermsMessage]}) - }catch{ - return interaction.channel.send({embeds:[bot.errorLog.noPermsMessage]}) - } - } - - /** - * @type {String} - */ - const name = interaction.channel.name - var prefix = "" - const tickets = config.options - tickets.forEach((ticket) => { - if (name.startsWith(ticket.channelprefix)){ - prefix = ticket.channelprefix - } - }) - - await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"deletenotranscript") - deleteTicket1ButtonChecker = false - }) -} \ No newline at end of file diff --git a/core/errorLogSystem.js b/core/errorLogSystem.js index b2ab1ff..8c03515 100644 --- a/core/errorLogSystem.js +++ b/core/errorLogSystem.js @@ -10,15 +10,23 @@ const loadChalk = async () => { const embed = discord.EmbedBuilder const c = discord.Colors -exports.noPermsMessage = new embed() +/**@param {discord.User} user*/ +exports.noPermsMessage = (user) => { + return new embed() .setColor(c.Red) .setTitle(":x: "+l.errors.noPermsTitle) .setDescription(l.errors.noPermsDescription) + .setFooter({iconURL:user.displayAvatarURL(),text:user.tag}) +} -exports.noPermsDelete = new embed() +/**@param {discord.User} user*/ +exports.noPermsDelete = (user) => { + return new embed() .setColor(c.Red) .setTitle(":x: "+l.errors.noPermsTitle) .setDescription(l.errors.noPermsDelete) + .setFooter({iconURL:user.displayAvatarURL(),text:user.tag}) +} /**@param {String} message */ exports.invalidArgsMessage = (message) => { @@ -93,7 +101,7 @@ const normalLog = (debugString) => { /** * - * @param {"system"|"command"|"info"|"api"} type + * @param {"system"|"command"|"info"|"api"|"debug"} type * @param {String} message * @param {[{key:String,value:String}]} params */ @@ -117,10 +125,13 @@ exports.log = async (type,message,params) => { }else if (ptype == "system"){ console.log(chalk.green("[system] ")+message+" "+chalk.yellow(parameters)) }else if (ptype == "api"){ - if (require("./api/modules/base").enableApiLogs == true){ + if (require("./api/api.json").enableAPIconsolelogs == true){ console.log(chalk.red("[api v"+require("./api/api.json").version+"] ")+message+" "+chalk.yellow(parameters)) } ptype = "api v"+require("./api/api.json").version + }else if (ptype == "debug"){ + if (!process.argv.some((v) => v == "--debug")) return + console.log(chalk.redBright("[DEBUG] ")+message+" "+chalk.yellow(parameters)) } const cd = new Date() diff --git a/core/getoptions.js b/core/getoptions.js deleted file mode 100644 index b691a67..0000000 --- a/core/getoptions.js +++ /dev/null @@ -1,116 +0,0 @@ -const bot = require("../index") -const config = bot.config - -/** - * @param {Number} index - * @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDMMessage"|"ticketmessage"} value - */ -exports.getTicketValue = (index,value) => { - if (value == "id"){ - return "OTnewT"+config.options[index][value] - } - return config.options[index][value] -} - -/** - * @param {Number} index - * @param {"id"|"name"|"description"|"icon"|"label"|"type"|"url"} value - */ - exports.getWebsiteValue = (index,value) => { - return config.options[index][value] -} - -/** - * @param {Number} index - * @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"roles"|"mode"|"enableDMMessage"} value - */ -exports.getRoleValue = (index,value) => { - return config.options[index][value] -} - -/** - * @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDMMessage"|"ticketmessage"} value - */ - exports.getTicketValues = (value) => { - var result = [] - config.options.forEach((o) => { - if (value == "id"){ - result.push("OTnewT"+o[value]) - }else{ - result.push(o[value]) - } - }) - return result -} - -/** - * @param {"id"|"name"|"description"|"icon"|"label"|"type"|"url"} value - */ - exports.getWebsiteValues = (value) => { - var result = [] - config.options.forEach((o) => { - result.push(o[value]) - }) - return result -} - -/** - * @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"roles"|"mode"|"enableDMMessage""} value - */ -exports.getRoleValues = (value) => { - var result = [] - config.options.forEach((o) => { - result.push(o[value]) - }) - return result -} - -class TicketOptions { - constructor() { - this.id = "" - this.name = "" - this.description = "" - this.icon = "" - this.label = "" - this.type = "" - this.color = "" - this.adminroles = ["",""] - this.channelprefix = "" - this.category = "" - this.message = "" - this.enableDMMessage = true - this.ticketmessage = "" - } -} -/** - * - * @param {String} id - * @returns {TicketOptions|false} - */ -exports.getOptionsById = (id) => { - var result = false - config.options.forEach((option) => { - if ("OTnewT"+option.id == id){ - result = option - } - }) - return result -} - -exports.exportedOptionClass = class { - constructor() { - this.id = "" - this.name = "" - this.description = "" - this.icon = "" - this.label = "" - this.type = "" - this.color = "" - this.adminroles = ["",""] - this.channelprefix = "" - this.category = "" - this.message = "" - this.enableDMMessage = true - this.ticketmessage = "" - } -} \ No newline at end of file diff --git a/core/interactionHandlers/buttons/close.js b/core/interactionHandlers/buttons/close.js index 1a8a445..46b7224 100644 --- a/core/interactionHandlers/buttons/close.js +++ b/core/interactionHandlers/buttons/close.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../getoptions") const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder const mc = config.main_color diff --git a/core/interactionHandlers/buttons/firstmsg.js b/core/interactionHandlers/buttons/firstmsg.js index 53edd15..fbbc910 100644 --- a/core/interactionHandlers/buttons/firstmsg.js +++ b/core/interactionHandlers/buttons/firstmsg.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../getoptions") const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder const mc = config.main_color diff --git a/core/interactionHandlers/buttons/verifyBars.js b/core/interactionHandlers/buttons/verifyBars.js index 7d1b864..cbd8453 100644 --- a/core/interactionHandlers/buttons/verifyBars.js +++ b/core/interactionHandlers/buttons/verifyBars.js @@ -5,7 +5,7 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../getoptions") + const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder const mc = config.main_color @@ -15,6 +15,14 @@ const arb = discord.ActionRowBuilder const bs = discord.ButtonStyle exports.closeVerifyBar = new arb() + .addComponents( + new button() + .setCustomId("OTcloseTicketReason") + .setDisabled(false) + .setStyle(bs.Primary) + .setEmoji("💬") + .setLabel(l.buttons.closeWithReason) + ) .addComponents( new button() .setCustomId("OTcloseTicketTrue") diff --git a/core/interactionHandlers/embeds/commands.js b/core/interactionHandlers/embeds/commands.js index c7bab3e..990bd23 100644 --- a/core/interactionHandlers/embeds/commands.js +++ b/core/interactionHandlers/embeds/commands.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../getoptions") const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder const mc = config.main_color @@ -13,37 +12,45 @@ const mc = config.main_color /** * * @param {discord.User} addedUser + * @param {discord.User} adder * @returns {discord.EmbedBuilder} */ -exports.addEmbed = (addedUser) => { +exports.addEmbed = (addedUser,adder) => { return new embed() .setTitle("⬆️ "+l.commands.userAddedTitle.replace("{0}",addedUser.username)) .setColor(mc) - .setFooter({text:addedUser.tag,iconURL:addedUser.displayAvatarURL()}) + .setFooter({text:adder.tag,iconURL:adder.displayAvatarURL()}) + .setThumbnail(addedUser.displayAvatarURL({extension:"png"})) } /** * * @param {discord.User} removedUser + * @param {discord.User} remover * @returns {discord.EmbedBuilder} */ -exports.removeEmbed = (removedUser) => { +exports.removeEmbed = (removedUser,remover) => { return new embed() .setTitle("⬇️ "+l.commands.userRemovedTitle.replace("{0}",removedUser.username)) .setColor(mc) - .setFooter({text:removedUser.tag,iconURL:removedUser.displayAvatarURL()}) + .setFooter({text:remover.tag,iconURL:remover.displayAvatarURL()}) + .setThumbnail(removedUser.displayAvatarURL({extension:"png"})) } /** * * @param {discord.User} closer + * @param {String} description * @returns {discord.EmbedBuilder} */ -exports.closeEmbed = (closer) => { - return new embed() +exports.closeEmbed = (closer,description) => { + const embd = new embed() .setTitle("🔒 "+l.commands.closeTitle) .setColor(mc) .setFooter({text:closer.tag,iconURL:closer.displayAvatarURL()}) + + if (description) embd.setDescription(description) + return embd } /** @@ -83,6 +90,31 @@ exports.renameEmbed = (renamer,newname) => { .setFooter({text:reopener.tag,iconURL:reopener.displayAvatarURL()}) } +/** + * + * @param {discord.User} claimer + * @param {discord.User} user + * @returns {discord.EmbedBuilder} + */ + exports.claimEmbed = (claimer,user) => { + return new embed() + .setTitle("📌 "+l.commands.claimTitle.replace("{0}",claimer.username)) + .setColor(mc) + .setFooter({text:user.tag,iconURL:user.displayAvatarURL()}) +} + +/** + * + * @param {discord.User} unclaimer + * @returns {discord.EmbedBuilder} + */ + exports.unclaimEmbed = (unclaimer) => { + return new embed() + .setTitle("🆓 "+l.commands.unclaimTitle) + .setColor(mc) + .setFooter({text:unclaimer.tag,iconURL:unclaimer.displayAvatarURL()}) +} + /** * * @param {Boolean} done diff --git a/core/interactionHandlers/handlers/accepted/closing.js b/core/interactionHandlers/handlers/accepted/closing.js index cc21393..27dc578 100644 --- a/core/interactionHandlers/handlers/accepted/closing.js +++ b/core/interactionHandlers/handlers/accepted/closing.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../../getoptions") const permissionChecker = require("../../../utils/permisssionChecker") const storage = bot.storage const hiddendata = bot.hiddenData @@ -33,7 +32,7 @@ module.exports = () => { if (config.system.closeMode == "adminonly"){ if (!permissionChecker.command(interaction.user.id,interaction.guild.id)){ if (!permissionChecker.sendUserNoPerms(interaction.user)){ - permissionChecker.sendChannelNoPerms(interaction.channel) + permissionChecker.sendChannelNoPerms(interaction.channel,interaction.user) } interaction.message.edit({components:[firstcomponents]}) closeTicketButtonChecker = false @@ -56,7 +55,7 @@ module.exports = () => { }) interaction.channel.send({embeds:[bot.embeds.commands.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) - await require("../../../ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close",false,true) + await require("../../../ticketActions/ticketCloser").NEWcloseTicket(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 new file mode 100644 index 0000000..bae9523 --- /dev/null +++ b/core/interactionHandlers/handlers/accepted/closingReason.js @@ -0,0 +1,99 @@ +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.main_color + +const button = discord.ButtonBuilder +const arb = discord.ActionRowBuilder +const bs = discord.ButtonStyle + +const modal = discord.ModalBuilder +const tis = discord.TextInputStyle +const tib = discord.TextInputBuilder + +module.exports = () => { + //theModal + const reasonModal = new modal() + .setTitle(l.buttons.closeWithReason) + .setCustomId("OTCloseReasonModal") + + const reasonInput = new arb() + .addComponents([ + new tib() + .setCustomId('OTreasonInput') + .setLabel(l.messages.modalreason) + .setStyle(tis.Short) + .setMaxLength(100) + .setRequired(true) + .setValue("") + .setPlaceholder("reason") + ]) + + reasonModal.addComponents(reasonInput) + + + + + + + //CLOSE WITH REASON + var closeTicketButtonChecker = false + + client.on("interactionCreate",async interaction => { + if (!interaction.isButton()) return + if (interaction.customId != "OTcloseTicketReason") return + + if (closeTicketButtonChecker == true) return interaction.deferUpdate() + closeTicketButtonChecker = true + + const firstcomponents = interaction.message.components + + if (config.system.closeMode == "adminonly"){ + if (!permissionChecker.command(interaction.user.id,interaction.guild.id)){ + if (!permissionChecker.sendUserNoPerms(interaction.user)){ + permissionChecker.sendChannelNoPerms(interaction.channel,interaction.user) + } + interaction.message.edit({components:[firstcomponents]}) + closeTicketButtonChecker = false + return interaction.deferUpdate() + } + } + + interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) + await interaction.showModal(reasonModal) + + }) + + client.on("interactionCreate",async (interaction) => { + if (interaction.type != discord.InteractionType.ModalSubmit) return + if (interaction.customId != "OTCloseReasonModal") return + + interaction.reply({embeds:[bot.embeds.commands.closeEmbed(interaction.user)],components:[bot.buttons.close.closeCommandRow]}) + + const reason = interaction.fields.getTextInputValue("OTreasonInput") + + /** + * @type {String} + */ + const name = interaction.channel.name + var prefix = "" + const tickets = config.options + tickets.forEach((ticket) => { + if (name.startsWith(ticket.channelprefix)){ + prefix = ticket.channelprefix + } + }) + + //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) + 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 9a64891..900db9b 100644 --- a/core/interactionHandlers/handlers/accepted/deleting.js +++ b/core/interactionHandlers/handlers/accepted/deleting.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../../getoptions") const permissionChecker = require("../../../utils/permisssionChecker") const storage = bot.storage const hiddendata = bot.hiddenData @@ -32,7 +31,7 @@ module.exports = () => { if (!permissionChecker.command(interaction.user.id,interaction.guild.id)){ if (!permissionChecker.sendUserNoDelete(interaction.user)){ - permissionChecker.sendChannelNoDelete(interaction.channel) + permissionChecker.sendChannelNoDelete(interaction.channel,interaction.user) } await interaction.message.edit({components:[firstcomponents]}) deleteTicketButtonChecker = false @@ -53,7 +52,7 @@ module.exports = () => { interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) await interaction.message.edit({components:[bot.buttons.close.openRowDisabled]}) - await require("../../../ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true) + await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete",false,true) deleteTicketButtonChecker = false }) @@ -70,10 +69,9 @@ module.exports = () => { const firstcomponents = bot.buttons.close.closeCommandRow - console.log("closed with NO TRANSCRIPT") if (!permissionChecker.command(interaction.user.id,interaction.guild.id)){ if (!permissionChecker.sendUserNoDelete(interaction.user)){ - permissionChecker.sendChannelNoDelete(interaction.channel) + permissionChecker.sendChannelNoDelete(interaction.channel,interaction.user) } await interaction.message.edit({components:[firstcomponents]}) deleteTicketButtonChecker1 = false @@ -93,7 +91,7 @@ module.exports = () => { }) interaction.channel.send({embeds:[bot.embeds.commands.deleteEmbed(interaction.user)]}) - await require("../../../ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"deletenotranscript",false,true) + await require("../../../ticketActions/ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"deletenotranscript",false,true) deleteTicketButtonChecker1 = false }) } \ No newline at end of file diff --git a/core/interactionHandlers/handlers/accepted/reopening.js b/core/interactionHandlers/handlers/accepted/reopening.js index 4b404b5..2cbc080 100644 --- a/core/interactionHandlers/handlers/accepted/reopening.js +++ b/core/interactionHandlers/handlers/accepted/reopening.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../../getoptions") const permissionChecker = require("../../../utils/permisssionChecker") const storage = bot.storage const hiddendata = bot.hiddenData @@ -24,6 +23,6 @@ module.exports = () => { interaction.deferUpdate() interaction.message.edit({embeds:[bot.embeds.commands.reopenEmbed(interaction.user)],components:[bot.buttons.close.openRowNormal]}) - require("../../../ticketReopener").reopenTicket(interaction.guild,interaction.channel,interaction.user) + require("../../../ticketActions/ticketReopener").reopenTicket(interaction.guild,interaction.channel,interaction.user) }) } \ No newline at end of file diff --git a/core/interactionHandlers/handlers/firstmsg.js b/core/interactionHandlers/handlers/firstmsg.js index bf340db..cd8c748 100644 --- a/core/interactionHandlers/handlers/firstmsg.js +++ b/core/interactionHandlers/handlers/firstmsg.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../getoptions") const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder diff --git a/core/interactionHandlers/handlers/handlers.js b/core/interactionHandlers/handlers/handlers.js index 6685c5d..5dea097 100644 --- a/core/interactionHandlers/handlers/handlers.js +++ b/core/interactionHandlers/handlers/handlers.js @@ -7,4 +7,5 @@ module.exports = () => { require("./accepted/closing")() require("./accepted/reopening")() require("./accepted/deleting")() + require("./accepted/closingReason")() } \ No newline at end of file diff --git a/core/interactionHandlers/handlers/sendTranscript.js b/core/interactionHandlers/handlers/sendTranscript.js index 0f857e3..c1f1c65 100644 --- a/core/interactionHandlers/handlers/sendTranscript.js +++ b/core/interactionHandlers/handlers/sendTranscript.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../getoptions") const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder diff --git a/core/interactionHandlers/handlers/verifyBars.js b/core/interactionHandlers/handlers/verifyBars.js index 64d7c99..a365bcd 100644 --- a/core/interactionHandlers/handlers/verifyBars.js +++ b/core/interactionHandlers/handlers/verifyBars.js @@ -5,7 +5,6 @@ const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("../../getoptions") const storage = bot.storage const hiddendata = bot.hiddenData const embed = discord.EmbedBuilder diff --git a/core/languageManager.js b/core/languageManager.js index 9e5f103..31641de 100644 --- a/core/languageManager.js +++ b/core/languageManager.js @@ -1,6 +1,6 @@ const index = require("../index") -if (index.developerMode){ +if (index.developerConfig){ var config = require("../devConfig.json") }else{var config = require("../config.json")} @@ -14,6 +14,9 @@ else if (config.languagefile.startsWith("french")) localLanguage = require("../l else if (config.languagefile.startsWith("romanian")) localLanguage = require("../language/romanian.json") else if (config.languagefile.startsWith("arabic")) localLanguage = require("../language/arabic.json") else if (config.languagefile.startsWith("spanish")) localLanguage = require("../language/spanish.json") +else if (config.languagefile.startsWith("portuguese")) localLanguage = require("../language/portuguese.json") +else if (config.languagefile.startsWith("italian")) localLanguage = require("../language/italian.json") + const errorLog = async () => { const chalk = await (await import("chalk")).default diff --git a/core/slashSystem/slashDisable.js b/core/slashSystem/slashDisable.js index 6ed3fda..82018a0 100644 --- a/core/slashSystem/slashDisable.js +++ b/core/slashSystem/slashDisable.js @@ -2,7 +2,6 @@ const discord = require("discord.js") const bot = require("../../index") const client = require("../../index").client const config = bot.config -const getoptions = require("../getoptions") module.exports = async () => { const chalk = (await import("chalk")).default diff --git a/core/slashSystem/slashEnable.js b/core/slashSystem/slashEnable.js index ee86197..cc39c23 100644 --- a/core/slashSystem/slashEnable.js +++ b/core/slashSystem/slashEnable.js @@ -2,7 +2,7 @@ const discord = require("discord.js") const bot = require("../../index") const client = require("../../index").client const config = bot.config -const getoptions = require("../getoptions") +const configParser = require("../utils/configParser") const act = discord.ApplicationCommandType const acot = discord.ApplicationCommandOptionType @@ -11,12 +11,12 @@ module.exports = async () => { const chalk = (await import("chalk")).default const sid = config.server_id - const ids = getoptions.getTicketValues("id") + const ids = configParser.getTicketValuesArray("id") /**@type {[{name:String,value:String}]} */ var choices = [] ids.forEach((id) => { - const option = getoptions.getOptionsById(id) - if (option.type == "ticket"){ + const option = configParser.getTicketById(id) + if (option){ choices.push({name:option.name,value:option.id}) } }) @@ -32,18 +32,22 @@ module.exports = async () => { //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 10")+" commands ready! (this can take up to 40 seconds)") - if (readystats >= 10){ + process.stdout.write("[status] there are "+chalk.blue(readystats+" out of 12")+" commands ready! (this can take up to 40 seconds)") + if (readystats >= 12){ console.log(chalk.green("\nready!")) - console.log(chalk.bgBlue("you can now start the bot with 'npm start'!")) + console.log(chalk.blue("you can now start the bot with "+chalk.bgBlue("'npm start'")+"!")) process.exit(1) } },100) + //slashtranslation + const ST = require("../../language/slashcmds/slash.json").data + //create a ticket (/new or /ticket) client.application.commands.create({ name:"ticket", description:"Create a ticket!", + descriptionLocalizations:ST.newticket, defaultPermission:true, type:act.ChatInput, options:[ @@ -53,7 +57,6 @@ module.exports = async () => { description:"The type of ticket.", required:true, choices:choices - } ] },sid).then(() => { @@ -65,6 +68,7 @@ module.exports = async () => { description:"Create a ticket!", defaultPermission:true, type:act.ChatInput, + descriptionLocalizations:ST.newticket, options:[ { type:acot.String, @@ -82,8 +86,9 @@ module.exports = async () => { //help client.application.commands.create({ name:"help", - description:"The help menu", + description:"View the available commands.", defaultPermission:true, + descriptionLocalizations:ST.help, type:act.ChatInput },sid).then(() => { readystats++ @@ -95,7 +100,15 @@ module.exports = async () => { name:"close", description:"Close the current ticket.", defaultPermission:true, - type:act.ChatInput + descriptionLocalizations:ST.close, + type:act.ChatInput, + options:[{ + name:"reason", + type:discord.ApplicationCommandOptionType.String, + required:false, + description:"The reason to close this ticket.", + maxLength:100 + }] },sid).then(() => { readystats++ }) @@ -105,6 +118,7 @@ module.exports = async () => { name:"delete", description:"Delete the current ticket.", defaultPermission:true, + descriptionLocalizations:ST.delete, type:act.ChatInput },sid).then(() => { readystats++ @@ -115,6 +129,7 @@ module.exports = async () => { name:"message", description:"Create a ticket message.", defaultPermission:true, + descriptionLocalizations:ST.message, type:act.ChatInput, options:[ { @@ -136,6 +151,7 @@ module.exports = async () => { name:"add", description:"Add people to this ticket.", defaultPermission:true, + descriptionLocalizations:ST.add, type:act.ChatInput, options:[ { @@ -154,6 +170,7 @@ module.exports = async () => { name:"remove", description:"Remove people from this ticket.", defaultPermission:true, + descriptionLocalizations:ST.remove, type:act.ChatInput, options:[ { @@ -172,6 +189,7 @@ module.exports = async () => { name:"rename", description:"Rename this ticket.", defaultPermission:true, + descriptionLocalizations:ST.rename, type:act.ChatInput, options:[ { @@ -190,6 +208,36 @@ module.exports = async () => { name:"reopen", description:"Reopen this ticket.", defaultPermission:true, + descriptionLocalizations:ST.reopen, + type:act.ChatInput + },sid).then(() => { + readystats++ + }) + + //claim + client.application.commands.create({ + name:"claim", + description:"Claim this ticket / claim it for someone else.", + defaultPermission:true, + type:act.ChatInput, + options:[ + { + name:"user", + type:acot.User, + required:false, + description:"The user to claim for." + } + ] + + },sid).then(() => { + readystats++ + }) + + //unclaim + client.application.commands.create({ + name:"unclaim", + description:"Unclaim this ticket.", + defaultPermission:true, type:act.ChatInput },sid).then(() => { readystats++ diff --git a/core/ticketCloser.js b/core/ticketActions/ticketCloser.js similarity index 79% rename from core/ticketCloser.js rename to core/ticketActions/ticketCloser.js index 203a04c..8963ec6 100755 --- a/core/ticketCloser.js +++ b/core/ticketActions/ticketCloser.js @@ -1,36 +1,13 @@ const discord = require('discord.js') -const bot = require('../index') +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 -const permsChecker = require("./utils/permisssionChecker") +const permsChecker = require("../utils/permisssionChecker") -exports.runThis = () => { - client.on("interactionCreate",async (interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "sendTranscript") return - - interaction.deferUpdate() - - const channelmessages = await interaction.channel.messages.fetch() - - channelmessages.sweep((msgSweep) => { - return msgSweep.author.id == client.user.id - }) - - var fileattachment = await require("./transcript").createTranscript(channelmessages,interaction.channel) - - if (fileattachment == false){ - log("system","internal error: transcript is not created!") - interaction.channel.send({embeds:[bot.errorLog.serverError(l.errors.somethingWentWrongTranscript)]}) - return - } - - interaction.channel.send({content:"**"+l.messages.hereIsTheTranscript+"**",files:[fileattachment]}) - }) -} +const pendingDelete = [] /** * @@ -47,10 +24,13 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => const chalk = await (await import("chalk")).default const channelmessages = await channel.messages.fetch() - const newReason = reason ? reason : "none" + const newReason = reason ? reason : l.messages.none //start code + //FIX CHANNEL COULD BE CLOSED AFTER DELETE: + if (pendingDelete.includes(channel.id)) return false + //remove ot bot from transcript channelmessages.sweep((msgSweep) => {return msgSweep.author.id == client.user.id}) @@ -88,21 +68,28 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => await channel.send({content:"**"+l.messages.gettingdeleted+"**"}) } 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) //getID & send DM & send api event - await channel.messages.fetchPinned().then(msglist => { + await channel.messages.fetchPinned().then(async msglist => { var firstmsg = msglist.last() if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value.value - const ticketData = require("./getoptions").getOptionsById("OTnewT"+ticketId) + const ticketData = require("../utils/configParser").getTicketById(ticketId,true) - require("./api/modules/events").onTicketDelete(user,channel,guild,new Date(),{name:channel.name,status:"deleted",ticketOptions:ticketData}) + require("../api/modules/events").onTicketDelete(user,channel,guild,new Date(),{name:channel.name,status:"deleted",ticketOptions:ticketData}) const id = hiddendata.data.find(d => d.key == "openerid").value + const sphd = bot.hiddenData.removeHiddenData(firstmsg.embeds[0].description) + sphd.hiddenData.data.push({key:"pendingdelete",value:"true"}) + const newEmbed = new discord.EmbedBuilder(firstmsg.embeds[0].data) + newEmbed.setDescription(sphd.description + bot.hiddenData.writeHiddenData(sphd.hiddenData.type,sphd.hiddenData.data)) + await firstmsg.edit({embeds:[newEmbed]}) + if (!id) return false try{ @@ -163,10 +150,20 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - const ticketData = require("./getoptions").getOptionsById("OTnewT"+ticketId) + const ticketData = require("../utils/configParser").getTicketById(ticketId,true) if (!ticketData) return + if (ticketData.closedCategory.enable){ + /**@type {discord.CategoryChannel} */ + const category = guild.channels.cache.find(c => c.id == ticketData.closedCategory.id && c.type == discord.ChannelType.GuildCategory) + try { + channel.setParent(category) + }catch{ + bot.errorLog.log("system","failed to move channel to new category!") + } + } + /** * @type {String[]} */ @@ -236,9 +233,9 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - const ticketData = require("./getoptions").getOptionsById("OTnewT"+ticketId) + const ticketData = require("../utils/configParser").getTicketById(ticketId,true) - require("./api/modules/events").onTicketClose(user,channel,guild,new Date(),{name:channel.name,status:"closed",ticketOptions:ticketData},newReason) + require("../api/modules/events").onTicketClose(user,channel,guild,new Date(),{name:channel.name,status:"closed",ticketOptions:ticketData},newReason) const id = hiddendata.data.find(d => d.key == "openerid").value @@ -278,9 +275,9 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false const hiddendata = bot.hiddenData.readHiddenData(firstmsg.embeds[0].description) const ticketId = hiddendata.data.find(d => d.key == "type").value - const ticketData = require("./getoptions").getOptionsById("OTnewT"+ticketId) + const ticketData = require("../utils/configParser").getTicketById(ticketId,true) - require("./api/modules/events").onTicketDelete(user,channel,guild,new Date(),{name:channel.name,status:"deleted",ticketOptions:ticketData}) + require("../api/modules/events").onTicketDelete(user,channel,guild,new Date(),{name:channel.name,status:"deleted",ticketOptions:ticketData}) const id = hiddendata.data.find(d => d.key == "openerid").value @@ -298,20 +295,21 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => if (enableTranscript == true && mode != "deletenotranscript"){ - const transcriptReason = (mode == "close") ? "**reason:** "+newReason : "**reason:** none" + const transcriptReason = (mode == "close") ? "**"+l.messages.reason+":** "+newReason : "**"+l.messages.reason+":** "+l.messages.none + const closedByPrefix = (mode.startsWith("delete")) ? l.messages.deletedby : l.messages.closedby if (config.system.enable_transcript || config.system.enable_DM_transcript){ - var fileattachment = await require("./transcript").createTranscript(channelmessages,channel) + var fileattachment = await require("../transcript").createTranscript(channelmessages,channel) if (fileattachment == false){log("system","internal error: transcript is not created!");return} } - if (config.system.enable_transcript){ + if (config.system.enable_transcript && !require("../api/api.json").disable.transcripts.server){ const transcriptEmbed = new discord.EmbedBuilder() .setColor(config.main_color) .setTitle("📄 "+l.messages.newTranscriptTitle) .setDescription(transcriptReason) - .setFooter({text:"closed by: "+user.tag+" | ticket: "+channelname,iconURL:user.displayAvatarURL()}) + .setFooter({text:closedByPrefix+": "+user.tag+" | ticket: "+channelname,iconURL:user.displayAvatarURL()}) guild.channels.cache.find(c => c.id == config.system.transcript_channel).send({ embeds:[transcriptEmbed], @@ -319,12 +317,12 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => }) } - if (config.system.enable_DM_transcript){ + if (config.system.enable_DM_transcript && !require("../api/api.json").disable.transcripts.dm){ const transcriptEmbed = new discord.EmbedBuilder() .setColor(config.main_color) .setTitle("📄 "+l.messages.newTranscriptTitle) .setDescription(transcriptReason) - .setFooter({text:"closed by: "+user.tag+" | ticket: "+channelname,iconURL:user.displayAvatarURL()}) + .setFooter({text:closedByPrefix+": "+user.tag+" | ticket: "+channelname,iconURL:user.displayAvatarURL()}) if (!isDatabaseError) ticketOpener.send({ embeds:[transcriptEmbed], @@ -340,6 +338,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode,reason,nomessage) => //await timer() setTimeout(async () => { + pendingDelete.shift() await channel.delete() },6000) } diff --git a/core/ticketOpener.js b/core/ticketActions/ticketOpener.js similarity index 87% rename from core/ticketOpener.js rename to core/ticketActions/ticketOpener.js index 17a1d19..f6264c4 100755 --- a/core/ticketOpener.js +++ b/core/ticketActions/ticketOpener.js @@ -1,22 +1,34 @@ const discord = require('discord.js') -const bot = require('../index') +const bot = require('../../index') const client = bot.client const config = bot.config const l = bot.language const log = bot.errorLog.log -const getconfigoptions = require("./getoptions") +const configParser = require("../utils/configParser") const storage = bot.storage module.exports = () => { + //dropdown placeholder + client.on("interactionCreate",(interaction) => { + if (!interaction.isSelectMenu()) return + if (interaction.customId != "OTdropdownMenu") return + if (interaction.values.includes("OTChooseTicket")) interaction.deferUpdate() + + }) + + var closeButton = bot.buttons.firstmsg.firstmsgRowNormal //ticket button click / create ticket - client.on("interactionCreate",(interaction) => { + client.on("interactionCreate",async (interaction) => { if (interaction.isChatInputCommand() && (interaction.commandName == "new" || interaction.commandName == "ticket")){ var customId = "OTnewT"+interaction.options.getString("type") }else if (interaction.isButton()){ var customId = interaction.customId + }else if (interaction.isSelectMenu() && (interaction.customId == "OTdropdownMenu")){ + var customId = interaction.values[0] + }else return if (interaction.isButton()){ @@ -30,17 +42,19 @@ module.exports = () => { } - if (getconfigoptions.getTicketValues("id").includes(customId)){ + if (configParser.getTicketValuesArray("id").includes(customId)){ //ticketoptions from config - const currentTicketOptions = getconfigoptions.getOptionsById(customId) + const currentTicketOptions = configParser.getTicketById(customId) - if (currentTicketOptions == false || currentTicketOptions.type != "ticket") return interaction.reply({embeds:[bot.errorLog.serverError(l.errors.anotherOption)]}) + if (currentTicketOptions == false) return interaction.reply({embeds:[bot.errorLog.serverError(l.errors.anotherOption)]}) if (interaction.isButton()){ interaction.deferUpdate() }else if (interaction.isChatInputCommand()){ interaction.reply({embeds:[bot.errorLog.success(l.messages.createdTitle,l.messages.createdDescription)]}) + }else if (interaction.isSelectMenu()){ + await interaction.deferUpdate() } 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){ @@ -170,6 +184,8 @@ module.exports = () => { }else{ ticketEmbed.setDescription(hiddendata) } + + if (currentTicketOptions.thumbnail.enable) ticketEmbed.setThumbnail(currentTicketOptions.thumbnail.url) ticketChannel.send({ content:"<@"+interaction.member.id+"> @here", @@ -181,7 +197,7 @@ module.exports = () => { }) log("system","created new ticket",[{key:"ticket",value:ticketName},{key:"user",value:interaction.user.tag}]) - require("./api/modules/events").onTicketOpen(interaction.user,ticketChannel,interaction.guild,new Date(),{name:ticketName,status:"open",ticketOptions:currentTicketOptions}) + require("../api/modules/events").onTicketOpen(interaction.user,ticketChannel,interaction.guild,new Date(),{name:ticketName,status:"open",ticketOptions:currentTicketOptions}) }) }else{ try { diff --git a/core/ticketActions/ticketReopener.js b/core/ticketActions/ticketReopener.js new file mode 100755 index 0000000..10ecdf7 --- /dev/null +++ b/core/ticketActions/ticketReopener.js @@ -0,0 +1,52 @@ +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 +const pfb = discord.PermissionFlagsBits + +/** + * + * @param {discord.Guild} guild + * @param {discord.TextBasedChannel} channel + * @param {discord.User} user + * @returns + */ +const reopenTicket = (guild,channel,user) => { + log("system","re-opened a ticket",[{key:"ticket",value:channel.name},{key:"user",value:user.tag}]) + + 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] + } + permissionsArray.push({ + id:guild.roles.everyone, + type:"role", + allow:everyoneAllowPerms, + deny:everyoneDenyPerms + }) + + channel.permissionOverwrites.cache.forEach((p) => { + if (p.type == 1){ + permissionsArray.push({ + id:p.id, + type:"member", + allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel], + deny:[] + }) + } + }) + + channel.permissionOverwrites.set(permissionsArray) + + require("../api/modules/events").onTicketReopen(user,channel,guild,new Date(),{name:channel.name,status:"reopened",ticketOptions:false}) +} +exports.reopenTicket = reopenTicket \ No newline at end of file diff --git a/core/ticketReopener.js b/core/ticketReopener.js deleted file mode 100755 index e3cbd97..0000000 --- a/core/ticketReopener.js +++ /dev/null @@ -1,214 +0,0 @@ -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 -const pfb = discord.PermissionFlagsBits - -/** - * - * @param {discord.Guild} guild - * @param {discord.TextBasedChannel} channel - * @param {discord.User} user - * @returns - */ -const reopenTicket = (guild,channel,user) => { - log("system","re-opened a ticket",[{key:"ticket",value:channel.name},{key:"user",value:user.tag}]) - - 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] - } - permissionsArray.push({ - id:guild.roles.everyone, - type:"role", - allow:everyoneAllowPerms, - deny:everyoneDenyPerms - }) - - channel.permissionOverwrites.cache.forEach((p) => { - if (p.type == 1){ - permissionsArray.push({ - id:p.id, - type:"member", - allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel], - deny:[] - }) - } - }) - - channel.permissionOverwrites.set(permissionsArray) - - require("./api/modules/events").onTicketReopen(user,channel,guild,new Date(),{name:channel.name,status:"reopened",ticketOptions:false}) -} -exports.reopenTicket = reopenTicket - -exports.runThis = () => { - var closeRowNormal = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("closeTicket") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setLabel(l.buttons.close) - .setEmoji("🔒") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicket") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - - var closeRowClosed = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("deleteTicket1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Danger) - .setLabel(l.buttons.delete) - .setEmoji("✖️") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("sendTranscript") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setLabel(l.buttons.sendTranscript) - .setEmoji("📄") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("reopenTicket") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Success) - .setLabel(l.buttons.reopen) - .setEmoji("✔") - ) - - var reopenBar = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("reopenTicketTrue") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("✅") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("reopenTicketFalse") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("❌") - ) - - var reopenBar1 = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("reopenTicketTrue1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("✅") - ) - .addComponents( - new discord.ButtonBuilder() - .setCustomId("reopenTicketFalse1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("❌") - ) - - var reopenCommandBar = new discord.ActionRowBuilder() - .addComponents( - new discord.ButtonBuilder() - .setCustomId("reopenTicket1") - .setDisabled(false) - .setStyle(discord.ButtonStyle.Secondary) - .setEmoji("🔓") - ) - - - - - - //NORMAL WAY - client.on("interactionCreate",(interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "reopenTicket") return - - interaction.deferUpdate() - interaction.message.edit({components:[reopenBar]}) - - }) - - client.on("interactionCreate",(interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "reopenTicketFalse") return - - interaction.deferUpdate() - interaction.message.edit({components:[closeRowClosed]}) - - }) - - client.on("interactionCreate",(interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "reopenTicketTrue") return - - interaction.deferUpdate() - - const embed = new discord.EmbedBuilder() - .setColor(config.main_color) - .setTitle(":unlock: "+l.messages.reopenTitle+" :unlock:") - .setDescription(l.messages.reopenDescription) - - interaction.message.edit({embeds:[embed],components:[closeRowNormal]}) - - reopenTicket(interaction.guild,interaction.channel,interaction.user) - }) - - - //COMMAND WAY - client.on("interactionCreate",(interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "reopenTicket1") return - - interaction.deferUpdate() - interaction.message.edit({components:[reopenBar1]}) - - }) - - client.on("interactionCreate",(interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "reopenTicketFalse1") return - - interaction.deferUpdate() - interaction.message.edit({components:[reopenCommandBar]}) - - }) - - client.on("interactionCreate",(interaction) => { - if (!interaction.isButton()) return - if (interaction.customId != "reopenTicketTrue1") return - - interaction.deferUpdate() - - const embed = new discord.EmbedBuilder() - .setColor(config.main_color) - .setTitle(":unlock: "+l.messages.reopenTitle+" :unlock:") - .setDescription(l.messages.reopenDescription) - - interaction.message.edit({content:null,embeds:[embed],components:[closeRowNormal]}) - - reopenTicket(interaction.guild,interaction.channel,interaction.user) - }) -} \ No newline at end of file diff --git a/core/transcript.js b/core/transcript.js index fcbd111..f0829fe 100755 --- a/core/transcript.js +++ b/core/transcript.js @@ -50,7 +50,7 @@ exports.createTranscript = async (messagecollection,channel) => { try { const cd = new Date() const months = ["January","February","March","April","May","June","July","August","September","October","November","December"] - const dateString = cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getSeconds()+":"+cd.getMinutes()+":"+cd.getHours() + const dateString = cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getHours()+":"+cd.getMinutes()+":"+cd.getSeconds() const filearray = ["open ticket transcript:\ntranscript creation: "+dateString+"\nticket name: "+ticketuserdata.ticketname+"\nticket opener: "+ticketuserdata.ticketopener.name,"\nTRANSCRIPT START:"] messagecollection.reverse() diff --git a/core/utils/configParser.js b/core/utils/configParser.js new file mode 100644 index 0000000..20797cd --- /dev/null +++ b/core/utils/configParser.js @@ -0,0 +1,187 @@ +const bot = require("../../index") +const config = bot.config +const l = bot.language + +//TYPEDEFS: +//================== + +//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}, closedCategory:{enable:Boolean,id:String}}} 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 */ + +//OTWebsiteOptions +/**@typedef {{id: String,name: String,description: String,icon: String,label: String,type: "ticket"|"role"|"website",url:String}} OTWebsiteOptions */ + + +//OTConfigMessage +/**@typedef {{id: string, name: string, description: string, dropdown: boolean, enableFooter: boolean, footer: string, enableThumbnail: boolean, thumbnail: string, enableCustomColor: boolean, color: string, options: string[], enableTicketExplaination: boolean, enableMaxTicketsWarning: boolean}} OTConfigMessage*/ + +//StringOptions +/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDmOnOpen"|"ticketmessage"|"thumbnail"|"closedCategory"} OTTicketStringOptions */ +/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"roles"|"mode"|"enableDmOnOpen"} OTRoleStringOptions */ +/**@typedef {"id"|"name"|"description"|"icon"|"label"|"type"|"url"} OTWebsiteStringOptions */ + +//FUNCTIONS: +//================== + +/** @param {String} id the id of the embed @returns {OTConfigMessage}*/ +exports.getConfigMessage = (id) => { + var returned = config.messages.find(a => a.id == id) + if (returned){ + return returned + } + var result = config.messages[0] + if (!result){ + throw new Error("'messages' object in config.json is empty") + return + } + return result +} + +/** + * + * @param {String} id + * @param {Boolean} withoutOTnewT + * @returns {OTTicketOptions|false} + */ + exports.getTicketById = (id,withoutOTnewT) => { + var result = false + if (withoutOTnewT){ + config.options.forEach((option) => { + if (option.id == id && option.type == "ticket"){ + result = option + } + }) + }else{ + config.options.forEach((option) => { + if ("OTnewT"+option.id == id && option.type == "ticket"){ + result = option + } + }) + } + return result +} + +/** + * + * @param {String} id + * @param {Boolean} withoutOTnewR + * @returns {OTRoleOptions|false} + */ + exports.getRoleById = (id,withoutOTnewR) => { + var result = false + if (withoutOTnewR){ + config.options.forEach((option) => { + if (option.id == id && option.type == "role"){ + result = option + } + }) + }else{ + config.options.forEach((option) => { + if ("OTnewR"+option.id == id && option.type == "role"){ + result = option + } + }) + } + return result +} + +/** + * + * @param {String} id + * @returns {OTWebsiteOptions|false} + */ + exports.getWebsiteById = (id) => { + var result = false + config.options.forEach((option) => { + if (option.id == id && option.type == "website"){ + result = option + } + }) + return result +} + +/** + * @param {OTTicketStringOptions} value + * @returns {String[]} + */ +exports.getTicketValuesArray = (value,idWithoutOTnewT) => { + var result = [] + const prefix = idWithoutOTnewT ? "" : "OTnewT" + config.options.forEach((opt) => { + if (opt.type == "ticket"){ + if (value == "id"){ + result.push(prefix+opt[value]) + }else{ + result.push(opt[value]) + } + } + }) + return result +} + +/** + * @param {OTRoleStringOptions} value + * @returns {String[]} + */ + exports.getRoleValuesArray = (value,idWithoutOTnewR) => { + var result = [] + const prefix = idWithoutOTnewR ? "" : "OTnewR" + config.options.forEach((opt) => { + if (o.type == "role"){ + if (value == "id"){ + result.push(prefix+opt[value]) + }else{ + result.push(opt[value]) + } + } + }) + return result +} + +/** + * @param {OTWebsiteStringOptions} value + * @returns {String[]} + */ + exports.getWebsiteValuesArray = (value) => { + var result = [] + config.options.forEach((opt) => { + if (o.type == "website"){ + result.push(opt[value]) + } + }) + return result +} + +/**@type {OTTicketOptions} */ +this.ticketType = {} + +/**@type {OTRoleOptions} */ +this.roleType = {} + +/**@type {OTWebsiteOptions} */ +this.websiteType = {} + +/**@type {OTConfigMessage} */ +this.messageType = {} + + +//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}, url:String, closedCategory:{enable:Boolean,id:String}}} OTAllOptions */ + +/** + * + * @param {String} id + * @returns {Boolean} + */ + exports.optionExists = (id) => { + var result = false + config.options.forEach((option) => { + if (option.id == id){ + result = true + } + }) + return result +} \ No newline at end of file diff --git a/core/utils/getButton.js b/core/utils/getButton.js index 5aeff34..86db8dc 100644 --- a/core/utils/getButton.js +++ b/core/utils/getButton.js @@ -1,7 +1,6 @@ const discord = require("discord.js") const bot = require("../../index") const config = bot.config -const getoptions = require("../getoptions") const l = bot.language /**@returns {"DANGER"|"SUCCESS"|"PRIMARY"|"SECONDARY"} */ @@ -81,7 +80,7 @@ exports.rawButtonData = class { this.type = "" this.color = "" - this.enableDMMessage = true + this.enableDmOnOpen = true this.url = "" this.roles = ["",""] this.mode = "" diff --git a/core/utils/getDropdown.js b/core/utils/getDropdown.js new file mode 100644 index 0000000..52174d4 --- /dev/null +++ b/core/utils/getDropdown.js @@ -0,0 +1,46 @@ +const discord = require("discord.js") +const bot = require("../../index") +const config = bot.config +const l = bot.language + +const configParser = require("./configParser") +/** + * + * @param {String[]} ids + * @returns {discord.SelectMenuBuilder|false} + */ +exports.getDropdown = (ids) => { + const dropdown = new discord.SelectMenuBuilder() + .setCustomId("OTdropdownMenu") + .setDisabled(false) + .setMaxValues(1) + .setMinValues(1) + .setPlaceholder(l.messages.chooseATicket) + .addOptions( + new discord.SelectMenuOptionBuilder() + .setDefault(true) + .setLabel(l.messages.chooseATicket) + .setValue("OTChooseTicket") + ) + + ids.forEach((id) => { + const option = configParser.getTicketById(id,true) + if (option){ + const selectComponent = new discord.SelectMenuOptionBuilder() + .setDefault(false) + .setValue("OTnewT"+option.id) + + if (!option.label && !option.icon){ + selectComponent.setLabel("OT ERROR: no description/emoji") + }else{ + if (option.label) selectComponent.setLabel(option.label) + if (option.icon) selectComponent.setEmoji(option.icon) + } + + dropdown.addOptions(selectComponent) + } + }) + + + return dropdown +} \ No newline at end of file diff --git a/core/ticketMessageEmbed.js b/core/utils/getEmbed.js similarity index 64% rename from core/ticketMessageEmbed.js rename to core/utils/getEmbed.js index bcc9d39..aa44034 100644 --- a/core/ticketMessageEmbed.js +++ b/core/utils/getEmbed.js @@ -1,8 +1,8 @@ const discord = require('discord.js') -const bot = require('../index') +const bot = require('../../index') const client = bot.client const config = bot.config -const getButton = require("./utils/getButton") +const getButton = require("./getButton") const l = bot.language /** @@ -16,7 +16,7 @@ const l = bot.language exports.createEmbed = (id) => { //----------------------------------- //general importing - const data = require("./utils/getTicketMessages").getTicketMessage(id) + const data = require("./configParser").getConfigMessage(id) /**@type {discord.ButtonBuilder[]}*/ var buttons = [] /**@type {getButton.rawButtonData[]} */ @@ -60,31 +60,44 @@ exports.createEmbed = (id) => { description = description+"\n\n"+l.commands.maxTicketWarning.replace("{0}",config.system.max_allowed_tickets) } - embed.setDescription(description) - //----------------------------------- + if (description) embed.setDescription(description) //----------------------------------- - //create the components - var AmountOfRows = Math.ceil(buttons.length / 4) - var currentRow = 0 - /** - * @type {discord.MessageActionRow[]} - */ - var componentRows = [] - for (let i = AmountOfRows; i > 0; i--){ + //----------------------------------- + //create the components IF DROPDOWN IS FALSE + if (!data.dropdown){ + var AmountOfRows = Math.ceil(buttons.length / 4) + var currentRow = 0 - componentRows.push(new discord.ActionRowBuilder()) - } + /** + * @type {discord.MessageActionRow[]} + */ + var componentRows = [] - buttons.forEach((button,index) => { - componentRows[currentRow].addComponents([button]) + for (let i = AmountOfRows; i > 0; i--){ - if (index == 3 || index == 7 || index == 11 || index == 15 || index == 19 || index == 23 || index == 27 || index == 31 || index == 35 || index == 39){ - currentRow = currentRow + 1 + componentRows.push(new discord.ActionRowBuilder()) } - }) + + buttons.forEach((button,index) => { + componentRows[currentRow].addComponents([button]) + + if (index == 3 || index == 7 || index == 11 || index == 15 || index == 19 || index == 23 || index == 27 || index == 31 || index == 35 || index == 39){ + currentRow = currentRow + 1 + } + }) + + //create the component IF DROPDOWN is true + }else{ + const ids = data.options + const dropdown = require("./getDropdown").getDropdown(ids) + var componentRows = [ + new discord.ActionRowBuilder() + .setComponents(dropdown) + ] + } //----------------------------------- diff --git a/core/utils/getTicketMessages.js b/core/utils/getTicketMessages.js deleted file mode 100644 index bd97d14..0000000 --- a/core/utils/getTicketMessages.js +++ /dev/null @@ -1,16 +0,0 @@ -const bot = require("../../index") -const config = bot.config -const l = bot.language - -exports.getTicketMessage = (input) => { - var returned = config.messages.find(a => a.id == input) - if (returned){ - return returned - } - var result = config.messages[0] - if (!result){ - throw new Error("'messages' object in config.json is empty") - return - } - return result -} \ No newline at end of file diff --git a/core/utils/hiddendata.js b/core/utils/hiddendata.js index 9920dd0..53dc898 100644 --- a/core/utils/hiddendata.js +++ b/core/utils/hiddendata.js @@ -49,4 +49,18 @@ exports.writeHiddenData = (type,data) => { const result = "[ ](OTDATA|"+type+"//"+datastring+")" return result +} + +/** + * + * @param {String} description + * @returns {{description:String,hiddenData:hiddenData}} + */ +exports.removeHiddenData = (description) => { + const hiddenData = this.readHiddenData(description) + + const splitted = description.split("[ ](OTDATA") + const original = splitted[0] + + return {description:original,hiddenData:hiddenData} } \ No newline at end of file diff --git a/core/utils/liveStatus.js b/core/utils/liveStatus.js new file mode 100644 index 0000000..e5e57db --- /dev/null +++ b/core/utils/liveStatus.js @@ -0,0 +1,15 @@ +const discord = require('discord.js') +const bot = require('../../index') +const client = bot.client +const config = bot.config +const log = bot.errorLog.log + +const loadChalk = async () => { + return await (await import("chalk")).default +} + +module.exports = async () => { + const chalk = await loadChalk() + + //LIVESTATUS SOON +} \ No newline at end of file diff --git a/core/utils/permisssionChecker.js b/core/utils/permisssionChecker.js index c1a0192..8ca662c 100644 --- a/core/utils/permisssionChecker.js +++ b/core/utils/permisssionChecker.js @@ -26,7 +26,7 @@ exports.command = (memberid,guildid) => { */ exports.sendUserNoPerms = (user) => { try { - user.send({embeds:[bot.errorLog.noPermsMessage]}) + user.send({embeds:[bot.errorLog.noPermsMessage(user)]}) return true }catch{ return false @@ -54,7 +54,7 @@ exports.sendUserNoPerms = (user) => { */ exports.sendUserNoDelete = (user) => { try { - user.send({embeds:[bot.errorLog.noPermsDelete]}) + user.send({embeds:[bot.errorLog.noPermsDelete(user)]}) return true }catch{ return false @@ -64,11 +64,12 @@ exports.sendUserNoPerms = (user) => { /** * * @param {discord.TextChannel} channel + * @param {discord.User} user * @returns {Boolean} */ - exports.sendChannelNoPerms = (channel) => { + exports.sendChannelNoPerms = (channel,user) => { try { - channel.send({embeds:[bot.errorLog.noPermsMessage]}) + channel.send({embeds:[bot.errorLog.noPermsMessage(user)]}) return true }catch{ return false @@ -78,9 +79,10 @@ exports.sendUserNoPerms = (user) => { /** * * @param {discord.TextChannel} channel + * @param {discord.User} user * @returns {Boolean} */ - exports.sendChannelNoTicket = (channel) => { + exports.sendChannelNoTicket = (channel,user) => { try { channel.send({embeds:[bot.errorLog.notInATicket]}) return true @@ -92,11 +94,12 @@ exports.sendUserNoPerms = (user) => { /** * * @param {discord.TextChannel} channel + * @param {discord.User} user * @returns {Boolean} */ - exports.sendChannelNoDelete = (channel) => { + exports.sendChannelNoDelete = (channel,user) => { try { - channel.send({embeds:[bot.errorLog.noPermsDelete]}) + channel.send({embeds:[bot.errorLog.noPermsDelete(user)]}) return true }catch{ return false diff --git a/core/utils/warningManager.js b/core/utils/warningManager.js deleted file mode 100644 index 702b118..0000000 --- a/core/utils/warningManager.js +++ /dev/null @@ -1,19 +0,0 @@ -const discord = require('discord.js') -const bot = require('../../index') -const client = bot.client -const config = bot.config -const log = bot.errorLog.log - -const loadChalk = async () => { - return await (await import("chalk")).default -} - -//ENABLE message for when there is too less translation -const enableNoTranslationMessage = true - -module.exports = async () => { - const chalk = await loadChalk() - if (enableNoTranslationMessage){ - console.log(chalk.red("[warning]"),"WARNING!!\n"+chalk.blue("We have a small problem with translation atm, so it can be that "+chalk.redBright("some translations are in English!")+"\n\nYou can help us if you want by joining our server!\n")) - } -} \ No newline at end of file diff --git a/index.js b/index.js index 7fa703a..8a09539 100644 --- a/index.js +++ b/index.js @@ -9,51 +9,80 @@ // | \____/ | | | | | | | \ | // \__________/ |__| \__________| |__| \___| - -const discord = require('discord.js') +const discord = require("discord.js") const fs = require('fs') const {GatewayIntentBits,Partials} = discord -const client = new discord.Client({ - intents:[ - GatewayIntentBits.DirectMessages, - GatewayIntentBits.GuildInvites, - GatewayIntentBits.GuildMembers, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.Guilds, - GatewayIntentBits.MessageContent - ], - partials:[Partials.Channel,Partials.Message] -}) +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 exports.client = client - client.setMaxListeners(50) +if (process.argv.some((v) => v == "--debug")) console.log("[TEMP_DEBUG]","created client") -if (process.argv[2]){ - if (process.argv[2].endsWith("d")){ - var isDev = true - console.log("starting in dev mode...") - }else{var isDev = false} -}else{var isDev = false} +var tempconfig = require("./config.json") +/**@type {Boolean} */ +var isDevConfig = false -exports.developerMode = isDev +if (process.argv.some((v) => v == "--devconfig")){ + async function logFLAGS(){ + const chalk = await (await import("chalk")).default + console.log(chalk.blue("[FLAGS] => used dev config instead of normal config")) + }; logFLAGS() + isDevConfig = true + try{ + tempconfig = require("./devConfig.json") + }catch{tempconfig = require("./config.json")} +}else{ + tempconfig = require("./config.json") +} +if (process.argv.some((v) => v == "--nochecker")){ + async function logFLAGS(){ + const chalk = await (await import("chalk")).default + console.log(chalk.blue("[FLAGS] => disabled checker.js")) + }; logFLAGS() +} +if (process.argv.some((v) => v == "--debug")){ + async function logFLAGS(){ + const chalk = await (await import("chalk")).default + console.log(chalk.blue("[FLAGS] => enabled DEBUG mode")) + }; logFLAGS() +} +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") -if (isDev){ - try { - var config = require('./devConfig.json') - }catch{ - console.log("devConfig.json not found! Trying the normal config...") - var config = require("./config.json") - } -}else{var config = require('./config.json')} +const config = tempconfig exports.config = config +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.hiddenData = require("./core/utils/hiddendata") +this.errorLog.log("debug","loaded hiddendataTM") exports.embeds = { commands:require("./core/interactionHandlers/embeds/commands") @@ -63,8 +92,10 @@ exports.buttons = { firstmsg:require("./core/interactionHandlers/buttons/firstmsg"), verifybars:require("./core/interactionHandlers/buttons/verifyBars") } +this.errorLog.log("debug","loaded buttons & embeds") client.on('ready',async () => { + this.errorLog.log("debug","client logged in") var statusSet = false const setStatus = (type,text) => { if (statusSet == true) return @@ -78,13 +109,15 @@ client.on('ready',async () => { statusSet = true log("system","loaded status",[{key:"type",value:type},{key:"text",value:text}]) } + this.errorLog.log("debug","bot status loaded") const chalk = await (await import("chalk")).default if (!process.argv[2]){ console.log(chalk.red("WELCOME TO OPEN TICKET!")) + this.errorLog.log("debug","loaded console interface") log("info","open ticket ready",[{key:"version",value:require("./package.json").version},{key:"language",value:config.languagefile}]) - require("./core/utils/warningManager")() + require("./core/utils/liveStatus")() console.log(chalk.blue("\n\nlogs:")+"\n============") if (config.status.enabled){ @@ -105,8 +138,9 @@ client.on('ready',async () => { if (!process.argv[2].startsWith("slash")){ console.log(chalk.red("WELCOME TO OPEN TICKET!")) + this.errorLog.log("debug","loaded console interface") log("info","open ticket ready",[{key:"version",value:require("./package.json").version},{key:"language",value:config.languagefile}]) - require("./core/utils/warningManager")() + require("./core/utils/liveStatus")() console.log(chalk.blue("\n\nlogs:")+"\n============") if (config.status.enabled){ @@ -118,6 +152,7 @@ client.on('ready',async () => { await client.guilds.cache.find((g) => g.id == config.server_id).members.fetch() }else{ console.log(chalk.red("STARTING IN ")+chalk.blue("SLASH MODE")+chalk.red("...")) + this.errorLog.log("debug","slashmode activated") console.log("logs:\n================") console.log("client logged in...") console.log("loading files...") @@ -135,16 +170,17 @@ client.on('ready',async () => { //load plugins require("./core/api/pluginlauncher")() + this.errorLog.log("debug","loading plugins") }) - -if (!isDev){ - require("./core/checker").checker() -} +if (!require("./core/api/api.json").disable.checkerjs.all) require("./core/checker").checker() + this.errorLog.log("debug","loading checker.js") + this.errorLog.log("debug","checking config...") if (process.argv[2] && process.argv[2].startsWith("slash")){ //do nothing }else{ + this.errorLog.log("debug","LOADING COMMANDS") //commands require('./commands/ticket')() require("./commands/help")() @@ -154,29 +190,38 @@ if (process.argv[2] && process.argv[2].startsWith("slash")){ require("./commands/add")() require("./commands/remove")() require("./commands/reopen")() + require("./commands/claim")() + require("./commands/unclaim")() + this.errorLog.log("debug","LOADING CORE") //core - require('./core/ticketOpener')() - require("./core/ticketCloser").runThis() - //require("./core/closebuttons")() // => everything is now in ./core/interactionHandlers/ + require('./core/ticketActions/ticketOpener')() require("./core/reactionRoles")() - require("./core/ticketReopener").runThis() + this.errorLog.log("debug","LOADING INTERACTION HANDLERS") //InteractionHandlers require("./core/interactionHandlers/handlers/handlers")() + //require("./test")() } +this.errorLog.log("debug","loading api") const APIEvents = require("./core/api/modules/events") +const APIConfig = require("./core/api/api.json") 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==========================" fs.writeFileSync("./openticketdebug.txt",content+"\nDEBUG: "+debugString) + } } const errorLog = (errorString,stack) => { + if (!APIConfig.disable.debug.all){ const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n\n==========================" fs.writeFileSync("./openticketdebug.txt",content+"\nERROR: "+errorString+" STACK: "+stack) + } } +this.errorLog.log("debug","OT error system loaded successfully") client.on("debug", async (message) => { if (message.startsWith("Provided token:")){ @@ -194,4 +239,5 @@ process.on("uncaughtException",async (error,origin) => { APIEvents.onError(error.name+": "+error.message,new Date()) }) -client.login(config.auth_token) \ No newline at end of file +if (!APIBase.embeddedMode) client.login(config.auth_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 eb5fd1b..3b5745b 100644 --- a/language/arabic.json +++ b/language/arabic.json @@ -1,75 +1,83 @@ { - "errors":{ - "missingArgsTitle":"حجج باطلة", - "missingArgsDescription":"حجة مفقودة", - "noPermsTitle":"ليس لديك إذن", - "noPermsDescription":"You need the `ADMINISTRATOR` permission or be in the list of allowed roles!", - "noPermsDelete":"Only admins can delete a ticket!", - "chooseFromListTitle":"بطاقة التعريف غير صالحة", - "chooseFromListDescription":"اختر أحد المعرفات أدناه:", - "boterror":"مشكلة في الروبوت", - "notInTicketTitle":"أنت لست في تذكرة!", - "notInTicketDescription":"هذا الأمر لا يعمل خارج التذاكر!", - "ticketDoesntExist":"هذه التذكرة لم تعد موجودة!", - "roleDoesntExist":"هذا الدور لم يعد موجودًا!", - "anotherOption":"هذا الخيار ليس تذكرة بل نوع آخر!", - "maxAmountTitle":"بلغ الحد الأقصى!", - "maxAmountDescription":"لقد وصلت إلى الحد الأقصى لعدد التذاكر المسموح بها!\nلذلك لا يمكنك إنشاء واحدة جديدة!", - "somethingWentWrong":"**هناك خطأ ما!**\nالرجاء المحاولة مرة أخرى!", - "somethingWentWrongTranscript":"**حدث خطأ ما أثناء كتابة النص!**\nالرجاء المحاولة مرة أخرى!" - }, - "commands":{ - "userAddedTitle":"Added {0} to this ticket!", - "userRemovedTitle":"Removed {0} from this ticket!", - "renameTitle":"Changed the name to {0}!", - "closeTitle":"Closed this ticket!", - "deleteTitle":"Deleting this ticket...", - "reopenTitle":"Re-Opened this ticket!", + "errors": { + "missingArgsTitle": "قيمة غير صالحة!", + "missingArgsDescription": "قيمة مفقودة", + "noPermsTitle": "ليس لديك برمشنات !", + "noPermsDescription": "أنت بحاجة الى برمشن `ADMINISTRATOR` او أن تكون في قائمة المسموح بهم!", + "noPermsDelete": "فقط الإداريين يمكنهم حذف التكت!", + "chooseFromListTitle": "Invalid ID", + "chooseFromListDescription": "قم بأختيار أحد من الأيديات من الأسفل:", + "boterror": "خلل في البوت !", + "notInTicketTitle": "انت لست في تكت!", + "notInTicketDescription": "هذا الأمر لا يعمل خارج التكت!", + "ticketDoesntExist": "هذا التكت لم يعد فعال!", + "roleDoesntExist": "خطاً ,لم تعد الرتبة موجوده!", + "anotherOption": "هذا الخيار ليس التكت و لكنه شيء أخر!", + "maxAmountTitle": "خطأ , تم الوصول الى الحد الأقصى!", + "maxAmountDescription": "لقد وصلت الى الحد الأقصى لعدد التكتات المسموحة بها!\nSo لا يمكنك فتح واحدة أخرى!", + "somethingWentWrong": "**هناك خطاً!**\nأعد المحاولة لاحقاً!", + "somethingWentWrongTranscript": "هناك خطاً في محاولة طبع التكت!**\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!", - "ticketWarning":"The embed is in the message below!", - "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" - }, - "helpMenu":{ - "title":"Available Commands:", - "header1":"**اذهب إلى {0} لإنشاء تذكرة!**\n\n", - "header2":"**قم بتشغيل الأمر `/new` أو `/ticket` لإنشاء تذكرة!**\n\n", + "ticketWarning": "هذا الأمبد موجود بالفعل في الرسالة بالأسفل!", + "maxTicketWarning": "**تحذير:** _يمكنك فقط فتح {0} تكت في الوقت!_" + }, + "helpMenu": { + "title": "الأوامر المتاحة:", + "header1": "**أذهب الى {0} لإنشاء تذكرة!**\n\n", + "header2": "**قم بكتابة أمر `/new` او `/ticket` لفتح تكت!**\n\n", - "msgCmd":"تفرخ تضمين مع الأزرار. (المسؤولون فقط)", - "renameCmd":"إعادة تسمية تذكرة. (بدون مسافات)", - "closeCmd":"أغلق التذكرة.", - "deleteCmd":"حذف التذكرة.", - "addCmd":"أضف مستخدمًا إلى التذكرة.", - "removeCmd":"إزالة مستخدم من التذكرة.", - "reopenCmd":"أعد فتح التذكرة بعد إغلاقه." - }, - "buttons":{ - "close":"إغلاق التذكرة", - "delete":"حذف التذكرة", - "reopen":"إعادة فتح التذكرة", - "sendTranscript":"إرسال ملف النص" - }, - "messages":{ - "reopenTitle":"أعيد فتح هذه التذكرة!", - "reopenDescription":"لا تتردد في التحدث مرة أخرى!", - "closedTitle":"أغلقت هذه التذكرة!", - "closedDescription":"يمكن للمسؤولين فقط التحدث في هذه التذكرة الآن!\n\n*انقر فوق الزر أدناه لحذف هذه التذكرة أو إعادة فتحها!*", - "createdTitle":"تم إنشاء التذكرة!", - "createdDescription":"تم إنشاء تذكرتك ، يمكنك اكتشافها عن طريق ping", + "msgCmd": "أنشاء أيمبد مع الأزرار. (الأداريين فقط)", + "renameCmd": "إعادة تسمية التكت. (بدون مسافات)", + "closeCmd": "أغلاق التكت.", + "deleteCmd": "حذف التكت.", + "addCmd": "إضافة مستخدم الى التكت.", + "removeCmd": "إزالة مستخدم من التكت.", + "reopenCmd": "إعادة فتح تكت بعد إغلاقة." + }, + "buttons": { + "close": "إغلاق التكت", + "delete": "حذف التكت", + "reopen": "إعادة فتح التكت", + "sendTranscript": "طبع التكت", + "closeWithReason":"close with reason" + }, + "messages": { + "reopenTitle": "تم إعادة فتح التكت بنجاح!", + "reopenDescription": "لا تتردد في فتح التكت مرة أخرى , حظاً موفقاً!", + "closedTitle": "تم إغلاق التكت!", + "closedDescription": "فقط الأداريين يمكنهم التحدث في هذا التكت الأن!\n\n*أضغط على الزر بالأسفل لحذف التكت او إعادة فتحة مجدداً!*", + "createdTitle": "تم إنشاء تكت!", + "createdDescription": "تم أنشاء تكت , قم بأنتظار الدعم في الطريق!", - "newTicketDmTitle":"تذكرة جديدة!", - "closedTicketDmTitle":"تم إغلاق التذكرة!", - "deletedTicketDmTitle":"تم حذف التذكرة!", - "closedTicketDmDescription":"تم إغلاق تذكرتك!", - "deletedTicketDmDescription":"تم حذف تذكرتك!", - "reopenTicketDmTitle":"أعيد فتح التذكرة!", - "reopenTicketDmDescription":"تم إعادة فتح تذكرتك!", - "newTranscriptTitle":"نسخة جديدة هنا!", - "hereIsTheTranscript":"هذا هو النص:", + "newTicketDmTitle": "تكت جديد!", + "closedTicketDmTitle": "تم إغلاق التكت!", + "deletedTicketDmTitle": "تم حذف التكت!", + "closedTicketDmDescription": "تم أغلاق تذكرتك من قبل إداري", + "deletedTicketDmDescription": "تم حذف تذكرتك من قبل إداري!", + "reopenTicketDmTitle": "تم إعادة فتح تذكرتك!", + "reopenTicketDmDescription": "تم إعادة فتح التكت!", + "newTranscriptTitle": "توجد نسخة تكت جديدة هنا!", + "hereIsTheTranscript": "هذا هي النسخة:", - "chooseCategory":"اختر فئة:", - "gettingdeleted":"...يتم حذف التذكرة", + "chooseCategory": "أختر الكتقاجوري:", + "gettingdeleted": "يتم حذف التكت...", - "none":"none", - "reason":"reason" - } + "none": "لا يوجد", + "reason": "سبب", + + "deletedby":"deleted by", + "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", + "chooseATicket": "Choose a ticket" + } } \ No newline at end of file diff --git a/language/custom.json b/language/custom.json index 9496227..480d7f4 100644 --- a/language/custom.json +++ b/language/custom.json @@ -25,6 +25,8 @@ "closeTitle":"Closed this ticket!", "deleteTitle":"Deleting this ticket...", "reopenTitle":"Re-Opened this ticket!", + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", "ticketWarning":"The embed is in the message below!", "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" @@ -46,7 +48,8 @@ "close":"Close Ticket", "delete":"Delete Ticket", "reopen":"Re-Open Ticket", - "sendTranscript":"Transcript" + "sendTranscript":"Transcript", + "closeWithReason":"close with reason" }, "messages":{ "reopenTitle":"Re-Opened this ticket!", @@ -70,6 +73,11 @@ "gettingdeleted":"Ticket is getting deleted...", "none":"none", - "reason":"reason" + "reason":"reason", + + "deletedby":"deleted by", + "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", + "chooseATicket": "Choose a ticket" } } \ No newline at end of file diff --git a/language/czech.json b/language/czech.json index 93bdeb4..99c2e55 100644 --- a/language/czech.json +++ b/language/czech.json @@ -25,6 +25,8 @@ "closeTitle":"Zavři tento ticket!", "deleteTitle":"Smaž tento ticket!", "reopenTitle":"Znovu otevři ticket!", + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", "ticketWarning":"The embed is in the message below!", "maxTicketWarning":"**Varovaní:** _Můžeš si vytvořit použe {0} ticket(s) v jednu chvíli!_" @@ -46,7 +48,8 @@ "close":"Zavři ticket", "delete":"Smaž ticket", "reopen":"Znovu otevři ticket", - "sendTranscript":"Odešli log ticketu" + "sendTranscript":"Odešli log ticketu", + "closeWithReason":"close with reason" }, "messages":{ "reopenTitle":"Ticket znovu otevřen!", @@ -70,6 +73,11 @@ "gettingdeleted":"Ticket bude smazán", "none":"nic", - "reason":"důvod" + "reason":"důvod", + + "deletedby":"deleted by", + "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", + "chooseATicket": "Choose a ticket" } } \ No newline at end of file diff --git a/language/dutch.json b/language/dutch.json index 4bd61eb..a6fecec 100644 --- a/language/dutch.json +++ b/language/dutch.json @@ -25,6 +25,8 @@ "closeTitle":"Ticket gesloten!", "deleteTitle":"Ticket aan het verwijderen...", "reopenTitle":"Ticket heropend!", + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", "ticketWarning":"De embed is in het bericht hier onder!", "maxTicketWarning":"**Waarschuwing:** _Je kan maar {0} ticket(s) tegelijkertijd maken!_" @@ -46,7 +48,8 @@ "close":"Sluit Ticket", "delete":"Verwijder Ticket", "reopen":"Heropen Ticket", - "sendTranscript":"Transcript" + "sendTranscript":"Transcript", + "closeWithReason":"sluit met reden" }, "messages":{ "reopenTitle":"Ticket heropend!", @@ -70,6 +73,11 @@ "gettingdeleted":"Ticket wordt verwijderd...", "none":"geen", - "reason":"reden" + "reason":"reden", + + "deletedby":"verwijderd door", + "closedby":"gesloten door", + "modalreason":"Wat is de reden om dit ticket te sluiten?", + "chooseATicket": "Kies een ticket" } } \ No newline at end of file diff --git a/language/english.json b/language/english.json index 9496227..480d7f4 100644 --- a/language/english.json +++ b/language/english.json @@ -25,6 +25,8 @@ "closeTitle":"Closed this ticket!", "deleteTitle":"Deleting this ticket...", "reopenTitle":"Re-Opened this ticket!", + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", "ticketWarning":"The embed is in the message below!", "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" @@ -46,7 +48,8 @@ "close":"Close Ticket", "delete":"Delete Ticket", "reopen":"Re-Open Ticket", - "sendTranscript":"Transcript" + "sendTranscript":"Transcript", + "closeWithReason":"close with reason" }, "messages":{ "reopenTitle":"Re-Opened this ticket!", @@ -70,6 +73,11 @@ "gettingdeleted":"Ticket is getting deleted...", "none":"none", - "reason":"reason" + "reason":"reason", + + "deletedby":"deleted by", + "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", + "chooseATicket": "Choose a ticket" } } \ No newline at end of file diff --git a/language/french.json b/language/french.json index fcac829..92839c1 100644 --- a/language/french.json +++ b/language/french.json @@ -25,6 +25,8 @@ "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!", "ticketWarning":"L'intégration est dans le message ci-dessous!", "maxTicketWarning":"**Attention :** _Vous ne pouvez créer que {0} ticket(s) à la fois !_" @@ -46,7 +48,8 @@ "close":"Fermer le ticket", "delete":"Supprimer le billet", "reopen":"Billet de réouverture", - "sendTranscript":"Transcript" + "sendTranscript":"Transcript", + "closeWithReason":"fermer avec une raison" }, "messages":{ "reopenTitle":"A rouvert ce ticket!", @@ -70,6 +73,11 @@ "gettingdeleted":"Le ticket est en cours de suppression...", "none":"rien", - "reason":"raison" + "reason":"raison", + + "deletedby":"supprimé par", + "closedby":"fermé par", + "modalreason":"Qu’elle est la raison pour fermer ce ticket?", + "chooseATicket": "Choisir un ticket" } } \ No newline at end of file diff --git a/language/german.json b/language/german.json index 01d29a7..2284a57 100644 --- a/language/german.json +++ b/language/german.json @@ -25,6 +25,8 @@ "closeTitle":"Closed this ticket!", "deleteTitle":"Deleting this ticket...", "reopenTitle":"Re-Opened this ticket!", + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", "ticketWarning":"The embed is in the message below!", "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" @@ -46,7 +48,8 @@ "close":"Ticket schließen", "delete":"Ticket löschen", "reopen":"Ticket wieder öffnen", - "sendTranscript":"Transcript-Datei senden" + "sendTranscript":"Transcript-Datei senden", + "closeWithReason":"Geschlossen mit dem Grund" }, "messages":{ "reopenTitle":"Dieses Ticket wiedereröffnet!", @@ -70,6 +73,11 @@ "gettingdeleted":"Ticket wird gelöscht...", "none":"none", - "reason":"reason" + "reason":"reason", + + "deletedby":"Gelöscht von", + "closedby":"Geschlossen von", + "modalreason":"Was ist der Grund für das schließen des Tickets?", + "chooseATicket": "Wähle ein Ticket" } } \ No newline at end of file diff --git a/language/italian.json b/language/italian.json new file mode 100644 index 0000000..cf7bb87 --- /dev/null +++ b/language/italian.json @@ -0,0 +1,83 @@ +{ + "errors":{ + "missingArgsTitle":"Argomenti non validi!", + "missingArgsDescription":"Argomento mancante", + "noPermsTitle":"Permessi mancanti!", + "noPermsDescription":"Hai bisogno del permesso `ADMINISTRATOR` e essere nella lista dei ruoli accettati!", + "noPermsDelete":"Solo gli amministratori possono chiudere un ticket!", + "chooseFromListTitle":"ID non valido", + "chooseFromListDescription":"Scegli uno degli ID sotto:", + "boterror":"Errore del bot!", + "notInTicketTitle":"Non sei in un ticket!", + "notInTicketDescription":"Questo comando non funziona fuori da un ticket!", + "ticketDoesntExist":"Questo ticket non esiste più!", + "roleDoesntExist":"Questo ruolo non esiste più!", + "anotherOption":"Questa opzione non è di un ticket!", + "maxAmountTitle":"Massimo numero raggiunto!", + "maxAmountDescription":"Hai raggiunto il massimo numero di ticket consentiti!\nNon puoi crearne altri!", + "somethingWentWrong":"**Qualcosa è andato storto!**\nPerfavore riprova un'altra volta!", + "somethingWentWrongTranscript":"Qualcosa è andata storta durante la trascrizione!**\nPerfavore riprova un'altra volta!" + }, + "commands":{ + "userAddedTitle":"Aggiunto {0} al ticket!", + "userRemovedTitle":"Rimosso {0} da questo ticket!", + "renameTitle":"Cambia il nome in {0}!", + "closeTitle":"Chiudo questo ticket!", + "deleteTitle":"Eliminando questo ticket...", + "reopenTitle":"Ri-Aperto questo ticket!", + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", + + "ticketWarning":"L'embed è nel messaggio sotto!", + "maxTicketWarning":"**Attenzione:** _Tu puoi creare solo {0} ticket(s) per volta!_" + }, + "helpMenu":{ + "title":"Comandi disponibili:", + "header1":"**Vai a {0} per creare un ticket!**\n\n", + "header2":"**Esegui il comando `/new` o `/ticket` per creare un ticket!**\n\n", + + "msgCmd":"Crea un embed con pulsanti. (solo amministratori)", + "renameCmd":"Rinomina un ticket. (senza spazi)", + "closeCmd":"Chiudi un ticket.", + "deleteCmd":"Elimina un ticket.", + "addCmd":"Aggiungi un membro al ticket.", + "removeCmd":"Rimuovi un membro dal ticket.", + "reopenCmd":"Riapri un ticket dopo averlo chiuso." + }, + "buttons":{ + "close":"Chiudi il ticket", + "delete":"Elimina il ticket", + "reopen":"Riapri il ticket", + "sendTranscript":"Trascrizione", + "closeWithReason":"chiudi con un motivo" + }, + "messages":{ + "reopenTitle":"Riaperto questo ticket!", + "reopenDescription":"Sentiti libero di parlare di nuovo!", + "closedTitle":"Chiudo questo ticket!", + "closedDescription":"Solo gli amministratori possono parlare in questo ticket ora!\n\n*Clicca sul bottone sotto per chiudere o riaprire questo ticket!*", + "createdTitle":"Ticket creato!", + "createdDescription":"Il tuo ticket è stato creato, puoi capirlo dal ping!", + + "newTicketDmTitle":"Nuovo ticket!", + "closedTicketDmTitle":"Ticket chiuso!", + "deletedTicketDmTitle":"Ticket eliminato!", + "closedTicketDmDescription":"Il tuo ticket è chiuso!", + "deletedTicketDmDescription":"Il tuo ticket è stato eliminato!", + "reopenTicketDmTitle":"Ticket riaperto!", + "reopenTicketDmDescription":"Il tuo ticket è stato riaperto!", + "newTranscriptTitle":"Un nuova trascrizione è qui!", + "hereIsTheTranscript":"Qui è la trascrizione:", + + "chooseCategory":"scegli una categoria:", + "gettingdeleted":"Il ticket sta per essere chiuso...", + + "none":"nessuno", + "reason":"motivo", + + "deletedby":"eliminato da", + "closedby":"chiuso da", + "modalreason":"Quale'è il motivo per chiudere il ticket?", + "chooseATicket": "Scegli un ticket" + } +} \ No newline at end of file diff --git a/language/portuguese.json b/language/portuguese.json new file mode 100644 index 0000000..81561b5 --- /dev/null +++ b/language/portuguese.json @@ -0,0 +1,83 @@ +{ + "errors":{ + "missingArgsTitle":"Argumentos inválidos!", + "missingArgsDescription":"Argumento ausente", + "noPermsTitle":"Sem permissões!", + "noPermsDescription":"Você precisa da permissão `ADMINISTRATOR` ou estar na lista de funções permitidas!", + "noPermsDelete":"Somente administradores podem deletar um ticket!", + "chooseFromListTitle":"ID inválido", + "chooseFromListDescription":"Escolha um dos IDs abaixo:", + "boterror":"Erro de bot!", + "notInTicketTitle":"Você não está em um ticket!", + "notInTicketDescription":"Este comando não funciona fora dos tickets!", + "ticketDoesntExist":"Este ticket não existe mais!", + "roleDoesntExist":"Esta função não existe mais!", + "anotherOption":"Esta opção não é um ticket, mas sim outro tipo!", + "maxAmountTitle":"Quantidade máxima atingida!", + "maxAmountDescription":"Você atingiu o número máximo de tickets permitidos!\nEntão você não pode criar um novo!", + "somethingWentWrong":"**Algo deu errado!**\nPor favor, tente novamente outra vez!", + "somethingWentWrongTranscript":"Algo deu errado ao fazer a transcrição!**\nPor favor, tente novamente outra vez!" + }, + "commands":{ + "userAddedTitle":"Adicionado {0} a este ticket!", + "userRemovedTitle":"Removido {0} deste ticket!", + "renameTitle":"Mudou o nome para {0}!", + "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!", + + "ticketWarning":"A incorporação está na mensagem abaixo!", + "maxTicketWarning":"**Cuidado:** _Você só pode criar {0} ticket(s) de cada vez!!_" + }, + "helpMenu":{ + "title":"Comandos Disponíveis:", + "header1":"**Vá para {0} para criar um ticket!**\n\n", + "header2":"**Execute o comando `/new` ou `/ticket` para criar um ticket!**\n\n", + + "msgCmd":"Gerar uma incorporação com botões. (somente administradores)", + "renameCmd":"Renomear um ticket. (sem espaços)", + "closeCmd":"Fechar um ticket.", + "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." + }, + "buttons":{ + "close":"Fechar Ticket", + "delete":"Excluir Ticket", + "reopen":"Reabrir Ticket", + "sendTranscript":"Transcrição", + "closeWithReason":"close with reason" + }, + "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!", + + "newTicketDmTitle":"Novo Ticket!", + "closedTicketDmTitle":"Ticket fechado!", + "deletedTicketDmTitle":"Ticket excluído!", + "closedTicketDmDescription":"Seu ticket está fechado!", + "deletedTicketDmDescription":"Seu bilhete foi excluído!", + "reopenTicketDmTitle":"Ticket reaberto!", + "reopenTicketDmDescription":"Seu ticket foi reaberto!", + "newTranscriptTitle":"Uma nova transcrição está aqui!", + "hereIsTheTranscript":"Aqui está a transcrição:", + + "chooseCategory":"Escolha a categoria:", + "gettingdeleted":"Ticket está sendo deletado...", + + "none":"none", + "reason":"reason", + + "deletedby":"deleted by", + "closedby":"closed by", + "modalreason":"What is the reason for closing this ticket?", + "chooseATicket": "Choose a ticket" + } +} \ No newline at end of file diff --git a/language/romanian.json b/language/romanian.json index 42f906d..d9d0113 100644 --- a/language/romanian.json +++ b/language/romanian.json @@ -25,6 +25,8 @@ "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!", "ticketWarning":"Embed-ul se afla in mesajul de mai jos!", "maxTicketWarning":"**Avertizare:** _Poti creea doar {0} tickete active!_" @@ -46,7 +48,8 @@ "close":"Inchide ticket-ul", "delete":"Sterge ticket-ul", "reopen":"Re-deschide un ticket", - "sendTranscript":"Transcript" + "sendTranscript":"Transcript", + "closeWithReason":"Inchide cu motiv" }, "messages":{ "reopenTitle":"Ticket Re-deschis!", @@ -70,6 +73,11 @@ "gettingdeleted":"Ticket-ul se sterge...", "none":"niciunul", - "reason":"Motiv" + "reason":"Motiv", + + "deletedby":"Sters de", + "closedby":"Inchis de", + "modalreason":"Care este motivul pentru inchiderea acestui ticket?", + "chooseATicket": "Alege un ticket" } } \ No newline at end of file diff --git a/language/slashcmds/slash.json b/language/slashcmds/slash.json new file mode 100644 index 0000000..a3b8f56 --- /dev/null +++ b/language/slashcmds/slash.json @@ -0,0 +1,139 @@ +{ + "examples":{ + "en-GB":"english", + "en-US":"english", + "nl":"dutch", + "ro":"romanian", + "de":"german", + "cs":"czech", + "fr":"french", + "es-ES":"spanish", + "it":"italian", + + "MISSING":"arabic,portuguese", + "NOTAVAILABLE":"arabic,portuguese,czech" + }, + "data":{ + "help":{ + "en-GB":"A list of the available commands.", + "en-US":"A list of the available commands.", + "nl":"Een lijst met de beschikbare commands.", + "ro":"O lista a comenzilor disponibile.", + "de":"Eine Liste der verfügbaren Befehle.", + "cs":"A list of the available commands", + "fr":"Une liste des commandes.", + "es-ES":"Una lista de los comandos disponibles.", + "it":"Una lista di tutti i comandi disponibili." + }, + "message":{ + "en-GB":"Spawn an embed with buttons.", + "en-US":"Spawn an embed with buttons.", + "nl":"Spawn een embed met knoppen.", + "ro":"Deschide un embed cu butoane.", + "de":"Sendet ein Embed mit Knöpfen.", + "cs":"Spawn an embed with buttons.", + "fr":"Créer un embed avec des boutons.", + "es-ES":"Genera un embed con botones.", + "it":"Genera un embed con un pulsante." + }, + "close":{ + "en-GB":"Close a ticket.", + "en-US":"Close a ticket.", + "nl":"Sluit een ticket", + "ro":"Inchide un ticket.", + "de":"Schließe ein Ticket.", + "cs":"Close a ticket.", + "fr":"Fermer un ticket.", + "es-ES":"Cierra un ticket.", + "it":"Chiudi un ticket." + }, + "delete":{ + "en-GB":"Delete a ticket.", + "en-US":"Delete a ticket.", + "nl":"Verwijder een ticket", + "ro":"Sterge un ticket.", + "de":"Lösche ein Ticket.", + "cs":"Delete a ticket.", + "fr":"Supprimer un ticket.", + "es-ES":"Elimina un ticket.", + "it":"Elimina un ticket." + }, + "reopen":{ + "en-GB":"Re-Open a ticket.", + "en-US":"Re-Open a ticket.", + "nl":"Heropen een ticket.", + "ro":"Re-deschide un ticket.", + "de":"Wiedereröffnung eines Tickets.", + "cs":"Re-Open a ticket.", + "fr":"Re-ouvrir un ticket.", + "es-ES":"Re-abre un ticket.", + "it":"Ri-Apri un ticket." + }, + "add":{ + "en-GB":"Add another user to a ticket.", + "en-US":"Add another user to a ticket.", + "nl":"Voeg een andere user toe aan een ticket.", + "ro":"Adauga un utilizator la acest ticket.", + "de":"Füge einen anderen Nutzer zum Ticket hinzu.", + "cs":"Add another user to a ticket.", + "fr":"Ajouter un utilisateur au ticket.", + "es-ES":"Agrega otro usuario al ticket.", + "it":"Aggiungi un membro al ticket" + }, + "remove":{ + "en-GB":"Remove a user from a ticket.", + "en-US":"Remove a user from a ticket.", + "nl":"Verwijder een user van een ticket.", + "ro":"Sterge un utilizator dintr-un ticket.", + "de":"Entferne einen Nutzer von dem Ticket.", + "cs":"Remove a user from a ticket.", + "fr":"Enlever quelqu’un du ticket.", + "es-ES":"Elimina otro usuario del ticket.", + "it":"Rimuovi un membro dal ticket" + }, + "newticket":{ + "en-GB":"Create a ticket", + "en-US":"Create a ticket", + "nl":"Maak een ticket aan", + "ro":"Creeaza un ticket.", + "de":"Erstelle ein Ticket.", + "cs":"Create a ticket", + "fr":"Créer un ticket", + "es-ES":"Crear un ticket.", + "it":"Crea un ticket" + }, + "rename":{ + "en-GB":"Rename a ticket channel.", + "en-US":"Rename a ticket channel.", + "nl":"Hernoem een ticket channel.", + "ro":"Redenumeste un ticket.", + "de":"Benenne einen Ticket Channel.", + "cs":"Rename a ticket channel", + "fr":"Renommer un ticket.", + "es-ES":"Renombrar un canal de ticket.", + "it":"Rinomina il canale di un ticket." + }, + "claim":{ + "en-GB":"", + "en-US":"", + "nl":"", + "ro":"", + "de":"", + "cs":"", + "fr":"", + "es-ES":"", + "it":"" + }, + "unclaim":{ + "en-GB":"", + "en-US":"", + "nl":"", + "ro":"", + "de":"", + "cs":"", + "fr":"", + "es-ES":"", + "it":"" + } + } +} \ No newline at end of file diff --git a/language/spanish.json b/language/spanish.json index cc2586b..15527bb 100644 --- a/language/spanish.json +++ b/language/spanish.json @@ -1,75 +1,83 @@ -{ - "errors":{ - "missingArgsTitle":"¡Argumentos inválidos!", - "missingArgsDescription":"Argumento faltante.", - "noPermsTitle":"¡Sin permisos!", - "noPermsDescription":"You need the `ADMINISTRATOR` permission or be in the list of allowed roles!", - "noPermsDelete":"Only admins can delete a ticket!", - "chooseFromListTitle":"ID Invalida", - "chooseFromListDescription":"Elije una de las ID de abajo:", - "boterror":"¡Error del bot!", - "notInTicketTitle":"¡No te encuentras en un ticket!", - "notInTicketDescription":"¡Este comando no funciona fuera de los tickets!", - "ticketDoesntExist":"¡Este ticket no existe!", - "roleDoesntExist":"¡Este rol no existe!", - "anotherOption":"¡Esta opción no es un ticket, si no otra cosa!", - "maxAmountTitle":"¡Máxima cantidad alcanzada!", - "maxAmountDescription":"¡Has alcanzado la máxima cantidad de tickets permitida!\n¡Por lo que no puedes crear otro!", - "somethingWentWrong":"**¡Algo salió mal!**\n¡Prueba dentro de un rato!", - "somethingWentWrongTranscript":"**¡Algo salió mal al hacer el transcript!**\n¡Prueba en otro momento!" - }, - "commands":{ - "userAddedTitle":"Added {0} to this ticket!", - "userRemovedTitle":"Removed {0} from this ticket!", - "renameTitle":"Changed the name to {0}!", - "closeTitle":"Closed this ticket!", - "deleteTitle":"Deleting this ticket...", - "reopenTitle":"Re-Opened this ticket!", - - "ticketWarning":"The embed is in the message below!", - "maxTicketWarning":"**Warning:** _You can only create {0} ticket(s) at a time!_" - }, - "helpMenu":{ - "title":"Available Commands:", - "header1":"**¡Dirígete a {0} para crear un nuevo ticket!**\n\n", - "header2":"**¡Ejecuta el comando `/new` o `/ticket` para crear un ticket!**\n\n", - - "msgCmd":"Generar un embed con botones. (Solo admins)", - "renameCmd":"Renombrar un ticket. (Sin espacios)", - "closeCmd":"Cerrar un ticket.", - "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." - }, - "buttons":{ - "close":"Cerrar ticket.", - "delete":"Eliminar ticket", - "reopen":"Re-Abrir ticket", - "sendTranscript":"Obtener transcript." - }, - "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!", - - "newTicketDmTitle":"¡Nuevo ticket!", - "closedTicketDmTitle":"¡Ticket cerrado!", - "deletedTicketDmTitle":"¡Ticket eliminado!", - "closedTicketDmDescription":"¡Tu ticket fué cerrado!", - "deletedTicketDmDescription":"¡Tu ticket fué eliminado!", - "reopenTicketDmTitle":"¡Ticket re-abierto!", - "reopenTicketDmDescription":"¡Tu ticket se vió abierto de nuevo!", - "newTranscriptTitle":"¡Un nuevo transcript está aquí!", - "hereIsTheTranscript":"Aquí está el transcript:", - - "chooseCategory":"elije una categoría:", - "gettingdeleted":"El ticket se está viendo eliminado...", - - "none":"none", - "reason":"reason" - } +{ + "errors":{ + "missingArgsTitle":"¡Argumentos inválidos!", + "missingArgsDescription":"Argumento faltante.", + "noPermsTitle":"¡Sin permisos!", + "noPermsDescription":"Necesitas el permiso de `ADMINISTRADOR` o estar en la lista de roles permitidos!", + "noPermsDelete":"Solo los administradores pueden eliminar un ticket.!", + "chooseFromListTitle":"ID Invalida", + "chooseFromListDescription":"Elije una de las ID de abajo:", + "boterror":"¡Error del bot!", + "notInTicketTitle":"¡No te encuentras en un ticket!", + "notInTicketDescription":"¡Este comando no funciona fuera de los tickets!", + "ticketDoesntExist":"¡Este ticket no existe!", + "roleDoesntExist":"¡Este rol no existe!", + "anotherOption":"¡Esta opción no es un ticket, si no otra cosa!", + "maxAmountTitle":"¡Máxima cantidad alcanzada!", + "maxAmountDescription":"¡Has alcanzado la máxima cantidad de tickets permitida!\n¡Por lo que no puedes crear otro!", + "somethingWentWrong":"**¡Algo salió mal!**\n¡Prueba dentro de un rato!", + "somethingWentWrongTranscript":"**¡Algo salió mal al hacer el transcript!**\n¡Prueba en otro momento!" + }, + "commands":{ + "userAddedTitle":"Se agregó {0} al ticket!", + "userRemovedTitle":"Se eliminó {0} del ticket!", + "renameTitle":"Cambió el nombre a {0}!", + "closeTitle":"Cerró este ticket!", + "deleteTitle":"Eliminando este ticket...", + "reopenTitle":"Re-abrió este boleto!", + "claimTitle":"This ticket is now claimed to {0}", + "unclaimTitle":"This ticket isn't claimed anymore!", + + "ticketWarning":"La inserción está en el mensaje a continuación!", + "maxTicketWarning":"**Advertencia:** _Solo puedes crear {0} ticket(s) a la vez!_" + }, + "helpMenu":{ + "title":"Comandos disponibles:", + "header1":"**¡Dirígete a {0} para crear un nuevo ticket!**\n\n", + "header2":"**¡Ejecuta el comando `/new` o `/ticket` para crear un ticket!**\n\n", + + "msgCmd":"Generar un embed con botones. (Solo admins)", + "renameCmd":"Renombrar un ticket. (Sin espacios)", + "closeCmd":"Cerrar un ticket.", + "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." + }, + "buttons":{ + "close":"Cerrar ticket.", + "delete":"Eliminar ticket", + "reopen":"Re-Abrir ticket", + "sendTranscript":"Obtener transcript.", + "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!", + + "newTicketDmTitle":"¡Nuevo ticket!", + "closedTicketDmTitle":"¡Ticket cerrado!", + "deletedTicketDmTitle":"¡Ticket eliminado!", + "closedTicketDmDescription":"¡Tu ticket fué cerrado!", + "deletedTicketDmDescription":"¡Tu ticket fué eliminado!", + "reopenTicketDmTitle":"¡Ticket re-abierto!", + "reopenTicketDmDescription":"¡Tu ticket se vió abierto de nuevo!", + "newTranscriptTitle":"¡Un nuevo transcript está aquí!", + "hereIsTheTranscript":"Aquí está el transcript:", + + "chooseCategory":"Elije una categoría:", + "gettingdeleted":"El ticket se está viendo eliminado...", + + "none":"Ninguna.", + "reason":"Razón", + + "deletedby":"eliminado por", + "closedby":"cerrado por", + "modalreason":"Cúal es la razón para cerrar este ticket?", + "chooseATicket": "Elije un ticket" + } } \ No newline at end of file diff --git a/package.json b/package.json index 817eebe..68219c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-ticket", - "version": "2.5.0", + "version": "3.0.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": {