diff --git a/Commands/closeticket.js b/Commands/closeticket.js index c0bcb6d..7a50c70 100644 --- a/Commands/closeticket.js +++ b/Commands/closeticket.js @@ -6,6 +6,7 @@ const fs = require("fs"); const Discord = require("discord.js"); const yaml = require('js-yaml'); const supportbot = yaml.load(fs.readFileSync('./Data/supportbot.yml', 'utf8')); +const cmdconfig = yaml.load(fs.readFileSync('./Data/commands.yml', 'utf8')); const Command = require("../Structures/Command.js"); const TicketNumberID = require('../Structures/TicketID.js'); @@ -17,8 +18,8 @@ async function asyncForEach(array, callback) { } module.exports = new Command({ - name: "close", - description: "Close a support ticket", + name: cmdconfig.CloseTicket, + description: cmdconfig.CloseTicketDesc, type: "BOTH", slashCommandOptions: [], permission: "SEND_MESSAGES", diff --git a/Commands/info.js b/Commands/info.js index f259408..de0b959 100644 --- a/Commands/info.js +++ b/Commands/info.js @@ -6,12 +6,13 @@ const fs = require("fs"); const Discord = require("discord.js"); const yaml = require('js-yaml'); const supportbot = yaml.load(fs.readFileSync('./Data/supportbot.yml', 'utf8')); +const cmdconfig = yaml.load(fs.readFileSync('./Data/commands.yml', 'utf8')); const Command = require("../Structures/Command.js"); module.exports = new Command({ - name: "info", - description: "Displays information about your server!", + name: cmdconfig.InfoCommand, + description: cmdconfig.InfoCommandDesc, type: "BOTH", slashCommandOptions: [], permission: "SEND_MESSAGES", diff --git a/Data/TicketData.json b/Data/TicketData.json index c937d51..9e26dfe 100644 --- a/Data/TicketData.json +++ b/Data/TicketData.json @@ -1,5 +1 @@ -{ - "854057237495676938": { - "id": 8 - } -} \ No newline at end of file +{} \ No newline at end of file diff --git a/Data/commands.yml b/Data/commands.yml new file mode 100644 index 0000000..5b30388 --- /dev/null +++ b/Data/commands.yml @@ -0,0 +1,31 @@ +# ___ _ ___ _ +# / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_ +# \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | | +# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_| +# |_| |_| +# +# SupportBot created by Emerald Services +# Installed with MIT License +# +# Discord Support: https:#emeraldsrv.dev/discord +# Community Resources: https:#emeraldsrv.dev/resources + +# ------------------------------- +# Commamnd Name Configuration +# ------------------------------- + +OpenTicket: "ticket" +CloseTicket: "close" +InfoCommand: "info" +PingCommand: "ping" + +# --------------------------------------- +# Commamnd Description Configuration +# --------------------------------------- + +OpenTicketDesc: "Open a new support ticket." +CloseTicketDesc: "Close your support ticket" +InfoCommandDesc: "Get information about the brand" +PingCommandDesc: "Pong!" + + diff --git a/Data/supportbot.yml b/Data/supportbot.yml index be47bdc..08e63d3 100644 --- a/Data/supportbot.yml +++ b/Data/supportbot.yml @@ -10,13 +10,15 @@ # Discord Support: https:#emeraldsrv.dev/discord # Community Resources: https:#emeraldsrv.dev/resources +SupportBot_Version: "7.2 pre-2" + # ------------------------- # General Configuration # ------------------------- Name: "SupportBot" Prefix: "!" -Token: "BOT_TOKEN" +Token: "TOKEN" # ------------------------- # Activity Configuration @@ -63,6 +65,7 @@ LockdownRole: "@everyone" Staff: "Support Team" Admin: "Project Developer" TicketBlackListRole: "Blacklisted" + # ------------------------- # Tickets Configuration # ------------------------- @@ -85,25 +88,6 @@ AllowTicketMentions: true # Set to true to allow the ticket to mention the author and the support team. # Set to false to dis-allow mentions within tickets. -# --- Panel Config --- -# --- Start --- - -ReactionChannel: "create-ticket" -ReactionEmoji: "📩" -# For cusomt emojis: <:emoji_name:EMOJI_ID> - -ReactionTickets: true -ReactionMessage: "React with %reaction_emoji% to create a Support Ticket!" - -ReactionPanel_Description: true -ReactionDescription: "Create a support ticket to contact a member of staff." - -ReactionPanel_Thumbnail: true -ReactionThumbnail: "https://hotemoji.com/images/dl/5/ticket-emoji-by-twitter.png" - -ReactionPanel_Image: true -ReactionImage: "https://wallpapercave.com/wp/wp4462546.jpg" - # --- Creation Config --- # --- Start --- diff --git a/Data/ticket-panel-id.yml b/Data/ticket-panel-id.yml new file mode 100644 index 0000000..b129648 --- /dev/null +++ b/Data/ticket-panel-id.yml @@ -0,0 +1,7 @@ +# Place the Message ID for your Ticket Panel. +# If you do not have one. Leave it blank! It will generate for you! + +TicketPanelID: '' + + + diff --git a/Data/ticket-panel.yml b/Data/ticket-panel.yml index e69de29..2e951a6 100644 --- a/Data/ticket-panel.yml +++ b/Data/ticket-panel.yml @@ -0,0 +1,42 @@ +# ___ _ ___ _ +# / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_ +# \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | | +# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_| +# |_| |_| +# +# SupportBot created by Emerald Services +# Installed with MIT License +# +# Discord Support: https:#emeraldsrv.dev/discord +# Community Resources: https:#emeraldsrv.dev/resources + +# ------------------------------- +# Ticket Panel Configuration +# ------------------------------- + +TicketPanel: true + +# ---------------------------------------- +# Ticket Panel Message Configuration +# ---------------------------------------- + +Channel: "create-ticket" +ButtonEmoji: "📩" +ButtonLabel: "Open Ticket" +ButtonColour: "SUCCESS" +# Colour Options: +# -> PRIMARY - Blurple +# -> SECONDARY - Grey +# -> SUCCESS - Green +# -> DANGER - Red + +PanelTitle: "Need Help? Create a Support Ticket." + +TicketPanel_Description: true +TicketPanel_Thumbnail: false +TicketPanel_Image: false + +PanelMessage: "Click the button to open a new support ticket." +PanelThumbnail: "https://i.imgur.com/ieeZejl.png" +PanelImage: "https://i.imgur.com/5NkcmDq.png" + diff --git a/Events/messageReactionAdd.js b/Events/messageReactionAdd.js new file mode 100644 index 0000000..a1b3129 --- /dev/null +++ b/Events/messageReactionAdd.js @@ -0,0 +1,40 @@ +// SupportBot | Emerald Services +// Ready Event + +const fs = require("fs"); + +const Discord = require("discord.js"); +const yaml = require('js-yaml'); +const supportbot = yaml.load(fs.readFileSync('./Data/supportbot.yml', 'utf8')); +const cmdconfig = yaml.load(fs.readFileSync('./Data/commands.yml', 'utf8')); +const panelconfig = yaml.load(fs.readFileSync('./Data/ticket-panel.yml', 'utf8')); + +const Event = require("../Structures/Event.js"); + +module.exports = new Event("messageReactionAdd", async (client) => { + + let message = { + guild: reaction.message.channel.guild, + author: user, + content: "N/A", + channel: reaction.message.channel + } + + if (panelconfig.TicketPanel) { + if (reaction.message.id === panelconfig.TicketPanelID) { + if (reaction.emoji.name == panelconfig.ButtonEmoji || reaction.emoji.id == panelconfig.ButtonEmoji) { + await reaction.users.remove(user.id) + + try { + const cmd = client.commands.get(cmdconfig.OpenTicket); + if(!cmd) return; + + cmd.run(message, message.content); + } catch (error) { + console.error(error); + } + } + } + } + +}); \ No newline at end of file diff --git a/commands/ping.js b/commands/ping.js index 541fb0f..f4a831e 100644 --- a/commands/ping.js +++ b/commands/ping.js @@ -6,12 +6,13 @@ const fs = require("fs"); const Discord = require("discord.js"); const yaml = require('js-yaml'); const supportbot = yaml.load(fs.readFileSync('./Data/supportbot.yml', 'utf8')); +const cmdconfig = yaml.load(fs.readFileSync('./Data/commands.yml', 'utf8')); const Command = require("../Structures/Command.js"); module.exports = new Command({ - name: "ping", - description: "Shows the ping of the bot!", + name: cmdconfig.PingCommand, + description: cmdconfig.PingCommandDesc, type: "BOTH", slashCommandOptions: [], permission: "SEND_MESSAGES", diff --git a/commands/ticket.js b/commands/ticket.js index bd4f467..b6ef2ac 100644 --- a/commands/ticket.js +++ b/commands/ticket.js @@ -6,6 +6,7 @@ const fs = require("fs"); const Discord = require("discord.js"); const yaml = require('js-yaml'); const supportbot = yaml.load(fs.readFileSync('./Data/supportbot.yml', 'utf8')); +const cmdconfig = yaml.load(fs.readFileSync('./Data/commands.yml', 'utf8')); const Command = require("../Structures/Command.js"); const TicketNumberID = require('../Structures/TicketID.js'); @@ -17,8 +18,8 @@ async function asyncForEach(array, callback) { } module.exports = new Command({ - name: "ticket", - description: "Creates a support ticket", + name: cmdconfig.OpenTicket, + description: cmdconfig.OpenTicketDesc, type: "BOTH", slashCommandOptions: [], permission: "SEND_MESSAGES", diff --git a/events/interactionCreate.js b/events/interactionCreate.js index 7b74a6a..60d0118 100644 --- a/events/interactionCreate.js +++ b/events/interactionCreate.js @@ -6,10 +6,132 @@ const fs = require("fs"); const Discord = require("discord.js"); const yaml = require('js-yaml'); const supportbot = yaml.load(fs.readFileSync('./Data/supportbot.yml', 'utf8')); +const cmdconfig = yaml.load(fs.readFileSync('./Data/commands.yml', 'utf8')); const Event = require("../Structures/Event.js"); module.exports = new Event("interactionCreate", (client, interaction) => { + + if (interaction.isCommand()) return; + + const command = client.commands.find(cmd => cmd.name.toLowerCase() == interaction.commandName); + + if(interaction.isButton()) { + if(interaction.customId === 'openticket') { + interaction.message.fetch() + interaction.deferUpdate() + let message = { + guild: client.guilds.cache.get(interaction.message.guildId), + author: client.users.cache.get(interaction.user.id), + content: "N/A", + channel: client.channels.cache.get(interaction.message.channelId) + } + try { + const cmd = client.commands.get(cmdconfig.OpenTicket); + if(!cmd) return; + cmd.run(message, message.content) + } + catch (error){ + console.error(error) + } + } + + if(interaction.customId === 'ticketclose') { + if(interaction.channel.name.startsWith(`${supportbot.TicketChannel}-`)) { + interaction.message.fetch() + interaction.deferUpdate() + const DeleteTicketEmbed = new Discord.MessageEmbed() + .setDescription(supportbot.TicketDeleteMessage) + .setColor(supportbot.EmbedColour) + interaction.channel.send({embeds: [DeleteTicketEmbed]}) + + let logChannel = interaction.guild.channels.cache.find(channel => channel.name === supportbot.TranscriptLog) || interaction.guild.channels.cache.find(channel => channel.id === supportbot.TranscriptLog) + + let user = interaction.user + let name = interaction.channel.name; + let ticketChannel = interaction.channel + let reason = "No Reason Provided." + + interaction.channel.send({content: `**${supportbot.ClosingTicket}**`}) + .then(() => { + const logEmbed = new Discord.MessageEmbed() + .setTitle(supportbot.TranscriptTitle) + .setColor(supportbot.EmbedColour) + .setFooter(supportbot.EmbedFooter) + .addField("Closed By", user.username) + .addField("Reason", reason) + + interaction.channel.messages.fetch({limit: 100}).then(msgs => { + let html = '' + + msgs = msgs.sort( ( a, b ) => a.createdTimestamp - b.createdTimestamp ); + html += `Server Name: ${interaction.guild.name}
` + html += `Ticket: ${ticketChannel.name}
` + html += `Message: ${msgs.size} Messages


` + + + msgs.forEach(msg => { + if(msg.content) { + html += `User: ${msg.author.tag}
`; + html += `Message: ${msg.content}
`; + html += `-----

`; + } + }) + + const TranscriptSavedEmbed = new Discord.MessageEmbed() + .setDescription(supportbot.TranscriptSavedMessage) + .setColor(supportbot.SuccessColour) + interaction.channel.send({embeds: [TranscriptSavedEmbed]}) + + let file = new Discord.MessageAttachment( Buffer.from( html ), `${name}.html` ) + logChannel.send({embeds: [logEmbed], files: [file]}) + + setTimeout(() => interaction.channel.delete(), supportbot.TicketDeleteTime) + + }) + }) + } + } + if(interaction.customId === 'ticketlock') { + if(interaction.channel.name.startsWith(`${supportbot.TicketChannel}`)) { + interaction.message.fetch() + interaction.deferUpdate() + let Admin = interaction.guild.roles.cache.find(AdminUser => AdminUser.name === supportbot.Admin) || interaction.guild.roles.cache.find(AdminUser => AdminUser.id === supportbot.Admin) + let all = interaction.channel.permissionOverwrites.cache + + let parent = interaction.guild.channels.cache.find(c => c.name === `${supportbot.LockTicketCategory}`) || interaction.guild.channels.cache.find(c => c.id === `${supportbot.LockTicketCategory}`) + if(parent) { + interaction.channel.setParent(parent.id) + } + + all.forEach(perm => { + interaction.channel.permissionOverwrites.delete(perm.id) + + }) + interaction.channel.permissionOverwrites.create(Admin.id, {VIEW_CHANNEL: true}) + + interaction.channel.permissionOverwrites.create(interaction.guild.id, {VIEW_CHANNEL: false}) + + + const ticketDeleteButton = new Discord.MessageButton() + .setCustomId('ticketclose') + .setLabel('Close') + .setStyle(supportbot.TicketDeleteColour) + .setEmoji(supportbot.TicketDeleteEmoji) + + const row = new Discord.MessageActionRow() + .addComponents(ticketDeleteButton) + const ArchiveEmbed = new Discord.MessageEmbed() + .setTitle("Archived") + .setDescription(`Archived ${interaction.channel.name}`) + .setColor(`${supportbot.SuccessColour}`) + + interaction.channel.send({embeds: [ArchiveEmbed]}) + interaction.message.edit({components: [row]}) + } + } + } + if (interaction.user.bot || !interaction.isCommand() || !interaction.guild) return; @@ -20,8 +142,6 @@ module.exports = new Event("interactionCreate", (client, interaction) => { .slashCommandOptions.map(v => `${interaction.options.get(v.name).value}`) ]; - const command = client.commands.find(cmd => cmd.name.toLowerCase() == interaction.commandName); - const NotValid = new Discord.MessageEmbed() .setDescription(`:x: \`Invalid Command\` `) .setColor(supportbot.ErrorColour) diff --git a/events/ready.js b/events/ready.js index 9ff647b..d5af8f0 100644 --- a/events/ready.js +++ b/events/ready.js @@ -6,10 +6,16 @@ const fs = require("fs"); const Discord = require("discord.js"); const yaml = require('js-yaml'); const supportbot = yaml.load(fs.readFileSync('./Data/supportbot.yml', 'utf8')); +const panelconfig = yaml.load(fs.readFileSync('./Data/ticket-panel.yml', 'utf8')); const Event = require("../Structures/Event.js"); module.exports = new Event("ready", client => { + client.user.setActivity(supportbot.BotActivity, { + type: supportbot.ActivityType, + url: supportbot.StreamingURL + }); + console.log(`\u001b[32m`, `┏━━━┓╋╋╋╋╋╋╋╋╋╋╋╋╋┏┓┏━━┓╋╋╋┏┓`) console.log(`\u001b[32m`, `┃┏━┓┃╋╋╋╋╋╋╋╋╋╋╋╋┏┛┗┫┏┓┃╋╋┏┛┗┓`) console.log(`\u001b[32m`, `┃┗━━┳┓┏┳━━┳━━┳━━┳┻┓┏┫┗┛┗┳━┻┓┏┛`) @@ -21,7 +27,8 @@ module.exports = new Event("ready", client => { console.log(` `) console.log(`\u001b[31m`, `――――――――――――――――――――――――――――――――――――――――――――`) console.log(` `) - console.log(`\u001b[33m`, `${supportbot.Bot_Name} v${supportbot.SupportBot_Version}`, `\u001b[36m`, `Connected to Discord`) + console.log(`\u001b[33m`, `${supportbot.Name} v${supportbot.SupportBot_Version}`, `\u001b[36m`, `Connected to Discord`) + console.log(`\u001b[33m`, `Resources:`, `\u001b[36m`, `https://emeraldsrv.dev/resources`) console.log(`\u001b[33m`, `Documentation:`, `\u001b[36m`, `https://supportbot.emeraldsrv.dev`) console.log(`\u001b[33m`, `Discord:`, `\u001b[36m`, `https://emeraldsrv.dev/discord`) console.log(`\u001b[33m`, `Hosting:`, `\u001b[36m`, `https://emeraldsrv.dev/hosting`) @@ -29,4 +36,58 @@ module.exports = new Event("ready", client => { console.log(`\u001b[37m`, `SupportBot proudly created by Emerald Services`) console.log(` `) console.log(`\u001b[31m`, `――――――――――――――――――――――――――――――――――――――――――――`) + + if (panelconfig.TicketPanel) { + let chan1 = client.channels.cache.find(channel => channel.name === panelconfig.Channel) + + if (!chan1) { + console.log('\u001b[33m', "[WARN] Ticket reaction panel is not setup, You can do so via the configuration file!") + return false; + } + + const panelid = yaml.load(fs.readFileSync('./Data/ticket-panel-id.yml', 'utf8')); + + chan1.messages.fetch(panelid.TicketPanelID).catch(async r => { + let embed = new Discord.MessageEmbed() + .setTitle(`${panelconfig.PanelTitle}`) + .setColor(supportbot.SuccessColour) + .setFooter(supportbot.EmbedFooter); + + if (panelconfig.TicketPanel_Description) { + embed.setDescription(panelconfig.PanelMessage) + } + + if (panelconfig.TicketPanel_Thumbnail) { + embed.setThumbnail(panelconfig.PanelThumbnail) + } + + if (panelconfig.TicketPanel_Image) { + embed.setImage(panelconfig.PanelImage) + } + + let button = new Discord.MessageButton() + .setLabel(panelconfig.ButtonLabel) + .setCustomId('openticket') + .setStyle(panelconfig.ButtonColour) + + let row = new Discord.MessageActionRow() + .addComponents(button) + + + await chan1.send({ + embeds: [embed], + components: [row] + }).then(r => { + let data = { + "TicketPanelID": `${r.id}` + } + let yamlStr = yaml.dump(data); + fs.writeFileSync('./Data/ticket-panel-id.yml', yamlStr, 'utf8'); + + }).catch(e => { + console.log("Raw"+e) + }) + }) + } + }); \ No newline at end of file diff --git a/node_modules/.DS_Store b/node_modules/.DS_Store new file mode 100644 index 0000000..96322cd Binary files /dev/null and b/node_modules/.DS_Store differ diff --git a/node_modules/@discordjs/.DS_Store b/node_modules/@discordjs/.DS_Store new file mode 100644 index 0000000..95c68c2 Binary files /dev/null and b/node_modules/@discordjs/.DS_Store differ diff --git a/node_modules/@types/.DS_Store b/node_modules/@types/.DS_Store new file mode 100644 index 0000000..fd5310d Binary files /dev/null and b/node_modules/@types/.DS_Store differ diff --git a/node_modules/discord-api-types/.DS_Store b/node_modules/discord-api-types/.DS_Store new file mode 100644 index 0000000..ecd0812 Binary files /dev/null and b/node_modules/discord-api-types/.DS_Store differ diff --git a/node_modules/discord.js/.DS_Store b/node_modules/discord.js/.DS_Store new file mode 100644 index 0000000..321c7df Binary files /dev/null and b/node_modules/discord.js/.DS_Store differ diff --git a/node_modules/js-yaml/.DS_Store b/node_modules/js-yaml/.DS_Store new file mode 100644 index 0000000..bcd0c6d Binary files /dev/null and b/node_modules/js-yaml/.DS_Store differ diff --git a/node_modules/type-fest/.DS_Store b/node_modules/type-fest/.DS_Store new file mode 100644 index 0000000..7eea95d Binary files /dev/null and b/node_modules/type-fest/.DS_Store differ