├── example.env ├── .gitignore ├── example.replit ├── config.json ├── package.json ├── README.md ├── LICENSE └── index.js /example.env: -------------------------------------------------------------------------------- 1 | TOKEN= "" 2 | Mongo= "" 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .replit 2 | .env 3 | node_modules 4 | -------------------------------------------------------------------------------- /example.replit: -------------------------------------------------------------------------------- 1 | language = "nodejs" 2 | run = "node index.js" 3 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "prefix": "!", 3 | "status":{ 4 | "name": "tickets!", 5 | "type": "streaming" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tickets-button-bot", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/TajuModding/Discord-Button-Tickets-Bot" 12 | }, 13 | "keywords": [], 14 | "author": "Tejas Lamba#1924", 15 | "license": "ISC", 16 | "dependencies": { 17 | "discord-buttons": "^4.0.0", 18 | "discord-reply": "^0.1.2", 19 | "discord.js": "^12.5.3", 20 | "dotenv": "^10.0.0", 21 | "express": "^4.17.1", 22 | "quickmongo": "^3.0.2", 23 | "randomstring": "^1.2.1", 24 | "st.db": "^2.0.0" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ticket bot with buttons 2 | 3 | - Easy ticket bot in djs with buttons! 4 | - You can make a copy of this and host on replit. 5 | 6 | ### **How to use?** 7 | - Modify the setting in the `config.json` file 8 | - Download the repo, create a `.env` file, and add your `TOKEN` into it. 9 | - You need to change guildOnly to your guild id or simply delete this line. 10 | 11 | ### Requirements 12 | - Node `12.x+` 13 | - `discord.js` npm 14 | - `discord-buttons ^3.1.1` npm 15 | - `st.db` npm 16 | - `randomstring` npm 17 | - `express` np 18 | 19 | # If you like the project, don't forget to give a star to it 🌟 20 | 21 | 22 | 23 | ## Any bug or suggestion ! 24 | - Contact With Me Discord: Tejas Lamba#1924 25 | - or Discord Server [Rainbow Studios](https://discord.gg/xtessK2DPA) 26 | 27 | ## Rainbow Studio 28 | - [Discord Server](https://discord.gg/xtessK2DPA) 29 | - [Github](https://github.com/TeamRainbowDevs/) 30 | 31 | ## Licens 32 | - [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0) 33 | 34 | ## Credits 35 | [Single guild](https://github.com/TajuModding/Discord-Button-Tickets-Bot/tree/single-guild) - [TajuModding](https://github.com/TajuModding)
36 | [Multi guild](https://github.com/TajuModding/Discord-Button-Tickets-Bot) - [Xynnix](https://github.com/Xynnix) 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const Discord = require("discord.js"); 2 | const client = new Discord.Client({ 3 | disableMentions: 'everyone' 4 | }) 5 | require("dotenv").config() 6 | require('discord-reply'); 7 | const { Database } = require("quickmongo"); 8 | const db = new Database(process.env.Mongo) 9 | const randomstring = require("randomstring"); 10 | const disbut = require('discord-buttons'); 11 | require('discord-buttons')(client); 12 | const { MessageMenu, MessageMenuOption } = require('discord-buttons'); 13 | const config = require(`./config.json`) 14 | const prefix = config.prefix; 15 | 16 | async function channelLog(embed) { 17 | if (!config.log_channel_id) return; 18 | let ch = await client.channels.cache.get(config.log_channel_id) || message.guild.channels.cache.find(channel => channel.name.match("log")); 19 | if (!ch) return console.log(`Pls fill config.json`) 20 | ch.send(embed) 21 | } 22 | 23 | client.on('ready', async () => { 24 | await console.clear() 25 | channelLog(`> The **Bot** is connecting to discord API`) 26 | console.log(`Made by Tejas Lamba$1924`) 27 | console.log(`Credits | Visa2Code | https://discord.gg/xtessK2DPA`) 28 | console.log(`Join above or you gay`) 29 | client.user.setActivity(config.status.name, { type: config.status.type.toUpperCase(), url: "https://twitch.tv/SmallCadaver" }) 30 | }); 31 | client.on("message", async(message) =>{ 32 | if (message.author.bot || !message.guild) return; 33 | let args = message.content.toLowerCase().split(" "); 34 | let command = args.shift() 35 | if (command == prefix + `help`) { 36 | let embed = new Discord.MessageEmbed() 37 | .setTitle(`Bot commands list`) 38 | .setDescription(`> \`${prefix}send\` - Send a message to open tickets 39 | > \`${prefix}add\` - Adds a member to a specific ticket 40 | > \`${prefix}remove\` - Removes a member to a specific ticket. 41 | > \`${prefix}delete\` - Delete a specific ticket 42 | > \`${prefix}close\` - Close a specific ticket 43 | > \`${prefix}open\` - Open a specific ticket 44 | > \`${prefix}rename\` - Rename a specific ticket 45 | > \`${prefix}setchannels\` - set channels relating to ticket log and category 46 | > \`${prefix}setstaff\` - set staff roles`) 47 | .setTimestamp() 48 | .setColor(0x5865F2) 49 | .setFooter(`All rights belong to https://discord.gg/xtessK2DPA`) 50 | message.lineReply({ embed: embed }) 51 | } 52 | if (command == prefix + `add`) { 53 | if (!message.member.hasPermission('MANAGE_MESSAGES')) return message.lineReply(`:x: This command requires \`MANAGE_MESSAGES\` permission.`); 54 | let args = message.content.split(' ').slice(1).join(' '); 55 | let channel = message.mentions.channels.first() || message.channel; 56 | const sfats = await db.get(`Staff_${message.guild.id}`) 57 | if (!sfats) return message.lineReply({ embed: { description: `this server needs to set up their staff roles first! \`{prefix}setstaff\``, color: 0x5865F2 } }) 58 | if (await db.get(`ticket_${channel.id}_${message.guild.id}`)) { 59 | let member = message.mentions.members.first() || message.guild.members.cache.get(args || message.guild.members.cache.find(x => x.user.username === args || x.user.username === args)); 60 | if (!member) return message.lineReply(`Mention a member of its ID`); 61 | try { 62 | channel.updateOverwrite(member.user, { 63 | VIEW_CHANNEL: true, 64 | SEND_MESSAGES: true, 65 | ATTACH_FILES: true, 66 | READ_MESSAGE_HISTORY: true, 67 | }).then(() => { 68 | message.lineReply({ embed: { description: `${member} has been successfully added to ${channel}`, color: 0x5865F2 } }); 69 | let log_embed = new Discord.MessageEmbed() 70 | .setTitle(`A person has been added to a ticket`) 71 | .addField(`Ticket`, `<#${channel.id}>`) 72 | .addField(`Added Person`, member.user) 73 | .addField(`Action by`, `<@!${message.author.id}>`) 74 | .setTimestamp() 75 | .setColor(`GREEN`) 76 | .setFooter(message.guild.name, message.guild.iconURL()) 77 | channelLog(log_embed) 78 | }); 79 | } 80 | catch (e) { 81 | return message.channel.send(`An error occurred, please try again!`); 82 | } 83 | } 84 | } 85 | if (command == prefix + `remove`) { 86 | if (!message.member.hasPermission('MANAGE_MESSAGES')) return message.lineReply(`:x: This command requires \`MANAGE_MESSAGES\` permission.`); 87 | let args = message.content.split(' ').slice(1).join(' '); 88 | let channel = message.mentions.channels.first() || message.channel; 89 | const sfats = await db.get(`Staff_${message.guild.id}`) 90 | if (!sfats) return message.lineReply({ embed: { description: `this server needs to set up their staff roles first! \`{prefix}setstaff\``, color: 0x5865F2 } }) 91 | if (await db.get(`ticket_${channel.id}_${message.guild.id}`)) { 92 | let member = message.mentions.members.first() || message.guild.members.cache.get(args || message.guild.members.cache.find(x => x.user.username === args || x.user.username === args)); 93 | if (!member) return message.lineReply(`Mention a member of its ID`); 94 | try { 95 | channel.updateOverwrite(member.user, { 96 | VIEW_CHANNEL: false, 97 | }).then(() => { 98 | let log_embed = new Discord.MessageEmbed() 99 | .setTitle(`People removed to ticket`) 100 | .addField(`Ticket`, `<#${channel.id}>`) 101 | .addField(`person added`, member.user) 102 | .addField(`Action by`, `<@!${message.author.id}>`) 103 | .setTimestamp() 104 | .setColor(`RED`) 105 | .setFooter(message.guild.name, message.guild.iconURL()) 106 | channelLog(log_embed) 107 | message.lineReply({ embed: { description: `Successfully delete ${member} from ${channel}`, color: 0x5865F2 } }); 108 | }); 109 | } 110 | catch (e) { 111 | return message.channel.send(`An error occurred, please try again!`); 112 | } 113 | } 114 | } 115 | if (command == prefix + 'delete') { 116 | if (!message.member.hasPermission('MANAGE_MESSAGES')) return message.lineReply(`:x: This command requires \`MANAGE_MESSAGES\` permission.`); 117 | let channel = message.mentions.channels.first() || message.channel; 118 | const sfats = await db.get(`Staff_${message.guild.id}`) 119 | if (!sfats) return message.lineReply({ embed: { description: `this server needs to set up their staff roles first! \`{prefix}setstaff\``, color: 0x5865F2 } }) 120 | if (await db.get(`ticket_${channel.id}_${message.guild.id}`)) { 121 | message.lineReply({ embed: { description: `Your order is executed after 5 seconds, and it will be closed`, color: 0x5865F2 } }) 122 | setTimeout(async () => { 123 | let log_embed = new Discord.MessageEmbed() 124 | .setTitle(`Ticket Deleted`) 125 | .addField(`Ticket number`, `${await db.get(`ticket_${channel.id}_${message.guild.id}`).count}`) 126 | .addField(`Ticket by`,`<@!${await db.get(`ticket_${channel.id}_${message.guild.id}`).ticket_by}>`) 127 | .addField(`Action by`, `<@!${message.author.id}>`) 128 | .setTimestamp() 129 | .setColor(`RED`) 130 | .setFooter(message.guild.name, message.guild.iconURL()) 131 | channelLog(log_embed) 132 | channel.delete() 133 | }, 5000) 134 | } 135 | } 136 | if (command == prefix + 'close') { 137 | if (!message.member.hasPermission('MANAGE_MESSAGES')) return message.lineReply(`:x: This command requires \`MANAGE_MESSAGES\` permission.`); 138 | let channel = message.mentions.channels.first() || message.channel; 139 | const sfats = await db.get(`Staff_${message.guild.id}`) 140 | if (!sfats) return message.lineReply({ embed: { description: `this server needs to set up their staff roles first! \`{prefix}setstaff\``, color: 0x5865F2 } }) 141 | if (await db.get(`ticket_${channel.id}_${message.guild.id}`)) { 142 | let msg = await message.lineReply({ embed: { description: `Your order is executed after 5 seconds, and it will be closed`, color: 0x5865F2 } }) 143 | setTimeout(async () => { 144 | try { 145 | msg.delete() 146 | channel.send({ embed: { description: `Ticket has been closed by <@!${message.author.id}>`, color: `YELLOW` } }) 147 | let type = 'member' 148 | await Promise.all(channel.permissionOverwrites.filter(o => o.type === type).map(o => o.delete())); 149 | channel.setName(`closed-${(await db.get(`ticket_${channel.id}_${message.guild.id}`))}`) 150 | let log_embed = new Discord.MessageEmbed() 151 | .setTitle(`Ticket closed`) 152 | .addField(`Ticket`, `<#${channel.id}>`) 153 | .addField(`Action by`, `<@!${message.author.id}>`) 154 | .setTimestamp() 155 | .setColor(`YELLOW`) 156 | .setFooter(message.guild.name, message.guild.iconURL()) 157 | channelLog(log_embed) 158 | } catch (e) { 159 | return message.channel.send(`An error occurred, please try again!`); 160 | } 161 | }, 1000) 162 | } 163 | } 164 | 165 | if (command == prefix + 'open') { 166 | if (!message.member.hasPermission('MANAGE_MESSAGES')) return message.lineReply(`:x: This command requires \`MANAGE_MESSAGES\` permission.`); 167 | let channel = message.mentions.channels.first() || message.channel; 168 | const sfats = await db.get(`Staff_${message.guild.id}`) 169 | if (!sfats) return message.lineReply({ embed: { description: `this server needs to set up their staff roles first! \`{prefix}setstaff\``, color: 0x5865F2 } }) 170 | if (await db.get(`ticket_${channel.id}_${message.guild.id}`)) { 171 | let msg = await message.lineReply({ embed: { description: `Your order is executed after 5 seconds`, color: 0x5865F2 } }) 172 | setTimeout(async () => { 173 | try { 174 | msg.delete() 175 | channel.send({ embed: { description: `Ticket opened by <@!${message.author.id}>`, color: `GREEN` } }) 176 | let meember = client.users.cache.get(await db.get(`ticket_${channel.id}_${message.guild.id}`).ticket_by); 177 | channel.updateOverwrite(meember, { 178 | VIEW_CHANNEL: true, 179 | SEND_MESSAGES: true, 180 | ATTACH_FILES: true, 181 | READ_MESSAGE_HISTORY: true, 182 | }) 183 | channel.updateOverwrite((await db.get(`Staff_${message.guild.id}.Admin`)), { 184 | VIEW_CHANNEL: true, 185 | SEND_MESSAGES: true, 186 | ATTACH_FILES: true, 187 | READ_MESSAGE_HISTORY: true, 188 | }) 189 | channel.updateOverwrite((await db.get(`Staff_${message.guild.id}.Moder`)), { 190 | VIEW_CHANNEL: true, 191 | SEND_MESSAGES: true, 192 | ATTACH_FILES: true, 193 | READ_MESSAGE_HISTORY: true, 194 | }) 195 | channel.setName(`ticket-${await db.get(`ticket_${channel.id}_${message.guild.id}`).count}`) 196 | let log_embed = new Discord.MessageEmbed() 197 | .setTitle(`Ticket has reopened`) 198 | .addField(`Ticket`, `<#${channel.id}>`) 199 | .addField(`Action by`, `<@!${message.author.id}>`) 200 | .setTimestamp() 201 | .setColor(`GREEN`) 202 | .setFooter(message.guild.name, message.guild.iconURL()) 203 | channelLog(log_embed) 204 | } catch (e) { 205 | return message.channel.send(`An error occurred, please try again!`); 206 | } 207 | }, 1000) 208 | } 209 | } 210 | if (command == prefix + 'rename' || command == prefix + 'setname') { 211 | if (!message.member.hasPermission('MANAGE_MESSAGES')) return message.lineReply(`:x: This command requires \`MANAGE_MESSAGES\` permission.`); 212 | let channel = message.mentions.channels.first() || message.channel; 213 | const sfats = await db.get(`Staff_${message.guild.id}`) 214 | if (!sfats) return message.lineReply({ embed: { description: `this server needs to set up their staff roles first! \`{prefix}setstaff\``, color: 0x5865F2 } }) 215 | if (await db.get(`ticket_${channel.id}_${message.guild.id}`)) { 216 | let args = message.content.split(' ').slice(1).join(' '); 217 | if (!args) return message.lineReply({ embed: { description: `Please select the name you want for the ticket`, color: 0x5865F2 } }) 218 | channel.setName(args) 219 | message.delete() 220 | let log_embed = new Discord.MessageEmbed() 221 | .setTitle(`Ticket name change`) 222 | .addField(`New name`, args) 223 | .addField(`Ticket`, `<#${channel.id}>`) 224 | .addField(`by`, `<@!${message.author.id}>`) 225 | .setTimestamp() 226 | .setColor(0x5865F2) 227 | .setFooter(message.guild.name, message.guild.iconURL()) 228 | channelLog(log_embed) 229 | } 230 | } 231 | if (command == prefix + 'setstaff'){ 232 | console.log(args) 233 | if (!message.member.hasPermission('ADMINISTRATOR')) return message.lineReply(`:x: This command requires \`ADMINISTRATOR\` permission.`); 234 | if (args.length != 2) return message.lineReply({ embed: { description: `Please provide an Admin role id, *then* a Mod role id with this command! `, color: 0x5865F2 } }) 235 | if (message.mentions.roles.length < 2 && !Number(args[0]) && !Number(args[1])) return message.lineReply({ embed: { description: `Please mention an Admin role (or iD) first, *then* a Mod role (or iD) with this command! `, color: 0x5865F2 } }) 236 | const Admin = message.guild.roles.cache.get(args[0]); 237 | const Moder = message.guild.roles.cache.get(args[1]); 238 | await db.set(`Staff_${message.guild.id}.Admin`, Admin.id) 239 | await db.set(`Staff_${message.guild.id}.Moder`, Moder.id) 240 | message.react("✅") 241 | } 242 | if (command == prefix + 'setchannels'){ 243 | if (!message.member.hasPermission('ADMINISTRATOR')) return message.lineReply(`:x: This command requires \`ADMINISTRATOR\` permission.`); 244 | if (args.length != 2) return message.lineReply({ embed: { description: `Please mention a channelid, *then* a categoryid with this command! `, color: 0x5865F2 } }) 245 | if (message.mentions.roles.length < 2 && !Number(args[0]) && !Number(args[1])) return message.lineReply({ embed: { description: `Please mention an Log Channel (or iD), *then* a Category (or iD) with this command! `, color: 0x5865F2 } }) 246 | const txt = message.guild.channels.cache.get(args[0]); 247 | const cat = message.guild.channels.cache.get(args[1]); 248 | if (txt.type !== "text") return message.channel.send("The first input should be a text channel"); 249 | if (cat.type !== "category") return message.channel.send("The second input should be a text category"); 250 | await db.set(`Channels_${message.guild.id}.Log`, txt.id) 251 | await db.set(`Channels_${message.guild.id}.Cat`, cat.id) 252 | message.react("✅") 253 | } 254 | if (command == prefix + 'send' || command == prefix + 'ticket') { 255 | if (!message.member.hasPermission('ADMINISTRATOR')) return message.lineReply(`:x: This command requires \`ADMINISTRATOR\` permission.`); 256 | const sfats = await db.get(`Staff_${message.guild.id}`) 257 | const sfas = await db.get(`Channels_${message.guild.id}`) 258 | if (!sfats || sfats === null) return message.lineReply({ embed: { description: `This server needs to set up their staff roles first! \`${prefix}setstaff\``, color: 0x5865F2 } }) 259 | if (!sfas || sfas === null) return message.lineReply({ embed: { description: `This server needs to set up their ticket channels first! \`${prefix}setchannels\``, color: 0x5865F2 } }) 260 | let idd = randomstring.generate({ length: 20 }) 261 | let args = message.content.split(' ').slice(1).join(' '); 262 | if (!args) args = `Tickets` 263 | let button1 = new MessageMenuOption() 264 | .setLabel('Special Support') 265 | .setEmoji('🔴') 266 | .setValue("men") 267 | .setDescription('Use this to contact Admins+ only!') 268 | let button3 = new MessageMenuOption() 269 | .setLabel('General Support') 270 | .setEmoji('🟠') 271 | .setValue("hlp") 272 | .setDescription('Use this to contact Helpers and higher ranks!') 273 | let select = new MessageMenu() 274 | .setID(idd) 275 | .setPlaceholder('Create A ticket!') 276 | .setMaxValues(1) 277 | .setMinValues(1) 278 | .addOptions(button1, button3) 279 | let embed = new Discord.MessageEmbed() 280 | .setTitle(args) 281 | .setDescription("To create a ticket, select one of the options below from the menu.") 282 | .setThumbnail(message.guild.iconURL()) 283 | .setTimestamp() 284 | .setColor(0x5865F2) 285 | .setFooter(message.guild.name, message.guild.iconURL()) 286 | let msg = await message.channel.send({ embed: embed, component: select }).then(async msg => { 287 | msg.pin() 288 | let log_embed = new Discord.MessageEmbed() 289 | .setTitle(`A message has been sent to open new tickets`) 290 | .addField(`Channel`, `<#${message.channel.id}>`) 291 | .addField(`by`, `<@!` + message.author.id + `>`) 292 | .setTimestamp() 293 | .setColor(0x5865F2) 294 | .setFooter(message.guild.name, message.guild.iconURL()) 295 | channelLog(log_embed) 296 | await db.set(`tickets_${idd}_${message.guild.id}`, { 297 | reason: args, 298 | msgID: msg.id, 299 | id: idd, 300 | options: [button1, button3], 301 | guildName: message.guild.name, 302 | guildAvatar: message.guild.iconURL(), 303 | channelID: message.channel.id 304 | }) 305 | }) 306 | } 307 | }) 308 | 309 | 310 | client.on('clickMenu', async (button) => { 311 | console.log(button.values) 312 | if (await db.get(`tickets_${button.id}_${button.message.guild.id}`)) { 313 | await button.reply.send(`Your ticket is being processed. Please wait `, true) 314 | await db.math(`counts_${button.message.id}_${button.message.guild.id}`, `+`, 1) 315 | let count = await db.get(`counts_${button.message.id}_${button.message.guild.id}`) 316 | let channel; 317 | await button.clicker.fetch(); 318 | if (button.values[0] === "men") { // Admins + 319 | button.guild.channels.create(`ticket-${count}`, { 320 | permissionOverwrites: [ 321 | { 322 | id: button.guild.roles.everyone, 323 | deny: ['VIEW_CHANNEL'], 324 | }, 325 | { 326 | id: (await db.get(`Staff_${button.message.guild.id}.Admin`)), 327 | allow: ['VIEW_CHANNEL', `READ_MESSAGE_HISTORY`, `ATTACH_FILES`, `SEND_MESSAGES`,`MANAGE_MESSAGES`], 328 | }, 329 | { 330 | id: button.clicker.user.id, 331 | allow: ['VIEW_CHANNEL', `READ_MESSAGE_HISTORY`, `ATTACH_FILES`, `SEND_MESSAGES`], 332 | }, 333 | ], parent: (await db.get(`Channels_${button.message.guild.id}.Cat`)), position: 1, topic: `A Ticket : <@!${button.clicker.user.id}>`, reason: "All rights reserved to Visa2Code" 334 | }).then(async channel => { 335 | channel = channel 336 | await db.set(`ticket_${channel.id}_${button.message.guild.id}`, { count: count, ticket_by: button.clicker.user.id }) 337 | 338 | await button.reply.edit(` 339 | **Your ticket has been successfully opened** <#${channel.id}>`, true) 340 | let log_embed = new Discord.MessageEmbed() 341 | .setTitle(`New ticket opened`) 342 | .addField(`Ticket`, `<#${channel.id}>`) 343 | .addField(`Ticket by`, `<@!${button.clicker.user.id}>`) 344 | .addField(`Ticket number`, count) 345 | .setTimestamp() 346 | .setColor(`GREEN`) 347 | channelLog(log_embed) 348 | const embedticket = new Discord.MessageEmbed() 349 | .setTimestamp() 350 | .setTitle("Specialised Support") 351 | .setFooter(`Ticket opened at`) 352 | .setColor(0x5865F2) 353 | .setDescription(`Support will be with you soon.\n 354 | To close this ticket, interact with 🔒`) 355 | let idd = randomstring.generate({ length: 25 }) 356 | let bu1tton = new disbut.MessageButton() 357 | .setStyle(`gray`) 358 | .setEmoji(`🔒`) 359 | .setLabel(`Close`) 360 | .setID(idd) 361 | channel.send(`Welcome <@!${button.clicker.user.id}>`, { embed: embedticket, component: bu1tton }).then(msg => { 362 | msg.pin() 363 | }) 364 | }) 365 | } 366 | if (button.values[0] === "hlp"){ // help + 367 | button.guild.channels.create(`ticket-${count}`, { 368 | permissionOverwrites: [ 369 | { 370 | id: button.guild.roles.everyone, 371 | deny: ['VIEW_CHANNEL'], 372 | }, 373 | { 374 | id: (await db.get(`Staff_${button.message.guild.id}.Admin`)), 375 | allow: ['VIEW_CHANNEL', `READ_MESSAGE_HISTORY`, `ATTACH_FILES`, `SEND_MESSAGES`,`MANAGE_MESSAGES`], 376 | }, 377 | { 378 | id: (await db.get(`Staff_${button.message.guild.id}.Moder`)), 379 | allow: ['VIEW_CHANNEL', `READ_MESSAGE_HISTORY`, `ATTACH_FILES`, `SEND_MESSAGES`,`MANAGE_MESSAGES`], 380 | }, 381 | { 382 | id: button.clicker.user.id, 383 | allow: ['VIEW_CHANNEL', `READ_MESSAGE_HISTORY`, `ATTACH_FILES`, `SEND_MESSAGES`], 384 | }, 385 | ], parent: (await db.get(`Channels_${button.message.guild.id}.Cat`)), position: 1, topic: `A Ticket : <@!${button.clicker.user.id}>`, reason: "All rights reserved to Visa2Code" 386 | }).then(async channel => { 387 | channel = channel 388 | await db.set(`ticket_${channel.id}_${button.message.guild.id}`, { count: count, ticket_by: button.clicker.user.id }) 389 | 390 | await button.reply.edit(` 391 | **Your ticket has been successfully opened** <#${channel.id}>`, true) 392 | let log_embed = new Discord.MessageEmbed() 393 | .setTitle(`New ticket opened`) 394 | .addField(`Ticket`, `<#${channel.id}>`) 395 | .addField(`Ticket by`, `<@!${button.clicker.user.id}>`) 396 | .addField(`Ticket number`, count) 397 | .setTimestamp() 398 | .setColor(`GREEN`) 399 | channelLog(log_embed) 400 | const embedticket = new Discord.MessageEmbed() 401 | .setTimestamp() 402 | .setTitle("General Support") 403 | .setFooter(`Ticket opened at`) 404 | .setColor(0x5865F2) 405 | .setDescription(`Support will be with you soon.\n 406 | To close this ticket, interact with 🔒`) 407 | let idd = randomstring.generate({ length: 25 }) 408 | await db.set(`close_${button.clicker.user.id}`, idd) 409 | let bu1tton = new disbut.MessageButton() 410 | .setStyle(`gray`) 411 | .setEmoji(`🔒`) 412 | .setLabel(`Close`) 413 | .setID(idd) 414 | channel.send(`Welcome <@!${button.clicker.user.id}>`, { embed: embedticket, component: bu1tton }).then(msg => { 415 | msg.pin() 416 | }) 417 | }) 418 | } 419 | } 420 | }); 421 | client.on('clickButton', async (button1) => { 422 | await button1.clicker.fetch() 423 | let idd = randomstring.generate({ length: 25 }) 424 | await db.set(`close_${button1.clicker.user.id}_sure`, idd) 425 | if (button1.id == (await db.get(`close_${button1.clicker.user.id}`))) { 426 | let bu0tton = new disbut.MessageButton() 427 | .setStyle(`red`) 428 | .setLabel(`close`) 429 | .setID(idd) 430 | await button1.reply.send(`Are you sure you want to close this ticket?`, { component: bu0tton, ephemeral: true }); 431 | } 432 | }) 433 | client.on('clickButton', async (button) => { 434 | await button.clicker.fetch() 435 | if (button.id == (await db.get(`close_${button.clicker.user.id}_sure`))) { 436 | await button.reply.send(`Your order is executed after 5 seconds, and it will be closed`, true) 437 | let ch = button.channel 438 | if (!ch) return; 439 | setTimeout(async () => { 440 | try { 441 | await ch.send({ embed: { description: `The ticket has already been closed <@!${button.clicker.user.id}>`, color: `YELLOW` } }); 442 | let type = 'member' 443 | await Promise.all(ch.permissionOverwrites.filter(o => o.type === type).map(o => o.delete())); 444 | ch.setName(`closed-ticket`) 445 | let log_embed = new Discord.MessageEmbed() 446 | .setTitle(`Ticket closed`) 447 | .addField(`Ticket`, `<#${ch.id}>`) 448 | .addField(`Action by`, `<@!${button.clicker.user.id}>`) 449 | .setTimestamp() 450 | .setColor(`YELLOW`) 451 | channelLog(log_embed) 452 | } catch (e) { 453 | return button.channel.send(`An error occurred, please try again!`); 454 | } 455 | }, 4000) 456 | } 457 | }) 458 | client.login(process.env.TOKEN); 459 | --------------------------------------------------------------------------------