v2.4.0 push 4

This commit is contained in:
DJj123dj
2022-07-29 18:17:26 +02:00
parent ffa075d177
commit a69f2ee5a1
17 changed files with 248 additions and 210 deletions
+24 -18
View File
@@ -18,47 +18,53 @@ This is an open-source discord ticket bot, you can configure it and it comes wit
### Thanks to these people:
- DJ-Lite: for doing the administration
- Sanke: for translation & new ideas
- Everyone that reported a bug
#### And our translators!
- ExothDE: for translation
- 1x1: for translation
- R0JO: for translation
- Everyone that reported a bug
- t0miiis for translation
## features
- discord buttons
- discord interaction buttons
- slash & text commands
- close, delete & re-open tickets
- translation (we are searching for translators!)
- translation in 8 different languages
- dynamic database system
- advanced transcripts
- transcripts
- add/remove users from a ticket
- large embed customisation
- create custom ticket names, icons & colors
- create url's & reaction roles!
- uses discord.js v13
- configure your own ticket options
- remove credits if you want (don't do it please 😉)
- unlimited tickets at the same time
- 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 :(
- 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!**
**At this moment you still need discord.js v13!**
This will change soon!
You can clone or download this project.
### packages
- chalk => version `latest`
- discord.js => version `latest`
- express => version `latest`
- node-localstorage => version `latest`
- axios => version `latest`
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 the discord server**.
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:
@@ -78,4 +84,4 @@ _v2.4.0 stable_
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)
+2
View File
@@ -15,6 +15,7 @@ module.exports = () => {
if (!msg.guild) return
if (!permsChecker.command(msg.author.id,msg.guild.id)){
permsChecker.sendUserNoPerms(msg.author)
return
}
msg.channel.messages.fetchPinned().then(msglist => {
@@ -40,6 +41,7 @@ module.exports = () => {
if (!interaction.guild) return
if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
permsChecker.sendUserNoPerms(interaction.user)
return
}
interaction.deferReply()
+2
View File
@@ -13,6 +13,7 @@ module.exports = () => {
if (!msg.guild) return
if (!permsChecker.command(msg.author.id,msg.guild.id)){
permsChecker.sendUserNoPerms(msg.author)
return
}
msg.channel.messages.fetchPinned().then(msglist => {
@@ -47,6 +48,7 @@ module.exports = () => {
if (!interaction.guild) return
if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
permsChecker.sendUserNoPerms(interaction.user)
return
}
interaction.channel.messages.fetchPinned().then(msglist => {
+2
View File
@@ -15,6 +15,7 @@ module.exports = () => {
if (!msg.guild) return
if (!permsChecker.command(msg.author.id,msg.guild.id)){
permsChecker.sendUserNoPerms(msg.author)
return
}
interaction.deferReply()
@@ -43,6 +44,7 @@ module.exports = () => {
if (!interaction.guild) return
if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
permsChecker.sendUserNoPerms(interaction.user)
return
}
+2
View File
@@ -18,6 +18,7 @@ module.exports = () => {
if (!msg.guild) return
if (!permsChecker.command(msg.author.id,msg.guild.id)){
permsChecker.sendUserNoPerms(msg.author)
return
}
var newname = msg.content.split(config.prefix+"rename")[1].substring(1)
@@ -60,6 +61,7 @@ module.exports = () => {
if (!interaction.guild) return
if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
permsChecker.sendUserNoPerms(interaction.user)
return
}
var newname = interaction.options.getString("name")
+8 -4
View File
@@ -32,18 +32,22 @@ module.exports = () => {
})
client.on("interactionCreate",(interaction) => {
client.on("interactionCreate",async (interaction) => {
if (!interaction.isChatInputCommand()) return
if (interaction.commandName != "reopen") return
interaction.deferReply()
await interaction.deferReply()
interaction.channel.messages.fetchPinned().then(msglist => {
interaction.channel.messages.fetchPinned().then(async msglist => {
var firstmsg = msglist.last()
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}])
+2
View File
@@ -20,6 +20,7 @@ module.exports = () => {
if (!msg.guild) return
if (!permsChecker.command(msg.author.id,msg.guild.id)){
permsChecker.sendUserNoPerms(msg.author)
return
}
const id = msg.content.split(config.prefix+"msg")[1].substring(1) ? msg.content.split(config.prefix+"msg")[1].substring(1) : false
@@ -43,6 +44,7 @@ module.exports = () => {
if (!interaction.guild) return
if (!permsChecker.command(interaction.user.id,interaction.guild.id)){
permsChecker.sendUserNoPerms(interaction.user)
return
}
const id = interaction.options.getString("id")
+5
View File
@@ -78,11 +78,16 @@
"id":"1",
"name":"Choose Your Ticket",
"description":"You can click one of the buttons below!",
"enableFooter":false,
"footer":"Open Ticket v2.4.0 - I'm a footer!",
"enableThumbnail":false,
"thumbnail":"https://www.example.com/catmemes/cat.png",
"enableCustomColor":false,
"color":"#ffffff",
"options":["general","apply"],
"enableTicketExplaination":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(...)
...
+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
}
}
}
+74 -4
View File
@@ -11,6 +11,11 @@ const storage = bot.storage
const ticketOpenListeners = []
const ticketCloseListeners = []
const ticketDeleteListeners = []
const ticketReopenListeners = []
const transcriptCreationListeners = []
const commandListeners = []
const reactionRoleListeners = []
/**
*
@@ -72,6 +77,51 @@ exports.onTicketDelete = (user,channel,guild,date,ticketdata) => {
}
/**
*
* @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.Message[]} messages
* @param {discord.TextChannel} channel
* @param {discord.Guild} guild
* @param {Date} date
*/
exports.transcriptCreation = (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{}
})
}
//onTicketAdd
//onTicketRemove
//command
//reactionrole
//error
//EVENT CALLBACKS:
/**
@@ -83,6 +133,14 @@ exports.onTicketDelete = (user,channel,guild,date,ticketdata) => {
* @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
*/
//EVENT EXPORT:
/**@param {TicketActionEvent} callback */
@@ -100,8 +158,20 @@ const onTicketDelete = (callback) => {
ticketDeleteListeners.push(callback)
}
exports.events = {
onTicketOpen:onTicketOpen,
onTicketClose:onTicketClose,
onTicketDelete:onTicketDelete
/**@param {TicketActionEvent} callback */
const onTicketReopen = (callback) => {
ticketReopenListeners.push(callback)
}
/**@param {TranscriptCreationEvent} callback */
const onTranscriptCreation = (callback) => {
transcriptCreationListeners.push(callback)
}
exports.events = {
onTicketOpen,
onTicketClose,
onTicketDelete,
onTicketReopen,
onTranscriptCreation
}
+23 -1
View File
@@ -41,7 +41,7 @@ exports.checker = async () => {
}
/**@param {String} 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")
}
}
@@ -311,6 +311,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
if (errorList.length > 0 || warnList.length > 0){
+3
View File
@@ -75,6 +75,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode) => {
if (!guild) return
if (!permsChecker.command(user.id,guild.id)){
permsChecker.sendUserNoPerms(user)
return
}
//start delete proccess
@@ -115,6 +116,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode) => {
if (!guild) return
if (!permsChecker.command(user.id,guild.id)){
permsChecker.sendUserNoPerms(user)
return
}
}
@@ -202,6 +204,7 @@ exports.NEWcloseTicket = async (member,channel,prefix,mode) => {
if (!guild) return
if (!permsChecker.command(user.id,guild.id)){
permsChecker.sendUserNoPerms(user)
return
}
//start delete proccess
+6 -1
View File
@@ -33,11 +33,16 @@ exports.createEmbed = (id) => {
//-----------------------------------
//create the embed
const embed = new discord.EmbedBuilder()
.setColor(data.color)
.setTitle(data.name)
if (data.enableFooter) embed.setFooter({text:data.footer})
if (data.enableThumbnail) embed.setThumbnail(data.thumbnail)
if (data.enableCustomColor){
embed.setColor(data.color)
}else{
embed.setColor(config.main_color)
}
var description = data.description
if (data.enableTicketExplaination){
description = description+"\n\n__"+l.messages.chooseCategory+"__\n"
+47 -124
View File
@@ -92,6 +92,51 @@ module.exports = () => {
.setEmoji("🔓")
)
/**
*
* @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 == "member"){
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})
}
//NORMAL WAY
client.on("interactionCreate",(interaction) => {
if (!interaction.isButton()) return
@@ -126,38 +171,7 @@ module.exports = () => {
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)
reopenTicket(interaction.guild,interaction.channel,interaction.user)
})
@@ -193,97 +207,6 @@ module.exports = () => {
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")}
})
reopenTicket(interaction.guild,interaction.channel,interaction.user)
})
//DASHBOARD (comming soon!)
/**
*
* @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 == "member"){
permissionsArray.push({
id:p.id,
type:"member",
allow:[pfb.AddReactions,pfb.AttachFiles,pfb.EmbedLinks,pfb.SendMessages,pfb.ViewChannel],
deny:[]
})
}
})
channel.permissionOverwrites.set(permissionsArray)
}
}
+4 -2
View File
@@ -44,6 +44,8 @@ const getUserInfo = (channel) => {
exports.createTranscript = async (messagecollection,channel) => {
const ticketuserdata = await getUserInfo(channel)
require("./api/modules/events").transcriptCreation(messagecollection,channel,channel.guild,new Date())
try {
const cd = new Date()
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*"}
const msgstats = "files: "+msg.attachments.size+" | embeds: "+msg.embeds.length+" | isbot: "+msg.author.bot
filearray.push("["+timestamp.getDate()+"/"+timestamp.getMonth()+"/"+timestamp.getFullYear()+" | "+timestamp.getHours()+":"+timestamp.getMinutes()+":"+timestamp.getSeconds()+" | "+msg.author.tag+" ] ["+msgstats+"]\n"+content+"\n")
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")
})
if (filearray.length < 2) filearray.push("transcript is empty")
+1
View File
@@ -13,6 +13,7 @@
"author": "DJdj Development",
"license": "ISC",
"dependencies": {
"axios": "^0.27.2",
"chalk": "^5.0.1",
"discord.js": "^14.0.2",
"express": "^4.17.1",