Merge pull request #24 from DJj123dj/dev

v2.4.0 pre release
This commit is contained in:
Jasper
2022-08-02 14:15:24 +02:00
committed by GitHub
32 changed files with 992 additions and 394 deletions
+27 -21
View File
@@ -7,7 +7,7 @@ make a ticket in our server to start!
*if you translate, you will come in the credits* *if you translate, you will come in the credits*
# open-ticket # 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.3.3%20stable-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v2.3.3) [![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) [![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.4.0%20stable-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v2.4.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! This is an open-source discord ticket bot, you can configure it and it comes with cool features like transcripts & custom options!
@@ -18,51 +18,57 @@ This is an open-source discord ticket bot, you can configure it and it comes wit
### Thanks to these people: ### Thanks to these people:
- DJ-Lite: for doing the administration - DJ-Lite: for doing the administration
- Sanke: for translation & new ideas - Sanke: for translation & new ideas
- Everyone that reported a bug
#### And our translators!
- ExothDE: for translation - ExothDE: for translation
- 1x1: for translation - 1x1: for translation
- R0JO: for translation - R0JO: for translation
- Everyone that reported a bug - t0miiis for translation
## features ## features
- discord buttons - discord interaction buttons
- slash & text commands - slash & text commands
- close, delete & re-open tickets - close, delete & re-open tickets
- translation (we are searching for translators!) - translation in 8 different languages
- dynamic database system - dynamic database system
- advanced transcripts - transcripts
- add/remove users from a ticket - add/remove users from a ticket
- large embed customisation - custom colors & name for embeds
- create custom ticket names, icons & colors - customise your ticket
- create url's & reaction roles! - create url buttons for websites
- uses discord.js v13 - create reaction roles
- configure your own ticket options - build with discord.js v14
- remove credits if you want (don't do it please 😉) - configure everything per ticket
- unlimited tickets at the same time - remove credits if you want :(
- unlimited tickets spread over multiple messages
*comming soon:*
- dashboard
- view transcripts in dashboard
- share transcripts
- close with reason
- more translation
## installation ## installation
**You need `node.js 16` to run this project!** **You need `node.js 16` to run this project!**
**At this moment you still need discord.js v13!**
This will change soon!
You can clone or download this project.
### packages ### packages
- chalk => version `latest` - chalk => version `latest`
- discord.js => version `latest` - discord.js => version `latest`
- express => version `latest` - express => version `latest`
- node-localstorage => version `latest` - node-localstorage => version `latest`
- axios => version `latest`
You can install all of them by running `npm install` You can install all of them by running `npm install`
## running ## running
you can run `node index.js` but i would recommend you to use `npm start` 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 the discord server**. if there are any errors, you can open an **issue on github** or **contact me in our discord server**.
### config ### config
Our config documentation is moved to another file: Our config documentation is moved to another file:
[click here to view](https://www.github.com/DJj123dj/open-ticket/wiki/config-v2.3.3) [click here to view](https://www.github.com/DJj123dj/open-ticket/wiki/config-v2.4.0)
### intents & permissions ### 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 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
@@ -74,8 +80,8 @@ You can also configure your own permissions
## information ## information
_v2.3.3 stable_ _v2.4.0 stable_
changelog: [click here](https://www.github.com/DJj123dj/open-ticket/wiki/Changelog) changelog: [click here](https://www.github.com/DJj123dj/open-ticket/wiki/Changelog)
© 2022 - DJdj Development | [website](https://www.dj-dj.be) | [discord](https://discord.com/invite/26vT9wt3n3) © 2022 - DJdj Development | [website](https://www.dj-dj.be) | [discord](https://discord.dj-dj.be) | [terms of service](https://www.dj-dj.be/terms)
+24 -9
View File
@@ -4,6 +4,9 @@ const client = bot.client
const config = bot.config const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
client.on("messageCreate",msg => { client.on("messageCreate",msg => {
@@ -11,12 +14,10 @@ module.exports = () => {
var user = msg.mentions.users.first() var user = msg.mentions.users.first()
if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" `<user>`:\n`"+config.prefix+"add <user>`")]}) if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" `<user>`:\n`"+config.prefix+"add <user>`")]})
if (!msg.member.permissions.has("ManageChannels") && !msg.member.permissions.has("Administrator") && config.main_adminroles.some((item)=>{return msg.member.roles.cache.has(item)}) == false){ if (!msg.guild) return
try { if (!permsChecker.command(msg.author.id,msg.guild.id)){
return msg.member.send({embeds:[bot.errorLog.noPermsMessage]}) permsChecker.sendUserNoPerms(msg.author)
}catch{ return
return msg.channel.send({embeds:[bot.errorLog.noPermsMessage]})
}
} }
msg.channel.messages.fetchPinned().then(msglist => { msg.channel.messages.fetchPinned().then(msglist => {
@@ -30,6 +31,12 @@ module.exports = () => {
var loguser = msg.mentions.users.first() var loguser = msg.mentions.users.first()
log("command","someone used the 'add' command",[{key:"user",value:msg.author.tag}]) 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}]) 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 ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("../core/getoptions").getOptionsById("newT"+ticketId)
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())
}) })
}) })
@@ -39,12 +46,14 @@ module.exports = () => {
if (interaction.commandName != "add") return if (interaction.commandName != "add") return
const user = interaction.options.getUser("user") const user = interaction.options.getUser("user")
const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) if (!interaction.guild) return
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
interaction.reply({embeds:[bot.errorLog.noPermsMessage],ephemeral:true}) permsChecker.sendUserNoPerms(interaction.user)
return return
} }
interaction.deferReply()
interaction.channel.messages.fetchPinned().then(msglist => { interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
@@ -56,6 +65,12 @@ module.exports = () => {
var loguser = user var loguser = user
log("command","someone used the 'add' command",[{key:"user",value:interaction.user.tag}]) 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}]) 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 ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("../core/getoptions").getOptionsById("newT"+ticketId)
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())
}) })
+7
View File
@@ -4,6 +4,9 @@ const client = bot.client
const config = bot.config const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
client.on("messageCreate",msg => { client.on("messageCreate",msg => {
@@ -27,6 +30,7 @@ module.exports = () => {
msg.channel.send({embeds:[bot.errorLog.success(l.commands.closeTitle,l.commands.closeDescription)],components:[closebutton]}) msg.channel.send({embeds:[bot.errorLog.success(l.commands.closeTitle,l.commands.closeDescription)],components:[closebutton]})
log("command","someone used the 'close' command",[{key:"user",value:msg.author.tag}]) 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())
}) })
@@ -37,6 +41,8 @@ module.exports = () => {
if (!interaction.isChatInputCommand()) return if (!interaction.isChatInputCommand()) return
if (interaction.commandName != "close") return if (interaction.commandName != "close") return
interaction.deferReply()
interaction.channel.messages.fetchPinned().then(msglist => { interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
@@ -54,6 +60,7 @@ module.exports = () => {
interaction.reply({embeds:[bot.errorLog.success(l.commands.closeTitle,l.commands.closeDescription)],components:[closebutton]}) interaction.reply({embeds:[bot.errorLog.success(l.commands.closeTitle,l.commands.closeDescription)],components:[closebutton]})
log("command","someone used the 'close' command",[{key:"user",value:interaction.user.tag}]) 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())
}) })
}) })
+14 -10
View File
@@ -4,17 +4,18 @@ const client = bot.client
const config = bot.config const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
client.on("messageCreate",msg => { client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix+"delete")) return if (!msg.content.startsWith(config.prefix+"delete")) return
if (!msg.member.permissions.has("ManageChannels") && !msg.member.permissions.has("Administrator") && config.main_adminroles.some((item)=>{return msg.member.roles.cache.has(item)}) == false){ if (!msg.guild) return
try { if (!permsChecker.command(msg.author.id,msg.guild.id)){
return msg.member.send({embeds:[bot.errorLog.noPermsMessage]}) permsChecker.sendUserNoPerms(msg.author)
}catch{ return
return msg.channel.send({embeds:[bot.errorLog.noPermsMessage]})
}
} }
msg.channel.messages.fetchPinned().then(msglist => { msg.channel.messages.fetchPinned().then(msglist => {
@@ -34,7 +35,7 @@ module.exports = () => {
msg.channel.send({embeds:[bot.errorLog.success(l.commands.deleteTitle,l.commands.deleteDescription)],components:[closebutton]}) msg.channel.send({embeds:[bot.errorLog.success(l.commands.deleteTitle,l.commands.deleteDescription)],components:[closebutton]})
log("command","someone used the 'delete' command",[{key:"user",value:msg.author.tag}]) 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,9 +45,11 @@ module.exports = () => {
if (!interaction.isChatInputCommand()) return if (!interaction.isChatInputCommand()) return
if (interaction.commandName != "delete") return if (interaction.commandName != "delete") return
const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) interaction.deferReply()
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){
interaction.reply({embeds:[bot.errorLog.noPermsMessage],ephemeral:true}) if (!interaction.guild) return
if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
permsChecker.sendUserNoPerms(interaction.user)
return return
} }
@@ -67,6 +70,7 @@ module.exports = () => {
interaction.reply({embeds:[bot.errorLog.success(l.commands.deleteTitle,l.commands.deleteDescription)],components:[closebutton]}) interaction.reply({embeds:[bot.errorLog.success(l.commands.deleteTitle,l.commands.deleteDescription)],components:[closebutton]})
log("command","someone used the 'close' command",[{key:"user",value:interaction.user.tag}]) log("command","someone used the 'close' 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())
}) })
}) })
+5
View File
@@ -5,6 +5,8 @@ const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
const helpEmbed = new discord.EmbedBuilder() const helpEmbed = new discord.EmbedBuilder()
.setColor(config.main_color) .setColor(config.main_color)
@@ -24,6 +26,7 @@ module.exports = () => {
if (!args[1]){ if (!args[1]){
msg.channel.send({embeds:[helpEmbed]}) msg.channel.send({embeds:[helpEmbed]})
log("command","someone used the 'help' command",[{key:"user",value:msg.author.tag}]) log("command","someone used the 'help' command",[{key:"user",value:msg.author.tag}])
APIEvents.onCommand("help",true,msg.author,msg.channel,msg.guild,new Date())
return return
} }
@@ -31,6 +34,7 @@ module.exports = () => {
msg.channel.send({embeds:[helpEmbed]}) msg.channel.send({embeds:[helpEmbed]})
log("command","someone used the 'help' command",[{key:"user",value:msg.author.tag}]) log("command","someone used the 'help' command",[{key:"user",value:msg.author.tag}])
APIEvents.onCommand("help",true,msg.author,msg.channel,msg.guild,new Date())
} }
}) })
@@ -40,5 +44,6 @@ module.exports = () => {
interaction.reply({embeds:[helpEmbed]}) interaction.reply({embeds:[helpEmbed]})
log("command","someone used the 'help' command",[{key:"user",value:interaction.user.tag}]) log("command","someone used the 'help' command",[{key:"user",value:interaction.user.tag}])
APIEvents.onCommand("help",true,interaction.user,interaction.channel,interaction.guild,new Date())
}) })
} }
+22 -9
View File
@@ -4,6 +4,9 @@ const client = bot.client
const config = bot.config const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
client.on("messageCreate",msg => { client.on("messageCreate",msg => {
@@ -11,14 +14,14 @@ module.exports = () => {
var user = msg.mentions.users.first() var user = msg.mentions.users.first()
if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" `<user>`:\n`"+config.prefix+"remove <user>`")]}) if (!user) return msg.channel.send({embeds:[bot.errorLog.invalidArgsMessage(l.errors.missingArgsDescription+" `<user>`:\n`"+config.prefix+"remove <user>`")]})
if (!msg.member.permissions.has("ManageChannels") && !msg.member.permissions.has("Administrator") && config.main_adminroles.some((item)=>{return msg.member.roles.cache.has(item)}) == false){ if (!msg.guild) return
try { if (!permsChecker.command(msg.author.id,msg.guild.id)){
return msg.member.send({embeds:[bot.errorLog.noPermsMessage]}) permsChecker.sendUserNoPerms(msg.author)
}catch{ return
return msg.channel.send({embeds:[bot.errorLog.noPermsMessage]})
}
} }
interaction.deferReply()
msg.channel.messages.fetchPinned().then(msglist => { msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
@@ -31,6 +34,11 @@ module.exports = () => {
log("command","someone used the 'remove' command",[{key:"user",value:msg.author.tag}]) 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}]) 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 ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("../core/getoptions").getOptionsById("newT"+ticketId)
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())
}) })
}) })
@@ -40,9 +48,9 @@ module.exports = () => {
if (interaction.commandName != "remove") return if (interaction.commandName != "remove") return
const user = interaction.options.getUser("user") const user = interaction.options.getUser("user")
const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) if (!interaction.guild) return
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
interaction.reply({embeds:[bot.errorLog.noPermsMessage],ephemeral:true}) permsChecker.sendUserNoPerms(interaction.user)
return return
} }
@@ -60,6 +68,11 @@ module.exports = () => {
log("command","someone used the 'remove' command",[{key:"user",value:interaction.user.tag}]) 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}]) 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 ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("../core/getoptions").getOptionsById("newT"+ticketId)
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())
}) })
+14 -10
View File
@@ -4,6 +4,9 @@ const client = bot.client
const config = bot.config const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
client.on("messageCreate",msg => { client.on("messageCreate",msg => {
@@ -14,12 +17,10 @@ module.exports = () => {
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]})
if (!msg.member.permissions.has("ManageChannels") && !msg.member.permissions.has("Administrator") && config.main_adminroles.some((item)=>{return msg.member.roles.cache.has(item)}) == false){ if (!msg.guild) return
try { if (!permsChecker.command(msg.author.id,msg.guild.id)){
return msg.member.send({embeds:[bot.errorLog.noPermsMessage]}) permsChecker.sendUserNoPerms(msg.author)
}catch{ return
return msg.channel.send({embeds:[bot.errorLog.noPermsMessage]})
}
} }
var newname = msg.content.split(config.prefix+"rename")[1].substring(1) var newname = msg.content.split(config.prefix+"rename")[1].substring(1)
@@ -42,7 +43,7 @@ module.exports = () => {
log("command","someone used the 'rename' command",[{key:"user",value:msg.author.tag}]) log("command","someone used the 'rename' command",[{key:"user",value:msg.author.tag}])
log("system","ticket renamed",[{key:"user",value:msg.author.tag},{key:"ticket",value:name},{key:"newname",value:newname}]) log("system","ticket renamed",[{key:"user",value:msg.author.tag},{key:"ticket",value:name},{key:"newname",value:newname}])
APIEvents.onCommand("rename",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date())
}) })
@@ -52,14 +53,16 @@ module.exports = () => {
if (!interaction.isChatInputCommand()) return if (!interaction.isChatInputCommand()) return
if (interaction.commandName != "rename") return if (interaction.commandName != "rename") return
interaction.deferReply()
interaction.channel.messages.fetchPinned().then(msglist => { interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id)return interaction.reply({embeds:[bot.errorLog.notInATicket]}) if (firstmsg == undefined || firstmsg.author.id != client.user.id)return interaction.reply({embeds:[bot.errorLog.notInATicket]})
const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) if (!interaction.guild) return
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
interaction.reply({embeds:[bot.errorLog.noPermsMessage],ephemeral:true}) permsChecker.sendUserNoPerms(interaction.user)
return return
} }
@@ -81,6 +84,7 @@ module.exports = () => {
log("command","someone used the 'rename' command",[{key:"user",value:interaction.user.tag}]) log("command","someone used the 'rename' command",[{key:"user",value:interaction.user.tag}])
log("system","ticket renamed",[{key:"user",value:interaction.user.tag},{key:"ticket",value:name},{key:"newname",value:newname}]) log("system","ticket renamed",[{key:"user",value:interaction.user.tag},{key:"ticket",value:name},{key:"newname",value:newname}])
APIEvents.onCommand("rename",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date())
}) })
}) })
} }
+14 -3
View File
@@ -4,6 +4,9 @@ const client = bot.client
const config = bot.config const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
var reopenCommandBar = new discord.ActionRowBuilder() var reopenCommandBar = new discord.ActionRowBuilder()
@@ -27,23 +30,31 @@ module.exports = () => {
log("command","someone used the 'reopen' command",[{key:"user",value:msg.author.tag}]) 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())
}) })
}) })
client.on("interactionCreate",(interaction) => { client.on("interactionCreate",async (interaction) => {
if (!interaction.isChatInputCommand()) return if (!interaction.isChatInputCommand()) return
if (interaction.commandName != "reopen") return if (interaction.commandName != "reopen") return
interaction.channel.messages.fetchPinned().then(msglist => { await interaction.deferReply()
interaction.channel.messages.fetchPinned().then(async msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]}) if (firstmsg == undefined || firstmsg.author.id != client.user.id) return msg.channel.send({embeds:[bot.errorLog.notInATicket]})
interaction.reply({embeds:[bot.errorLog.success(l.commands.reopenTitle,l.commands.reopenDescription)],components:[reopenCommandBar]}) try {
await interaction.reply({embeds:[bot.errorLog.success(l.commands.reopenTitle,l.commands.reopenDescription)],components:[reopenCommandBar]})
}catch{
await interaction.editReply({embeds:[bot.errorLog.success(l.commands.reopenTitle,l.commands.reopenDescription)],components:[reopenCommandBar]})
}
log("command","someone used the 'reopen' command",[{key:"user",value:interaction.user.tag}]) 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())
}) })
+15 -11
View File
@@ -4,6 +4,9 @@ const client = bot.client
const config = bot.config const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const permsChecker = require("../core/utils/permisssionChecker")
const APIEvents = require("../core/api/modules/events")
module.exports = () => { module.exports = () => {
/**@type {String[]} */ /**@type {String[]} */
@@ -16,12 +19,10 @@ module.exports = () => {
client.on("messageCreate", msg => { client.on("messageCreate", msg => {
if (msg.content.startsWith(config.prefix+"msg"||config.prefix+"message")){ if (msg.content.startsWith(config.prefix+"msg"||config.prefix+"message")){
if (!msg.member.permissions.has("ManageChannels") && !msg.member.permissions.has("Administrator") && config.main_adminroles.some((item)=>{return msg.member.roles.cache.has(item)}) == false){ if (!msg.guild) return
try { if (!permsChecker.command(msg.author.id,msg.guild.id)){
return msg.member.send({embeds:[bot.errorLog.noPermsMessage]}) permsChecker.sendUserNoPerms(msg.author)
}catch{ return
return msg.channel.send({embeds:[bot.errorLog.noPermsMessage]})
}
} }
const id = msg.content.split(config.prefix+"msg")[1].substring(1) ? msg.content.split(config.prefix+"msg")[1].substring(1) : false const id = msg.content.split(config.prefix+"msg")[1].substring(1) ? msg.content.split(config.prefix+"msg")[1].substring(1) : false
@@ -34,7 +35,8 @@ module.exports = () => {
msg.channel.send({embeds:[embed],components:componentRows}) msg.channel.send({embeds:[embed],components:componentRows})
log("command","someone used the 'msg' command",[{key:"user",value:msg.author.tag},{key:"id",value:id}]) log("command","someone used the 'message' command",[{key:"user",value:msg.author.tag},{key:"id",value:id}])
APIEvents.onCommand("message",permsChecker.command(msg.author.id,msg.guild.id),msg.author,msg.channel,msg.guild,new Date())
} }
}) })
@@ -42,9 +44,9 @@ module.exports = () => {
if (!interaction.isChatInputCommand()) return if (!interaction.isChatInputCommand()) return
if (interaction.commandName != "message") return if (interaction.commandName != "message") return
const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) if (!interaction.guild) return
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
interaction.reply({embeds:[bot.errorLog.noPermsMessage],ephemeral:true}) permsChecker.sendUserNoPerms(interaction.user)
return return
} }
@@ -57,7 +59,9 @@ module.exports = () => {
interaction.reply({content:l.commands.ticketWarning}) interaction.reply({content:l.commands.ticketWarning})
interaction.channel.send({embeds:[embed],components:componentRows}) interaction.channel.send({embeds:[embed],components:componentRows})
log("command","someone used the 'msg' command",[{key:"user",value:interaction.user.tag},{key:"id",value:id}]) log("command","someone used the 'message' command",[{key:"user",value:interaction.user.tag},{key:"id",value:id}])
APIEvents.onCommand("message",permsChecker.command(interaction.user.id,interaction.guild.id),interaction.user,interaction.channel,interaction.guild,new Date())
}) })
} }
+6 -2
View File
@@ -1,5 +1,4 @@
{ {
"bot_name":"Wumpus",
"main_color":"#ffffff", "main_color":"#ffffff",
"server_id":"server id (for slash cmds)", "server_id":"server id (for slash cmds)",
"auth_token":"auth token", "auth_token":"auth token",
@@ -78,11 +77,16 @@
"id":"1", "id":"1",
"name":"Choose Your Ticket", "name":"Choose Your Ticket",
"description":"You can click one of the buttons below!", "description":"You can click one of the buttons below!",
"enableFooter":false, "enableFooter":false,
"footer":"Open Ticket v2.3.3 - I'm a footer!", "footer":"Open Ticket v2.4.0 - I'm a footer!",
"enableThumbnail":false, "enableThumbnail":false,
"thumbnail":"https://www.example.com/catmemes/cat.png", "thumbnail":"https://www.example.com/catmemes/cat.png",
"enableCustomColor":false,
"color":"#ffffff", "color":"#ffffff",
"options":["general","apply"], "options":["general","apply"],
"enableTicketExplaination":true, "enableTicketExplaination":true,
"enableMaxTicketsWarning":true "enableMaxTicketsWarning":true
-56
View File
@@ -1,56 +0,0 @@
# OT-API Documentation
Extend open ticket with your own features!
The api is made for EXTENDING open ticket, not replacing! So with this api you are not able to replace existing features! You can only add your own features!
### DISCLAIMER:
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!**
## Events:
Everything in the `events.js` file!
### onTicketOpen(...)
This function is executed when a new ticket is created. It happens after everything else is done, so the channel is already created!
Parameters:
- user: `discord.User`
- channel: `discord.TextChannel`
- guild: `discord.Guild`
- date: `Date`
- ticketdata: `OT TicketData` or `false` (more info further down this document)
### onTicketClose(...)
This function is executed when a ticket gets closed, it can happen multiple times with one ticket (because of reopen).
Parameters:
- user: `discord.User`
- channel: `discord.TextChannel`
- guild: `discord.Guild`
- date: `Date`
- ticketdata: `OT TicketData` or `false` (more info further down this document)
### onTicketDelete(...)
This function is executed when a ticket gets deleted, it can happen only 1 time.
Parameters:
- user: `discord.User`
- channel: `discord.TextChannel`
- guild: `discord.Guild`
- date: `Date`
- ticketdata: `OT TicketData` or `false` (more info further down this document)
### onTicketReopen(...)
...
### onTranscriptCreation(...)
...
### onCommand(...)
...
### onReactionRole(...)
...
+18
View File
@@ -0,0 +1,18 @@
//base
const bot = require("../../index")
exports.client = bot.client
exports.config = bot.config
exports.utils = {
log:bot.errorLog.log(),
storage:bot.storage
}
//events
const events = require("./modules/events").events
exports.events = events
//actions
const actions = require("./modules/actions").actions
//comming soon
//exports.actions = actions
+44 -1
View File
@@ -1,3 +1,46 @@
{ {
"version":"1.0.0" "version":"1.0.0",
"disclaimer":"DISABLE doesn't work yet! Below this message!",
"disable":{
"messages":{
"ticketCreated":false,
"ticketClosed":false,
"ticketDeleted":false,
"ticketReopened":false
},
"transcripts":{
"server":false,
"dm":false
},
"commands":{
"text":{
"help":false,
"msg":false,
"close":false,
"delete":false,
"reopen":false,
"new":false,
"add":false,
"remove":false,
"rename":false
},
"slash":{
"help":false,
"msg":false,
"close":false,
"delete":false,
"reopen":false,
"new":false,
"add":false,
"remove":false,
"rename":false
}
},
"checkerjs":{
"token":false,
"all":false
}
}
} }
+7
View File
@@ -0,0 +1,7 @@
//ACTIONS:
//EXPORT ACTIONS:
exports.actions = {
}
+2
View File
@@ -14,6 +14,8 @@ const storage = bot.storage
//used when creating plugins! //used when creating plugins!
exports.enableApiLogs = false exports.enableApiLogs = false
//DOESN'T WORK YET
//this is used when embedding open ticket into another bot //this is used when embedding open ticket into another bot
exports.embeddedMode = false exports.embeddedMode = false
exports.clientLocation = require("../../../index").client exports.clientLocation = require("../../../index").client
-9
View File
@@ -1,9 +0,0 @@
const discord = require("discord.js")
const client = require("../../../index").client
module.exports = () => {
//this code will run when the bot starts!
}
+297 -3
View File
@@ -6,6 +6,22 @@ const log = bot.errorLog.log
const l = bot.language const l = bot.language
const storage = bot.storage const storage = bot.storage
//EVENT API:
const ticketOpenListeners = []
const ticketCloseListeners = []
const ticketDeleteListeners = []
const ticketReopenListeners = []
const ticketAddListeners = []
const ticketRemoveListeners = []
const transcriptCreationListeners = []
const commandListeners = []
const reactionRoleListeners = []
const errorListeners = []
/** /**
* *
* @param {discord.User} user * @param {discord.User} user
@@ -18,7 +34,11 @@ exports.onTicketOpen = (user,channel,guild,date,ticketdata) => {
//system //system
bot.errorLog.log("api","new ticket created",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) bot.errorLog.log("api","new ticket created",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
//custom code ticketOpenListeners.forEach((func) => {
try {
func(user,channel,guild,date,ticketdata)
}catch{}
})
} }
@@ -34,7 +54,11 @@ exports.onTicketClose = (user,channel,guild,date,ticketdata) => {
//system //system
bot.errorLog.log("api","ticket closed",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) bot.errorLog.log("api","ticket closed",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
//custom code ticketCloseListeners.forEach((func) => {
try {
func(user,channel,guild,date,ticketdata)
}catch{}
})
} }
@@ -50,6 +74,276 @@ exports.onTicketDelete = (user,channel,guild,date,ticketdata) => {
//system //system
bot.errorLog.log("api","ticket deleted",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}]) bot.errorLog.log("api","ticket deleted",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
//custom code ticketDeleteListeners.forEach((func) => {
try {
func(user,channel,guild,date,ticketdata)
}catch{}
})
} }
/**
*
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:Object|false}} ticketdata
*/
exports.onTicketReopen = (user,channel,guild,date,ticketdata) => {
//system
bot.errorLog.log("api","ticket reopened",[{key:"userid",value:user.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
ticketReopenListeners.forEach((func) => {
try {
func(user,channel,guild,date,ticketdata)
}catch{}
})
}
/**
*
* @param {discord.User} user
* @param {discord.User} editeduser
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:Object|false}} ticketdata
*/
exports.onTicketAdd = (user,editeduser,channel,guild,date,ticketdata) => {
//system
bot.errorLog.log("api","user added to ticket",[{key:"userid",value:user.id},{key:"editeduser",value:editeduser.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
ticketAddListeners.forEach((func) => {
try {
func(user,editeduser,channel,guild,date,ticketdata)
}catch{}
})
}
/**
*
* @param {discord.User} user
* @param {discord.User} editeduser
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:Object|false}} ticketdata
*/
exports.onTicketRemove = (user,editeduser,channel,guild,date,ticketdata) => {
//system
bot.errorLog.log("api","user removed from ticket",[{key:"userid",value:user.id},{key:"editeduser",value:editeduser.id},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id},{key:"ticketdata",value:JSON.stringify(ticketdata)}])
ticketRemoveListeners.forEach((func) => {
try {
func(user,editeduser,channel,guild,date,ticketdata)
}catch{}
})
}
/**
*
* @param {discord.Message[]} messages
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
*/
exports.onTranscriptCreation = (messages,channel,guild,date) => {
//system
bot.errorLog.log("api","transcript created",[{key:"messages",value:JSON.stringify(messages)},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id}])
transcriptCreationListeners.forEach((func) => {
try {
func(messages,channel,guild,date)
}catch{}
})
}
/**@typedef {"help"|"message"|"close"|"delete"|"reopen"|"rename"|"add"|"remove"} OTCommandType */
/**
*
* @param {OTCommandType} type
* @param {Boolean} hasPerms
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
*/
exports.onCommand = (type,hasPerms,user,channel,guild,date) => {
//system
bot.errorLog.log("api","someone used a command",[{key:"type",value:type},{key:"hasPerms",value:hasPerms},{key:"userid",value:user},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id}])
commandListeners.forEach((func) => {
try {
func(type,hasPerms,user,channel,guild,date)
}catch{}
})
}
/**@typedef {"add"|"remove"|"add&remove"} OTReactionRoleType */
/**@typedef {"add"|"remove"} OTReactionRoleMode */
/**
* @param {OTReactionRoleMode} mode
* @param {OTReactionRoleType} type
* @param {discord.Role} role
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
*/
exports.onReactionRole = (mode,type,role,user,channel,guild,date) => {
//system
bot.errorLog.log("api","someone used a reaction role",[{key:"mode",value:mode},{key:"type",value:type},{key:"roleid",value:role.id},{key:"userid",value:user},{key:"channelid",value:channel.id},{key:"guildid",value:guild.id}])
reactionRoleListeners.forEach((func) => {
try {
func(mode,type,role,user,channel,guild,date)
}catch{}
})
}
/**
* @param {String} err
* @param {Date} date
*/
exports.onError = (err,date) => {
//system
bot.errorLog.log("api","there is an error",[{key:"error",value:err}])
errorListeners.forEach((func) => {
try {
func(err,date)
}catch{}
})
}
//EVENT CALLBACKS:
/**
* @callback TicketActionEvent
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:Object|false}} ticketdata
*/
/**
* @callback TranscriptCreationEvent
* @param {discord.Message[]} messages
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
*/
/**
* @callback TicketUserChangeEvent
* @param {discord.User} user
* @param {discord.User} editeduser
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
* @param {{name:String,status:"open"|"closed"|"deleted"|"reopened",ticketOptions:Object|false}} ticketdata
*/
/**
* @callback CommandEvent
* @param {OTCommandType} type
* @param {Boolean} hasPerms
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
*/
/**
* @callback ReactionRoleEvent
* @param {OTReactionRoleMode} mode
* @param {OTReactionRoleType} type
* @param {discord.Role} role
* @param {discord.User} user
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
*/
/**
* @callback ErrorEvent
* @param {String} error
* @param {Date} date
*/
//EVENT EXPORT:
/**@param {TicketActionEvent} callback */
const onTicketOpen = (callback) => {
ticketOpenListeners.push(callback)
}
/**@param {TicketActionEvent} callback */
const onTicketClose = (callback) => {
ticketCloseListeners.push(callback)
}
/**@param {TicketActionEvent} callback */
const onTicketDelete = (callback) => {
ticketDeleteListeners.push(callback)
}
/**@param {TicketActionEvent} callback */
const onTicketReopen = (callback) => {
ticketReopenListeners.push(callback)
}
/**@param {TicketUserChangeEvent} callback */
const onTicketAdd = (callback) => {
ticketAddListeners.push(callback)
}
/**@param {TicketUserChangeEvent} callback */
const onTicketRemove = (callback) => {
ticketRemoveListeners.push(callback)
}
/**@param {TranscriptCreationEvent} callback */
const onTranscriptCreation = (callback) => {
transcriptCreationListeners.push(callback)
}
/**@param {CommandEvent} callback */
const onCommand = (callback) => {
commandListeners.push(callback)
}
/**@param {ReactionRoleEvent} callback */
const onReactionRole = (callback) => {
commandListeners.push(callback)
}
/**@param {ErrorEvent} callback */
const onError = (callback) => {
errorListeners.push(callback)
}
exports.events = {
onTicketOpen,
onTicketClose,
onTicketDelete,
onTicketReopen,
onTicketAdd,
onTicketRemove,
onTranscriptCreation,
onCommand,
onReactionRole,
onError
}
+26
View File
@@ -0,0 +1,26 @@
const fs = require("fs")
const bot = require("../../index")
const log = bot.errorLog.log
module.exports = () => {
const files = fs.readdirSync("./plugins")
var totalcount = 0
var successcount = 0
var failcount = 0
files.forEach((file) => {
if (file.endsWith(".plugin.js")){
try {
require("../../plugins/"+file)()
successcount++
totalcount++
}catch{
failcount++
totalcount++
}
}
})
log("info","loaded plugins",[{key:"success",value:successcount},{key:"error",value:failcount},{key:"total",value:totalcount}])
}
+24 -3
View File
@@ -41,7 +41,7 @@ exports.checker = async () => {
} }
/**@param {String} value */ /**@param {String} value */
const checkToken = (value) => { const checkToken = (value) => {
if (value.includes(" ") || value.length < 40 || value.length > 70){ if (value.includes(" ") || value.length < 40 || value.length > 90){
createError("'auth_token' | your token is invalid") createError("'auth_token' | your token is invalid")
} }
} }
@@ -245,14 +245,13 @@ exports.checker = async () => {
//--------------------------| //--------------------------|
//--------------------------| //--------------------------|
var configArray = ["bot_name","main_color","server_id","auth_token","main_adminroles","prefix","languagefile","credits","status","system","options","messages"] var configArray = ["main_color","server_id","auth_token","main_adminroles","prefix","languagefile","credits","status","system","options","messages"]
configArray.forEach((item) => { configArray.forEach((item) => {
if (config[item] == undefined){ if (config[item] == undefined){
throw new Error("\n\nMAIN ERROR: the item '"+item+"' doesn't exist in config.json") throw new Error("\n\nMAIN ERROR: the item '"+item+"' doesn't exist in config.json")
} }
}) })
checkType(config.bot_name,"string","bot_name")
checkHexColor(config.main_color,"main_color") checkHexColor(config.main_color,"main_color")
checkDiscord("serverid",config.server_id,"server_id") checkDiscord("serverid",config.server_id,"server_id")
checkToken(config.auth_token) checkToken(config.auth_token)
@@ -311,6 +310,28 @@ exports.checker = async () => {
}) })
//discord check
/**
const discord = require("discord.js")
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]
})
await client.guilds.fetch()
if (!client.guilds.cache.find(g => g.id == config.server_id)){
createError("'server_id' | i'm not in a server with this id!")
}
*/
//the end //the end
if (errorList.length > 0 || warnList.length > 0){ if (errorList.length > 0 || warnList.length > 0){
+4 -4
View File
@@ -167,7 +167,7 @@ module.exports = () => {
} }
}) })
await require("./ticketCloser").closeTicket(interaction,prefix,"close") await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close")
closeTicketButtonChecker = false closeTicketButtonChecker = false
}) })
@@ -218,7 +218,7 @@ module.exports = () => {
} }
}) })
await require("./ticketCloser").closeTicket(interaction,prefix,"close") await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"close")
closeTicket1ButtonChecker = false closeTicket1ButtonChecker = false
}) })
@@ -270,7 +270,7 @@ module.exports = () => {
} }
}) })
await require("./ticketCloser").closeTicket(interaction,prefix,"delete") await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"delete")
deleteTicketButtonChecker = false deleteTicketButtonChecker = false
}) })
@@ -325,7 +325,7 @@ module.exports = () => {
} }
}) })
await require("./ticketCloser").closeTicket(interaction,prefix,"deletenotranscript") await require("./ticketCloser").NEWcloseTicket(interaction.member,interaction.channel,prefix,"deletenotranscript")
deleteTicket1ButtonChecker = false deleteTicket1ButtonChecker = false
}) })
} }
+8 -8
View File
@@ -92,8 +92,8 @@ const normalLog = (debugString) => {
* @param {String} message * @param {String} message
* @param {[{key:String,value:String}]} params * @param {[{key:String,value:String}]} params
*/ */
exports.log = async (ptype,message,params) => { exports.log = async (type,message,params) => {
var type = ptype var ptype = type
const chalk = await loadChalk() const chalk = await loadChalk()
var paramstring = "" var paramstring = ""
if (params){ if (params){
@@ -105,20 +105,20 @@ exports.log = async (ptype,message,params) => {
} }
const parameters = params ? "("+paramstring+")" : " " const parameters = params ? "("+paramstring+")" : " "
if (type == "command"){ if (ptype == "command"){
console.log(chalk.green("[command] ")+message+" "+chalk.yellow(parameters)) console.log(chalk.green("[command] ")+message+" "+chalk.yellow(parameters))
}else if (type == "info"){ }else if (ptype == "info"){
console.log(chalk.blue("[info] ")+message+" "+chalk.yellow(parameters)) console.log(chalk.blue("[info] ")+message+" "+chalk.yellow(parameters))
}else if (type == "system"){ }else if (ptype == "system"){
console.log(chalk.green("[system] ")+message+" "+chalk.yellow(parameters)) console.log(chalk.green("[system] ")+message+" "+chalk.yellow(parameters))
}else if (type == "api"){ }else if (ptype == "api"){
if (require("./api/modules/base").enableApiLogs == true){ if (require("./api/modules/base").enableApiLogs == true){
console.log(chalk.red("[api v"+require("./api/api.json").version+"] ")+message+" "+chalk.yellow(parameters)) console.log(chalk.red("[api v"+require("./api/api.json").version+"] ")+message+" "+chalk.yellow(parameters))
} }
type = "api v"+require("./api/api.json").version ptype = "api v"+require("./api/api.json").version
} }
const cd = new Date() const cd = new Date()
const months = ["January","February","March","April","May","June","July","August","September","October","November","December"] const months = ["January","February","March","April","May","June","July","August","September","October","November","December"]
normalLog("["+cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getSeconds()+":"+cd.getMinutes()+":"+cd.getHours()+"] ["+type+"] "+message+" "+parameters) normalLog("["+cd.getDate()+" "+months[cd.getMonth()-1]+" "+cd.getFullYear()+" - "+cd.getSeconds()+":"+cd.getMinutes()+":"+cd.getHours()+"] ["+ptype+"] "+message+" "+parameters)
} }
+12
View File
@@ -6,6 +6,8 @@ const log = bot.errorLog.log
const l = bot.language const l = bot.language
const storage = bot.storage const storage = bot.storage
const APIEvents = require("./api/modules/events")
module.exports = async () => { module.exports = async () => {
const chalk = await (await import("chalk")).default const chalk = await (await import("chalk")).default
@@ -34,23 +36,33 @@ module.exports = async () => {
interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role) interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role)
log("system","added role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}]) log("system","added role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
APIEvents.onReactionRole("add","add",apirole,interaction.user,interaction.channel,interaction.guild,new Date())
}) })
}else if (mode == "remove"){ }else if (mode == "remove"){
option.roles.forEach((role) => { option.roles.forEach((role) => {
interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role) interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role)
log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}]) log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
APIEvents.onReactionRole("remove","remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date())
}) })
}else if (mode == "add&remove"){ }else if (mode == "add&remove"){
option.roles.forEach((role) => { option.roles.forEach((role) => {
if (interaction.guild.members.cache.find(u => u.id == user.id).roles.cache.has(role)){ if (interaction.guild.members.cache.find(u => u.id == user.id).roles.cache.has(role)){
interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role) interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role)
log("system","added role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}]) log("system","added role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
APIEvents.onReactionRole("add","add&remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date())
}else { }else {
interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role) interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role)
log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}]) log("system","removed role (reaction roles)",[{key:"user",value:interaction.user.tag},{key:"role",value:role}])
const apirole = interaction.guild.roles.cache.find(r => r.id == role)
APIEvents.onReactionRole("remove","add&remove",apirole,interaction.user,interaction.channel,interaction.guild,new Date())
} }
}) })
} }
+144 -92
View File
@@ -5,37 +5,63 @@ const config = bot.config
const log = bot.errorLog.log const log = bot.errorLog.log
const l = bot.language const l = bot.language
const storage = bot.storage const storage = bot.storage
const permsChecker = require("./utils/permisssionChecker")
exports.runThis = () => {
client.on("interactionCreate",async (interaction) => {
if (!interaction.isButton()) return
if (interaction.customId != "sendTranscript") return
interaction.deferUpdate()
/**
*
* @param {discord.Interaction} interaction
* @param {String} prefix
* @param {"delete"|"close"|"deletenotranscript"} mode
*/
exports.closeTicket = async (interaction,prefix,mode) => {
const chalk = await (await import("chalk")).default
const channelmessages = await interaction.channel.messages.fetch() const channelmessages = await interaction.channel.messages.fetch()
const channel = interaction.channel
channelmessages.sweep((msgSweep) => { channelmessages.sweep((msgSweep) => {
return msgSweep.author.id == client.user.id return msgSweep.author.id == client.user.id
}) })
/** var fileattachment = await require("./transcript").createTranscript(channelmessages,interaction.channel)
* @type {String} ticketuserarray
*/
const ticketuserarray = interaction.channel.name
const ticketusername = ticketuserarray.split(prefix)[1]
var getuserID = storage.get("userTicketStorage",interaction.channel.id) if (fileattachment == false){
try { log("system","internal error: transcript is not created!")
var getusernameStep1 = client.users.cache.find(u => u.id === getuserID) interaction.channel.send({embeds:[bot.errorLog.serverError(l.errors.somethingWentWrongTranscript)]})
var isDatabaseError = false return
}catch{
var isDatabaseError = true
} }
if (!getusernameStep1){ interaction.channel.send({content:"**"+l.messages.hereIsTheTranscript+"**",files:[fileattachment]})
})
}
/**
*
* @param {discord.GuildMember} member
* @param {discord.TextChannel} channel
* @param {String} prefix
* @param {"delete"|"close"|"deletenotranscript"} mode
*/
exports.NEWcloseTicket = async (member,channel,prefix,mode) => {
const guild = channel.guild
const user = member.user
const chalk = await (await import("chalk")).default
const channelmessages = await channel.messages.fetch()
//start code
//remove ot bot from transcript
channelmessages.sweep((msgSweep) => {return msgSweep.author.id == client.user.id})
/**@type {String}*/
const channelname = channel.name
const ticketOpenerChannelName = channelname.split(prefix)[1]
//get user that opened the ticket
var getuserID = storage.get("userTicketStorage",channel.id)
try {
var ticketOpener = client.users.cache.find(u => u.id === getuserID)
var isDatabaseError = false
}catch{var isDatabaseError = true}
if (!ticketOpener){
console.log(chalk.red("[database error]"),"something went wrong when getting the data in the database.\nNo panic, this error fixes itself!") console.log(chalk.red("[database error]"),"something went wrong when getting the data in the database.\nNo panic, this error fixes itself!")
var isDatabaseError = true var isDatabaseError = true
} }
@@ -44,22 +70,23 @@ exports.closeTicket = async (interaction,prefix,mode) => {
var deleteRequired = false var deleteRequired = false
if (mode == "delete"){ if (mode == "delete"){
const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) //delete
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ //check perms
try { if (!guild) return
return interaction.member.send({embeds:[bot.errorLog.noPermsMessage]}) if (!permsChecker.command(user.id,guild.id)){
}catch{ permsChecker.sendUserNoPerms(user)
return interaction.channel.send({embeds:[bot.errorLog.noPermsMessage]}) return
}
} }
//start delete proccess
deleteRequired = true deleteRequired = true
await interaction.channel.send({content:"**"+l.messages.gettingdeleted+"**"}) await channel.send({content:"**"+l.messages.gettingdeleted+"**"})
log("system","deleted a ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name}]) log("system","deleted a ticket",[{key:"user",value:user.tag},{key:"ticket",value:channel.name}])
if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1) if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1)
//getID & send DM //getID & send DM & send api event
await interaction.channel.messages.fetchPinned().then(msglist => { await channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
@@ -67,7 +94,7 @@ exports.closeTicket = async (interaction,prefix,mode) => {
const ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1] const ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("./getoptions").getOptionsById("newT"+ticketId) const ticketData = require("./getoptions").getOptionsById("newT"+ticketId)
require("./api/modules/events").onTicketDelete(interaction.user,interaction.channel,interaction.guild,new Date(),{name:interaction.channel.name,status:"deleted",ticketOptions:ticketData}) require("./api/modules/events").onTicketDelete(user,channel,guild,new Date(),{name:channel.name,status:"deleted",ticketOptions:ticketData})
if (!firstmsg.embeds[0].author) return false if (!firstmsg.embeds[0].author) return false
const id = firstmsg.embeds[0].author.name const id = firstmsg.embeds[0].author.name
@@ -76,42 +103,90 @@ exports.closeTicket = async (interaction,prefix,mode) => {
try{ try{
if (config.system.enable_DM_Messages){ if (config.system.enable_DM_Messages){
interaction.member.send({embeds:[bot.errorLog.custom(l.messages.deletedTicketDmTitle,l.messages.deletedTicketDmDescription,":ticket:",config.main_color)]}) member.send({embeds:[bot.errorLog.custom(l.messages.deletedTicketDmTitle,l.messages.deletedTicketDmDescription,":ticket:",config.main_color)]})
} }
} }
catch{log("system","can't send DM to member, member doesn't allow dm's")} catch{log("system","can't send DM to member, member doesn't allow dm's")}
}) })
}else if (mode == "close"){ }else if (mode == "close"){
//close
//check perms
if (config.system.closeMode == "adminonly"){ 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 (!guild) return
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ if (!permsChecker.command(user.id,guild.id)){
try { permsChecker.sendUserNoPerms(user)
return interaction.member.send({embeds:[bot.errorLog.noPermsMessage]}) return
}catch{
return interaction.channel.send({embeds:[bot.errorLog.noPermsMessage]})
}
} }
} }
//set new permissions
var permissionArray = [] var permissionArray = []
const pfb = discord.PermissionFlagsBits const pfb = discord.PermissionFlagsBits
if (!isDatabaseError) permissionArray.push({ if (!isDatabaseError) permissionArray.push({
id:getusernameStep1, id:ticketOpener,
type:"member", type:"member",
allow:[pfb.ViewChannel], allow:[pfb.ViewChannel],
deny:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages] deny:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages]
}) })
permissionArray.push({ permissionArray.push({
id:interaction.guild.roles.everyone, id:guild.roles.everyone,
type:"role", type:"role",
deny:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel] deny:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel]
}) })
interaction.channel.permissionOverwrites.set(permissionArray) //add main adminroles
config.main_adminroles.forEach((role,index) => {
try {
const adminrole = guild.roles.cache.find(r => r.id == role)
if (!adminrole) return
permissionArray.push({
id:adminrole,
type:"role",
allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel]
})
}catch{
log("system","invalid role! At 'config.json => main_adminroles:"+index)
}
})
//add ticket adminroles
await channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
const ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("./getoptions").getOptionsById("newT"+ticketId)
if (!ticketData) return
/**
* @type {String[]}
*/
const ticketadmin = ticketData.adminroles
ticketadmin.forEach((role,index) => {
if (!config.main_adminroles.includes(role)){
try {
const adminrole = guild.roles.cache.find(r => r.id == role)
if (!adminrole) return
permissionArray.push({
id:adminrole,
type:"role",
allow:[pfb.AddReactions,pfb.ViewChannel],
deny:[pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages]
})
}catch{
log("system","invalid role! At 'config.json => options/ticket/...:"+index)
}
}
})
})
channel.permissionOverwrites.set(permissionArray)
//message //message
var closeButtonRow = new discord.ActionRowBuilder() var closeButtonRow = new discord.ActionRowBuilder()
@@ -144,20 +219,20 @@ exports.closeTicket = async (interaction,prefix,mode) => {
.setColor(config.main_color) .setColor(config.main_color)
.setTitle(":lock: "+l.messages.closedTitle+" :lock:") .setTitle(":lock: "+l.messages.closedTitle+" :lock:")
.setDescription(l.messages.closedDescription) .setDescription(l.messages.closedDescription)
interaction.channel.send({embeds:[embed],components:[closeButtonRow]}) channel.send({embeds:[embed],components:[closeButtonRow]})
log("system","closed a ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name}]) log("system","closed a ticket",[{key:"user",value:user.tag},{key:"ticket",value:channel.name}])
//getID & send DM //getID & send DM & send api event
await interaction.channel.messages.fetchPinned().then(msglist => { await channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
const ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1] const ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("./getoptions").getOptionsById("newT"+ticketId) const ticketData = require("./getoptions").getOptionsById("newT"+ticketId)
require("./api/modules/events").onTicketClose(interaction.user,interaction.channel,interaction.guild,new Date(),{name:interaction.channel.name,status:"closed",ticketOptions:ticketData}) require("./api/modules/events").onTicketClose(user,channel,guild,new Date(),{name:channel.name,status:"closed",ticketOptions:ticketData})
const id = firstmsg.embeds[0].author.name const id = firstmsg.embeds[0].author.name
@@ -165,7 +240,7 @@ exports.closeTicket = async (interaction,prefix,mode) => {
try{ try{
if (config.system.enable_DM_Messages){ if (config.system.enable_DM_Messages){
interaction.member.send({embeds:[bot.errorLog.custom(l.messages.closedTicketDmTitle,l.messages.closedTicketDmDescription,":ticket:",config.main_color)]}) member.send({embeds:[bot.errorLog.custom(l.messages.closedTicketDmTitle,l.messages.closedTicketDmDescription,":ticket:",config.main_color)]})
} }
} }
catch{log("system","can't send DM to member, member doesn't allow dm's")} catch{log("system","can't send DM to member, member doesn't allow dm's")}
@@ -173,22 +248,24 @@ exports.closeTicket = async (interaction,prefix,mode) => {
}else if (mode == "deletenotranscript"){ }else if (mode == "deletenotranscript"){
//delete with no transcript
const permsmember = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id) //check perms
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){ if (!guild) return
interaction.channel.send({embeds:[bot.errorLog.noPermsMessage]}) if (!permsChecker.command(user.id,guild.id)){
permsChecker.sendUserNoPerms(user)
return return
} }
//start delete proccess
enableTranscript = false enableTranscript = false
deleteRequired = true deleteRequired = true
interaction.channel.send({content:"**"+l.messages.gettingdeleted+"**"}) channel.send({content:"**"+l.messages.gettingdeleted+"**"})
log("system","deleted a ticket",[{key:"user",value:interaction.user.tag},{key:"ticket",value:interaction.channel.name}]) log("system","deleted a ticket",[{key:"user",value:user.tag},{key:"ticket",value:channel.name}])
if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1) if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1)
//getID & send DM //getID & send DM & send api event
await interaction.channel.messages.fetchPinned().then(msglist => { await channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last() var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
@@ -196,7 +273,7 @@ exports.closeTicket = async (interaction,prefix,mode) => {
const ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1] const ticketId = firstmsg.embeds[0].footer.text.split("Ticket Type: ")[1]
const ticketData = require("./getoptions").getOptionsById("newT"+ticketId) const ticketData = require("./getoptions").getOptionsById("newT"+ticketId)
require("./api/modules/events").onTicketDelete(interaction.user,interaction.channel,interaction.guild,new Date(),{name:interaction.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 = firstmsg.embeds[0].author.name const id = firstmsg.embeds[0].author.name
@@ -204,7 +281,7 @@ exports.closeTicket = async (interaction,prefix,mode) => {
try{ try{
if (config.system.enable_DM_Messages){ if (config.system.enable_DM_Messages){
interaction.member.send({embeds:[bot.errorLog.custom(l.messages.deletedTicketDmTitle,l.messages.deletedTicketDmDescription,":ticket:",config.main_color)]}) member.send({embeds:[bot.errorLog.custom(l.messages.deletedTicketDmTitle,l.messages.deletedTicketDmDescription,":ticket:",config.main_color)]})
} }
} }
catch{log("system","can't send DM to member, member doesn't allow dm's")} catch{log("system","can't send DM to member, member doesn't allow dm's")}
@@ -224,11 +301,11 @@ exports.closeTicket = async (interaction,prefix,mode) => {
const transcriptEmbed = new discord.EmbedBuilder() const transcriptEmbed = new discord.EmbedBuilder()
.setColor(config.main_color) .setColor(config.main_color)
.setTitle(l.messages.newTranscriptTitle) .setTitle(l.messages.newTranscriptTitle)
.setAuthor({name:interaction.user.username,iconURL:interaction.user.displayAvatarURL({format:"png"})}) .setAuthor({name:user.username,iconURL:user.displayAvatarURL({format:"png"})})
.setDescription(l.messages.newTranscriptDescription) .setDescription(l.messages.newTranscriptDescription)
.setFooter({text:"ticket: "+ticketuserarray}) .setFooter({text:"ticket: "+channelname})
interaction.guild.channels.cache.find(c => c.id == config.system.transcript_channel).send({ guild.channels.cache.find(c => c.id == config.system.transcript_channel).send({
embeds:[transcriptEmbed], embeds:[transcriptEmbed],
files:[fileattachment] files:[fileattachment]
}) })
@@ -239,9 +316,9 @@ exports.closeTicket = async (interaction,prefix,mode) => {
.setColor(config.main_color) .setColor(config.main_color)
.setTitle(l.messages.newTranscriptTitle) .setTitle(l.messages.newTranscriptTitle)
.setDescription(l.messages.newTranscriptDescription) .setDescription(l.messages.newTranscriptDescription)
.setFooter({text:"ticket: "+ticketuserarray}) .setFooter({text:"ticket: "+channelname})
if (!isDatabaseError) getusernameStep1.send({ if (!isDatabaseError) ticketOpener.send({
embeds:[transcriptEmbed], embeds:[transcriptEmbed],
files:[fileattachment] files:[fileattachment]
}) })
@@ -253,31 +330,6 @@ exports.closeTicket = async (interaction,prefix,mode) => {
setTimeout(() => {resolve(true)},7000) setTimeout(() => {resolve(true)},7000)
})} })}
await timer() await timer()
await interaction.channel.delete() await channel.delete()
} }
} }
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]})
})
}
+6 -4
View File
@@ -33,11 +33,16 @@ exports.createEmbed = (id) => {
//----------------------------------- //-----------------------------------
//create the embed //create the embed
const embed = new discord.EmbedBuilder() const embed = new discord.EmbedBuilder()
.setColor(data.color)
.setTitle(data.name) .setTitle(data.name)
if (data.enableFooter) embed.setFooter({text:data.footer}) if (data.enableFooter) embed.setFooter({text:data.footer})
if (data.enableThumbnail) embed.setThumbnail(data.thumbnail) if (data.enableThumbnail) embed.setThumbnail(data.thumbnail)
if (data.enableCustomColor){
embed.setColor(data.color)
}else{
embed.setColor(config.main_color)
}
var description = data.description var description = data.description
if (data.enableTicketExplaination){ if (data.enableTicketExplaination){
description = description+"\n\n__"+l.messages.chooseCategory+"__\n" description = description+"\n\n__"+l.messages.chooseCategory+"__\n"
@@ -91,6 +96,3 @@ exports.createEmbed = (id) => {
const returnedData = {embed:embed,componentRows:componentRows} const returnedData = {embed:embed,componentRows:componentRows}
return returnedData return returnedData
} }
this.createEmbed()
+77 -154
View File
@@ -92,160 +92,6 @@ module.exports = () => {
.setEmoji("🔓") .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]})
})
const pfb = discord.PermissionFlagsBits
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]})
log("system","re-opened a ticket",[{key:"ticket",value:interaction.channel.name},{key:"user",value:interaction.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:interaction.guild.roles.everyone,
type:"role",
allow:everyoneAllowPerms,
deny:everyoneDenyPerms
})
interaction.channel.permissionOverwrites.cache.forEach((p) => {
if (p.type == "member"){
permissionsArray.push({
id:p.id,
type:"member",
allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel],
deny:[]
})
}
})
interaction.channel.permissionOverwrites.set(permissionsArray)
})
//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]})
log("system","re-opened a ticket",[{key:"ticket",value:interaction.channel.name},{key:"user",value:interaction.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:interaction.guild.roles.everyone,
type:"role",
allow:everyoneAllowPerms,
deny:everyoneDenyPerms
})
interaction.channel.permissionOverwrites.cache.forEach((p) => {
if (p.type == "member"){
permissionsArray.push({
id:p.id,
type:"member",
allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel],
deny:[]
})
}
})
interaction.channel.permissionOverwrites.set(permissionsArray)
//getID & send DM
interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id) return false
const id = firstmsg.embeds[0].author.name
if (!id) return false
try{
if (config.system.enable_DM_Messages){
interaction.member.send({embeds:[bot.errorLog.custom(l.messages.reopenTicketDmTitle,l.messages.reopenTicketDmDescription,":ticket:",config.main_color)]})
}
}
catch{log("system","can't send DM to member, member doesn't allow dm's")}
})
})
//DASHBOARD (comming soon!)
/** /**
* *
* @param {discord.Guild} guild * @param {discord.Guild} guild
@@ -285,5 +131,82 @@ module.exports = () => {
}) })
channel.permissionOverwrites.set(permissionsArray) channel.permissionOverwrites.set(permissionsArray)
require("./api/modules/events").onTicketReopen(user,channel,guild,new Date(),{name:channel.name,status:"reopened",ticketOptions:false})
} }
//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]})
})
const pfb = discord.PermissionFlagsBits
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)
})
} }
+4 -2
View File
@@ -44,6 +44,8 @@ const getUserInfo = (channel) => {
exports.createTranscript = async (messagecollection,channel) => { exports.createTranscript = async (messagecollection,channel) => {
const ticketuserdata = await getUserInfo(channel) const ticketuserdata = await getUserInfo(channel)
require("./api/modules/events").onTranscriptCreation(messagecollection,channel,channel.guild,new Date())
try { try {
const cd = new Date() const cd = new Date()
const months = ["January","February","March","April","May","June","July","August","September","October","November","December"] const months = ["January","February","March","April","May","June","July","August","September","October","November","December"]
@@ -57,8 +59,8 @@ exports.createTranscript = async (messagecollection,channel) => {
if (msg.content){var content = msg.content}else{var content = "*empty message*"} if (msg.content){var content = msg.content}else{var content = "*empty message*"}
const msgstats = "files: "+msg.attachments.size+" | embeds: "+msg.embeds.length+" | isbot: "+msg.author.bot const msgstats = "files: "+msg.attachments.size+", embeds: "+msg.embeds.length
filearray.push("["+timestamp.getDate()+"/"+timestamp.getMonth()+"/"+timestamp.getFullYear()+" | "+timestamp.getHours()+":"+timestamp.getMinutes()+":"+timestamp.getSeconds()+" | "+msg.author.tag+" ] ["+msgstats+"]\n"+content+"\n") filearray.push("["+timestamp.getDate()+"/"+timestamp.getMonth()+"/"+timestamp.getFullYear()+", "+timestamp.getHours()+":"+timestamp.getMinutes()+":"+timestamp.getSeconds()+"|"+msg.author.tag+"] ["+msgstats+"]\n"+content+"\n")
}) })
if (filearray.length < 2) filearray.push("transcript is empty") if (filearray.length < 2) filearray.push("transcript is empty")
+3
View File
@@ -0,0 +1,3 @@
/**
* @typedef {String|Boolean} OTErrorType
*/
+76
View File
@@ -0,0 +1,76 @@
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
/**
*
* @param {String} memberid
* @param {String} guildid
* @returns {Boolean} has permissions?
*/
exports.command = (memberid,guildid) => {
const permsmember = client.guilds.cache.find(g => g.id == guildid).members.cache.find(m => m.id == memberid)
if (config.main_adminroles.some((item)=>{return permsmember.roles.cache.has(item)}) == false && !permsmember.permissions.has("Administrator") && !permsmember.permissions.has("ManageGuild")){
return false
}else {return true}
}
/**
*
* @param {discord.User} user
* @returns {Boolean}
*/
exports.sendUserNoPerms = (user) => {
try {
user.send({embeds:[bot.errorLog.noPermsMessage]})
return true
}catch{
return false
}
}
/**
*
* @param {discord.User} user
* @returns {Boolean}
*/
exports.sendUserNoTicket = (user) => {
try {
user.send({embeds:[bot.errorLog.notInATicket]})
return true
}catch{
return false
}
}
/**
*
* @param {discord.TextChannel} channel
* @returns {Boolean}
*/
exports.sendChannelNoPerms = (channel) => {
try {
channel.send({embeds:[bot.errorLog.noPermsMessage]})
return true
}catch{
return false
}
}
/**
*
* @param {discord.TextChannel} channel
* @returns {Boolean}
*/
exports.sendChannelNoTicket = (channel) => {
try {
channel.send({embeds:[bot.errorLog.notInATicket]})
return true
}catch{
return false
}
}
+7
View File
@@ -117,6 +117,9 @@ client.on('ready',async () => {
process.exit(1) process.exit(1)
} }
} }
//load plugins
require("./core/api/pluginlauncher")()
}) })
if (!isDev){ if (!isDev){
@@ -148,6 +151,8 @@ if (process.argv[2] && process.argv[2].startsWith("slash")){
} }
const APIEvents = require("./core/api/modules/events")
const debugLog = (debugString) => { const debugLog = (debugString) => {
const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n<OPEN TICKET DEBUG FILE:>\n==========================" const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n<OPEN TICKET DEBUG FILE:>\n=========================="
fs.writeFileSync("./openticketdebug.txt",content+"\nDEBUG: "+debugString) fs.writeFileSync("./openticketdebug.txt",content+"\nDEBUG: "+debugString)
@@ -169,6 +174,8 @@ process.on("uncaughtException",async (error,origin) => {
const chalk = await (await import("chalk")).default const chalk = await (await import("chalk")).default
console.log(chalk.red("\nOPEN TICKET ERROR: ")+error+"\n"+chalk.green("\nCreate a ticket in our support server for more information!\nIf you do this, you might help us to avoid a future bug!\n")) console.log(chalk.red("\nOPEN TICKET ERROR: ")+error+"\n"+chalk.green("\nCreate a ticket in our support server for more information!\nIf you do this, you might help us to avoid a future bug!\n"))
errorLog(error.name+": "+error.message+" | origin: "+origin,error.stack) errorLog(error.name+": "+error.message+" | origin: "+origin,error.stack)
APIEvents.onError(error.name+": "+error.message,new Date())
}) })
client.login(config.auth_token) client.login(config.auth_token)
+79
View File
@@ -0,0 +1,79 @@
{
"errors":{
"missingArgsTitle":"Neplatné argumenty",
"missingArgsDescription":"Chybí argumenty",
"noPermsTitle":"Nemáš práva!",
"noPermsDescription":"Nemáš dostatečné práva na tento příkaz!\n Potřebuješ ADMINISTRATOR aby jsi mohl provést příkaz!",
"chooseFromListTitle":"Neplatné ID",
"chooseFromListDescription":"Vyber si z těchto ID:",
"boterror":"Error!",
"notInTicketTitle":"Nejsi v ticketu!",
"notInTicketDescription":"Tento příkaz nefunguje mimo tickety!",
"ticketDoesntExist":"Tento ticket už bohužel neexistuje!",
"roleDoesntExist":"Tato role bohužel neexistuje!",
"anotherOption":"Tato možnost není ticket ale něco jiného!",
"maxAmountTitle":"Maximální počet ticketů dosažen!",
"maxAmountDescription":"Dosáhl jsi maximálního povoleného počtu ticketů!\n Nemůžeš si vytvořit nový!",
"somethingWentWrong":"**Něco je špatně**\nProsím zkus to příště znovu!",
"somethingWentWrongTranscript":"Něco je špatně s transcriptem!**\nProsím zkus to příště znovu!"
},
"commands":{
"userAddedTitle":"Uživatel přidán!",
"userAddedDescription":"{0} je přidán do ticketu!",
"userRemovedTitle":"Uživatel odebrán!",
"userRemovedDescription":"{0} je odstraněn z ticketu!",
"renameTitle":"Jméno bylo změněno!",
"renameWarning":"Varování: jméno kanálu můžeš změnit pouze 2x za minutu!",
"closeTitle":"Zavři tento ticket!",
"closeDescription":"Můžeš zavřít ticket kliknutím na tlačítko níže!",
"deleteTitle":"Smaž tento ticket!",
"deleteDescription":"Můžeš smazat ticket kliknutím na tlačítko níže!",
"reopenTitle":"Znovu otevři ticket!",
"reopenDescription":"Můžeš znovu otevřít tento ticket kliknutínm na tlačítko níže!",
"ticketWarning":"The embed is in the message below!",
"maxTicketWarning":"**Varovaní:** _Můžeš si vytvořit použe {0} ticket(s) v jednu chvíli!_"
},
"helpMenu":{
"title":"Příkazy:",
"header1":"**Běž {0} vytvořit si ticket!**\n\n",
"header2":"**Použij příkaz `/new` nebo `/ticket` k vytvoření ticketu!**\n\n",
"msgCmd":"Vytvoř možnost otevírat tickety přes tlačítko. (ADMIN)",
"renameCmd":"Přejmenovat ticket. (Žádné mezery)",
"closeCmd":"Zavři ticket.",
"deleteCmd":"Smaž ticket.",
"addCmd":"Přidej člena do ticketu.",
"removeCmd":"Odebere člena z ticketu.",
"reopenCmd":"Znovu otevři ticket po uzavření."
},
"buttons":{
"close":"Zavři ticket",
"delete":"Smaž ticket",
"reopen":"Znovu otevři ticket",
"sendTranscript":"Odešli log ticketu"
},
"messages":{
"reopenTitle":"Ticket znovu otevřen!",
"reopenDescription":"Cítím se skvěle že si můžeme zase povídat!",
"closedTitle":"Zavřený ticket!",
"closedDescription":"Pouze admin team zde může nyní komunikovat!\n\n*Klikni na tlačítko níže pro smazání nebo znovu otevření ticketu!*",
"createdTitle":"Ticket vytvořen!",
"createdDescription":"Váš tiket je vytvořen, můžete ho zjistit pomocí pingu!",
"newTicketDmTitle":"Nový ticket!",
"closedTicketDmTitle":"Ticket uzavřen!",
"deletedTicketDmTitle":"Ticket smazán!",
"closedTicketDmDescription":"Tvůj ticket byl uzavřen!",
"deletedTicketDmDescription":"Tvůj ticket byl smazán!",
"reopenTicketDmTitle":"Ticket znovu otevřen!",
"reopenTicketDmDescription":"Tvůj ticket byl znovu otevřen!",
"newTranscriptTitle":"Nový log ticketu je zde!",
"newTranscriptDescription":"Zde najdeš log svého ticketu!",
"hereIsTheTranscript":"Zde je log:",
"chooseCategory":"Vyber kategorii:"
}
}
+2 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "open-ticket", "name": "open-ticket",
"version": "2.3.3", "version": "2.4.0",
"description": "This is an open-source discord ticket bot, you can configure it and it comes with cool features like a transcript.", "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", "main": "index.js",
"scripts": { "scripts": {
@@ -13,6 +13,7 @@
"author": "DJdj Development", "author": "DJdj Development",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"axios": "^0.27.2",
"chalk": "^5.0.1", "chalk": "^5.0.1",
"discord.js": "^14.0.2", "discord.js": "^14.0.2",
"express": "^4.17.1", "express": "^4.17.1",
+22
View File
@@ -0,0 +1,22 @@
const discord = require("discord.js")
const api = require("../core/api/api.js")
module.exports = () => {
const {client,config,events,utils,actions} = api
//this code will run when the bot starts!
//in this example, we will say "hello" in the console when someone opens a ticket!
/**
events.onTicketOpen((user,channel,guild,date,ticketdata) => {
console.log("hello, someone opened a ticket!")
})
*/
}