Compare commits

...
40 Commits
Author SHA1 Message Date
Jasper 8875c9ff01 Merge pull request #8 from DJj123dj/dev
Update README.md
2022-05-07 17:00:47 +02:00
DJj123dj 9b378caff5 Update README.md 2022-05-07 17:00:26 +02:00
Jasper 821a49cb0b Merge pull request #7 from DJj123dj/dev
Update README.md
2022-05-07 16:59:54 +02:00
DJj123dj ebacb92b99 Update README.md 2022-05-07 16:58:58 +02:00
Jasper e1eb3f252b Merge pull request #6 from DJj123dj/dev
Dev to Main (version 2.0)
2022-05-07 14:31:13 +02:00
Jasper 49405b848e Merge branch 'main' into dev 2022-05-07 14:30:53 +02:00
DJj123dj 5dcd36d290 the final push 2022-05-07 14:25:01 +02:00
DJj123dj d00a26a1e0 added reactionRoles & changed links to wiki
The reaction roles work now!
2022-05-06 17:27:04 +02:00
DJj123dj 8c9eddd4a1 added dynamic database & everything is now v2.0.0
Changed everything from v1.4.0 to v2.0.0 & added the dynamic database system
2022-05-05 17:52:42 +02:00
DJj123dj 046cef0088 updated the button system for new types of buttons
You can now also create "website" & "role" tickets. more on these types in the following updates
2022-05-04 20:02:51 +02:00
DJj123dj 0f143c7ebb deleted the old commands 2022-05-04 19:02:59 +02:00
Jasper 4cc12eb727 Delete .DS_Store 2022-05-04 19:02:20 +02:00
DJj123dj e3e5c04096 added the "add" & "remove" commands 2022-05-04 18:42:33 +02:00
DJj123dj eddbcf9acd Update TEMPDOCS.md 2022-05-04 18:11:11 +02:00
DJj123dj 3c2f39df9c Update README.md 2022-05-04 18:08:09 +02:00
Jasper ca4532931b Update README.md 2022-05-04 18:07:23 +02:00
DJj123dj 14ad1f48f3 test discord webhook 2022-05-04 18:03:35 +02:00
DJj123dj fa8741aef8 test discord webhook 2022-05-04 18:00:40 +02:00
DJj123dj 130fd98d0c bug fix
fixed not starting up because of a temporary config file
2022-05-04 15:26:40 +02:00
DJj123dj a9770ec66c Update slashEnable.js 2022-05-02 15:02:27 +02:00
DJj123dj f163769de4 updated cleardatabase with chalk 2022-05-02 14:54:52 +02:00
DJj123dj 07de112f32 added some new commands
- rename
- close
- delete
2022-05-02 12:41:15 +02:00
DJj123dj 8e7a98b810 created cleardatabase system 2022-05-02 11:35:41 +02:00
DJj123dj 92c1e8fce0 Update .gitignore 2022-05-02 11:21:45 +02:00
DJj123dj 4e73626072 created devConfig.json 2022-05-02 11:20:04 +02:00
DJj123dj 943e7b6fef removed token :) 2022-05-02 11:13:18 +02:00
DJj123dj af8d6351af 1.4.0 beta 2022-05-02 11:07:56 +02:00
DJj123dj 5fc3ba3279 Update checker.js 2022-04-02 17:03:13 +02:00
DJj123dj 6df23d84bc v1.3.2
This is the first stable version of open-ticket 1.3
2022-04-02 16:38:00 +02:00
DJj123dj 8cab4cc686 v1.3.1
Bug fixes
2022-03-31 18:38:49 +02:00
DJj123dj 21e3a88b87 v1.3.0
Changes in changelog
2022-03-30 17:09:55 +02:00
DJj123dj 1451769ebf Update README.md 2022-03-24 11:40:28 +01:00
DJj123dj da3017ff95 Update README.md 2022-03-24 11:40:01 +01:00
DJj123dj 43186c8a0e Update README.md 2022-03-24 11:37:44 +01:00
DJj123dj 63632e3a66 added new stuff to readme file 2022-03-23 20:45:33 +01:00
DJj123dj 8981c9e60e v1.2.2
some bugs fixed!
2022-03-04 10:20:47 +01:00
DJj123dj 4a90a2d19a v1.2.1
- added the option to remove credits
- fixed the bug where ticket_system crashes the bot
- in the help menu is now the correct prefix displayed
2022-02-20 09:20:26 +01:00
DJj123dj 49b71ecdc6 Merge branch 'main' of https://github.com/DJj123dj/open-ticket 2021-12-07 18:19:22 +01:00
DJj123dj af1c3288c0 Version 1.2.0
Many changes! :D
2021-12-07 18:19:07 +01:00
Jasper 7d89ac713b Delete .DS_Store 2021-12-01 15:31:31 +01:00
32 changed files with 2271 additions and 524 deletions
Vendored
BIN
View File
Binary file not shown.
+4
View File
@@ -0,0 +1,4 @@
node_modules/
package-lock.json
devConfig.json
.DS_Store
+35 -41
View File
@@ -1,69 +1,63 @@
# open-ticket # open-ticket
This is an open-source discord ticket bot, you can configure it and it comes with cool features like a transcript. [![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.0.0%20stable-brightgreen.svg?style=flat-square)](https://github.com/DJj123dj/open-ticket/releases/tag/v2.0.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)
(WARNING: the bot's language is Dutch, there will be an English version soon!) This is an open-source discord ticket bot, you can configure it and it comes with cool features like transcripts & custom options!
<img src="logo.png" alt="Open Ticket logo" style="height: 200px; width:200px;"/>
[![q&a](https://img.shields.io/badge/Q&A-click%20here-blue.svg?style=flat-square)](https://www.github.com/DJj123dj/open-ticket/wiki/q&a)
## features ## features
- discord interaction buttons - discord interaction buttons
- slash & text commands
- close or delete tickets
- translation possible
- dynamic database system
- transcripts - transcripts
- add/remove users from ticket - add/remove users from ticket
- custom colors & name - custom colors & name
- has tickets for questions, partners & job applications - create custom ticket names, icons & colors
- create url buttons for websites
- uses discord.js 13
- configure your own ticket options
- remove credits if you want
- unlimited tickets at the same time
- localisation in +5 languages (soon™)
## installation ## installation
You need `node.js 16` to run this project, if you don't want to install `node.js 16` then there is a npm package that can help you. **You need `node.js 16` to run this project!**
You can clone this project for download. You can clone or download this project.
### packages ### packages
- canvas => version `^2.8.0` - chalk => version `latest`
- discord.js => version `^13.2.0` - discord.js => version `latest`
- express => version `^4.17.1` - express => version `latest`
- node-localstorage => version `^2.2.1` - node-localstorage => version `latest`
The packages are also in package.json! You can install all of them by running `npm install`
### node.js 16 package
if you don't want to install `node.js 16`, you can install this package too
- node => version ^16.10.0
_npm install node@16_
## 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. if there are any errors, you can open an **issue on github** or **contact me in the discord server**.
### config (required) ### config
- `server_name` => the name from your server. Our config documentation is moved to another file:
- `server_logo`=> the logo from your server. [click here to view](https://www.github.com/DJj123dj/open-ticket/wiki/config-v2.0.0)
- `bot_name`=> the bot's name.
- `main_color`=> the color used in all embeds.
- `auth_token`=> the bot's token (Discord Developer Portal)
- `botperms_role`=> the id from a role that can run admin commands with the bot.
- `prefix`=> the bot's prefix.
- `ticket_system/ticket_channel` => the channel where you are gonna put the !ticket msg.
- `ticket_system/ticket_category` => the category for tickets.
- `ticket_system/member_role` => this role doesn't have access to tickets
(WARNING: @everyone does have access to tickets, so make sure all members have a member role!).
- `ticket_system/transcript_channel` => the channel for transcripts.
- `ticket_system/enable_transcripts` => enable transcripts.
- `ticket_system/enable_category` => enable tickets in category.
- `status/type` => PLAYING | STREAMING | LISTENING | WATCHING | CUSTOM | COMPETING
- `status/text` => the status text
### 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
- `SERVER MEMBERS INTENT` - `SERVER MEMBERS INTENT`
- `MESSAGE CONTENT INTENT` - `MESSAGE CONTENT INTENT`
The bot needs `ADMINISTRATOR` permissions to work the best. To work the best, the bot needs `ADMINISTRATOR` permissions.
You can also configure your own permissions
## credits ## information
the package contains a license, there are also credits in the bot. It is forbidden to extract these licenses and credits from it!
_v1.1.2_ _v2.0.0 unstable_
© 2021 - DJdj Development | [website](https://www.dj-dj.be) | [discord](https://discord.com/invite/26vT9wt3n3) 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)
+5
View File
@@ -0,0 +1,5 @@
# documentation
The documentation is not available here, go to the [wiki](https://github.com/DJj123dj/open-ticket/wiki) instead. (the wiki isn't fully done yet!)
## 2.0.0 beta
There is currently no documentation available for open-ticket v2.0.0 beta. So if you want to test it, you need to figure it out on yourself at the moment!
+65
View File
@@ -0,0 +1,65 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
module.exports = () => {
client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix+"add")) return
var user = msg.mentions.users.first()
if (!user){
return msg.channel.send({content:"**There is no user to add:**\nuse: `"+config.prefix+"add <user>`"})
}
if (!msg.member.permissions.has("MANAGE_CHANNELS") && !msg.member.permissions.has("ADMINISTRATOR")){
return msg.channel.send({content:"You have no permissions to add someone to the channel!\nYou need the `ADMINISTRATOR` or `MANAGE_CHANNELS` permission"})
}
msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
msg.channel.send({content:"You are not in a ticket!"})
return
}
msg.channel.permissionOverwrites.create(user.id, { VIEW_CHANNEL:true, ADD_REACTIONS:true,ATTACH_FILES:true, EMBED_LINKS:true, SEND_MESSAGES:true})
msg.channel.send({content:"Added "+user.tag+" to the ticket"})
if (config.logs){console.log("[system] added user to ticket (name:"+user.username+",ticket:"+msg.channel.name+")")}
var loguser = msg.mentions.users.first()
if (config.logs){console.log("[command] "+config.prefix+"add "+loguser.username+" (user:"+msg.author.username+")")}
})
})
client.on("interactionCreate",(interaction) => {
if (!interaction.isCommand()) return
if (interaction.commandName != "add") return
const user = interaction.options.getUser("user")
const member = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id)
if (!member.permissions.has("MANAGE_CHANNELS") && !member.permissions.has("ADMINISTRATOR")){
return interaction.reply({content:"You have no permissions to add someone to the channel!\nYou need the `ADMINISTRATOR` or `MANAGE_CHANNELS` permission"})
}
interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
interaction.reply({content:"You are not in a ticket!"})
return
}
interaction.channel.permissionOverwrites.create(user.id, { VIEW_CHANNEL:true, ADD_REACTIONS:true,ATTACH_FILES:true, EMBED_LINKS:true, SEND_MESSAGES:true})
interaction.reply({content:"Added "+user.tag+" to the ticket"})
if (config.logs){console.log("[system] added user to ticket (name:"+user.username+",ticket:"+interaction.channel.name+")")}
var loguser = user
if (config.logs){console.log("[command] "+config.prefix+"add "+loguser.username+" (user:"+interaction.user.username+")")}
})
})
}
+64
View File
@@ -0,0 +1,64 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
module.exports = () => {
client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix+"close")) return
msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
msg.channel.send({content:"You are not in a ticket!"})
return
}
const closebutton = new discord.MessageActionRow()
.addComponents([
new discord.MessageButton()
.setCustomId("closeTicketTrue1")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("🔒")
])
msg.channel.send({content:"**Click on the button below to close this ticket!**",components:[closebutton]})
console.log("[system] closed a ticket via command")
})
})
client.on("interactionCreate",(interaction) => {
if (!interaction.isCommand()) return
if (interaction.commandName != "close") return
interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
interaction.reply({content:"You are not in a ticket!"})
return
}
const closebutton = new discord.MessageActionRow()
.addComponents([
new discord.MessageButton()
.setCustomId("closeTicketTrue1")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("🔒")
])
interaction.reply({content:"**Click on the button below to close this ticket!**",components:[closebutton]})
console.log("[system] closed a ticket via command")
})
})
}
+64
View File
@@ -0,0 +1,64 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
module.exports = () => {
client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix+"delete")) return
msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
msg.channel.send({content:"You are not in a ticket!"})
return
}
const closebutton = new discord.MessageActionRow()
.addComponents([
new discord.MessageButton()
.setCustomId("deleteTicketTrue")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("❌")
])
msg.channel.send({content:"**Click on the button below to delete this ticket!**",components:[closebutton]})
console.log("[system] deleted a ticket via command")
})
})
client.on("interactionCreate",(interaction) => {
if (!interaction.isCommand()) return
if (interaction.commandName != "delete") return
interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
interaction.reply({content:"You are not in a ticket!"})
return
}
const closebutton = new discord.MessageActionRow()
.addComponents([
new discord.MessageButton()
.setCustomId("deleteTicketTrue")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("❌")
])
interaction.reply({content:"**Click on the button below to delete this ticket!**",components:[closebutton]})
console.log("[system] deleted a ticket via command")
})
})
}
+35
View File
@@ -0,0 +1,35 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
module.exports = () => {
const helpEmbed = new discord.MessageEmbed()
.setColor(config.main_color)
.setTitle("Help Menu:")
const prefix = config.prefix
const header = config.system.ticket_channel ? "**Go to <#"+config.system.ticket_channel+"> to create a ticket!**\n\n" : "**Run the command `/new` or `/ticket` to create a ticket!**\n\n"
helpEmbed.setDescription(header+"`"+prefix+"msg <id>` ➜ _Spawn an embed with buttons. (admin only)_\n\n`"+prefix+"rename <name>` ➜ _Rename a ticket. (no spaces)_\n`"+prefix+"close` ➜ _Close a ticket._\n`"+prefix+"delete` ➜ _Delete a ticket._\n\n`"+prefix+"add <user>` ➜ _Add a user to the ticket._\n`"+prefix+"remove <user>` ➜ _Remove a user from the ticket._`")
if (config.credits) helpEmbed.setFooter({text:"Open-Ticket by DJdj Development | view on github for source code"})
client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix)) return
var args = msg.content.split(config.prefix)
if (!args[1].startsWith("close") && !args[1].startsWith("delete") && !args[1].startsWith("remove") && !args[1].startsWith("add") && !args[1].startsWith("msg") && !args[1].startsWith("remove") && !args[1].startsWith("rename")){
msg.channel.send({embeds:[helpEmbed]})
if (config.logs){console.log("[command] "+config.prefix+"ticket help (user:"+msg.author.username+")")}
}
})
client.on("interactionCreate",(interaction) => {
if (!interaction.isCommand()) return
if (interaction.commandName != "help") return
interaction.reply({embeds:[helpEmbed]})
})
}
+65
View File
@@ -0,0 +1,65 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
module.exports = () => {
client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix+"remove")) return
var user = msg.mentions.users.first()
if (!user){
return msg.channel.send({content:"**There is no user to remove:**\nuse: `"+config.prefix+"remove <user>`"})
}
if (!msg.member.permissions.has("MANAGE_CHANNELS") && !msg.member.permissions.has("ADMINISTRATOR")){
return msg.channel.send({content:"You have no permissions to remove someone from the channel!\nYou need the `ADMINISTRATOR` or `MANAGE_CHANNELS` permission"})
}
msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
msg.channel.send({content:"You are not in a ticket!"})
return
}
msg.channel.permissionOverwrites.delete(user.id)
msg.channel.send({content:"Deleted "+user.tag+" from the ticket"})
if (config.logs){console.log("[system] deleted user from ticket (name:"+user.username+",ticket:"+msg.channel.name+")")}
var loguser = msg.mentions.users.first()
if (config.logs){console.log("[command] "+config.prefix+"remove "+loguser.username+" (user:"+msg.author.username+")")}
})
})
client.on("interactionCreate",(interaction) => {
if (!interaction.isCommand()) return
if (interaction.commandName != "remove") return
const user = interaction.options.getUser("user")
const member = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id)
if (!member.permissions.has("MANAGE_CHANNELS") && !member.permissions.has("ADMINISTRATOR")){
return interaction.reply({content:"You have no permissions to remove someone from the channel!\nYou need the `ADMINISTRATOR` or `MANAGE_CHANNELS` permission"})
}
interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
interaction.reply({content:"You are not in a ticket!"})
return
}
interaction.channel.permissionOverwrites.delete(user.id)
interaction.reply({content:"Deleted "+user.tag+" from the ticket"})
if (config.logs){console.log("[system] removed user from ticket (name:"+user.username+",ticket:"+interaction.channel.name+")")}
var loguser = user
if (config.logs){console.log("[command] "+config.prefix+"remove "+loguser.username+" (user:"+interaction.user.username+")")}
})
})
}
+81
View File
@@ -0,0 +1,81 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
module.exports = () => {
client.on("messageCreate",msg => {
if (!msg.content.startsWith(config.prefix+"rename")) return
msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
msg.channel.send({content:"You are not in a ticket!"})
return
}
if (!msg.member.permissions.has("MANAGE_CHANNELS") && !msg.member.permissions.has("ADMINISTRATOR")){
return msg.channel.send({content:"You have no permissions to change the channel name!\nYou need the `ADMINISTRATOR` or `MANAGE_CHANNELS` permission"})
}
var newname = msg.content.split(config.prefix+"rename")[1].substring(1)
var name = msg.channel.name
var prefix = ""
const tickets = config.options
tickets.forEach((ticket) => {
if (name.startsWith(ticket.channelprefix)){
prefix = ticket.channelprefix
}
})
if (!prefix) prefix = "noprefix-"
msg.channel.setName(prefix+newname)
msg.channel.send({content:"**The name is changed!**\nWarning: you can only change the channel name 2 times per minute! (this is due discord rate limits)"})
console.log("[system] renamed a ticket via command")
})
})
client.on("interactionCreate",(interaction) => {
if (!interaction.isCommand()) return
if (interaction.commandName != "rename") return
interaction.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined || firstmsg.author.id != client.user.id){
interaction.reply({content:"You are not in a ticket!"})
return
}
const member = client.guilds.cache.find(g => g.id == interaction.guild.id).members.cache.find(m => m.id == interaction.member.id)
if (!member.permissions.has("MANAGE_CHANNELS") && !member.permissions.has("ADMINISTRATOR")){
return interaction.reply({content:"You have no permissions to change the channel name!\nYou need the `ADMINISTRATOR` or `MANAGE_CHANNELS` permission"})
}
var newname = interaction.options.getString("name")
var name = interaction.channel.name
var prefix = ""
const tickets = config.options
tickets.forEach((ticket) => {
if (name.startsWith(ticket.channelprefix)){
prefix = ticket.channelprefix
}
})
if (!prefix) prefix = "noprefix-"
interaction.channel.setName(prefix+newname)
interaction.reply({content:"**The name is changed!**\nWarning: you can only change the channel name 2 times per minute! (this is due discord rate limits)"})
console.log("[system] renamed a ticket via command")
})
})
}
+44 -34
View File
@@ -1,52 +1,62 @@
const discord = require('discord.js') const discord = require('discord.js')
const bot = require('../index') const bot = require('../index')
const client = bot.client const client = bot.client
const config = require("../config.json") const config = bot.config
var name = require('./ticketExtra').name
var stringDecoder = require('./ticketSystem').stringDecoder
/** =============================
** NOT READY YET
** =============================*/
module.exports = () => { module.exports = () => {
/**@type {String[]} */
var msgIds = []
config.messages.forEach((msg) => {
msgIds.push(msg.id)
})
client.on("messageCreate", msg => { client.on("messageCreate", msg => {
if (msg.content == config.prefix+"ticket msg"){ if (msg.content.startsWith(config.prefix+"msg")){
if (msg.member.roles.cache.has(config.botperms_role) == false && msg.author.id != "779742674932072469"){ if (config.main_adminroles.some((item)=>{return msg.member.roles.cache.has(item)}) == false){
msg.channel.send({content:"Je hebt geen permissions voor deze command!"}) msg.channel.send({content:"You have no permission to run this command!"})
return return
} }
var ticketButton = new discord.MessageActionRow() const id = msg.content.split(config.prefix+"msg")[1].substring(1) ? msg.content.split(config.prefix+"msg")[1].substring(1) : false
.addComponents(
new discord.MessageButton()
.setCustomId("newTicketVraag")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("❓")
)
.addComponents(
new discord.MessageButton()
.setCustomId("newTicketSolli")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("📝")
)
.addComponents(
new discord.MessageButton()
.setCustomId("newTicketPartner")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("💼")
)
var ticketEmbed = new discord.MessageEmbed() if (!id) return msg.channel.send({content:"**There is no id!**\nUse: `"+config.prefix+"msg <id>`"})
.setColor(config.main_color) if (!msgIds.includes(id)) return msg.channel.send({content:"**Invalid id!**\nChoose from this list:\n_"+msgIds.join("_\n_")+"_"})
.setDescription("**Maak een ticket:**\nKlik op een van de onderstaande knoppen om een ticket aan te maken.\n\n__kies een categorie:__\n\n❓: **Vragen**\nOverige vragen.\n\n📝: **Sollicitatie**\nDoe een sollicitatie.\n\n💼: **Partner**\nWord partner met ons.\n\n**opgepast: **_u kan maar één ticket tegelijkertijd aanmaken!_")
const {embed,componentRows} = require("../core/ticketMessageEmbed").createEmbed(id)
msg.channel.send({embeds:[ticketEmbed],components:[ticketButton]}) msg.channel.send({embeds:[embed],components:componentRows})
if (config.logs){console.log("[command] "+config.prefix+"ticket msg (user:"+msg.author.username+")")}
if (config.logs){console.log("[system] created ticket message")}
} }
}) })
client.on("interactionCreate", (interaction) => {
if (!interaction.isCommand()) return
if (interaction.commandName != "message") return
if (config.main_adminroles.some((item)=>{return interaction.guild.members.cache.find((m) => m.id == interaction.member.id).roles.cache.has(item)}) == false){
interaction.reply({content:"You have no permission to run this command!"})
return
}
const id = interaction.options.getString("id")
if (!msgIds.includes(id)) return interaction.reply({content:"**Invalid id!**\nChoose from this list:\n_"+msgIds.join("_\n_")+"_"})
const {embed,componentRows} = require("../core/ticketMessageEmbed").createEmbed(id)
interaction.reply({content:"The embed is in the message below!"})
interaction.channel.send({embeds:[embed],components:componentRows})
if (config.logs){console.log("[command] "+config.prefix+"ticket msg (user:"+interaction.member.user.username+")")}
if (config.logs){console.log("[system] created ticket message")}
})
} }
-156
View File
@@ -1,156 +0,0 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = require("../config.json")
var name = "DJdj Development"
exports.name = name
var stringDecoder = require('./ticketSystem').stringDecoder
module.exports = () => {
client.on("messageCreate",msg => {
var args = msg.content.split(" ")
if (args[0] == config.prefix+"solli"){
var SolliMsg = new discord.MessageEmbed()
.setColor(config.main_color)
.setDescription("**Hier is de informatie die wij nodig hebben voor een sollicitatie**\n\n**naam:** Je echte naam.\n**leeftijd:** Je leeftijd.\n**discord naam:** Je discord naam + tag (bv:Wumpus#0001).\n**minecraft naam:** Je minecraft naam.\n**waarom wil je staff worden:** De reden waarom je staff wilt worden.\n**+ punten:** Je plus punten.\n**- punten:** Je min punten.\n**Jou of iemand anders:** Waarom zouden we jou aan moeten nemen en niet een andere sollicitant?\n**ervaring:** Wat is je ervaring met MT servers?\n**andere server:** Ben je op dit moment staff op een andere server?\n**online:** Hoeveel uur per dag/week kan je online zijn?\n**functie:** Voor welke functie solliciteert u?")
.setTitle("Sollicitatie")
msg.channel.send({embeds:[SolliMsg]})
}
})
client.on("messageCreate",msg => {
var args = msg.content.split(" ")
if (args[0] == config.prefix+"ticket" && (args[1] == undefined ||args[1] == "" ||args[1] == null)){
var TicketHelpMsg = new discord.MessageEmbed()
.setColor(config.main_color)
.setDescription("**Ga naar <#"+config.ticket_system.ticket_channel+"> om een ticket te maken!**\n\n`!ticket msg` ➜ _Maak een ticket reageer bericht (staff only)._\n`!ticket rename` ➜ _Rename een ticket (geen spaties)._\n`!ticket close` ➜ _Close een ticket._\n`!ticket add <user>` ➜ _Voeg een speler toe aan het ticket._\n`!ticket remove <user>` ➜ _Verwijder een speler van het ticket._\n`!partner` ➜ _De informatie voor partners._\n`!solli` ➜ _De informatie voor solliciteren._")
.setTitle("Ticket commands")
.setFooter(stringDecoder+name)
msg.channel.send({embeds:[TicketHelpMsg]})
}
})
client.on("messageCreate",msg => {
var args = msg.content.split(" ")
if (args[0] == config.prefix+"partner"){
var PartnerMsg = new discord.MessageEmbed()
.setColor(config.main_color)
.setDescription("**Hier zijn de doelen die je moet hebben voor een partnership**\n\n**server:** De naam van je server.\n**beschrijving:** Waar gaat je server over?\n**members:** Het aantal members in je server.\n**invite:** Een oneindige invite.\n\n_als wij dit goedkeuren, kan je je 'invite bericht' plaatsen._")
.setTitle("Partnership")
msg.channel.send({embeds:[PartnerMsg]})
}
})
client.on("messageCreate",msg => {
var args = msg.content.split(" ")
if (args[0] == config.prefix+"ticket" && args[1] == "close"){
msg.channel.messages.fetchPinned().then(msglist => {
var firstmsg = msglist.last()
if (firstmsg == undefined){
msg.channel.send({content:"Ik heb de sluit knop niet gevonden!"})
}
if (firstmsg.author.id != client.user.id){
msg.channel.send({content:"Je bent niet in een ticket!"})
return
}
var CloseMsg = new discord.MessageEmbed()
.setColor(config.main_color)
.setDescription("klik [hier]("+firstmsg.url+") om het ticket te sluiten.")
.setTitle("Sluit dit ticket:")
msg.channel.send({embeds:[CloseMsg]})
})
}
})
client.on("messageCreate",msg => {
var args = msg.content.split(" ")
if (args[0] == config.prefix+"ticket" && args[1] == "rename"){
if (msg.member.roles.cache.has(config.botperms_role) == false && msg.author.id != "779742674932072469"){
msg.channel.send({content:"Je hebt geen permissions voor deze command!"})
return
}
var name = args[2]
msg.channel.messages.fetchPinned().then(msglist => {
if (msglist.last().author.id == client.user.id){
msg.channel.send({content:"De naam is veranderd!"}).then(rmsg => {
rmsg.channel.setName(name)
})
}else{
msg.channel.send({content:"Je bent niet in een ticket!"})
}
})
}
})
client.on("messageCreate",msg => {
var args = msg.content.split(" ")
if (args[0] == config.prefix+"ticket" && args[1] == "add"){
if (msg.member.roles.cache.has(config.botperms_role) == false && msg.author.id != "779742674932072469"){
msg.channel.send({content:"Je hebt geen permissions voor deze command!"})
return
}
msg.channel.messages.fetch().then(msglist => {
if (msglist.last().author.id != client.user.id){
msg.channel.send({content:"Je bent niet in een ticket!"})
return
}
if (args[2] == null || args[2] == undefined || args[2] == "" || args[2] == false){
msg.channel.send({content:"Niet genoeg parameters!"})
return
}
var user = msg.mentions.users.first()
if (!user){
return
}
msg.channel.permissionOverwrites.create(user.id, { VIEW_CHANNEL:true, ADD_REACTIONS:true,ATTACH_FILES:true, EMBED_LINKS:true, SEND_MESSAGES:true})
})
}
})
client.on("messageCreate",msg => {
var args = msg.content.split(" ")
if (args[0] == config.prefix+"ticket" && args[1] == "remove"){
if (msg.member.roles.cache.has(config.botperms_role) == false && msg.author.id != "779742674932072469"){
msg.channel.send({content:"Je hebt geen permissions voor deze command!"})
return
}
msg.channel.messages.fetchPinned().then(msglist => {
if (msglist.last().author.id != client.user.id){
msg.channel.send({content:"Je bent niet in een ticket!"})
return
}
if (args[2] == null || args[2] == undefined || args[2] == "" || args[2] == false){
msg.channel.send({content:"Niet genoeg parameters!"})
return
}
var user = msg.mentions.users.first()
if (!user){
return
}
msg.channel.permissionOverwrites.delete(user.id)
})
}
})
}
-252
View File
@@ -1,252 +0,0 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = require("../config.json")
const ticketStorage = bot.TicketStorage
const userTicketStorage = bot.userTicketStorage
const transcriptStorage = bot.transcriptStorage
var stringDecoder = "Created By "
exports.stringDecoder = stringDecoder
module.exports = () => {
var closeButton = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("closeTicket")
.setDisabled(false)
.setStyle("SECONDARY")
.setLabel("Sluit Ticket")
.setEmoji("❌")
)
client.on("interactionCreate",interaction => {
if (interaction.isButton() == false){
return
}
if (interaction.customId == "newTicketVraag"||interaction.customId == "newTicketSolli"||interaction.customId == "newTicketPartner"){
interaction.deferUpdate()
if (ticketStorage.getItem(interaction.member.id) == null ||ticketStorage.getItem(interaction.member.id) == "false"){
try{
interaction.member.send("**Je ticket is aangemaakt!**")
}
catch{console.log("cant send DM to member")}
ticketStorage.setItem(interaction.member.id,"true")
var ticketNumber = interaction.member.user.username
if (interaction.customId == "newTicketVraag"){
var ticketName = "vraag-"+ticketNumber
}else if (interaction.customId == "newTicketSolli"){
var ticketName = "solli-"+ticketNumber
}else if (interaction.customId == "newTicketPartner"){
var ticketName = "partner-"+ticketNumber
}
if (config.ticket_system.enable_category){
var Category = config.ticket_system.ticket_category
}else{var Category = null}
interaction.guild.channels.create(ticketName,{
type:"GUILD_TEXT",
parent:Category,
permissionOverwrites:[
{
id:interaction.member.id,
type:"member",
allow:["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES","VIEW_CHANNEL"]
},
{
id:config.botperms_role,
type:"role",
allow:["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES","VIEW_CHANNEL"]
},
{
id:config.ticket_system.member_role,
type:"role",
deny:["VIEW_CHANNEL"]
}
]
}).then(tChannel => {
userTicketStorage.setItem(tChannel.id,interaction.member.id)
var ticketEmbed = new discord.MessageEmbed()
.setColor(config.main_color)
if (interaction.customId == "newTicketVraag"){
ticketEmbed.setDescription("**Ticket gemaakt:**\nJe hebt gekozen voor **overige vragen**, zeg alvast maar je vraag, onze staffleden komen u zo helpen.\n\n_Klik op knop hieronder om dit ticket te sluiten_")
}else if (interaction.customId == "newTicketSolli"){
ticketEmbed.setDescription("**Ticket gemaakt:**\nJe hebt gekozen voor **sollicitatie**, neem maar tijd om u sollicitatie brief voor te bereiden. Met de `!solli` command kan je zien wat je allemaal moet zeggen.\n\n_Klik op knop hieronder om dit ticket te sluiten_")
}else if (interaction.customId == "newTicketPartner"){
ticketEmbed.setDescription("**Ticket gemaakt:**\nJe hebt gekozen voor **partner**, neem maar tijd om u partner brief voor te bereiden. Met de `!partner` command kan je zien wat de vereisen zijn.\n\n_Klik op knop hieronder om dit ticket te sluiten_")
}
tChannel.send({content:"<@"+interaction.member.id+"> <@&"+config.botperms_role+">",embeds:[ticketEmbed],components:[closeButton]}).then(firstmsg => {
firstmsg.pin()
})
})
}else{
try {
interaction.member.send("**Je hebt al een ticket open!**")
}
catch{console.log("cant send DM to member")}
}
}
})
var closeBar = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("closeTicketTrue")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("✅")
)
.addComponents(
new discord.MessageButton()
.setCustomId("closeTicketFalse")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("❌")
)
client.on("interactionCreate",interaction => {
if (interaction.isButton() == false){
return
}
if (interaction.customId == "closeTicket"){
interaction.deferUpdate()
interaction.message.edit({components:[closeBar]})
}
})
client.on("interactionCreate",interaction => {
if (interaction.isButton() == false){
return
}
if (interaction.customId == "closeTicketFalse"){
interaction.deferUpdate()
interaction.message.edit({components:[closeButton]})
}
})
client.on("interactionCreate",interaction => {
if (interaction.isButton() == false){
return
}
if (interaction.customId == "closeTicketTrue"){
interaction.deferUpdate()
interaction.channel.messages.fetch().then(messages => {
var transcriptArray = []
messages.forEach(msg => {
if (msg.author.id != client.user.id){
transcriptArray.push("["+msg.author.username+"]: "+msg.content)
}
})
var getuserID = userTicketStorage.getItem(interaction.channel.id)
var getusernameStep1 = client.users.cache.find(u => u.id === getuserID)
if (getusernameStep1 == null || getusernameStep1 == undefined || getusernameStep1 == false || getusernameStep1 == ""){
var getuserNAME = ":user niet in database:"
}else {
var getuserNAME = getusernameStep1.username
}
if (config.ticket_system.enable_transcript){
var transcript = transcriptArray.reverse().join("\n")
transcriptStorage.setItem(interaction.channel.id,transcript)
var splittedTranscript = [transcript.slice(0,2000)]
if (transcript.length > 4000){
splittedTranscript.push(transcript.slice(2000,4000))
splittedTranscript.push(transcript.slice(4000))
}else if (transcript.length > 2000){
splittedTranscript.push(transcript.slice(2000))
}
var transcriptEmbed = new discord.MessageEmbed()
.setColor(config.main_color)
.setAuthor(interaction.channel.name + " - ticket gemaakt door "+getuserNAME)
.setTitle("Er is een nieuw transcript!")
.setDescription(splittedTranscript[0])
.setFooter("ticket gesloten door "+interaction.member.user.username)
if (transcript.length > 4000){
var transcriptEmbed2 = new discord.MessageEmbed()
.setColor(config.main_color)
.setAuthor(interaction.channel.name + " - ticket gemaakt door "+getuserNAME)
.setTitle("Deel 2 van het transcript")
.setDescription(splittedTranscript[1])
.setFooter("ticket gesloten door "+interaction.member.user.username)
var transcriptEmbed3 = new discord.MessageEmbed()
.setColor(config.main_color)
.setAuthor(interaction.channel.name + " - ticket gemaakt door "+getuserNAME)
.setTitle("Deel 3 van het transcript")
.setDescription(splittedTranscript[1])
.setFooter("ticket gesloten door "+interaction.member.user.username)
client.channels.cache.find(ch => ch.id == config.ticket_system.transcript_channel).send({embeds:[transcriptEmbed,transcriptEmbed2,transcriptEmbed3]})
}else if (transcript.length > 2000){
var transcriptEmbed2 = new discord.MessageEmbed()
.setColor(config.main_color)
.setAuthor(interaction.channel.name + " - ticket gemaakt door "+getuserNAME)
.setTitle("Deel 2 van het transcript")
.setDescription(splittedTranscript[1])
.setFooter("ticket gesloten door "+interaction.member.user.username)
client.channels.cache.find(ch => ch.id == config.ticket_system.transcript_channel).send({embeds:[transcriptEmbed,transcriptEmbed2]})
}else{
client.channels.cache.find(ch => ch.id == config.ticket_system.transcript_channel).send({embeds:[transcriptEmbed]})
}
}
interaction.channel.delete()
ticketStorage.setItem(getuserID,"false")
try {
interaction.member.send("**Je ticket is gesloten door "+interaction.member.user.username+"!**")
}
catch{console.log("cant send DM to member")}
})
}
})
process.on('unhandledRejection',error => {
console.log("ERROR: "+error)
})
}
+78 -14
View File
@@ -1,26 +1,90 @@
{ {
"server_name":"Ticket Bot Land",
"server_logo":"https://www.example.com/another-example/yourlogo.png",
"bot_name":"Wumpus", "bot_name":"Wumpus",
"main_color":"#fffff", "main_color":"#fffff",
"auth_token":"the bot's auth token", "server_id":"server id (for slash cmds)",
"botperms_role":"the id from a role that can do anything with the bot", "auth_token":"auth token",
"prefix":"!", "main_adminroles":["discord role id"],
"prefix":"!ticket ",
"logs":true,
"languagefile":"english.json (currently not working)",
"credits":true,
"status":{ "status":{
"type":"PLAYING | STREAMING | LISTENING | WATCHING | CUSTOM | COMPETING", "enabled":true,
"type":"PLAYING",
"text":"!ticket" "text":"!ticket"
}, },
"ticket_system":{ "system":{
"ticket_channel":"id of the channel with the !ticket msg", "ticket_channel":"channel id",
"max_allowed_tickets":3,
"enable_DM_Messages":true,
"enable_category":false, "has@everyoneaccess":false,
"ticket_category":"the id of a category for the tickets", "member_role":"member role (doesn't have access to tickets)",
"member_role":"this role doesn't have access to tickets (WARNING: @everyone does have access to tickets, so make sure all members have a member role!)",
"enable_transcript":false, "enable_transcript":false,
"transcript_channel":"the channel for transcripts" "enable_DM_transcript":false,
} "transcript_channel":"channel id"
},
"options":[
{
"id":"general",
"name":"Question",
"description":"Create this ticket if you have a question.",
"icon":"🎫",
"label":"question",
"type":"ticket",
"color":"gray",
"adminroles":["role id"],
"channelprefix":"question-",
"category":"category id",
"message":"You created a ticket!",
"enableDMMessage":true
},
{
"id":"website",
"name":"Website",
"description":"Go to our website.",
"icon":"✅",
"label":"click here",
"type":"website",
"url":"https://www.dj-dj.be"
},
{
"id":"role",
"name":"Verify",
"description":"Click here to get the verify role.",
"icon":"👮🏼",
"label":"get a role",
"type":"role",
"color":"red",
"roles":["discord role id"],
"mode":"add&remove|remove|add",
"enableDMMessage":true
}
],
"messages":[
{
"id":"1",
"name":"Choose Your Ticket",
"description":"You can click one of the buttons below!\nYou can also customize all the embeds now!",
"enableFooter":true,
"footer":"Open Ticket v2.0.0 beta - sneakpeak",
"enableThumbnail":false,
"thumbnail":"https://www.example.com/catmemes/cat.png",
"color":"#0075e9",
"options":["general","apply"],
"enableTicketExplaination":true,
"enableMaxTicketsWarning":true
}
]
} }
+312
View File
@@ -0,0 +1,312 @@
exports.checker = async () => {
const chalk = await (await import("chalk")).default
const config = require("../config.json")
var errorList = []
var isError = false
var warnList = []
var isWarn = false
const createError = (message) => {
isError = true
errorList.push("open-ticket CONFIG ERROR: "+message)
}
const createWarn = (message) => {
isWarn = true
warnList.push("open-ticket CONFIG WARNING: "+message)
}
//validators
/**@param {"userid"|"roleid"|"channelid"|"serverid"|"categoryid"} mode @param {String} value @param {String} path */
const checkDiscord = (mode,value,path) => {
if (mode == "userid"){
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+"' | this user id is invalid")
}
}else if (mode == "channelid"){
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+"' | this channel id is invalid")
}
}else if (mode == "roleid"){
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+"' | this role id is invalid")
}
}else if (mode == "serverid"){
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+"' | this server id is invalid")
}
}else if (mode == "categoryid"){
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+"' | this category id is invalid")
}
}
}
/**@param {String} value */
const checkToken = (value) => {
if (value.includes(" ") || value.length < 40 || value.length > 70){
createError("'auth_token' | your token is invalid")
}
}
/**@param {String} value @param {String} path */
const checkColor = (value,path) => {
if (!/^#[a-f0-9]{6}$/.test(value)){
createError("'"+path+"' | invalid color!")
}
}
/**@param {String} value @param {String} path @param {Number} minLength @param {Number} maxLength @param {String} name */
const checkString = (value,minLength,maxLength,path,name) => {
if (value.length < minLength){
createError("'"+path+"' | "+name+" is too short!")
}else if (value.length > maxLength){
createError("'"+path+"' | "+name+" is too long!")
}
}
/**@param {"userid"|"roleid"|"channelid"|"serverid"} mode @param {String[]} arrayValue @param {String} path */
const checkDiscordArray = (mode,arrayValue,path) => {
if (mode == "userid"){
arrayValue.forEach((value,index) => {
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+":"+index+"' | this user id is invalid")
}
})
}else if (mode == "channelid"){
arrayValue.forEach((value,index) => {
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+":"+index+"' | this channel id is invalid")
}
})
}else if (mode == "roleid"){
arrayValue.forEach((value,index) => {
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+":"+index+"' | this role id is invalid")
}
})
}else if (mode == "serverid"){
arrayValue.forEach((value,index) => {
if (value.length < 16 || value.length > 20 || !/^\d+$/.test(value)){
createError("'"+path+":"+index+"' | this server id is invalid")
}
})
}
}
/**@param {String} value @param {"string"|"boolean"|"number"} type */
const checkType = (value,type,path) => {
if (type == "boolean"){
if (typeof value != "boolean"){
createError("'"+path+"' | invalid type, this must be a boolean!")
}
}else if (type == "number"){
if (typeof value != "number"){
createError("'"+path+"' | invalid type, this must be a number!")
}
}else if (type == "string"){
if (typeof value != "string"){
createError("'"+path+"' | invalid type, this must be a string!")
}
}
}
const checkButtonColor = (value,path) => {
if (value != "none" && value != "grey" && value != "gray" && value != "black" && value != "red" && value != "green" && value != "blue" && value != "blurple"){
createError("'"+path+"' | invalid color, it must be one of these: none, gray, red, green, blue!")
}
}
const getButtonClass = require("./utils/getButton").rawButtonData
/**@param {getButtonClass} option */
const checkOption = (option,path) => {
//id
checkType(option.id,"string",path+"/id")
if (option.id.includes(" ")){
createError("'"+path+"/id' | option id can't contain space characters!")
}
if (option.id.length > 20){
createError("'"+path+"/id' | option id max lenght is 20")
}
//name
checkType(option.name,"string",path+"/name")
if (option.name.length > 100){
createWarn("'"+path+"/name' | if your name is too long it maybe doesn't look so good!")
}
//description
checkType(option.description,"string",path+"/description")
//icon
const emojiRegex = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/gi;
if (option.icon.length > 0){
const isEmoji = emojiRegex.test(option.icon)
if (isEmoji == false){
createError("'"+path+"/icon' | invalid emoji or custom discord emoji")
}
}
checkType(option.icon,"string",path+"/icon")
//label
checkType(option.label,"string",path+"/label")
if (option.label.length < 1 && option.icon.length < 1){
createError("'"+path+"' | you need at least one of these: label, icon!")
}
//type
checkType(option.type,"string",path+"/type")
if (option.type != "ticket" && option.type != "website" && option.type != "role"){
createError("'"+path+"/type' | the type must be one of these: ticket, website, role!")
}
/**@type {"ticket"|"website"|"role"} */
const type = option.type
if (type == "ticket"){
//color
checkType(option.color,"string",path+"/color")
checkButtonColor(option.color,path+"/color")
//adminroles
checkDiscordArray("roleid",option.adminroles,path+"/adminroles")
//channelprefix
checkType(option.channelprefix,"string",path+"/channelprefix")
if (option.channelprefix.includes(" ")){
createWarn("'"+path+"/channelprefix' | this prefix can't contain spaces!")
}
//category
checkType(option.category,"string",path+"/category")
checkDiscord("categoryid",option.category,path+"/category")
//message
checkType(option.message,"string",path+"/message")
//enableDMmessage
checkType(option.enableDMMessage,"boolean",path+"/enableDMMessage")
}else if (type == "website"){
//url
checkType(option.url,"string",path+"/url")
if (option.url.includes(" ")){
createWarn("'"+path+"/url' | a url can't contain spaces")
}
if (option.url.length < 1){
createError("'"+path+"/url' | you have no url in this button")
}
if (!option.url.startsWith("https://") && !option.url.startsWith("http://") && !option.url.startsWith("discord://")){
createWarn("'"+path+"/url' | your url doesn't start with https or http!")
}
if (option.url.startsWith("http://")){
createWarn("'"+path+"/url' | your url is not a HTTPS link! discord maybe blocks this url!")
}
}else if (type == "role"){
//color
checkType(option.color,"string",path+"/color")
checkButtonColor(option.color,path+"/color")
//roles
checkDiscordArray("roleid",option.roles,path+"/roles")
//mode
checkType(option.mode,"string",path+"/mode")
if (option.mode != "add&remove" && option.mode != "add" && option.mode != "remove"){
createError("'"+path+"/mode' | mode must be one of these: add, remove, add&remove")
}
//enableDMmessage
checkType(option.enableDMMessage,"boolean",path+"/enableDMMessage")
}
}
//checker
var configArray = ["bot_name","main_color","server_id","auth_token","main_adminroles","prefix","logs","languagefile","credits","status","system","options","messages"]
configArray.forEach((item) => {
if (config[item] == undefined){
throw new Error("\n\nMAIN ERROR: the item '"+item+"' doesn't exist in config.json")
}
})
checkType(config.bot_name,"string","bot_name")
checkColor(config.main_color,"main_color")
checkDiscord("serverid",config.server_id,"server_id")
checkToken(config.auth_token)
checkDiscordArray("roleid",config.main_adminroles,"main_adminroles")
checkString(config.prefix,1,15,"prefix","prefix")
checkType(config.logs,"boolean","logs")
//languagefile (comming soon)
checkType(config.credits,"boolean","credits")
//status:
checkType(config.status.enabled,"boolean","status/enabled")
if (config.status.enabled){
if (config.status.type != "PLAYING" && config.status.type != "LISTENING" && config.status.type != "WATCHING"){
createError("'status/type' | not a valid status type!")
}
if (config.status.text.length < 1 || config.status.text.length > 40){
createError("'status/text' | text too long or short!")
}
}
//system:
if (config.system.ticket_channel){
if (config.system.ticket_channel.length < 16 || config.system.ticket_channel.length > 20 || !/^\d+$/.test(config.system.ticket_channel)){
createError("'system/ticket_channel' | this channel id is invalid")
}
}else createWarn("'"+path+"' | you have no ticket channel selected!")
checkType(config.system.max_allowed_tickets,"number","system/max_allowed_tickets")
checkType(config.system.enable_DM_Messages,"boolean","system/enable_DM_Messages")
checkType(config.system["has@everyoneaccess"],"boolean","system/has@everyoneaccess")
if (config.system.member_role != "" && config.system.member_role != " " && config.system.member_role != "false" && config.system.member_role != "null" && config.system.member_role != "0"){
checkDiscord("roleid",config.system.member_role,"system/member_role")
}
checkType(config.system.enable_transcript,"boolean","system/enable_transcript")
checkType(config.system.enable_DM_transcript,"boolean","system/enable_DM_transcript")
if (config.system.enable_transcript){
checkDiscord("channelid",config.system.transcript_channel,"system/transcript_channel")
}
//options
config.options.forEach((option,index) => {
checkOption(option,"options/"+index)
})
//the end
if (errorList.length > 0 || warnList.length > 0){
console.log("REPORT:\n===========================")
}
warnList.forEach((w) => {
const splitw = w.split("'")
if (splitw.length > 1){
var splitstring = chalk.yellow(splitw[0])+chalk.blue("'"+splitw[1]+"'")+chalk.yellow(splitw[2])
}else {var splitstring = chalk.yellow(splitw[0])}
console.log(splitstring)
})
errorList.forEach((e) => {
const splite = e.split("'")
if (splite.length > 1){
var splitstring = chalk.red(splite[0])+chalk.blue("'"+splite[1]+"'")+chalk.red(splite[2])
}else {var splitstring = chalk.red(splite[0])}
console.log(splitstring)
})
if (isError){
console.log("===========================")
console.log("=> "+chalk.bgRed("your bot doesn't work if you don't fix the above errors!"))
if (isWarn){
console.log("\n=> "+chalk.bgYellow("if you ignore warns, some things may work differently than expected!"))
}
process.exit(0)
}else if (isWarn == true && isError == false){
console.log("===========================")
console.log("=> "+chalk.bgYellow("if you ignore warns, some things may work differently than expected!"))
}
}
this.checker()
+236
View File
@@ -0,0 +1,236 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
module.exports = () => {
//closebar
var closeBar = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("closeTicketTrue")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("✅")
)
.addComponents(
new discord.MessageButton()
.setCustomId("closeTicketFalse")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("❌")
)
var deleteBar = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicketTrue")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("✅")
)
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicketFalse")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("❌")
)
var deleteBar1 = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicketTrue1")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("✅")
)
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicketFalse1")
.setDisabled(false)
.setStyle("SECONDARY")
.setEmoji("❌")
)
//closebutton
var closeRowNormal = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("closeTicket")
.setDisabled(false)
.setStyle("SECONDARY")
.setLabel("Close Ticket")
.setEmoji("🔒")
)
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicket")
.setDisabled(false)
.setStyle("DANGER")
.setLabel("Delete Ticket")
.setEmoji("✖️")
)
var closeRowClosed = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicket1")
.setDisabled(false)
.setStyle("DANGER")
.setLabel("Delete Ticket")
.setEmoji("✖️")
)
.addComponents(
new discord.MessageButton()
.setCustomId("sendTranscript")
.setDisabled(false)
.setStyle("SECONDARY")
.setLabel("Send Transcript File")
.setEmoji("📄")
)
//NORMAL CLOSE
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "closeTicket") return
interaction.deferUpdate()
interaction.message.edit({components:[closeBar]})
})
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "closeTicketFalse") return
interaction.deferUpdate()
interaction.message.edit({components:[closeRowNormal]})
})
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "closeTicketTrue") return
interaction.deferUpdate()
interaction.message.edit({components:[closeRowClosed]})
/**
* @type {String}
*/
const name = interaction.channel.name
var prefix = ""
const tickets = config.options
tickets.forEach((ticket) => {
if (name.startsWith(ticket.channelprefix)){
prefix = ticket.channelprefix
}
})
require("./ticketCloser").closeTicket(interaction,prefix,"close")
})
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "closeTicketTrue1") return
interaction.deferUpdate()
const closedButtonDisabled = new discord.MessageActionRow()
.addComponents([
new discord.MessageButton()
.setCustomId("closeTicketTrue1")
.setDisabled(true)
.setStyle("SECONDARY")
.setEmoji("🔒")
])
interaction.message.edit({components:[closedButtonDisabled]})
/**
* @type {String}
*/
const name = interaction.channel.name
var prefix = ""
const tickets = config.options
tickets.forEach((ticket) => {
if (name.startsWith(ticket.channelprefix)){
prefix = ticket.channelprefix
}
})
require("./ticketCloser").closeTicket(interaction,prefix,"close")
})
//NORMAL DELETE
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "deleteTicket") return
interaction.deferUpdate()
interaction.message.edit({components:[deleteBar]})
})
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "deleteTicketFalse") return
interaction.deferUpdate()
interaction.message.edit({components:[closeRowNormal]})
})
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "deleteTicketTrue") return
interaction.deferUpdate()
/**
* @type {String}
*/
const name = interaction.channel.name
var prefix = ""
const tickets = config.options
tickets.forEach((ticket) => {
if (name.startsWith(ticket.channelprefix)){
prefix = ticket.channelprefix
}
})
require("./ticketCloser").closeTicket(interaction,prefix,"delete")
})
//CLOSED DELETE
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "deleteTicket1") return
interaction.deferUpdate()
interaction.message.edit({components:[deleteBar1]})
})
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "deleteTicketFalse1") return
interaction.deferUpdate()
interaction.message.edit({components:[closeRowClosed]})
})
client.on("interactionCreate",interaction => {
if (!interaction.isButton()) return
if (interaction.customId != "deleteTicketTrue1") return
interaction.deferUpdate()
/**
* @type {String}
*/
const name = interaction.channel.name
var prefix = ""
const tickets = config.options
tickets.forEach((ticket) => {
if (name.startsWith(ticket.channelprefix)){
prefix = ticket.channelprefix
}
})
require("./ticketCloser").closeTicket(interaction,prefix,"deletenotranscript")
})
}
+53
View File
@@ -0,0 +1,53 @@
const fs = require('fs')
const readline = require("readline")
const rl = readline.createInterface({
input:process.stdin,
output:process.stdout,
terminal:true
})
const ask = async () => {
const chalk = await (await import("chalk")).default
rl.question(chalk.yellow("WARNING: are you sure that there are",chalk.red("no tickets open"),"at the moment? ")+chalk.green("(yes/no)")+"\n",(answer) => {
if (answer != "1" && !answer.toLowerCase().startsWith("yes")){
console.log(chalk.red("invalid answer"))
ask()
return
}
console.log(chalk.green("clearing data..."))
runClear()
rl.close()
})
}
ask()
const runClear = async () => {
const chalk = await (await import("chalk")).default
console.log(chalk.blue("You can get a node.js warning below, just ignore that, it's not important!"))
const dataPaths = ["./storage/dynamicDB"]
var index = 0
dataPaths.forEach((path) => {
try {
fs.rmdirSync(path,{recursive:true,force:true})
}catch{
//console.log(path,"doesn't exist")
}
setTimeout(() => {
try{
fs.mkdirSync(path)
}catch{
//console.log(path,"already exists")
}
index++
},500)
})
setInterval(() => {
if (index >= 1){
console.log(chalk.bgGreen("All local data is cleared!"))
process.exit(1)
}
},500)
}
@@ -0,0 +1,39 @@
const localstorage = require("node-localstorage")
const ls = new localstorage.LocalStorage("./storage/dynamicDB")
/**
*
* @param {String} category
* @param {String} id
* @param {String} value
* @returns {Boolean}
*/
exports.set = (category,id,value) => {
ls.setItem(category+"--"+id,value.toString())
return true
}
/**
*
* @param {String} category
* @param {String} id
* @returns {String|false}
*/
exports.get = (category,id) => {
const result = ls.getItem(category+"--"+id)
if (!result) return false
return result
}
/**
*
* @param {String} category
* @param {String} id
* @returns {Boolean}
*/
exports.delete = (category,id) => {
ls.removeItem(category+"--"+id)
return true
}
@@ -1,3 +1,22 @@
//Do not change this without knowing what you are doing!!
const databaseFile = "local"
//Do not change this without knowing what you are doing!!
try {
var db = require("./dynamicfiles/local")
}catch{
console.log("I couldn't find the database file! (location: ./core/dynamicdatabase/storage.js:2)")
process.exit(1)
}
module.exports = db
/** =============================
** NOT READY YET
** must be dynamic
** =============================*/
const LocalStorage = require("node-localstorage") const LocalStorage = require("node-localstorage")
const ticketStorage = new LocalStorage.LocalStorage("./storage/tickets") const ticketStorage = new LocalStorage.LocalStorage("./storage/tickets")
+114
View File
@@ -0,0 +1,114 @@
const bot = require("../index")
const config = bot.config
/**
* @param {Number} index
* @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDMMessage"} value
*/
exports.getTicketValue = (index,value) => {
if (value == "id"){
return "newT"+config.options[index][value]
}
return config.options[index][value]
}
/**
* @param {Number} index
* @param {"id"|"name"|"description"|"icon"|"label"|"type"|"url"} value
*/
exports.getWebsiteValue = (index,value) => {
return config.options[index][value]
}
/**
* @param {Number} index
* @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"roles"|"mode"|"enableDMMessage"} value
*/
exports.getRoleValue = (index,value) => {
return config.options[index][value]
}
/**
* @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"adminroles"|"channelprefix"|"category"|"message"|"enableDMMessage"} value
*/
exports.getTicketValues = (value) => {
var result = []
config.options.forEach((o) => {
if (value == "id"){
result.push("newT"+o[value])
}else{
result.push(o[value])
}
})
return result
}
/**
* @param {"id"|"name"|"description"|"icon"|"label"|"type"|"url"} value
*/
exports.getWebsiteValues = (value) => {
var result = []
config.options.forEach((o) => {
result.push(o[value])
})
return result
}
/**
* @param {"id"|"name"|"description"|"icon"|"label"|"type"|"color"|"roles"|"mode"|"enableDMMessage"} value
*/
exports.getRoleValues = (value) => {
var result = []
config.options.forEach((o) => {
result.push(o[value])
})
return result
}
class TicketOptions {
constructor() {
this.id = ""
this.name = ""
this.description = ""
this.icon = ""
this.label = ""
this.type = ""
this.color = ""
this.adminroles = ["",""]
this.channelprefix = ""
this.category = ""
this.message = ""
this.enableDMMessage = true
}
}
/**
*
* @param {String} id
* @returns {TicketOptions|false}
*/
exports.getOptionsById = (id) => {
var result = false
config.options.forEach((option) => {
if ("newT"+option.id == id){
result = option
}
})
return result
}
exports.exportedOptionClass = class {
constructor() {
this.id = ""
this.name = ""
this.description = ""
this.icon = ""
this.label = ""
this.type = ""
this.color = ""
this.adminroles = ["",""]
this.channelprefix = ""
this.category = ""
this.message = ""
this.enableDMMessage = true
}
}
+56
View File
@@ -0,0 +1,56 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
const storage = bot.storage
module.exports = async () => {
const chalk = await (await import("chalk")).default
client.on("interactionCreate",(interaction) => {
if (!interaction.isButton()) return
if (!interaction.customId.startsWith("newR")) return
interaction.deferUpdate()
const optionid = interaction.customId.split("newR")[1]
if (!optionid){
interaction.reply({content:"This button doesn't exist anymore"})
return
}
try {
const option = require("./utils/getButton").getOption(optionid)
/**@type {"add"|"remove"|"add&remove"} */
const mode = option.mode
const user = interaction.member
if (mode == "add"){
option.roles.forEach((role) => {
interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role)
console.log("[system] added role",role,"to",user.user.tag)
})
}else if (mode == "remove"){
option.roles.forEach((role) => {
interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role)
console.log("[system] removed role",role,"from",user.user.tag)
})
}else if (mode == "add&remove"){
option.roles.forEach((role) => {
if (interaction.guild.members.cache.find(u => u.id == user.id).roles.cache.has(role)){
interaction.guild.members.cache.find(u => u.id == user.id).roles.remove(role)
console.log("[system] removed role",role,"from",user.user.tag)
}else {
interaction.guild.members.cache.find(u => u.id == user.id).roles.add(role)
console.log("[system] added role",role,"to",user.user.tag)
}
})
}
}catch{
interaction.reply({ephemeral:true,content:"Something went wrong! Contact the owner of this bot for more information"})
}
})
}
+24
View File
@@ -0,0 +1,24 @@
const discord = require("discord.js")
const bot = require("../../index")
const client = require("../../index").client
const config = bot.config
const getoptions = require("../getoptions")
module.exports = async () => {
const chalk = (await import("chalk")).default
console.log(chalk.red("\nINSTRUCTIONS:\n\n1: Run the command you want to delete in discord.\n2: You get the message 'This command is now deleted!'\n3: There is also a message in the console that says the command is deleted.\n4: reload your discord."))
client.on("interactionCreate",(interaction) => {
if (!interaction.isCommand()) return console.log("this isn't a command!")
interaction.reply({content:"This command is now deleted!"})
try {
client.application.commands.delete(interaction.commandId,interaction.guild.id).then(() => {
console.log("deleted the command",chalk.blue(interaction.commandName),"(id:",interaction.commandId+")")
})
}catch{
console.log(chalk.red("something went wrong by the deleting of this command!"))
}
})
}
+182
View File
@@ -0,0 +1,182 @@
const discord = require("discord.js")
const bot = require("../../index")
const client = require("../../index").client
const config = bot.config
const getoptions = require("../getoptions")
module.exports = async () => {
const chalk = (await import("chalk")).default
const sid = config.server_id
const ids = getoptions.getTicketValues("id")
/**@type {[{name:String,value:String}]} */
var choices = []
ids.forEach((id) => {
const option = getoptions.getOptionsById(id)
choices.push({name:option.name,value:option.id})
})
/**@type {[{name:String,value:String}]} */
var msgchoices = []
config.messages.forEach((msg) => {
msgchoices.push({name:msg.id,value:msg.id})
})
var readystats = 0
process.stdout.write("[status] there are "+chalk.blue("0 out of 9")+" commands ready! (this can take up to 40 seconds)")
setInterval(() => {
process.stdout.cursorTo(0)
process.stdout.write("[status] there are "+chalk.blue(readystats+" out of 9")+" commands ready! (this can take up to 40 seconds)")
if (readystats >= 9){
console.log(chalk.green("\nready!"))
console.log(chalk.bgBlue("you can now start the bot with 'npm start'!"))
process.exit(1)
}
},100)
//create a ticket (/new or /ticket)
client.application.commands.create({
name:"ticket",
description:"Create a ticket!",
defaultPermission:true,
type:"CHAT_INPUT",
options:[
{
type:"STRING",
name:"type",
description:"The type of ticket.",
required:true,
choices:choices
}
]
},sid).then(() => {
readystats++
})
client.application.commands.create({
name:"new",
description:"Create a ticket!",
defaultPermission:true,
type:"CHAT_INPUT",
options:[
{
type:"STRING",
name:"type",
description:"The type of ticket.",
required:true,
choices:choices
}
]
},sid).then(() => {
readystats++
})
//help
client.application.commands.create({
name:"help",
description:"The help menu",
defaultPermission:true,
type:"CHAT_INPUT"
},sid).then(() => {
readystats++
})
//close
client.application.commands.create({
name:"close",
description:"Close the current ticket.",
defaultPermission:true,
type:"CHAT_INPUT"
},sid).then(() => {
readystats++
})
//delete
client.application.commands.create({
name:"delete",
description:"Delete the current ticket.",
defaultPermission:true,
type:"CHAT_INPUT"
},sid).then(() => {
readystats++
})
//msg
client.application.commands.create({
name:"message",
description:"Create a ticket message.",
defaultPermission:true,
type:"CHAT_INPUT",
options:[
{
type:"STRING",
name:"id",
description:"The message id.",
required:true,
choices:msgchoices
}
]
},sid).then(() => {
readystats++
})
//add
client.application.commands.create({
name:"add",
description:"Add people to this ticket.",
defaultPermission:true,
type:"CHAT_INPUT",
options:[
{
type:"USER",
name:"user",
description:"The user to add.",
required:true
}
]
},sid).then(() => {
readystats++
})
//remove
client.application.commands.create({
name:"remove",
description:"Remove people from this ticket.",
defaultPermission:true,
type:"CHAT_INPUT",
options:[
{
type:"USER",
name:"user",
description:"The user to remove.",
required:true
}
]
},sid).then(() => {
readystats++
})
//rename
client.application.commands.create({
name:"rename",
description:"Rename this ticket.",
defaultPermission:true,
type:"CHAT_INPUT",
options:[
{
type:"STRING",
name:"name",
description:"The new name (without prefix).",
required:true
}
]
},sid).then(() => {
readystats++
})
}
+156
View File
@@ -0,0 +1,156 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
const storage = bot.storage
/**
*
* @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()
channelmessages.sweep((msgSweep) => {
return msgSweep.author.id == client.user.id
})
/**
* @type {String} ticketuserarray
*/
const ticketuserarray = interaction.channel.name
const ticketusername = ticketuserarray.split(prefix)[1]
var getuserID = storage.get("userTicketStorage",interaction.channel.id)
try {
var getusernameStep1 = client.users.cache.find(u => u.id === getuserID)
var isDatabaseError = false
}catch{
var isDatabaseError = true
}
if (!getusernameStep1){
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 enableTranscript = true
if (mode == "delete"){
interaction.channel.delete()
if (config.logs){console.log("[system] deleted a ticket (name:"+interaction.channel.name+",user:"+interaction.user.username+")")}
if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1)
}else if (mode == "close"){
var permissionArray = []
if (!isDatabaseError) permissionArray.push({
id:getusernameStep1.id,
type:"member",
allow:["VIEW_CHANNEL"],
deny:["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES"]
})
permissionArray.push({
id:interaction.guild.id,
type:"role",
deny:["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES","VIEW_CHANNEL"]
})
interaction.channel.permissionOverwrites.set(permissionArray)
//message
var closeButtonRow = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicket1")
.setDisabled(false)
.setStyle("DANGER")
.setLabel("Delete Ticket")
.setEmoji("✖️")
)
.addComponents(
new discord.MessageButton()
.setCustomId("sendTranscript")
.setDisabled(false)
.setStyle("SECONDARY")
.setLabel("Send Transcript File")
.setEmoji("📄")
)
const embed = new discord.MessageEmbed()
.setColor(config.main_color)
.setTitle("Closed this ticket!")
.setDescription("Only admins can now talk in this ticket!\n\n*Click on the button below to delete this ticket*")
interaction.channel.send({embeds:[embed],components:[closeButtonRow]})
}else if (mode == "deletenotranscript"){
enableTranscript = false
interaction.channel.delete()
if (config.logs){console.log("[system] deleted a ticket (name:"+interaction.channel.name+",user:"+interaction.user.username+")")}
if (!isDatabaseError) storage.set("ticketStorage",getuserID,Number(storage.get("ticketStorage",getuserID)) - 1)
}
if (enableTranscript == true && mode != "deletenotranscript"){
if (config.system.enable_transcript || config.system.enable_DM_transcript){
var fileattachment = await require("./transcript").createTranscript(channelmessages)
if (fileattachment == false){console.log("[transcript] internal error: no transcript is created!");return}
}
if (config.system.enable_transcript){
const transcriptEmbed = new discord.MessageEmbed()
.setColor(config.main_color)
.setTitle("A new transcript is here!")
.setAuthor({name:interaction.user.username,iconURL:interaction.user.displayAvatarURL({format:"png"})})
.setDescription("You can find the transcript in the text file above!")
.setFooter({text:"ticket: "+ticketuserarray})
interaction.guild.channels.cache.find(c => c.id == config.system.transcript_channel).send({
embeds:[transcriptEmbed],
files:[fileattachment]
})
}
if (config.system.enable_DM_transcript){
const transcriptEmbed = new discord.MessageEmbed()
.setColor(config.main_color)
.setTitle("Here is a transcript of your ticket!")
.setDescription("You can find the transcript in the text file above!")
.setFooter({text:"ticket: "+ticketuserarray})
if (!isDatabaseError) getusernameStep1.send({
embeds:[transcriptEmbed],
files:[fileattachment]
})
}
}
}
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)
if (fileattachment == false){
console.log("[transcript] internal error: no transcript is created!")
interaction.channel.send({content:"**Something went wrong while making the transcript!**\nPlease try again another time!"})
return
}
interaction.channel.send({content:"**Here is the transcript:**",files:[fileattachment]})
})
}
+95
View File
@@ -0,0 +1,95 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
const getButton = require("./utils/getButton")
/**
*
* @param {String} id the id from an open-ticket embed
* @returns {{embed:discord.MessageEmbed,componentRows:discord.MessageActionRow[]}} discord embed
*/
exports.createEmbed = (id) => {
//-----------------------------------
//general importing
const data = require("./utils/getTicketMessages").getTicketMessage(id)
/**@type {discord.MessageButton[]}*/
var buttons = []
/**@type {getButton.rawButtonData[]} */
var buttonData = []
data.options.forEach((option) => {
var button = getButton.getButton(option)
var localButtonData = getButton.getOption(option)
if (button) buttons.push(button)
if (localButtonData) buttonData.push(localButtonData)
})
//-----------------------------------
//-----------------------------------
//create the embed
const embed = new discord.MessageEmbed()
.setColor(data.color)
.setTitle(data.name)
if (data.enableFooter) embed.setFooter({text:data.footer})
if (data.enableThumbnail) embed.setThumbnail(data.thumbnail)
var description = data.description
if (data.enableTicketExplaination){
description = description+"\n\n__choose a category:__\n"
var ticketExplainations = []
buttonData.forEach((button) => {
var explaination = button.icon+" **"+button.name+":**\n"+button.description
ticketExplainations.push(explaination)
})
description = description+ticketExplainations.join("\n\n")
}
if (data.enableMaxTicketsWarning){
description = description+"\n\n**Warning:** _You can only create "+config.system.max_allowed_tickets+" ticket(s) at a time!_"
}
embed.setDescription(description)
//-----------------------------------
//-----------------------------------
//create the components
var AmountOfRows = Math.ceil(buttons.length / 4)
var currentRow = 0
/**
* @type {discord.MessageActionRow[]}
*/
var componentRows = []
for (let i = AmountOfRows; i > 0; i--){
componentRows.push(new discord.MessageActionRow())
}
buttons.forEach((button,index) => {
componentRows[currentRow].addComponents([button])
if (index == 3 || index == 7 || index == 11 || index == 15 || index == 19 || index == 23 || index == 27 || index == 31 || index == 35 || index == 39){
currentRow = currentRow + 1
}
})
//-----------------------------------
//return everything
/**
* @type {{embed:discord.MessageEmbed,componentRows:discord.MessageActionRow[]}}
*/
const returnedData = {embed:embed,componentRows:componentRows}
return returnedData
}
this.createEmbed()
+168
View File
@@ -0,0 +1,168 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
const getconfigoptions = require("./getoptions")
const storage = bot.storage
module.exports = () => {
var closeButton = new discord.MessageActionRow()
.addComponents(
new discord.MessageButton()
.setCustomId("closeTicket")
.setDisabled(false)
.setStyle("SECONDARY")
.setLabel("Close Ticket")
.setEmoji("🔒")
)
.addComponents(
new discord.MessageButton()
.setCustomId("deleteTicket")
.setDisabled(false)
.setStyle("DANGER")
.setLabel("Delete Ticket")
.setEmoji("✖️")
)
//ticket button click / create ticket
client.on("interactionCreate",(interaction) => {
if (interaction.isCommand() && (interaction.commandName == "new" || interaction.commandName == "ticket")){
var customId = "newT"+interaction.options.getString("type")
}else if (interaction.isButton()){
var customId = interaction.customId
}else return
if (getconfigoptions.getTicketValues("id").includes(customId)){
if (interaction.isButton()){
interaction.deferUpdate()
}else if (interaction.isCommand()){
interaction.reply({content:"Your ticket is created!"})
}
//ticketoptions from config
const currentTicketOptions = getconfigoptions.getOptionsById(customId)
if (storage.get("ticketStorage",interaction.member.id) == null || storage.get("ticketStorage",interaction.member.id) == "false"|| Number(storage.get("ticketStorage",interaction.member.id)) < config.system.max_allowed_tickets){
try{
if (config.system.enable_DM_Messages){
interaction.member.send({content:currentTicketOptions.message})
}
}
catch{console.log("[system] can't send DM to member, member doesn't allow dm's")}
//update storage
storage.set("ticketStorage",interaction.member.id,Number(storage.get("ticketStorage",interaction.member.id))+1)
var ticketNumber = interaction.member.user.username
//set ticketName
var ticketName = currentTicketOptions.channelprefix+ticketNumber
var logsname = currentTicketOptions.name
//category
if (currentTicketOptions.category.length < 16 || currentTicketOptions.category.length > 20){
var newTicketCategory = null
}else{
var newTicketCategory = currentTicketOptions.category
}
var permissionsArray = []
//set everyone allowed
if (config.system['has@everyoneaccess']){
var everyoneAllowPerms = ["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES","VIEW_CHANNEL"]
var everyoneDenyPerms = []
}else{
var everyoneAllowPerms = []
var everyoneDenyPerms = ["VIEW_CHANNEL"]
}
permissionsArray.push({
id:interaction.guild.id,
type:"role",
allow:everyoneAllowPerms,
deny:everyoneDenyPerms
})
//add the user that created the ticket
permissionsArray.push({
id:interaction.member.id,
type:"member",
allow:["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES","VIEW_CHANNEL"]
})
//add main adminroles
config.main_adminroles.forEach((role) => {
permissionsArray.push({
id:role,
type:"role",
allow:["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES","VIEW_CHANNEL"]
})
})
//add ticket adminroles
/**
* @type {String[]}
*/
const ticketadmin = currentTicketOptions.adminroles
ticketadmin.forEach((role) => {
if (!config.main_adminroles.includes(role)){
permissionsArray.push({
id:role,
type:"role",
allow:["ADD_REACTIONS","ATTACH_FILES","EMBED_LINKS","SEND_MESSAGES","VIEW_CHANNEL"]
})
}
})
//add member role
if (config.system.member_role != "" && config.system.member_role != " " && config.system.member_role != "false" && config.system.member_role != "null" && config.system.member_role != "0"){
permissionsArray.push({
id:config.system.member_role,
type:"role",
deny:["VIEW_CHANNEL"]
})
}
//create the channel
interaction.guild.channels.create(ticketName,{
type:"GUILD_TEXT",
parent:newTicketCategory,
reason:"A new ticket was created",
permissionOverwrites:permissionsArray
}).then((ticketChannel) => {
storage.set("userTicketStorage",ticketChannel.id,interaction.member.id)
var ticketEmbed = new discord.MessageEmbed()
.setColor(config.main_color)
.setTitle("You created a ticket!")
.setDescription("The staff will help you soon!\n\n*Click on the button below to close the ticket!*")
ticketChannel.send({
content:"<@"+interaction.member.id+"> @everyone",
embeds:[ticketEmbed],
components:[closeButton]
}).then(firstmsg => {
firstmsg.pin()
})
if (config.logs){console.log("[system] created a new ticket (name:"+logsname+",user:"+interaction.user.username+")")}
})
}else{
try {
if (config.system.enable_DM_Messages){
interaction.member.send("you already have the maximum number of tickets allowed!")
}
}
catch{console.log("[system] can't send DM to member, member doesn't allow dm's")}
}
}
})
}
+36
View File
@@ -0,0 +1,36 @@
const discord = require('discord.js')
const bot = require('../index')
const client = bot.client
const config = bot.config
/**
*
* @param {discord.Message[]} messagecollection
* @returns new `discord.messageAttachment`
*/
exports.createTranscript = async (messagecollection) => {
try {
const filearray = ["TRANSCRIPT START:"]
messagecollection.reverse()
messagecollection.forEach((msg) => {
const timestamp = new Date(msg.createdTimestamp)
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")
})
if (filearray.length < 2) filearray.push("transcript is empty")
const filestring = filearray.join("\n")
const filebuff = Buffer.from(filestring,"utf-8")
return new discord.MessageAttachment(filebuff,"transcript.txt")
}catch(err){
console.log(err)
return false
}
}
+92
View File
@@ -0,0 +1,92 @@
const discord = require("discord.js")
const bot = require("../../index")
const config = bot.config
const getoptions = require("../getoptions")
/**@returns {"DANGER"|"SUCCESS"|"PRIMARY"|"SECONDARY"} */
const getColor = (color) => {
if (color.toLowerCase() == "red"){
return "DANGER"
}else if (color.toLowerCase() == "green"){
return "SUCCESS"
}else if (color.toLowerCase() == "blue" || color.toLowerCase() == "blurple"){
return "PRIMARY"
}else if (color.toLowerCase() == "black" || color.toLowerCase() == "gray" || color.toLowerCase() == "grey"){
return "SECONDARY"
}else if (color == "DANGER" || color == "SECONDARY" || color == "SUCCESS" || color == "PRIMARY"){
return color
}else if (color.toLowerCase() == "none" || color.toLowerCase() == "false" || color.toLowerCase() == ""){
return "SECONDARY"
}else return "SECONDARY"
}
const getOption = (id) => {
const result = config.options.find((option) => option.id == id)
if (!result){return false}else return result
}
exports.getOption = getOption
/**
*
* @param {String} id
* @returns {discord.MessageButton|false}
*/
exports.getButton = (id) => {
const option = getOption(id)
if (!option) return false
if (option.type == "ticket"){
var button = new discord.MessageButton()
.setCustomId("newT"+option.id)
.setDisabled(false)
.setStyle(getColor(option.color))
if (option.label){button.setLabel(option.label)}
if (option.icon){button.setEmoji(option.icon)}
if (!option.label && !option.icon){button.setLabel("no label or emoji")}
}else if (option.type == "website"){
var button = new discord.MessageButton()
.setDisabled(false)
.setStyle("LINK")
.setURL(option.url)
if (option.label){button.setLabel(option.label)}
if (option.icon){button.setEmoji(option.icon)}
if (!option.label && !option.icon){button.setLabel("no label or emoji")}
}else if (option.type == "role"){
var button = new discord.MessageButton()
.setCustomId("newR"+option.id)
.setDisabled(false)
.setStyle(getColor(option.color))
if (option.label){button.setLabel(option.label)}
if (option.icon){button.setEmoji(option.icon)}
if (!option.label && !option.icon){button.setLabel("no label or emoji")}
}
return button
}
exports.rawButtonData = class {
constructor() {
this.id = ""
this.name = ""
this.description = ""
this.icon = ""
this.label = ""
this.type = ""
this.color = ""
this.enableDMMessage = true
this.url = ""
this.roles = ["",""]
this.mode = ""
this.adminroles = ["",""]
this.channelprefix = ""
this.category = ""
this.message = ""
}
}
+14
View File
@@ -0,0 +1,14 @@
const bot = require("../../index")
const config = bot.config
exports.getTicketMessage = (input) => {
var returned = config.messages.find(a => a.id == input)
if (returned){
return returned
}
var result = config.messages[0]
if (!result){
throw new Error("'messages' object in config.json is empty")
return
}
return result
}
+113 -16
View File
@@ -1,28 +1,125 @@
const discord = require('discord.js') const discord = require('discord.js')
const config = require('./config.json') const fs = require('fs')
const intents = discord.Intents const intents = discord.Intents
const client = new discord.Client({intents:[intents.FLAGS.GUILDS,intents.FLAGS.GUILD_MESSAGES,intents.FLAGS.GUILD_MEMBERS]}) const client = new discord.Client({intents:[intents.FLAGS.GUILDS,intents.FLAGS.GUILD_MESSAGES,intents.FLAGS.GUILD_MEMBERS],partials:["CHANNEL"]})
exports.client = client exports.client = client
client.on('ready',() => { client.setMaxListeners(20)
console.log('ready')
client.user.setActivity(config.status.text,{type:config.status.type}) //change to FALSE on release
const isDev = false
//!!!!!!!!!!!
if (isDev){
try {
var config = require('./devConfig.json')
}catch{
console.log("devConfig.json not found! Trying the normal config...")
var config = require("./config.json")
}
}else{var config = require('./config.json')}
exports.config = config
client.on('ready',async () => {
const chalk = await (await import("chalk")).default
if (process.argv[2] != "slash"){
console.log(chalk.green("open-ticket ready!"))
if (config.logs){console.log(chalk.white("\n\nlogs:\n============"))}
if (config.status.enabled){
client.user.setActivity(config.status.text,{type:config.status.type})
}
}else{
console.log(chalk.red("STARTING IN ")+chalk.blue("SLASH MODE")+chalk.red("..."))
console.log("logs:\n================")
console.log("client logged in...")
console.log("loading files...")
if (process.argv[3] == "enable"){
console.log(chalk.green("switching to slashEnable.js"))
require("./core/slashSystem/slashEnable")()
}else if (process.argv[3] == "disable"){
console.log(chalk.green("switching to slashDisable.js"))
require("./core/slashSystem/slashDisable")()
}else{
console.log(chalk.red("Internal Error: unknown slash mode!"))
process.exit(1)
}
}
}) })
var storage = require('./storage/storage') require("./core/checker").checker()
exports.TicketStorage = storage.ticketStorage
exports.userTicketStorage = storage.userTicketStorage
exports.transcriptStorage = storage.transcriptStorage
exports.ticketNumberStorage = storage.ticketNumberStorage
var ticket = require('./commands/ticket') if (process.argv[2] != "slash"){
ticket() var storage = require('./core/dynamicdatabase/storage')
exports.storage = storage
var ticketSystem = require('./commands/ticketSystem') //commands
ticketSystem() require('./commands/ticket')()
require("./commands/help")()
require("./commands/close")()
require("./commands/delete")()
require("./commands/rename")()
require("./commands/add")()
require("./commands/remove")()
var ticketExtra = require("./commands/ticketExtra") //core
ticketExtra() require('./core/ticketOpener')()
require("./core/ticketCloser").runThis()
require("./core/closebuttons")()
require("./core/reactionRoles")()
/**
* We need:
* - checker.js
*/
}
//=====================================================================
//=====================================================================
//ERROR DEBUG MODE: turn not on exept when you know what you are doing!
var errorDebugMode = false
//ERROR DEBUG MODE: turn not on exept when you know what you are doing!
//=====================================================================
//=====================================================================
if (!errorDebugMode){
process.on("uncaughtException",async (error,origin) => {
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"))
})
}
if (errorDebugMode) {
const debugLog = (debugString) => {
const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n<OPEN TICKET DEBUG FILE:>\n=========================="
fs.writeFileSync("./openticketdebug.txt",content+"\nDEBUG: "+debugString)
}
const errorLog = (errorString,stack) => {
const content = fs.existsSync("./openticketdebug.txt") ? fs.readFileSync("./openticketdebug.txt").toString() : "==========================\n<OPEN TICKET DEBUG FILE:>\n=========================="
fs.writeFileSync("./openticketdebug.txt",content+"\nERROR: "+errorString+" STACK: "+stack)
}
client.on("debug", async (message) => {
if (message.startsWith("Provided token:")){
debugLog("Provided token: ***********bot token is invisible**************...")
return
}
debugLog(message)
});
const asyncfunction = async () => {
const chalk = await (await import("chalk")).default
console.log("\n\nopen-ticket debug:\n"+chalk.bgYellow("ENTERING DEBUG MODE:"))
}
asyncfunction()
process.on("uncaughtException",async (error,origin) => {
const chalk = await (await import("chalk")).default
console.log(chalk.red("\nMAIN ERROR: ")+"this error is saved in the debug file!")
errorLog(error.name+": "+error.message+" | origin: "+origin,error.stack)
})
}
client.login(config.auth_token) client.login(config.auth_token)
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

+19 -8
View File
@@ -1,19 +1,30 @@
{ {
"name": "safemt-tickets", "name": "open-ticket",
"version": "1.0.0", "version": "2.0.0",
"description": "", "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": {
"start": "node index.js", "start": "node index.js",
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"slashEnable": "node index.js slash enable",
"slashDisable": "node index.js slash disable",
"cleardata": "node ./core/dynamicdatabase/cleardata.js"
}, },
"author": "", "author": "DJdj Development",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"canvas": "^2.8.0", "chalk": "^5.0.1",
"discord.js": "^13.2.0", "discord.js": "^13.6.0",
"express": "^4.17.1", "express": "^4.17.1",
"node": "^16.10.0", "node": "^16.10.0",
"node-localstorage": "^2.2.1" "node-localstorage": "^2.2.1"
} },
"repository": {
"type": "git",
"url": "git+https://github.com/DJj123dj/open-ticket.git"
},
"bugs": {
"url": "https://github.com/DJj123dj/open-ticket/issues"
},
"homepage": "https://github.com/DJj123dj/open-ticket#readme"
} }