Compare commits

..
41 Commits
Author SHA1 Message Date
ItsNyoty ee9742d92b v7.7.3 2023-04-20 21:10:48 +02:00
ItsNyoty ec955d8dc9 Unclaim + Unlock 2023-04-20 21:07:09 +02:00
ItsNyoty bbeea5db3e Update issue templates 2023-04-19 21:59:13 +02:00
ItsNyoty 6e16cec661 Create CONTRIBUTING.md 2023-04-19 21:58:39 +02:00
ItsNyoty 9245157d71 Create SECURITY.md 2023-04-19 21:56:41 +02:00
ItsNyoty 787c9e62c5 Merge pull request #151 from Emerald-Services/add-code-of-conduct-1
Create CODE_OF_CONDUCT.md
2023-04-19 21:55:42 +02:00
ItsNyoty 628601518b Create CODE_OF_CONDUCT.md 2023-04-19 21:55:21 +02:00
ItsNyoty 87f974e00d Create FUNDING.yml 2023-04-19 21:27:23 +02:00
ItsNyoty 20acafbc64 Version update
V7.7.2 Final release
2023-04-19 15:58:03 +02:00
ItsNyoty 6a5406c4a8 Update ready.js
this made me drive crazy in my vscode terminal
2023-04-16 19:13:16 +02:00
1tzEmerald 949d113cff Merge pull request #145 from ItsNyoty/patch-6
TicketClaim
2022-12-17 23:56:28 +00:00
ItsNyoty bd1e59ba54 TicketClaim
Ticket Claim with channel permissions overwrite
2022-12-07 20:36:04 +01:00
1tzEmerald 364338a04e Merge pull request #142 from ItsNyoty/patch-2
Adding ticket claim values in config
2022-11-12 19:14:08 +00:00
1tzEmerald 684dc827a3 Merge pull request #144 from ItsNyoty/patch-4
Adding claim button
2022-11-12 19:13:55 +00:00
ItsNyoty fb97532bf5 Adding claim button 2022-11-12 12:58:02 +01:00
ItsNyoty a05812db10 Adding ticket claim values in config 2022-11-12 12:54:57 +01:00
1tzEmerald 96a50743ac Update supportbot.yml 2022-08-20 23:02:47 +01:00
1tzEmerald 5cd759eb86 Update README.md 2022-08-03 12:00:48 +01:00
1tzEmerald fd263d1f8e Update README.md 2022-07-26 11:37:27 +01:00
Xiled Emerald df5c35642d Update README.md 2022-07-01 22:21:18 +01:00
Xiled Emerald c9d2e471b7 Update README.md 2022-07-01 21:15:22 +01:00
Xiled Emerald d1bd624723 Update README.md 2022-07-01 21:14:46 +01:00
Xiled Emerald 1f2bd9c279 Update README.md 2022-07-01 21:14:30 +01:00
Xiled Emerald ab14b17cc9 Delete .DS_Store 2022-07-01 20:59:25 +01:00
Xiled Emerald e1244f779f Delete .DS_Store 2022-07-01 20:59:18 +01:00
Xiled Emerald d474f04122 Update README.md 2022-07-01 20:56:42 +01:00
Xiled Emerald 24c4cb0dd1 Update README.md 2022-07-01 20:56:25 +01:00
Xiled Emerald d7d765d4b9 Update README.md 2022-07-01 20:54:41 +01:00
Xiled Emerald bc82bf6c55 Delete .DS_Store 2022-06-30 15:50:13 +01:00
Xiled Emerald 213f84f509 Delete package-lock.json 2022-06-30 15:49:58 +01:00
Xiled Emerald 25c6c95ec5 Update README.md 2022-06-30 15:27:23 +01:00
Xiled Emerald 9118bff570 Update README.md 2022-06-30 15:26:24 +01:00
Xiled Emerald 3f3670b4f3 Update README.md 2022-06-30 15:19:21 +01:00
Xiled Emerald d448662072 Update README.md 2022-06-30 15:17:48 +01:00
Xiled Emerald 84fa2c3078 Update README.md 2022-06-30 15:17:37 +01:00
Xiled Emerald da88fe64ba Update README.md 2022-06-30 15:16:57 +01:00
Xiled Emerald d74cd36880 Update README.md 2022-06-30 15:13:26 +01:00
Xiled Emerald b8d1361796 Update README.md 2022-06-30 15:11:39 +01:00
Xiled Emerald b205132d1a Update README.md 2022-06-30 15:10:02 +01:00
Xiled Emerald 77812967de Update README.md 2022-06-29 00:50:43 +01:00
Xiled Emerald 6103fc9f04 Update README.md 2022-06-29 00:41:00 +01:00
36 changed files with 1577 additions and 2083 deletions

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [Emerald-Services]
+38
View File
@@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
+2
View File
@@ -0,0 +1,2 @@
node_modules/
.DS_Store
+45
View File
@@ -0,0 +1,45 @@
// SupportBot | Emerald Services
// Example (default) Addon
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
// Your Addon Config file! Saved in /Addons/Configs/YourAddonConfig.yml
// const config = yaml.load(fs.readFileSync('./Addons/Configs/YourAddonConfig.yml', 'utf8'));
const { Command, Event } = require("../Structures/Addon");
module.exports.commands = [
/*
// EXAMPLE COMMAND
new Command({
name: "hello",
description: "hello",
options: [],
permissions: ["SEND_MESSAGES"],
async run(interaction) {
const Embed = new Discord.MessageEmbed()
.setDescription("Hello World!")
.setColor(supportbot.InfoColour);
interaction.reply({
embeds: [Embed],
});
},
}),
*/
];
module.exports.events = [
/*
// EXAMPLE EVENT
new Event("ready", async (client) => {
console.log("Bot started!");
}),
*/
];
+92
View File
@@ -0,0 +1,92 @@
// SupportBot | Emerald Services
// Ticket Add Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.TicketAdd,
description: cmdconfig.TicketAddDesc,
options: [
{
name: "user",
description: "User to add",
type: "USER",
required: true,
},
],
permissions: ["SEND_MESSAGES"],
async run(interaction) {
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Staff, interaction.guild);
let Admin = await getRole(supportbot.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(
`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``
)
.setColor(supportbot.WarningColour);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
)
return interaction.reply({ ephemeral: true, embeds: [NoPerms] });
let TicketData = await JSON.parse(
fs.readFileSync("./Data/TicketData.json", "utf8")
);
let ticket = await TicketData.tickets.findIndex(
(t) => t.id === interaction.channel.id
);
if (ticket === -1) {
const Exists = new Discord.MessageEmbed()
.setTitle("No Ticket Found!")
.setDescription(supportbot.NoValidTicket)
.setColor(supportbot.WarningColour);
return interaction.reply({ ephemeral: true, embeds: [Exists] });
}
let uMember = interaction.options.getUser("user");
const UserNotExist = new Discord.MessageEmbed()
.setTitle("User Not Found!")
.setDescription(
`${supportbot.UserNotFound}\n\nTry Again:\`/${cmdconfig.TicketAdd} <user#0000>\``
)
.setColor(supportbot.ErrorColour);
if (!uMember) return interaction.reply({ embeds: [UserNotExist] });
await interaction.channel.permissionOverwrites.edit(uMember.id, {
VIEW_CHANNEL: true,
});
const Complete = new Discord.MessageEmbed()
.setTitle("User Added!")
.setDescription(supportbot.AddedUser.replace(/%user%/g, uMember.id))
.setTimestamp()
.setColor(supportbot.EmbedColour);
interaction.reply({ embeds: [Complete] });
TicketData.tickets[ticket].subUsers.push(uMember.id);
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(TicketData, null, 4),
(err) => {
if (err) console.error(err);
}
);
},
});
+140 -276
View File
@@ -1,50 +1,44 @@
// SupportBot | Emerald Services
// Close Ticket Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.CloseTicket.Command,
description: cmdconfig.CloseTicket.Description,
type: Discord.ApplicationCommandType.ChatInput,
name: cmdconfig.CloseTicket,
description: cmdconfig.CloseTicketDesc,
options: [
{
name: "reason",
description: "Ticket Close Reason",
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
},
],
permissions: cmdconfig.CloseTicket.Permission,
permissions: ["SEND_MESSAGES"],
async run(interaction) {
const { getRole, getChannel } = interaction.client;
if (supportbot.Ticket.Close.StaffOnly) {
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (supportbot.StaffOnly) {
let SupportStaff = await getRole(supportbot.Staff, interaction.guild);
let Admin = await getRole(supportbot.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new Discord.EmbedBuilder()
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
.setColor(supportbot.WarningColour);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
@@ -52,240 +46,136 @@ module.exports = new Command({
)
return interaction.reply({ embeds: [NoPerms] });
}
if (interaction.channel.type !== Discord.ChannelType.PrivateThread) {
const NotTicketChannel = new Discord.EmbedBuilder()
.setTitle("Invalid Channel!")
.setDescription("This command can only be used in a ticket thread.")
.setColor(supportbot.Embed.Colours.Warn);
return interaction.reply({ embeds: [NotTicketChannel], ephemeral: true });
}
await interaction.deferReply();
let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
let TicketData = tickets.tickets.findIndex((t) => t.id === interaction.channel.id);
let tickets = await JSON.parse(
fs.readFileSync("./Data/TicketData.json", "utf8")
);
let TicketData = await tickets.tickets.findIndex(
(t) => t.id === interaction.channel.id
);
let ticket = tickets.tickets[TicketData];
if (TicketData === -1) {
const Exists = new Discord.EmbedBuilder()
const Exists = new Discord.MessageEmbed()
.setTitle("No Ticket Found!")
.setDescription(msgconfig.Error.NoValidTicket)
.setColor(supportbot.Embed.Colours.Warn);
.setDescription(supportbot.NoValidTicket)
.setColor(supportbot.WarningColour);
return interaction.followUp({ embeds: [Exists] });
}
let reason = interaction.options?.getString("reason") || "No Reason Provided.";
const CloseButton = new Discord.ButtonBuilder()
.setCustomId("confirmCloseTicket")
.setLabel(supportbot.Ticket.Close.Confirmation_Button)
.setStyle(Discord.ButtonStyle.Danger);
const row = new Discord.ActionRowBuilder().addComponents(CloseButton);
const CloseTicketRequest = new Discord.EmbedBuilder()
.setTitle(`**${supportbot.Ticket.Close.Title}**`)
.setDescription(
`${msgconfig.Ticket.ConfirmClose}`
)
.setColor(supportbot.Embed.Colours.General);
await interaction.followUp({
embeds: [CloseTicketRequest],
components: [row],
});
const filter = (btnInteraction) => btnInteraction.customId === "confirmCloseTicket" && btnInteraction.user.id === interaction.user.id;
interaction.channel.awaitMessageComponent({ filter, time: 20000 })
.then(async (btnInteraction) => {
await handleCloseTicket(interaction, reason, ticket, TicketData);
await btnInteraction.reply({ content: "Ticket successfully closed.", ephemeral: true });
})
.catch((err) => {
interaction.followUp(`${msgconfig.Ticket.CloseTimeout}`);
console.error(err);
});
},
});
async function handleCloseTicket(interaction, reason, ticket, TicketData) {
const { getChannel } = interaction.client;
let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
let tUser = interaction.client.users.cache.get(ticket.user);
let transcriptChannel = await getChannel(supportbot.Ticket.Log.TranscriptLog, interaction.guild);
let logChannel = await getChannel(supportbot.Ticket.Log.TicketLog, interaction.guild);
if (!transcriptChannel || !logChannel)
return interaction.followUp("Some Channels seem to be missing!");
try {
tickets.tickets[TicketData].open = false;
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(tickets, null, 4),
(err) => {
if (err) console.error(err);
}
let tUser = interaction.client.users.cache.get(ticket.user);
let transcriptChannel = await getChannel(
supportbot.TranscriptLog,
interaction.guild
);
let logChannel = await getChannel(supportbot.TicketLog, interaction.guild);
let reason =
(await interaction.options?.getString("reason")) || "No Reason Provided.";
const transcriptEmbed = new Discord.EmbedBuilder()
.setTitle(supportbot.Ticket.Log.TranscriptTitle)
.setColor(supportbot.Embed.Colours.General)
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
})
.addFields(
{ name: "Ticket", value: `${interaction.channel.name} (${interaction.channel.id})` },
{ name: "User", value: `${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${tUser?.id || ticket.user})` },
{ name: "Closed By", value: interaction.user.tag },
{ name: "Reason", value: reason }
);
const logEmbed = new Discord.EmbedBuilder()
.setTitle(supportbot.Ticket.Log.TicketLog_Title)
.setColor(supportbot.Embed.Colours.General)
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
})
.addFields(
{ name: "Ticket", value: `${interaction.channel.name} (${interaction.channel.id})` },
{ name: "User", value: `${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${tUser?.id || ticket.user})` },
{ name: "Closed By", value: interaction.user.tag },
{ name: "Reason", value: reason }
);
let msgs = await interaction.channel.messages.fetch({ limit: 100 });
let html = `
<html>
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
<style>
body {
background-color: #1a1a1a;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
margin: 0;
padding: 0;
height: 100%;
display: flex;
flex-direction: column;
}
.container {
backdrop-filter: blur(10px);
background-color: rgba(0, 128, 0, 0.3);
border-radius: 15px;
padding: 20px;
margin: 20px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
flex-grow: 1;
display: flex;
flex-direction: column;
max-width: 1000px;
width: 100%;
margin: auto;
}
.message {
display: flex;
align-items: center;
margin-bottom: 10px;
padding: 10px;
background-color: rgba(255, 255, 255, 0.1);
border-radius: 10px;
}
.avatar {
width: 40px;
height: 40px;
border-radius: 50%;
margin-right: 10px;
}
.content {
flex: 1;
}
.username {
font-weight: bold;
}
.timestamp {
font-size: 0.8em;
color: #bbb;
}
.download-button {
background-color: #4CAF50;
color: white;
padding: 10px 20px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
margin-top: 20px;
border-radius: 5px;
}
</style>
</head>
<body>
<div class="container">
<h1 class="text-2xl font-bold mb-4">Ticket Transcript</h1>
<p><strong>Server Name:</strong> ${interaction.guild.name}</p>
<p><strong>Ticket:</strong> ${interaction.channel.name}</p>
<p><strong>Messages:</strong> ${msgs.size} Messages</p>
<div class="mt-4">
`;
msgs = msgs.sort((a, b) => a.createdTimestamp - b.createdTimestamp);
msgs.forEach((msg) => {
if (msg.content) {
html += `
<div class="message">
<img class="avatar" src="${msg.author.displayAvatarURL()}" alt="Avatar">
<div class="content">
<p class="username">${msg.author.tag}</p>
<p class="timestamp">${msg.createdAt.toLocaleString()}</p>
<p>${convertMarkdownToHTML(msg.content)}</p>
</div>
</div>
`;
}
});
const fileName = `${interaction.channel.name}.html`;
html += `
</div>
<a href="${fileName}" download class="download-button">Download Transcript</a>
</div>
</body>
</html>
`;
if (!supportbot.Ticket.Log.DisableTicketLogChannel) {
await logChannel.send({ embeds: [logEmbed] }).catch((err) => {
console.error(err);
if (!transcriptChannel || !logChannel)
return interaction.followUp("Some Channels seem to be missing!");
if (supportbot.CloseConfirmation) {
const CloseTicketRequest = new Discord.MessageEmbed()
.setTitle(`**${supportbot.ClosingTicket}**`)
.setDescription(
`Please confirm by repeating the following word.. \`${supportbot.ClosingConfirmation_Word}\` `
)
.setColor(supportbot.EmbedColour);
await interaction.followUp({ embeds: [CloseTicketRequest] });
let filter = (m) =>
m.content.toLowerCase() === supportbot.ClosingConfirmation_Word &&
m.author.id === interaction.user.id;
await interaction.channel.awaitMessages({
filter,
max: 1,
time: 20000,
errors: ["time"],
});
}
try {
tickets.tickets[TicketData].open = false;
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(tickets, null, 4),
(err) => {
if (err) console.error(err);
}
);
await interaction.followUp(`**${supportbot.ClosingTicket}**`);
const transcriptEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.TranscriptTitle)
.setColor(supportbot.EmbedColour)
.setFooter({
text: supportbot.EmbedFooter,
iconURL: interaction.user.displayAvatarURL(),
})
.addField(
"Ticket",
`${interaction.channel.name} (${interaction.channel.id})`
)
.addField(
"User",
`${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${
tUser?.id || ticket.user
})`
)
.addField("Closed By", interaction.user.tag)
.addField("Reason", reason);
const logEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.TicketLog_Title)
.setColor(supportbot.EmbedColour)
.setFooter({
text: supportbot.EmbedFooter,
iconURL: interaction.user.displayAvatarURL(),
})
.addField(
"Ticket",
`${interaction.channel.name} (${interaction.channel.id})`
)
.addField(
"User",
`${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${
tUser?.id || ticket.user
})`
)
.addField("Closed By", interaction.user.tag)
.addField("Reason", reason);
let msgs = await interaction.channel.messages.fetch({ limit: 100 });
let html = "";
let file = new Discord.AttachmentBuilder(
Buffer.from(html),
{ name: fileName }
);
msgs = msgs.sort((a, b) => a.createdTimestamp - b.createdTimestamp);
html += `<style>* {background-color: #2c2f33;color: #fff;font-family: Arial, Helvetica, sans-serif;}</style>`;
html += `<strong>Server Name:</strong> ${interaction.guild.name}<br>`;
html += `<strong>Ticket:</strong> ${interaction.channel.name}<br>`;
html += `<strong>Message:</strong> ${msgs.size} Messages<br><br><br>`;
await transcriptChannel
.send({ embeds: [transcriptEmbed], files: [file] })
.catch((err) => {
console.error(err);
await msgs.forEach((msg) => {
if (msg.content) {
html += `<strong>User:</strong> ${msg.author.tag}<br>`;
html += `<strong>Message:</strong> ${msg.content}<br>`;
html += `-----<br><br>`;
}
});
if (supportbot.Ticket.DMTranscripts) {
await tUser
?.send({ embeds: [transcriptEmbed], files: [file] })
.catch((err) => {
if (!(supportbot.DisableTicketLogChannel)) {
await logChannel.send({ embeds: [logEmbed] }).catch((err) => {
console.error(err);
});
}
let file = new Discord.MessageAttachment(
Buffer.from(html),
`${interaction.channel.name}.html`
);
await transcriptChannel
.send({ embeds: [transcriptEmbed], files: [file] })
.catch(async (err) => {
console.error(err);
});
if (supportbot.DMTranscripts) {
await tUser
?.send({ embeds: [transcriptEmbed], files: [file] })
.catch(async (err) => {
console.error(err);
});
if (ticket.subUsers) {
ticket.subUsers.forEach(async (subUser) => {
await interaction.client.users.cache
@@ -293,43 +183,17 @@ async function handleCloseTicket(interaction, reason, ticket, TicketData) {
?.send({ embeds: [transcriptEmbed], files: [file] });
});
}
}
await interaction.channel.delete().catch((error) => {
console.error(error);
if (error.code !== Discord.Constants.APIErrors.UNKNOWN_CHANNEL) {
console.error("Failed to delete the interaction:", error);
}
});
} catch (error) {
console.error(error);
}
}
function convertMarkdownToHTML(text) {
// Convert **bold** to <strong>bold</strong>
text = text.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
// Convert *italic* to <em>italic</em>
text = text.replace(/\*(.*?)\*/g, '<em>$1</em>');
// Convert __underline__ to <u>underline</u>
text = text.replace(/__(.*?)__/g, '<u>$1</u>');
// Convert ~~strikethrough~~ to <s>strikethrough</s>
text = text.replace(/~~(.*?)~~/g, '<s>$1</s>');
// Convert inline code `code` to <code>code</code>
text = text.replace(/`(.*?)`/g, '<code>$1</code>');
// Convert blockquotes > quote to <blockquote>quote</blockquote>
text = text.replace(/^> (.*?$)/gm, '<blockquote>$1</blockquote>');
// Convert multiline code blocks ```code``` to <pre><code>code</code></pre>
text = text.replace(/```(.*?)```/gs, '<pre><code>$1</code></pre>');
// Convert line breaks to <br>
text = text.replace(/\n/g, '<br>');
return text;
}
await interaction.channel.delete().catch(async (error) => {
console.error(error);
if (error.code !== Discord.Constants.APIErrors.UNKNOWN_CHANNEL) {
console.error("Failed to delete the interaction:", error);
}
});
} catch (error) {
console.error(error);
}
},
});
+43 -103
View File
@@ -1,161 +1,101 @@
// File path: ./commands/embed.js
// SupportBot | Emerald Services
// Embed Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Embed.Command,
description: cmdconfig.Embed.Description,
type: Discord.ApplicationCommandType.ChatInput,
name: cmdconfig.EmbedCommand,
description: cmdconfig.EmbedCommandDesc,
options: [
{
name: "title",
description: "Embed Title",
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
required: true,
},
{
name: "message",
description: "Embed Message",
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
required: true,
},
{
name: "color",
description: "Embed HEX Color",
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
required: false,
},
{
name: "fields",
description: "Embed Fields (title|content;title|content;...)",
type: Discord.ApplicationCommandOptionType.String,
name: "fieldtitle",
description: "Add an additional Embed Field",
type: "STRING",
required: false,
},
{
name: "fieldcontent",
description: "Add an additional Embed Field",
type: "STRING",
required: false,
},
{
name: "thumbnail",
description: "Embed Thumbnail URL",
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
required: false,
},
{
name: "image",
description: "Embed Image URL",
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
required: false,
},
{
name: "footer",
description: "Embed Footer Text",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "footericon",
description: "Embed Footer Icon URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "author",
description: "Embed Author Name",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "authoricon",
description: "Embed Author Icon URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "authorurl",
description: "Embed Author URL",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "timestamp",
description: "Include Timestamp",
type: Discord.ApplicationCommandOptionType.Boolean,
required: false,
},
{
name: "inline",
description: "Make Fields Inline",
type: Discord.ApplicationCommandOptionType.Boolean,
required: false,
}
],
permissions: cmdconfig.Embed.Permission,
permissions: ["SEND_MESSAGES"],
async run(interaction) {
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
let SupportStaff = await getRole(supportbot.Staff, interaction.guild);
let Admin = await getRole(supportbot.Admin, interaction.guild);
if (!SupportStaff || !Admin) {
return interaction.reply("Some roles seem to be missing!\nPlease check for errors when starting the bot.");
}
const NoPerms = new Discord.EmbedBuilder()
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``)
.setColor(supportbot.Embed.Colours.Warn);
.setDescription(
`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``
)
.setColor(supportbot.WarningColour);
if (
interaction.member.roles.cache.has(SupportStaff.id) ||
interaction.member.roles.cache.has(Admin.id)
) {
const EmbedTitle = interaction.options.getString("title").replace(/\\n/g, '\n');
const EmbedSubject = interaction.options.getString("message").replace(/\\n/g, '\n');
const GeneralColour = interaction.options.getString("color") || supportbot.Embed.Colours.Default;
const EmbedTitle = interaction.options.getString("title");
const EmbedSubject = interaction.options.getString("message");
const EmbedColour = interaction.options.getString("color");
const EmbedThumbnail = interaction.options.getString("thumbnail");
const EmbedImage = interaction.options.getString("image");
const EmbedFields = interaction.options.getString("fields");
const EmbedFooter = interaction.options.getString("footer")?.replace(/\\n/g, '\n');
const EmbedFooterIcon = interaction.options.getString("footericon");
const EmbedAuthor = interaction.options.getString("author")?.replace(/\\n/g, '\n');
const EmbedAuthorIcon = interaction.options.getString("authoricon");
const EmbedAuthorURL = interaction.options.getString("authorurl");
const EmbedTimestamp = interaction.options.getBoolean("timestamp");
const InlineFields = interaction.options.getBoolean("inline");
const EmbedFieldContent = interaction.options.getString("fieldcontent");
const EmbedFieldTitle = interaction.options.getString("fieldtitle");
const EmbedMsg = new Discord.EmbedBuilder()
const EmbedMsg = new Discord.MessageEmbed()
.setTitle(EmbedTitle)
.setDescription(EmbedSubject)
.setColor(GeneralColour)
.setColor(EmbedColour)
.setThumbnail(EmbedThumbnail)
.setImage(EmbedImage);
if (EmbedFields) {
const fieldsArray = EmbedFields.split(';');
fieldsArray.forEach(field => {
const [title, value] = field.split('|');
if (title && value) {
EmbedMsg.addFields({ name: title.replace(/\\n/g, '\n'), value: value.replace(/\\n/g, '\n'), inline: InlineFields || false });
}
});
}
if (EmbedFooter) {
EmbedMsg.setFooter({ text: EmbedFooter, iconURL: EmbedFooterIcon });
}
if (EmbedAuthor) {
EmbedMsg.setAuthor({ name: EmbedAuthor, iconURL: EmbedAuthorIcon, url: EmbedAuthorURL });
}
if (EmbedTimestamp) {
EmbedMsg.setTimestamp();
}
.setImage(EmbedImage)
if (EmbedFieldTitle && EmbedFieldContent) { EmbedMsg.addField(EmbedFieldTitle, EmbedFieldContent) };
interaction.reply({
embeds: [EmbedMsg],
+56 -40
View File
@@ -2,72 +2,88 @@
// Help Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Help.Command,
description: cmdconfig.Help.Description,
type: Discord.ApplicationCommandType.ChatInput,
name: cmdconfig.HelpCommand,
description: cmdconfig.HelpCommandDesc,
options: [],
permissions: cmdconfig.Help.Permission,
permissions: ["SEND_MESSAGES"],
async run(interaction) {
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin) {
let SupportStaff = await getRole(supportbot.Staff, interaction.guild);
let Admin = await getRole(supportbot.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
}
// Fetch all commands from the client's commands collection
let botCommands = "";
interaction.client.commands.forEach((command) => {
if (command.permissions) {
botCommands += `\`${command.name}\` `;
}
});
botCommands += `**/${cmdconfig.HelpCommand}** ${cmdconfig.HelpCommandDesc}\n`;
botCommands += `**/${cmdconfig.InfoCommand}** ${cmdconfig.InfoCommandDesc}\n`;
botCommands += `**/${cmdconfig.PingCommand}** ${cmdconfig.PingCommandDesc}\n`;
botCommands += `**/${cmdconfig.UserInfoCommand}** ${cmdconfig.UserInfoCommandDesc}\n`;
// Create embed
const HelpEmbed1 = new Discord.EmbedBuilder()
.setTitle(supportbot.General.Name + " Commands")
if (supportbot.DisableSuggestions === false) {
botCommands += `**/${cmdconfig.SuggestCommand}** ${cmdconfig.SuggestCommandDesc}\n`;
}
let ticketCommands = "";
ticketCommands += `**/${cmdconfig.OpenTicket}** ${cmdconfig.OpenTicketDesc}\n`;
ticketCommands += `**/${cmdconfig.CloseTicket}** ${cmdconfig.CloseTicketDesc}\n`;
let staffCommands = "";
staffCommands += `**/${cmdconfig.TicketAdd}** ${cmdconfig.TicketAddDesc}\n`;
staffCommands += `**/${cmdconfig.TicketRemove}** ${cmdconfig.TicketRemoveDesc}\n`;
staffCommands += `**/${cmdconfig.UserInfoCommand}** ${cmdconfig.UserInfoCommandDesc}\n`;
staffCommands += `**/${cmdconfig.TranslateCommand}** ${cmdconfig.TranslateCommandDesc}\n`;
const HelpEmbed1 = new Discord.MessageEmbed()
.setTitle(supportbot.Name + " Commands")
.setThumbnail(interaction.user.displayAvatarURL())
.setColor(supportbot.Embed.Colours.General)
.addFields({
name: "🖥️ Commands\n",
value: botCommands || "No commands available.",
inline: false,
.addFields(
{
name: "🖥️ General Commands\n",
value: `${botCommands}\n`,
inline: false,
},
{
name: "🎫 Support Commands\n",
value: `${ticketCommands}\n`,
inline: false,
}
)
.setColor(supportbot.EmbedColour)
.setFooter({
text: supportbot.EmbedFooter,
iconURL: interaction.user.displayAvatarURL(),
});
// Conditionally add Addons section
if (supportbot.General.Addons.Enabled) {
if (
interaction.member.roles.cache.has(SupportStaff.id) ||
interaction.member.roles.cache.has(Admin.id)
) {
HelpEmbed1.addFields({
name: "🛠️ Addons\n",
value: "No addons available.",
name: "🔐 Staff Commands\n",
value: `${staffCommands}\n`,
inline: false,
});
}
HelpEmbed1.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
});
interaction.reply({
ephemeral: true,
embeds: [HelpEmbed1],
});
interaction.reply({
ephemeral: true,
embeds: [HelpEmbed1],
});
},
});
+19 -30
View File
@@ -5,47 +5,36 @@ const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Info.Command,
description: cmdconfig.Info.Description,
name: cmdconfig.InfoCommand,
description: cmdconfig.InfoCommandDesc,
options: [],
permissions: cmdconfig.Info.Permission,
permissions: ["SEND_MESSAGES"],
async run(interaction) {
let disableCommand = true;
const InfoButton = new Discord.MessageButton()
.setLabel(supportbot.InfoButtonText)
.setURL(supportbot.InfoURL)
.setStyle("LINK");
const InfoButton = new Discord.ButtonBuilder()
.setLabel(msgconfig.Info.Button)
.setURL(msgconfig.Info.URL)
.setStyle("Link");
const inforow = new Discord.MessageActionRow().addComponents(InfoButton);
const inforow = new Discord.ActionRowBuilder().addComponents(InfoButton);
const InfoEmbed = new Discord.EmbedBuilder()
.setURL(msgconfig.Info.URL)
.setTitle(msgconfig.Info.Title)
.setDescription(msgconfig.Info.Description)
.setColor(msgconfig.Info.Colour)
interaction.reply({
embeds: [InfoEmbed],
components: [inforow],
});
const InfoEmbed = new Discord.MessageEmbed()
.setURL(supportbot.InfoURL)
.setTitle(supportbot.InfoTitle)
.setDescription(supportbot.AboutMe)
.setColor(supportbot.InfoColour);
interaction.reply({
embeds: [InfoEmbed],
components: [inforow],
});
},
});
});
+5 -7
View File
@@ -13,19 +13,17 @@ const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.Ping.Command,
description: cmdconfig.Ping.Description,
name: cmdconfig.PingCommand,
description: cmdconfig.PingCommandDesc,
options: [],
permissions: cmdconfig.Ping.Permission,
permissions: ["SEND_MESSAGES"],
async run(interaction) {
let disableCommand = true;
const PingEmbed = new Discord.EmbedBuilder()
const PingEmbed = new Discord.MessageEmbed()
.setDescription(
`:ping_pong: **Ping:** \`${interaction.client.ws.ping} ms\``
)
.setColor(supportbot.Embed.Colours.General);
.setColor(supportbot.EmbedColour);
interaction.reply({
embeds: [PingEmbed],
+94
View File
@@ -0,0 +1,94 @@
// SupportBot | Emerald Services
// Ticket Remove Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.TicketRemove,
description: cmdconfig.TicketRemoveDesc,
options: [
{
name: "user",
description: "User to remove",
type: "USER",
required: true,
},
],
permissions: ["SEND_MESSAGES"],
async run(interaction) {
const { getRole } = interaction.client;
let Staff = await getRole(supportbot.Staff, interaction.guild);
let Admin = await getRole(supportbot.Admin, interaction.guild);
if (!Staff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(
`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``
)
.setColor(supportbot.WarningColour);
if (
!interaction.member.roles.cache.has(Staff.id) &&
!interaction.member.roles.cache.has(Admin.id)
)
return interaction.reply({ embeds: [NoPerms] });
let TicketData = await JSON.parse(
fs.readFileSync("./Data/TicketData.json", "utf8")
);
let ticket = await TicketData.tickets.findIndex(
(t) => t.id === interaction.channel.id
);
if (ticket === -1) {
const Exists = new Discord.MessageEmbed()
.setTitle("No Ticket Found!")
.setDescription(supportbot.NoValidTicket)
.setColor(supportbot.WarningColour);
return interaction.reply({ ephemeral: true, embeds: [Exists] });
}
let uMember = interaction.options.getUser("user");
const UserNotExist = new Discord.MessageEmbed()
.setTitle("User Not Found!")
.setDescription(
`${supportbot.UserNotFound}\n\nTry Again:\`/${cmdconfig.TicketRemove} <user#0000>\``
)
.setColor(supportbot.ErrorColour);
if (!uMember) return interaction.reply({ ephemeral: true, embeds: [UserNotExist] });
await interaction.channel.permissionOverwrites.edit(uMember.id, {
VIEW_CHANNEL: false,
});
const Complete = new Discord.MessageEmbed()
.setTitle("User Removed!")
.setDescription(supportbot.RemovedUser.replace(/%user%/g, uMember.id))
.setTimestamp()
.setColor(supportbot.EmbedColour);
interaction.reply({ embeds: [Complete] });
TicketData.tickets[ticket].subUsers = TicketData.tickets[
ticket
].subUsers.filter((u) => u !== uMember.id);
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(TicketData, null, 4),
(err) => {
if (err) console.error(err);
}
);
},
});
+42 -73
View File
@@ -1,115 +1,84 @@
// SupportBot | Emerald Services
// Suggest Command
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
// Load configurations
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
// Ensure suggestions file exists and is correctly loaded
let suggestions;
try {
suggestions = require("../Data/SuggestionData.json");
} catch (error) {
suggestions = {};
}
module.exports = new Command({
name: cmdconfig.Suggestion.Command,
description: cmdconfig.Suggestion.Description,
type: Discord.ApplicationCommandType.ChatInput,
name: cmdconfig.SuggestCommand,
description: cmdconfig.SuggestCommandDesc,
options: [
{
name: "suggestion",
description: "Create a Suggestion",
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
required: true,
},
],
permissions: cmdconfig.Suggestion.Permission,
permissions: ["SEND_MESSAGES"],
async run(interaction) {
const { getChannel } = interaction.client;
const suggestChannel = await getChannel(
supportbot.Suggestions.Channel,
supportbot.SuggestionChannel,
interaction.guild
);
const NoChannel = new Discord.EmbedBuilder()
const NoChannel = new Discord.MessageEmbed()
.setTitle("Missing Channel!")
.setDescription(msgconfig.Error.InvalidChannel)
.setColor(supportbot.Embed.Colours.Error);
.setDescription(supportbot.InvalidChannel)
.setColor(supportbot.ErrorColour);
if (!suggestChannel) return interaction.reply({ embeds: [NoChannel] });
let suggestion = interaction.options.getString("suggestion");
const SuggestEmbed = new Discord.EmbedBuilder()
.addFields(
{ name: "Suggestion", value: suggestion, inline: true },
{ name: "From", value: `<@${interaction.user.id}>` },
{ name: `${supportbot.Suggestions.UpvoteEmoji} ${supportbot.Suggestions.UpvoteTitle}`, value: "0", inline: true },
{ name: `${supportbot.Suggestions.DownvoteEmoji} ${supportbot.Suggestions.DownvoteTitle}`, value: "0", inline: true }
)
const SuggestEmbed = new Discord.MessageEmbed()
.addField("Suggestion", suggestion, true)
.addField("From", `<@${interaction.user.id}>`)
.setThumbnail(interaction.user.displayAvatarURL())
.setFooter({
text: supportbot.Embed.Footer,
text: supportbot.EmbedFooter,
iconURL: interaction.user.displayAvatarURL(),
})
.setColor(supportbot.Embed.Colours.General);
.setColor(supportbot.EmbedColour);
const UpvoteButton = new Discord.ButtonBuilder()
.setCustomId("upvote")
.setEmoji(supportbot.Suggestions.UpvoteEmoji)
.setStyle(supportbot.Suggestions.Buttons.Upvote);
const suggestionMsg = await suggestChannel.send({ embeds: [SuggestEmbed] });
if (supportbot.SuggestionUpvote && supportbot.SuggestionDownvote) {
await suggestionMsg.react(supportbot.SuggestionUpvote);
await suggestionMsg.react(supportbot.SuggestionDownvote);
const DownvoteButton = new Discord.ButtonBuilder()
.setCustomId("downvote")
.setEmoji(supportbot.Suggestions.DownvoteEmoji)
.setStyle(supportbot.Suggestions.Buttons.Downvote);
const RemoveVoteButton = new Discord.ButtonBuilder()
.setCustomId("removevote")
.setLabel(supportbot.Suggestions.Buttons.RemoveVote_Title)
.setStyle(supportbot.Suggestions.Buttons.RemoveVote); // Red button
const row = new Discord.ActionRowBuilder().addComponents(UpvoteButton, DownvoteButton, RemoveVoteButton);
const suggestionMsg = await suggestChannel.send({ embeds: [SuggestEmbed], components: [row] });
suggestions[suggestionMsg.id] = {
suggestion: suggestion,
author: interaction.user.id,
upvotes: [],
downvotes: []
};
fs.writeFileSync("./Data/SuggestionData.json", JSON.stringify(suggestions, null, 2));
if (supportbot.Suggestions.Threads.Enabled) {
await suggestionMsg.startThread({
name: supportbot.Suggestions.Threads.Title,
autoArchiveDuration: 60,
type: Discord.ChannelType.PublicThread,
reason: supportbot.Suggestions.Threads.Reason,
});
if (supportbot.SuggestionThreads) {
await suggestionMsg.startThread({
name: `Suggestion-releated Thread`,
autoArchiveDuration: 60,
type: 'GUILD_PUBLIC_THREAD',
reason: 'Suggestion-releated thread',
})
}
}
const Submitted = new Discord.EmbedBuilder()
.setTitle(`${msgconfig.Suggestions.Sent_Title}`)
.setDescription(`${msgconfig.Suggestions.Sent}`)
.addFields(
{ name: "Sent to:", value: `<#${suggestChannel.id}>` },
const Submitted = new Discord.MessageEmbed()
.setTitle("Suggestion Submitted!")
.setDescription(
`:white_check_mark: You have successfully submitted a suggestion.`
)
.setColor(supportbot.Embed.Colours.Success);
.addField("Sent to:", `<#${suggestChannel.id}>`)
.setColor(supportbot.SuccessColour);
await interaction.reply({
return interaction.reply({
ephemeral: true,
embeds: [Submitted]
});
})
},
});
+200 -174
View File
@@ -1,84 +1,91 @@
// SupportBot | Emerald Services
// Ticket Command
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
ChannelType,
ActionRowBuilder,
ButtonBuilder,
StringSelectMenuBuilder,
StringSelectMenuOptionBuilder,
GuildMemberRoleManager,
MessageEmbed,
Permissions,
MessageButton,
MessageActionRow,
} = require("discord.js");
const yaml = require("js-yaml");
const panelconfig = yaml.load(fs.readFileSync("./Configs/ticket-panel.yml", "utf8"));
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
const TicketNumberID = require("../Structures/TicketID.js");
module.exports = new Command({
name: cmdconfig.OpenTicket.Command,
description: cmdconfig.OpenTicket.Description,
type: ApplicationCommandType.ChatInput,
name: cmdconfig.OpenTicket,
description: cmdconfig.OpenTicketDesc,
options: [
{
name: "reason",
description: "Ticket Reason",
type: ApplicationCommandOptionType.String,
type: "STRING",
},
],
permissions: cmdconfig.OpenTicket.Permission,
permissions: ["SEND_MESSAGES"],
async run(interaction) {
let disableCommand = true;
if (interaction.isCommand() && disableCommand)
return interaction.reply({
content: "This command is disabled",
ephemeral: true,
});
let department = interaction.customId?.split("-")[1] || null;
let TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const { getRole, getChannel } = interaction.client;
let TicketData = await JSON.parse(
fs.readFileSync("./Data/TicketData.json", "utf8")
);
const { getRole, getCategory } = interaction.client;
let User = interaction.guild.members.cache.get(interaction.user.id);
if (
supportbot.Ticket.TicketsPerUser &&
TicketData.tickets.filter((t) => t.user === interaction.user.id && t.open).length >= supportbot.Ticket.TicketsPerUser
supportbot.MaxAllowedTickets &&
TicketData.tickets.filter((t) => t.user === interaction.user.id && t.open)
.length >= supportbot.MaxAllowedTickets
) {
return interaction.reply({
embeds: [
{
title: "Too Many Tickets!",
description: `You can't have more than ${supportbot.Ticket.TicketsPerUser} open tickets!`,
color: supportbot.Embed.Colours.Warn,
description: `You can't have more than ${supportbot.MaxAllowedTickets} open tickets!`,
color: supportbot.WarningColour,
},
],
ephemeral: true,
});
}
if (User.roles.cache.has(supportbot.Roles.ModRoles.Blacklisted)) {
if (
User.roles.cache.has(
getRole(supportbot.TicketBlackListRole, interaction.guild).id
)
) {
return interaction.reply({
content: msgconfig.Ticket.Blacklisted,
ephemeral: true,
});
}
if (User.roles.cache.has(supportbot.Roles.ModRoles.Muted)) {
return interaction.reply({
content: msgconfig.Ticket.Muted,
content: supportbot.TicketBlackListMessage,
ephemeral: true,
});
}
// Ticket ID
let ticketNumberID = await TicketNumberID.pad();
const TicketSubject = interaction.options?.getString("reason") || msgconfig.Ticket.InvalidSubject;
const TicketExists = new EmbedBuilder()
// Ticket Subject
const TicketSubject =
interaction.options?.getString("reason") || supportbot.NoTicketSubject;
const TicketExists = new MessageEmbed()
.setTitle("Ticket Exists!")
.setDescription(msgconfig.Ticket.TicketExists);
.setDescription(supportbot.TicketExists);
if (
await interaction.guild.channels.cache.find(
(ticketChannel) => ticketChannel.name === `${supportbot.Ticket.Channel}${ticketNumberID}`
(ticketChannel) =>
ticketChannel.name === `${supportbot.TicketPrefix}${ticketNumberID}`
)
) {
return await interaction.reply({
@@ -86,80 +93,50 @@ module.exports = new Command({
ephemeral: true,
});
}
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
const Staff = await getRole(supportbot.Staff, interaction.guild);
const Admin = await getRole(supportbot.Admin, interaction.guild);
if (!Staff || !Admin)
return interaction.reply({
content: "Some roles seem to be missing!\nPlease check for errors when starting the bot.",
content:
"Some roles seem to be missing!\nPlease check for errors when starting the bot.",
ephemeral: true,
});
const TicketCategory = interaction.guild.channels.cache.find(
(c) => c.name === supportbot.Ticket.TicketCategory || c.id === supportbot.Ticket.TicketCategory
let TicketCategory = await getCategory(
supportbot.Departments[department].category,
interaction.guild
);
const channel = await getChannel(supportbot.Ticket.TicketCategory, interaction.guild);
const ticketChannel = await channel.threads.create({
name: `${supportbot.Ticket.Channel}${ticketNumberID}`,
type: ChannelType.PrivateThread,
parent: TicketCategory,
autoArchiveDuration: 60,
reason: 'support ticket',
});
if (supportbot.Ticket.ClaimTickets.Enabled === false) {
const InvStaff = await ticketChannel.send(`<@&${Staff.id}> <@&${Admin.id}>`)
setTimeout(() => {
InvStaff.delete();
}, 2000)
}
// TICKET CLAIMING SYSTEM [START]
if (supportbot.Ticket.ClaimTickets.Enabled) {
const InvStaff1 = await ticketChannel.send(`<@&${Admin.id}>`)
setTimeout(() => {
InvStaff1.delete();
}, 2000)
const claimChannel = await getChannel(
supportbot.Ticket.ClaimTickets.Channel,
interaction.guild
);
const claimEmbed = new EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage
.replace('%user%', interaction.user.id)
)
.setColor(supportbot.Embed.Colours.General);
const claimButton = new ButtonBuilder()
.setCustomId(`claimticket-${ticketChannel.id}`)
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle)
.setStyle(supportbot.Ticket.ClaimTickets.Button);
const row = new ActionRowBuilder().addComponents(claimButton);
await claimChannel.send({
content: `<@&${Staff.id}>`,
embeds: [claimEmbed],
components: [row]
const ticketChannel = await interaction.guild.channels.create(
`${supportbot.TicketPrefix}${ticketNumberID}`,
{
type: "GUILD_TEXT",
parent: TicketCategory.id,
permissionOverwrites: [
{
id: Admin.id,
allow: [Permissions.FLAGS.VIEW_CHANNEL],
},
{
id: interaction.user.id,
allow: [Permissions.FLAGS.VIEW_CHANNEL],
},
{
id: interaction.guild.id,
deny: [Permissions.FLAGS.VIEW_CHANNEL],
},
],
}
);
if (supportbot.AllowAllStaff) {
await ticketChannel.permissionOverwrites.edit(Staff.id, {
VIEW_CHANNEL: true,
});
}
// TICKET CLAIMING SYSTEM [END]
if (!department) {
await ticketChannel.members.add(interaction.user.id);
}
TicketData.tickets.push({
if (!department) {
await ticketChannel.permissionOverwrites.edit(interaction.user.id, {
SEND_MESSAGES: false,
});
}
await TicketData.tickets.push({
id: ticketChannel.id,
name: ticketChannel.name,
user: interaction.user.id,
@@ -167,10 +144,7 @@ module.exports = new Command({
reason: TicketSubject,
open: true,
subUsers: [],
createdAt: new Date().toISOString(),
claimedAt: null, // Will be updated when claimed
});
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(TicketData, null, 4),
@@ -179,103 +153,106 @@ module.exports = new Command({
}
);
const CreatedTicket = new EmbedBuilder()
const CreatedTicket = new MessageEmbed()
.setDescription(
msgconfig.Ticket.TicketCreatedAlert.replace(/%ticketauthor%/g, interaction.user.id)
supportbot.TicketCreatedAlert.replace(
/%ticketauthor%/g,
interaction.user.id
)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
)
.setColor(supportbot.Embed.Colours.General);
.setColor(supportbot.EmbedColour);
await interaction.reply({ embeds: [CreatedTicket], ephemeral: true });
if (supportbot.Ticket.AllowMentions) {
if (supportbot.AllowTicketMentions) {
await ticketChannel.send(`${interaction.user}`);
}
const TicketMessage = new EmbedBuilder()
.setAuthor({
name: msgconfig.Ticket.TicketAuthorTitle.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username),
iconURL: interaction.user.displayAvatarURL(),
})
const TicketMessage = new MessageEmbed()
.setTitle(
msgconfig.Ticket.TicketTitle.replace(/%ticketauthor%/g, interaction.user.id)
supportbot.Ticket_Title.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
)
.setDescription(
msgconfig.Ticket.TicketMessage.replace(/%ticketauthor%/g, interaction.user.id)
supportbot.TicketMessage.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
)
.setColor(supportbot.Embed.Colours.General);
.setColor(supportbot.EmbedColour);
const SelectMenus = new StringSelectMenuBuilder()
.setCustomId("ticketcontrolpanel")
.setPlaceholder("Ticket Control Panel")
.addOptions(
new StringSelectMenuOptionBuilder()
.setLabel("Add User")
.setDescription("Add a user to the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.AddUserEmoji)
.setValue("ticketadduser"),
new StringSelectMenuOptionBuilder()
.setLabel("Remove User")
.setDescription("Remove a user from the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.RemoveUserEmoji)
.setValue("ticketremoveuser"),
new StringSelectMenuOptionBuilder()
.setLabel("Close")
.setDescription("Close the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.CloseEmoji)
.setValue("ticketclose"),
new StringSelectMenuOptionBuilder()
.setLabel("Enable Invites")
.setDescription("Enable invites.")
.setEmoji(supportbot.SelectMenus.Tickets.EnableInvitesEmoji)
.setValue("enableinvites"),
new StringSelectMenuOptionBuilder()
.setLabel("Disable Invites")
.setDescription("Disable invites.")
.setEmoji(supportbot.SelectMenus.Tickets.DisableInvitesEmoji)
.setValue("disableinvites"),
);
if (supportbot.TicketSubject === "embed") {
if (TicketSubject !== "No Reason Provided.") {
TicketMessage.addFields({ name: "Reason", value: TicketSubject });
}
}
const row2 = new ActionRowBuilder().addComponents(SelectMenus);
if (supportbot.TicketSubject === "description") {
if (TicketSubject !== "No Reason Provided.") {
await ticketChannel.setTopic(
`Reason: ${TicketSubject} - User ID: ${interaction.user.id} - Ticket: ${ticketChannel.name}`
);
}
}
if (!department) {
TicketMessage.addFields({
name: "Departments",
value: ` **${supportbot.Departments.map((X) => X.title).join("\n")}**`,
});
}
const CloseButton = new MessageButton()
.setCustomId("ticketclose")
.setLabel("Close")
.setStyle(supportbot.TicketCloseColour)
.setEmoji(supportbot.TicketCloseEmoji);
const LockButton = new MessageButton()
.setCustomId("ticketlock")
.setLabel("Lock")
.setStyle(supportbot.TicketLockColour)
.setEmoji(supportbot.TicketLockEmoji);
const ClaimButton = new MessageButton()
.setCustomId("ticketclaim")
.setLabel("Claim")
.setStyle(supportbot.TicketClaimColour)
.setEmoji(supportbot.TicketClaimEmoji);
const row2 = new MessageActionRow().addComponents(CloseButton, LockButton, ClaimButton);
if (!department) {
try {
let buttons = supportbot.Departments.map((x) =>
new ButtonBuilder()
let buttons = await supportbot.Departments.map((x) =>
new MessageButton()
.setCustomId("Department" + supportbot.Departments.indexOf(x))
.setLabel(x.title)
.setStyle(x.color)
.setEmoji(x.emoji)
);
if (supportbot.Ticket.AllowMentions) {
await ticketChannel.send("<@&" + supportbot.Ticket.RoleMention + ">");
}
const row = new ActionRowBuilder().addComponents(buttons);
const row = new MessageActionRow().addComponents(buttons);
const m = await ticketChannel.send({
embeds: [TicketMessage],
components: [row2],
components: [row],
});
let collector;
try {
const filter = (i) => i.user.id === interaction.user.id;
await m.awaitMessageComponent({
collector = await m.awaitMessageComponent({
filter,
max: 1,
componentType: "BUTTON",
time: supportbot.Ticket.Timeout * 60000,
time: supportbot.Timeout * 60000,
});
} catch (e) {
if (e.code === "COLLECTOR_ERROR") {
if (e.code === "INTERACTION_COLLECTOR_ERROR") {
try {
let ticket = TicketData.tickets.findIndex((t) => t.id === ticketChannel.id);
TicketData = await JSON.parse(
fs.readFileSync("./Data/TicketData.json", "utf8")
);
let ticket = await TicketData.tickets.findIndex(
(t) => t.id === ticketChannel.id
);
TicketData.tickets[ticket].open = false;
fs.writeFileSync(
"./Data/TicketData.json",
@@ -287,22 +264,71 @@ module.exports = new Command({
interaction.user.send(
"Your ticket has timed out. Please open a new one, and select a department."
);
} catch (error) {
console.error("An error occurred while handling collector:", error);
}
} catch (e) {}
return await ticketChannel.delete();
}
}
} catch (error) {
console.error("Error sending message:", error);
}
let num = collector.customId.split("Department")[1];
let role = getRole(supportbot.Departments[num].role, interaction.guild);
let title = supportbot.Departments[num].title;
await ticketChannel.permissionOverwrites.edit(role.id, {
VIEW_CHANNEL: true,
});
await ticketChannel.permissionOverwrites.edit(interaction.user.id, {
SEND_MESSAGES: true,
});
await collector.reply({
embeds: [
{
description: `> Thank for reaching out to the **${title} Department**. Please provide us information regarding your query.`,
color: supportbot.EmbedColour,
},
],
});
if (supportbot.AllowTicketMentions) {
await ticketChannel.send("@here");
}
await collector.message.edit({
embeds: [TicketMessage],
components: [row2],
});
} catch (error) {}
} else {
await ticketChannel.send({
embeds: [TicketMessage],
components: [row2],
});
if (department) {
let role = await getRole(
supportbot.Departments[department].role,
interaction.guild
);
let title = supportbot.Departments[department].title;
await ticketChannel.permissionOverwrites.edit(role.id, {
VIEW_CHANNEL: true,
});
let TicketCat = await getCategory(
supportbot.Departments[department].category,
interaction.guild
);
await ticketChannel.setParent(TicketCat.id, { lockPermissions: false });
if (supportbot.AllowThanksForReachingOutMessage) {
await ticketChannel.send({
embeds: [
{
description: `> Thank for reaching out to the **${title} Department**. Please provide us information regarding your query.`,
color: supportbot.EmbedColour,
},
],
});
}
}
if (supportbot.AllowTicketMentions) {
await ticketChannel.send(supportbot.TicketRoleMention);
}
}
},
});
-115
View File
@@ -1,115 +0,0 @@
// ticketpanel.js
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandType,
ActionRowBuilder,
ButtonBuilder,
} = require("discord.js");
const yaml = require("js-yaml");
const panelconfig = yaml.load(fs.readFileSync("./Configs/ticket-panel.yml", "utf8"));
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.TicketPanel.Command,
description: cmdconfig.TicketPanel.Description,
type: ApplicationCommandType.ChatInput,
options: [],
permissions: cmdconfig.TicketPanel.Permission,
async run(interaction) {
if (!panelconfig.Panel) {
console.log(
"\u001b[31m",
`[TICKET PANEL]`,
"\u001b[33m",
"Ticket Panel is not setup, You can set this in", `\u001b[31m`, '/Configs/ticket-panel.yml', `\n `,
);
return interaction.reply({
content: "Ticket Panel is not set up. Please configure it in `/Configs/ticket-panel.yml`.",
ephemeral: true,
});
}
const channelName = panelconfig.Channel;
const channel = interaction.guild.channels.cache.find(ch => ch.name === channelName);
if (!channel) {
console.log(`[TICKET PANEL] ${channelName} channel not found. Please check your config file.`);
return interaction.reply({
content: `${channelName} channel not found. Please check your config file.`,
ephemeral: true,
});
}
const panelid = JSON.parse(fs.readFileSync("./Data/ticket-panel-id.json", "utf8"));
try {
await channel.messages.fetch(panelid.TicketPanelID);
return interaction.reply({
content: "Ticket panel message already exists.",
ephemeral: true,
});
} catch (error) {
let embed = new EmbedBuilder()
.setTitle(panelconfig.PanelTitle)
.setColor(panelconfig.PanelColour)
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
});
if (panelconfig.TicketPanel_Description) {
embed.setDescription(panelconfig.PanelMessage);
}
if (panelconfig.TicketPanel_Thumbnail) {
embed.setThumbnail(panelconfig.PanelThumbnail);
}
if (panelconfig.TicketPanel_Image) {
embed.setImage(panelconfig.PanelImage);
}
const createTicketButton = new ButtonBuilder()
.setCustomId("createticket")
.setLabel(panelconfig.Button.Text)
.setEmoji(panelconfig.Button.Emoji)
.setStyle(panelconfig.Button.Color);
let row = new ActionRowBuilder().addComponents(createTicketButton);
try {
const message = await channel.send({
embeds: [embed],
components: [row],
});
let data = {
id: panelid.id,
TicketPanelID: message.id,
};
fs.writeFileSync(
"./Data/ticket-panel-id.json",
JSON.stringify(data),
"utf8"
);
return interaction.reply({
content: "Ticket panel message has been sent!",
ephemeral: true,
});
} catch (e) {
console.log("Error sending message:", e);
return interaction.reply({
content: "An error occurred while sending the ticket panel message.",
ephemeral: true,
});
}
}
},
});
-56
View File
@@ -1,56 +0,0 @@
const { EmbedBuilder, ApplicationCommandType } = require("discord.js");
const fs = require("fs");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.TicketStats.Command,
description: cmdconfig.TicketStats.Description,
type: ApplicationCommandType.ChatInput,
permissions: ["SendMessages"], // Adjust permissions as needed
async run(interaction) {
if (supportbot.Ticket.ClaimTickets.Enabled) {
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const userId = interaction.user.id;
const ticketsClaimed = TicketData.tickets.filter(t => t.claimedBy === userId);
const ticketsOpen = ticketsClaimed.filter(t => t.open);
const totalTickets = ticketsClaimed.length;
let totalResponseTime = 0;
let responseCount = 0;
ticketsClaimed.forEach(ticket => {
if (ticket.claimedAt && ticket.createdAt) {
const responseTime = new Date(ticket.claimedAt) - new Date(ticket.createdAt);
totalResponseTime += responseTime;
responseCount++;
}
});
const averageResponseTime = responseCount ? totalResponseTime / responseCount : 0;
const averageResponseTimeMinutes = Math.round(averageResponseTime / 60000); // Convert to minutes
const statsEmbed = new EmbedBuilder()
.setTitle(msgconfig.TicketStats.Title)
.setDescription(`> Ticket stats for <@${interaction.user.id}>`)
.setColor(supportbot.Embed.Colours.General)
.addFields(
{ name: msgconfig.TicketStats.OpenTickets, value: `${ticketsOpen.length}`, inline: true },
{ name: msgconfig.TicketStats.TotalTickets, value: `${totalTickets}`, inline: true },
{ name: msgconfig.TicketStats.ResponseTime, value: `${averageResponseTimeMinutes} minutes`, inline: false }
);
await interaction.reply({ embeds: [statsEmbed], ephemeral: true });
}
}
});
+20 -29
View File
@@ -5,60 +5,51 @@ const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
)
);
const Command = require("../Structures/Command.js");
const translate = require("@vitalets/google-translate-api");
module.exports = new Command({
name: cmdconfig.Translate.Command,
description: cmdconfig.Translate.Description,
type: Discord.ApplicationCommandType.ChatInput,
name: cmdconfig.TranslateCommand, // Name of command
description: cmdconfig.TranslateCommandDesc, // Description of command
options: [
{
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
name: "language",
description: "A 2 letter language code",
required: true,
},
{
type: Discord.ApplicationCommandOptionType.String,
type: "STRING",
name: "text",
description: "The text to translate",
required: true,
}, // The input text for the translation
],
permissions: cmdconfig.Translate.Permission, // The permission the user/role at least requires
permissions: ["SEND_MESSAGES"], // The permission the user/role at least requires
async run(interaction) {
let disableCommand = true;
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
let SupportStaff = await getRole(supportbot.Staff, interaction.guild);
let Admin = await getRole(supportbot.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check the error logs."
);
const NoPerms = new Discord.EmbedBuilder()
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
.setColor(supportbot.WarningColour);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
@@ -71,7 +62,7 @@ module.exports = new Command({
let url = "https://www.science.co.il/language/Codes.php"; // URL to all available language codes
let text = await interaction.options.getString("text"); // Grab the text to translate by the user
let translatelog = await getChannel(
supportbot.Translate.Log,
supportbot.TranslateLogChannel,
interaction.guild
); // Grab the set logging channel for translations
@@ -81,8 +72,8 @@ module.exports = new Command({
if (err && err.code == 400) {
await interaction.reply({
embeds: [
new Discord.EmbedBuilder()
.setColor(supportbot.Embed.Colours.Warn)
new Discord.MessageEmbed()
.setColor(supportbot.WarningColour)
.setTitle("Valid Language Codes")
.setURL(url)
.setDescription(
@@ -96,9 +87,9 @@ module.exports = new Command({
if (!result) return;
// Embed containing language code, original text and translated text
let transembed = new Discord.EmbedBuilder()
let transembed = new Discord.MessageEmbed()
.setAuthor({ name: interaction.user.tag, iconURL: interaction.user.displayAvatarURL({ dynamic: true }) })
.setColor(supportbot.Embed.Colours.Success)
.setColor(supportbot.SuccessColour)
.setDescription(`**Translation to ${lang}**`)
.addFields(
{ name: "Original text", value: text },
+22 -32
View File
@@ -6,53 +6,43 @@ const moment = require("moment");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
)
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: cmdconfig.UserInfo.Command,
description: cmdconfig.UserInfo.Description,
type: Discord.ApplicationCommandType.ChatInput,
name: cmdconfig.UserInfoCommand, // Name of command
description: cmdconfig.UserInfoCommandDesc, // Description of command
options: [
{
type: Discord.ApplicationCommandOptionType.User,
type: "USER",
name: "user",
description: "The user you want to get info about.",
required: true,
}, // The user input
],
permissions: cmdconfig.UserInfo.Permission,
permissions: ["SEND_MESSAGES"], // The permission the user/role at least requires
async run(interaction) {
let disableCommand = true;
const { getRole } = interaction.client;
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
let SupportStaff = await getRole(supportbot.Staff, interaction.guild);
let Admin = await getRole(supportbot.Admin, interaction.guild);
if (!SupportStaff || !Admin)
return interaction.reply(
"Some roles seem to be missing!\nPlease check the error logs."
);
const NoPerms = new Discord.MessageEmbed()
.setTitle("Invalid Permissions!")
.setDescription(
`${supportbot.IncorrectPerms}\n\nRole Required: \`${supportbot.Staff}\` or \`${supportbot.Admin}\``
)
.setColor(supportbot.WarningColour);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
@@ -63,10 +53,10 @@ module.exports = new Command({
let user = await interaction.options.getUser("user") || interaction.author; // Grab the mentioned user
let member = await interaction.guild.members.cache.get(user.id) // Check for user and his ID
const UserNotExist = new Discord.EmbedBuilder()
const UserNotExist = new Discord.MessageEmbed()
.setTitle("User Not Found!")
.setDescription(
`${msgconfig.Error.UserNotFound}\n\nTry Again:\`/${cmdconfig.UserInfoCommand} <@!User_ID> or @User\``
`${supportbot.UserNotFound}\n\nTry Again:\`/${cmdconfig.UserInfoCommand} <@!User_ID> or @User\``
)
.setColor(supportbot.ErrorColour);
@@ -100,7 +90,7 @@ module.exports = new Command({
const userFlags = user.flags.toArray();
// Embed containing the userinfo
let userembed = new Discord.EmbedBuilder()
let userembed = new Discord.MessageEmbed()
.setTitle(`User Info for User: ${user.tag}`)
.setThumbnail(member.displayAvatarURL({ dynamic: true, size: 512 }))
.setColor(member.roles.highest.hexColor)
@@ -120,7 +110,7 @@ module.exports = new Command({
{ name: "Highest Role:", value: `${member.roles.highest.id === interaction.guild.id ? "None" : member.roles.highest.toString()}`, inline: true },
{ name: "Roles:", value: `${member.roles.cache.map(r => r).join(" ").replace("@everyone", " ") || "None"}`, inline: false },
)
.setFooter({ text: supportbot.Footer })
.setFooter({ text: supportbot.EmbedFooter })
.setTimestamp();
// Send embed [userembed]
+17 -81
View File
@@ -7,89 +7,25 @@
# SupportBot created by Emerald Services
# Installed with MIT License
#
# Discord Support: https://dsc.gg/emerald-dev
# Official Documentation: https://emeraldsrv.dev/wiki
# Third-Party Documentation: https://emeraldsrv.dev/third-party
#
# Command Configuration
# Discord Support: https://emeraldsrv.dev/discord
# Community Resources: https://emeraldsrv.dev/resources
Help:
Command: "help"
Description: "Get a list of all the commands."
Permission: ["SendMessages"]
Enabled: true
# -------------------------------
# Command Name Configuration
# -------------------------------
EnableAI:
Command: "enableai"
Description: "Talk with SupportBot"
Permission: ["SendMessages"]
Enabled: true
Info:
Command: "info"
Description: "Get information about the **ServerName**."
Permission: ["SendMessages"]
Enabled: true
TicketPanel:
Command: "ticketpanel"
Description: "Create the ticket creation panel"
Permission: ["Administrator"]
Enabled: true
TicketStats:
Command: "ticketstats"
Description: "Shows staff members their ticket statistics"
Permission: ["SendMessages"]
# Command is automatically disabled when the TicketClaims is disabled.
OpenTicket:
Command: "ticket"
Description: "Create a support ticket."
Permission: ["SendMessages"]
Enabled: true
Add:
Command: "add"
Description: "Add a user to the ticket."
Permission: ["SendMessages"]
Enabled: true
CloseTicket:
Command: "close"
Description: "Close a support ticket"
Permission: ["SendMessages"]
Enabled: true
Suggestion:
Command: "suggest"
Description: "Create a suggestion."
Permission: ["SendMessages"]
Enabled: true
Embed:
Command: "embed"
Description: "Build a discord embed."
Permission: ["SendMessages"]
Enabled: true
Translate:
Command: "translate"
Description: "Translate something to english"
Permission: ["SendMessages"]
Enabled: false
UserInfo:
Command: "userinfo"
Description: "Get info about a user."
Permission: ["SendMessages"]
Enabled: true
Ping:
Command: "ping"
Description: "Pong."
Permission: ["SendMessages"]
Enabled: true
Blacklist: "blacklist"
TicketAdd: "add"
TicketRemove: "remove"
OpenTicket: "ticket"
CloseTicket: "close"
InfoCommand: "info"
PingCommand: "ping"
HelpCommand: "help"
EmbedCommand: "embed"
SuggestCommand: "suggest"
TranslateCommand: "translate"
UserInfoCommand: "userinfo"
# ---------------------------------------
# Command Description Configuration
-118
View File
@@ -1,118 +0,0 @@
# ___ _ ___ _
# / __> _ _ ___ ___ ___ _ _ _| |_ | . > ___ _| |_
# \__ \| | || . \| . \/ . \| '_> | | | . \/ . \ | |
# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_|
# |_| |_|
#
# SupportBot created by Emerald Services
# Installed with MIT License
#
# Discord Support: https://dsc.gg/emerald-dev
# Official Documentation: https://emeraldsrv.com/wiki
# Third-Party Documentation: https://emeraldsrv.com/third-party
#
# Messages Configuration
Info:
Title: "About Us"
Description: "SupportBot is an open-sourced support system for discord. It's completely free to use with high amounts of customization to match your own brand."
Button: "Visit Site"
URL: "https://emeraldsrv.com"
Colour: "#f74343"
Welcome:
Embed:
Colour: "#f74343"
Title: "Welcome to ServerName"
Message: "> :smile: %joined_user% has just landed!"
Thumbnail: "BOT"
ImageEnabled: false
ImageURL: "https://animagelink.png/"
Leave:
Embed:
Colour: "#f74343"
Title: "Goodbye!"
Message: "> :slight_frown: %joined_user% has recently dropped out!"
Thumbnail: "BOT"
ImageEnabled: false
ImageURL: "https://animagelink.png/"
Suggestions:
Sent_Title: "Suggestion Sent!"
Sent: "> :white_check_mark: **You have successfully sent a suggestion.**"
NoSelfVote: "> :x: **You cannot vote on your own suggestion.**"
RemoveVoteButton: "Remove Vote"
Ticket:
# Available Placeholders:
# %ticketusername% - User who created the ticket.
# <@%ticketauthor%> - Tags the user who created the ticket.
# <#%ticketid%> - Mentions the ticket channel.
TicketAuthorTitle: "%ticketusername%'s Ticket"
TicketTitle: "Support Ticket"
TicketMessage: "> Hello <@%ticketauthor%>, Thank you for creating a support ticket\nPlease wait patiently whilst a member of our team reaches out to you."
TicketThumbnail: "https://images.emojiterra.com/google/android-pie/512px/1f39f.png"
TicketCreatedAlert: "> :ticket: Ticked Created: <#%ticketid%>"
TicketExists: "> ❌ Ticket already exists"
TicketClaim: "> :white_check_mark: Ticket claimed by" #The user who claimed the ticket will be added to the end of this message
TicketUnclaim: "> :white_check_mark: Ticket unclaimed by" #The user who claimed the ticket will be added to the end of this message
DisableInvites: "> 🔒 Invites have been disabled for this ticket."
EnableInvites: "> 🔓 Invites have been enabled for this ticket."
# Available Placeholders:
# <@%user%> - Tags the user who was added to the ticket.
AddUserToTicket_Title: "➕ Add User!"
AddUserToTicket: "> To add a user to this ticket, Tag them."
RemovedUserFromTicket_Title: "➖ Removed User!"
RemovedUserFromTicket: "> <@%user%> has been `Removed` from this ticket"
Blacklisted: "> :x: You are not allowed to open a ticket"
Muted: "> :x: You are `Muted` and therefore not allowed to open any tickets"
InvalidSubject: "> No Reason Provided!"
TranscriptSavedMessage: "📝 **Transcript Saved!**"
TicketLockMessage: "❌ **Ticket Locked!**"
TicketDeleteMessage: "⚠ **Ticket Deleting!**"
ClosingTicket: "> :warning: You have requested to close your support ticket."
ConfirmClose: "> Please confirm closing the ticket by clicking the button below."
CloseTimeout: "> Ticket close confirmation timed out."
ClaimTickets:
ClaimTitle: "Incoming Support Request!"
ClaimMessage: "> A new ticket has been created by <@!%user%>. Click the button below to claim this ticket."
ClaimMessage_Edit: "> <#%channel%> was claimed by <@!%user%>."
ClaimedTitle: "Ticket Claimed!"
Claimed: "> You have successfully claimed this ticket. <#%channel%>"
NoPermsToClaimTitle: "Error, no permissions!"
NoPermsToClaim: "> :x: **Err!** You do not permissions to claim this ticket."
TicketStats:
OpenTickets: "✅ Open Tickets"
TotalTickets: "🎫 Total Tickets"
ResponseTime: "⏱️ Average Response Time"
Title: "Your Ticket Stats"
Error:
IncorrectPerms: "> :x: **Err!** You do not have the correct permissions to use this."
InvalidChannel: "> :x: **Err!** Channel not found. Please create it!"
UserNotFound: "> :x: **Err!** This user doesn't exist, Are they in this server?"
NoValidTicket: "> :warning: You cannot execute this command here."
TicketExists: "> :warning: This ticket cannot be opened, It already exists!"
-40
View File
@@ -1,40 +0,0 @@
# -------------------------
# SupportBot AI
#
# In order to use the SupportBot AI, You need to setup an OpenAI Account.
# this can be done at https://platform.openai.com/
# -------------------------
Enabled: true
General:
Name: "SupportBot AI"
# What would you like to call your AI
Model: "gpt-4o"
# You can see a list of OpenAI Models here: https://platform.openai.com/docs/models
Tokens: 400
# Max tokens you can set is 400
# For more information about tokens, go to https://openai.com/api/pricing/
OpenAI_Key: "OPEN_AI_API_KEY"
# To create an OpenAI API key, go to https://platform.openai.com/api-keys
PastebinAPI_Key: "PASTEBIN_API_KEY"
# You can get your Pastebin API Key from https://pastebin.com
PastebinAPI_URL: "https://pastebin.com/api/api_post.php"
Channels:
AIChannel: "0000000000000000000"
# This is the channel where AI will respond in without needing to mention the bot.
Embed:
Color: 0x0cc559 # 0x<hexcode>
Footer: "SupportBot | Developed by Emerald Development"
Messages:
MessageTooLong: "The response was too long, so I've posted it here: {pastebin}"
ErrorResponse: "I didn't receive a proper response from OpenAI. Please try again later."
OpenAIError: "I'm having some trouble talking to SupportBot AI's Model, OpenAI. Please try again later."
AIDisabled: "I am disabled, You have enable me in `supportbot-ai.yml`"
+219 -164
View File
@@ -4,213 +4,268 @@
# <___/`___|| _/| _/\___/|_| |_| |___/\___/ |_|
# |_| |_|
#
# SupportBot created by Emerald Development
# SupportBot created by Emerald Services
# Installed with MIT License
#
# Discord Support: https://dsc.gg/emerald-dev
# Official Documentation: https://github.com/Emerald-Services/SupportBot/wiki
# Third-Party Documentation: COMING SOON
# Discord Support: https://emeraldsrv.dev/discord
# Community Resources: https://emeraldsrv.dev/resources
SupportBot_Version: "v8.0"
# Do not change the version number
SupportBot_Version: "v7.7.3"
# -------------------------
# General
# General Configuration
# -------------------------
General:
Name: "SupportBot"
Token: "BOT_TOKEN_HERE"
# To get your Discord Bot Token, Go to https://discord.com/developers/applications
Addons:
Enabled: false
# -------------------------
# Activity
# -------------------------
Activity:
Status: "SupportBot v8"
Type: "Competing"
# The Type can either be Playing, Watching, Listening or Competing
StreamingURL: "https://www.twitch.tv/YOUR_TWITCH_NAME"
# Set The Type to "Streaming" for a streaming status!
Name: "SupportBot"
Token: "BOT_TOKEN HTTPS://DISCORD.COM/DEVELOPERS"
# -------------------------
# Embeds
# Activity Configuration
# -------------------------
Embed:
Colours:
General: 0x0cc559 # 0x<hexcode>
Success: 0x04b545 # 0x<hexcode>
Error: 0xd13030 # 0x<hexcode>
Warn: 0xfca117 # 0x<hexcode>
BotActivity: "Here to help!"
Footer: "SupportBot | Developed by Emerald Development"
StreamingURL: "https://www.twitch.tv/YOUR_TWITCH_NAME"
# Set The ActivityType to "STREAMING" for a streaming status!
ActivityType: "PLAYING"
# Activity status can either be PLAYING, WATCHING, LISTENING or STREAMING.
# -------------------------
# Roles
# Embed Configuration
# -------------------------
Roles:
AutoRole:
Enabled: true
Role: "Member"
EmbedColour: "#f74343"
EmbedFooter: "SupportBot | Developed by Emerald Services"
StaffMember:
Staff: "Staff"
Admin: "Admin"
ErrorColour: "#d12519"
SuccessColour: "#04b545"
WarningColour: "#fca117"
ModRoles:
Muted: "Muted"
Blacklisted: "Blacklisted"
# -------------------------
# Role Configuration
# -------------------------
AutoRole: true
JoinRole: "SupportBot Member"
Staff: "SupportBot Staff"
Admin: "SupportBot Admin"
TicketBlackListRole: "Blacklisted"
# ----------------------------
# System Messages
# Join/Leave Configuration
# ----------------------------
Welcome:
Enabled: true
Channel: "🚨┃join-leave-logs"
Welcome: true
# set to false to disable joining logs
Leave:
Enabled: true
Channel: "🚨┃join-leave-logs"
WelcomeChannel: "join-leave-logs"
WelcomeColour: "#f74343"
WelcomeTitle: "User Joined!"
WelcomeMessage: "%joined_user% has joined the server!"
# Available Placeholders:
# %joined_user% - Mentions the user who joined
EmbedWelcomeImage: true
EmbedWelcomeImageURL: "https://media.discordapp.net/attachments/958247876344025108/986777740738986094/unknown.png"
EmbedWelcomeThumbnail: "BOT"
# "USER" will display the user's profile picture.
# "BOT" will display the bot's profile picture.
# false to disable
Leave: true
# set to false to disable leaving logs
LeaveChannel: "join-leave-logs"
LeaveColour: "#f74343"
LeaveTitle: "User Left!"
LeaveMessage: "%joined_user% has left the server!"
# Available Placeholders:
# %joined_user% - Mentions the user who joined
EmbedLeaveImage: true
EmbedLeaveImageURL: "https://cdn.discordapp.com/attachments/958247876344025108/986778170223120384/unknown.png"
EmbedLeaveThumbnail: false
# "USER" will display the user's profile picture.
# "BOT" will display the bot's profile picture.
# false to disable
# -------------------------
# Information Configuration
# -------------------------
InfoTitle: "Information"
InfoButtonText: "Visit Site"
AboutMe: "I am SupportBot"
InfoURL: "https://emeraldsrv.dev"
InfoColour: "#f74343"
# ----------------------------
# Suggestions
# Suggestions Configuration
# ----------------------------
Suggestions:
Channel: "📗┃suggestions"
UpvoteEmoji: "✅"
DownvoteEmoji: "❌"
SuggestionChannel: "suggestions"
SuggestionUpvote: "✅"
SuggestionDownvote: "❌"
UpvoteTitle: "Yes"
DownvoteTitle: "No"
SuggestionThreads: true
# set to false to disable threads being created from suggestions.
OwnSuggestion: true
# If false this will not allow the user to vote for a suggestion they created
# If true this will allow the user to vote for a suggestion they created
ShowUsers: true
Threads:
Enabled: true
Title: "Suggestion-releated Thread"
Reason: "A thread releted to this suggestion"
Buttons:
Upvote: "2"
Downvote: "2"
RemoveVote: "4"
RemoveVote_Title: "Remove Vote"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
DisableSuggestions: false
# Set to true to disable the suggestions feature.
# -------------------------
# Tickets
# Translate Configuration
# -------------------------
Ticket:
TicketCategory: "📗┃tickets" #Where tickets normally go with the /ticket command
# This is the channel name for the ticket threads to be created, NOT A DISCORD CATEGORY!
Channel: "ticket-" # The prefix for ticket channel names
TicketsPerUser: 100
DMTranscripts: true
TicketReason: true
# If ticket reason is set to false, It will not prompt to create a reason
TicketSubject: "description"
# "description" will display the ticket reason within the channel description
# "embed" will display the ticket reason within the ticket embed
Timeout: 5
# Set to true to allow all staff to access the ticket
Log:
TicketLog: "🚨┃ticket-data"
TicketLog_Title: "Ticket Closed"
DisableTicketLogChannel: false
TranscriptLog: "🚨┃ticket-data"
TranscriptTitle: "Ticket Transcript"
Close:
StaffOnly: true
# Set to false is anyone is able to close a ticket.
Confirmation_Button: "Confirm Close"
Title: "Are you sure you want to close this ticket?"
Invites:
StaffOnly: true
ClaimTickets:
Enabled: true
Channel: "1249723473757077624"
# Channel name or Channel ID
ButtonTitle: "Claim Ticket"
Button: "1"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
TranslateLogChannel: "translations-log"
# -------------------------
# Departments - NOT IN THIS UPDATE
# Tickets Configuration
# -------------------------
TicketPrefix: "ticket-" # The prefix for ticket channel names
TicketLog: "ticket-data"
TranscriptLog: "ticket-data"
DMTranscripts: true
TranscriptTitle: "Ticket Transcript"
TicketLog_Title: "Ticket Closed"
TicketBlackListMessage: "You are not allowed to open a ticket"
TicketRoleMention: "@here"
TicketClaimMessage: "Your ticket will be handled by" #Automaticly tags user to the end
TicketClaimTitle: "Ticket Claimed"
TicketUnclaimMessage: "Your ticket is now unclaimed by" #Automaticly tags user to the end
TicketUnclaimTitle: "Ticket Unclaimed"
# To ping a role: <@ROLE_ID>
MaxAllowedTickets: 2
TicketSubject: "description"
# "description" will display the ticket reason within the channel description
# "embed" will display the ticket reason within the ticket embed
AllowTicketMentions: true
# Set to true to allow the ticket to mention the author and the support team.
# Set false to dis-allow mentions within tickets.
AllowThanksForReachingOutMessage: true
# Set to true to allow the "Thanks for reaching out Message" to be sent when the ticket is created
DisableTicketLogChannel: false
# Set to true to disable the requirement of the "TicketLog"
# Set to true to also disable the ticket logs to be sent in the "TicketLogs" channel
# --- Creation Config ---
# --- Start ---
# Available Placeholders:
# %ticketusername% - User who created the ticket.
# <@%ticketauthor%> - Tags the user who created the ticket.
# <#%ticketid%> - Mentions the ticket channel.
Ticket_Title: "Server Support | %ticketusername%"
TicketMessage: "Hello <@%ticketauthor%>, Thank you for creating a support ticket\nPlease wait patiently whilst a member of our team reaches out to you."
Ticket_Thumbnail: "https://images.emojiterra.com/google/android-pie/512px/1f39f.png"
NoTicketSubject: "No Reason Provided!"
TicketCreatedAlert: ":ticket: Your support ticket has been created: <#%ticketid%>"
AddedUser: "👍 <@%user%> has been added to this ticket"
RemovedUser: "👍 <@%user%> has been removed from this ticket"
# -------------------------
# Tickets Categories
# -------------------------
Timeout: 5
# Set to true to allow all staff to access the ticket
AllowAllStaff: false
# Ticket roles are the roles that will be able to gain access to tickets depending on what department has been chosen.
Departments:
- title: "Create Ticket"
role: "Staff"
color: "2"
emoji: "🎫"
category: "TICKETS"
- title: "Support"
role: "SupportBot Staff"
color: "SECONDARY"
emoji: "1️⃣"
category: "Tickets"
# -------------------------
# Buttons
# -------------------------
Buttons:
Tickets:
ClaimEmoji: "🧑‍💻"
ClaimStyle: "1"
- title: "Billing Support"
role: "SupportBot Staff"
color: "SECONDARY"
emoji: "2️⃣"
category: "Tickets"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
- title: "Admin Team"
role: "SupportBot Admin"
color: "SECONDARY"
emoji: "3️⃣"
category: "Tickets"
# - title: "Other"
# role: "Staff"
# color: "SECONDARY"
# emoji: "3️⃣"
# category: "Tickets"
# -------------------------
# Select Menus
# -------------------------
# Discord Button Colour Selection
# PRIMARY - Blurple
# SECONDARY - Grey
# DANGER - Red
# SUCCESS - Green
SelectMenus:
Tickets:
PanelEmoji: "⚙️"
CloseEmoji: "🗑️"
ArchiveEmoji: "♻️"
LockTicketEmoji: "🔒"
UnLockTicketEmoji: "🔓"
EnableInvitesEmoji: "🔒"
DisableInvitesEmoji: "🔓"
AddUserEmoji: "➕"
RemoveUserEmoji: "➖"
# --- Buttons Config ---
# --- Start ---
LockTicketCategory: "Archive"
UnlockTicketCategory: "Tickets" #This moves the ticket back to the main category.
# -------------------------
# Misc
# -------------------------
TicketCloseEmoji: "❌"
TicketDeleteEmoji: "⛔"
TicketLockEmoji: "🔒"
TicketClaimEmoji: "🧑‍💻"
TicketUnlockEmoji: "🔓"
TicketUnclaimEmoji: "🧑‍💻"
Translate:
Log: "🚨┃logs"
TicketCloseColour: "DANGER"
TicketDeleteColour: "DANGER"
TicketLockColour: "PRIMARY"
TicketClaimColour: "SUCCESS"
TicketUnclaimColour: "DANGER"
TicketUnlockColour: "SUCCES"
# Discord Button Colour Selection
# PRIMARY - Blue
# SECONDARY - Grey
# DANGER - Red
# SUCCESS - Green
TranscriptSavedMessage: "📝 **Transcript Saved!**"
TicketLockMessage: "❌ **Ticket Locked!**"
TicketDeleteMessage: "⚠ **Ticket Deleting!**" # Tickets deleting after 5 seconds by default.
# --- Closing Config ---
# --- Start ---
StaffOnly: true
ClosingTicket: ":warning: You have requested to close your support ticket."
ClosingConfirmation_Word: "confirm"
CloseConfirmation: true
# ---------------------------
# Error / Warning Messages
# ---------------------------
IncorrectPerms: ":x: **Err!** You do not have the correct permissions to use this command."
InvalidChannel: ":x: **Err!** Channel not found. Please create it!"
UserNotFound: ":x: **Err!** This user doesn't exist, Are they in this server?"
NoValidTicket: ":warning: You cannot execute this command here."
TicketExists: ":warning: This ticket cannot be opened, It already exists!"
+8 -20
View File
@@ -14,33 +14,21 @@
# Ticket Panel Configuration
# -------------------------------
Panel: true
TicketPanel: true
# ----------------------------------------
# Ticket Panel Message Configuration #2b2d31
# Ticket Panel Message Configuration
# ----------------------------------------
Channel: "📗┃tickets"
# The channel used to create the ticket panel, Use command /ticketpanel to generate it.
Channel: "ticket-creation"
PanelTitle: "SupportBot"
PanelColour: "#0cc559"
Button:
Text: "Create Ticket"
Emoji: "🎫"
Color: "2"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Red
# 4 - Green
PanelTitle: "Need Help? Create a Support Ticket."
PanelColour: "#f74343"
TicketPanel_Description: true
TicketPanel_Thumbnail: false
TicketPanel_Thumbnail: true
TicketPanel_Image: true
PanelMessage: "Click on the button to file a `Ticket` and our team will try their best to assist you in the best way we can!"
PanelMessage: "Click the button to open a new support ticket."
PanelThumbnail: "https://i.imgur.com/ieeZejl.png"
PanelImage: "https://i.imgur.com/dejQvkg.png"
PanelImage: "https://i.imgur.com/5NkcmDq.png"
BIN
View File
Binary file not shown.
-1
View File
@@ -1 +0,0 @@
{}
-3
View File
@@ -1,3 +0,0 @@
{
}
+1 -5
View File
@@ -1,5 +1 @@
{
"tickets": [
{}
]
}
{"tickets": [{}]}
+1 -1
View File
@@ -1,4 +1,4 @@
{
"id": 0,
"TicketPanelID": "0000000000000000000"
"TicketPanelID": ""
}
+13 -22
View File
@@ -3,48 +3,39 @@ const Discord = require('discord.js');
const fs = require("fs");
const Event = require("../Structures/Event.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
module.exports = new Event("guildMemberAdd", async (client, member, interaction, guild) => {
if (supportbot.Welcome.Enabled) {
const WelcomeChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.Welcome.Channel)
if (supportbot.Welcome) {
const WelcomeChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.WelcomeChannel)
const WelcomeEmbed = new Discord.EmbedBuilder()
.setColor(msgconfig.Welcome.Embed.Colour)
.setTitle(msgconfig.Welcome.Embed.Title)
.setDescription(msgconfig.Welcome.Embed.Message.replace(/%joined_user%/g, member.user))
const WelcomeEmbed = new Discord.MessageEmbed()
.setColor(supportbot.WelcomeColour)
.setTitle(supportbot.WelcomeTitle)
.setDescription(supportbot.WelcomeMessage.replace(/%joined_user%/g, member.user))
.setTimestamp();
if (msgconfig.Welcome.Embed.Thumbnail === "BOT") {
if (supportbot.EmbedWelcomeThumbnail === "BOT") {
WelcomeEmbed.setThumbnail(client.user.displayAvatarURL())
}
if (msgconfig.Welcome.Embed.Thumbnail === "USER") {
if (supportbot.EmbedWelcomeThumbnail === "USER") {
WelcomeEmbed.setThumbnail(member.user.displayAvatarURL())
}
if (msgconfig.Welcome.Embed.ImageEnabled) {
WelcomeEmbed.setImage(msgconfig.Welcome.Embed.ImageURL)
if (supportbot.EmbedWelcomeImage) {
WelcomeEmbed.setImage(supportbot.EmbedWelcomeImageURL)
}
WelcomeChannel.send({
embeds: [WelcomeEmbed]
})
if (supportbot.Roles.AutoRole.Enabled) {
var role = member.guild.roles.cache.find(role => role.name === supportbot.Roles.AutoRole.Role);
if (supportbot.AutoRole) {
var role = member.guild.roles.cache.find(role => role.name === supportbot.JoinRole);
member.roles.add(role);
}
+13 -22
View File
@@ -3,47 +3,38 @@ const Discord = require('discord.js');
const fs = require("fs");
const Event = require("../Structures/Event.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
module.exports = new Event("guildMemberRemove", async (client, member, interaction, guild) => {
if (supportbot.Leave.Enabled) {
const LeaveChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.Leave.Channel)
if (supportbot.Leave) {
const LeaveChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.LeaveChannel)
const LeaveEmbed = new Discord.EmbedBuilder()
.setColor(msgconfig.Leave.Embed.Colour)
.setTitle(msgconfig.Leave.Embed.Title)
.setDescription(msgconfig.Leave.Embed.Message.replace(/%joined_user%/g, member.user))
const LeaveEmbed = new Discord.MessageEmbed()
.setColor(supportbot.LeaveColour)
.setTitle(supportbot.LeaveTitle)
.setDescription(supportbot.LeaveMessage.replace(/%joined_user%/g, member.user))
.setTimestamp();
if (msgconfig.Leave.Embed.Thumbnail === "BOT") {
if (supportbot.EmbedLeaveThumbnail === "BOT") {
LeaveEmbed.setThumbnail(client.user.displayAvatarURL())
}
if (msgconfig.Leave.Embed.Thumbnail === "USER") {
if (supportbot.EmbedLeaveThumbnail === "USER") {
LeaveEmbed.setThumbnail(member.user.displayAvatarURL())
}
if (msgconfig.Leave.Embed.ImageEnabled) {
LeaveEmbed.setImage(msgconfig.Leave.Embed.ImageURL)
if (supportbot.EmbedLeaveImage) {
LeaveEmbed.setImage(supportbot.EmbedLeaveImageURL)
}
LeaveChannel.send({
embeds: [LeaveEmbed]
})
console.log(`\u001b[31m`, `[-]`, `\u001b[33m`, `${member.user.username} left the server!`)
console.log(`\u001b[31m`, `[-]`, `\u001b[33m`, `${member.user.username} joined the server!`)
}
});
+272 -218
View File
@@ -1,31 +1,31 @@
// SupportBot | Emerald Services
// Interaction Create Event
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
const Event = require("../Structures/Event.js");
const TicketNumberID = require("../Structures/TicketID.js");
let suggestions;
try {
suggestions = require("../Data/SuggestionData.json");
} catch (error) {
suggestions = {};
}
module.exports = new Event("interactionCreate", async (client, interaction) => {
if (interaction.type == Discord.InteractionType.ApplicationCommand) {
if (interaction.isCommand()) {
const command = client.commands.find(
(cmd) => cmd.name.toLowerCase() === interaction.commandName
);
if (interaction.user.bot || !interaction.guild) return;
const NotValid = new Discord.EmbedBuilder()
const NotValid = new Discord.MessageEmbed()
.setDescription(`:x: \`Invalid Command\` `)
.setColor(supportbot.Embed.Colours.Error);
.setColor(supportbot.ErrorColour);
if (!command)
return interaction.reply({
@@ -34,11 +34,11 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
const permission = interaction.member.permissions.has(command.permissions);
const ValidPerms = new Discord.EmbedBuilder()
const ValidPerms = new Discord.MessageEmbed()
.setDescription(
"> :x: `Invalid Permissions` Do you have the correct permissions to execute this command?"
":x: `Invalid Permissions` Do you have the correct permissions to execute this command?"
)
.setColor(supportbot.Embed.Colours.Error);
.setColor(supportbot.ErrorColour);
if (!permission)
return interaction.reply({
@@ -46,64 +46,11 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
});
command.run(interaction);
}
if (interaction.isStringSelectMenu()) {
if (interaction.customId === "ticketcontrolpanel") {
const selectedOption = interaction.values[0];
const { getRole, getChannel } = interaction.client;
switch (selectedOption) {
case "ticketadduser":
const AddUserThreadTicket = new Discord.EmbedBuilder()
.setTitle(`${msgconfig.Ticket.AddUserToTicket}`)
.setDescription(`${msgconfig.Ticket.AddUserToTicket}`)
.setColor(supportbot.Embed.Colours.General);
await interaction.reply({
embeds: [AddUserThreadTicket],
ephemeral: true,
});
break;
case "ticketremoveuser":
await removeUserFromThread(interaction);
break;
case "ticketclose":
const closeCommand = client.commands.get(cmdconfig.CloseTicket.Command);
if (closeCommand) {
closeCommand.run(interaction);
} else {
console.error("[X] Close Command Not Found");
}
break;
case "enableinvites":
await handleInvites(interaction, true);
break;
case "disableinvites":
await handleInvites(interaction, false);
break;
}
}
}
if (interaction.isButton()) {
if (interaction.customId === 'createticket') {
try {
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
if (!cmd) return;
cmd.run(interaction);
} catch (error) {
console.error("Error executing the ticket command:", error);
await interaction.reply({
content: "An error occurred while creating the ticket.",
ephemeral: true,
});
}
}
if (interaction.customId === "openticket") {
if (
interaction.customId === "openticket" ||
interaction.customId.includes("department-")
) {
try {
const cmd = client.commands.get(cmdconfig.OpenTicket);
if (!cmd) return;
@@ -113,166 +60,273 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
}
}
if (interaction.customId.startsWith('claimticket-')) {
const ticketChannelId = interaction.customId.split('-')[1];
const ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
if (!ticketChannel) {
return interaction.reply({
content: "Ticket channel not found.",
ephemeral: true,
});
if (interaction.customId === "ticketclose") {
try {
const cmd = client.commands.get(cmdconfig.CloseTicket);
if (!cmd) return;
cmd.run(interaction);
} catch (error) {
console.error(error);
}
const { getRole, getChannel } = interaction.client;
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
const RolePerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (!Staff || !Admin) {
return interaction.reply({
embeds: [RolePerms],
ephemeral: true,
});
}
const NoPermsClaim = new Discord.EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.NoPermsToClaimTitle)
.setDescription(
msgconfig.Ticket.ClaimTickets.NoPermsToClaim.replace('%channel%', ticketChannel.name)
)
.setColor(supportbot.Embed.Colours.Error);
if (!interaction.member.roles.cache.has(Staff.id) && !interaction.member.roles.cache.has(Admin.id)) {
return interaction.reply({
embeds: [NoPermsClaim],
ephemeral: true,
});
}
await ticketChannel.members.add(interaction.user.id);
const pingclaimedstaff = await ticketChannel.send(`<@${interaction.user.id}>`);
setTimeout(() => {
pingclaimedstaff.delete();
}, 2000)
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const ticketIndex = TicketData.tickets.findIndex((t) => t.id === ticketChannelId);
if (ticketIndex !== -1) {
TicketData.tickets[ticketIndex].claimedBy = interaction.user.id;
TicketData.tickets[ticketIndex].claimedAt = new Date().toISOString();
fs.writeFileSync("./Data/TicketData.json", JSON.stringify(TicketData, null, 4));
}
const claimMessage = await interaction.message.fetch();
const claimedEmbed = new Discord.EmbedBuilder(claimMessage.embeds[0].data)
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
.setDescription(
msgconfig.Ticket.ClaimTickets.ClaimMessage_Edit.replace('%user%', interaction.user.id).replace('%channel%', ticketChannel.id)
)
.setColor(supportbot.Embed.Colours.Success);
const successfullyClaimed = new Discord.EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
.setDescription(msgconfig.Ticket.ClaimTickets.Claimed.replace('%channel%', ticketChannel.id))
.setColor(supportbot.Embed.Colours.Success);
await claimMessage.edit({ embeds: [claimedEmbed], components: [] });
await interaction.reply({
embeds: [successfullyClaimed],
ephemeral: true,
});
}
// SUGGESTION INTERACTIONS [START]
if (interaction.customId === 'upvote' || interaction.customId === 'downvote' || interaction.customId === 'removevote') {
const suggestion = suggestions[interaction.message.id];
if (!suggestion) return interaction.reply({ content: 'Suggestion not found.', ephemeral: true });
const userId = interaction.user.id;
const hasUpvoted = suggestion.upvotes.includes(userId);
const hasDownvoted = suggestion.downvotes.includes(userId);
if (interaction.customId === 'upvote') {
if (hasUpvoted) {
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
} else {
suggestion.upvotes.push(userId);
if (hasDownvoted) {
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
}
if (interaction.customId === "ticketlock") {
if (interaction.channel.name.startsWith(supportbot.TicketPrefix)) {
interaction.message.fetch();
let Admin =
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.name === supportbot.Admin
) ||
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.id === supportbot.Admin
);
if (!interaction.member.roles.cache.has(Admin.id)) {
return await interaction.reply({
content: "You don't have permission to do that.",
ephemeral: true,
});
}
} else if (interaction.customId === 'downvote') {
if (hasDownvoted) {
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
} else {
suggestion.downvotes.push(userId);
if (hasUpvoted) {
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
}
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) {
await interaction.channel.setParent(parent.id);
}
} else if (interaction.customId === 'removevote') {
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
}
fs.writeFileSync("./Data/SuggestionData.json", JSON.stringify(suggestions, null, 2));
all.forEach((perm) => {
interaction.channel.permissionOverwrites.delete(perm.id);
});
await interaction.channel.permissionOverwrites.create(Admin.id, {
VIEW_CHANNEL: true,
});
const upvoteCount = suggestion.upvotes.length;
const downvoteCount = suggestion.downvotes.length;
await interaction.channel.permissionOverwrites.create(
interaction.guild.id,
{
VIEW_CHANNEL: false,
}
);
const updatedEmbed = new Discord.EmbedBuilder(interaction.message.embeds[0].data)
.setFields([
{ name: 'Suggestion', value: suggestion.suggestion, inline: true },
{ name: 'From', value: `<@${suggestion.author}>` },
{ name: `${supportbot.Suggestions.UpvoteEmoji} ${supportbot.Suggestions.UpvoteTitle}`, value: `${upvoteCount}`, inline: true },
{ name: `${supportbot.Suggestions.DownvoteEmoji} ${supportbot.Suggestions.DownvoteTitle}`, value: `${downvoteCount}`, inline: true }
]);
const ticketDeleteButton = new Discord.MessageButton()
.setCustomId("ticketclose")
.setLabel("Close")
.setStyle(supportbot.TicketDeleteColour)
.setEmoji(supportbot.TicketDeleteEmoji);
await interaction.update({ embeds: [updatedEmbed] });
}
}
const ticketUnlockButton = new Discord.MessageButton()
.setCustomId("ticketunlock")
.setLabel("Unlock")
.setStyle(supportbot.TicketUnlockColour)
.setEmoji(supportbot.TicketUnlockEmoji);
async function handleInvites(interaction, enable) {
if (supportbot.Ticket.Invites.StaffOnly) {
const SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
const row = new Discord.MessageActionRow().addComponents(
ticketDeleteButton, ticketUnlockButton
);
const ArchiveEmbed = new Discord.MessageEmbed()
.setTitle("Archived")
.setDescription(`Archived ${interaction.channel.name}`)
.setColor(supportbot.SuccessColour);
if (!SupportStaff || !Admin) {
return interaction.reply("Some roles seem to be missing!\nPlease check for errors when starting the bot.");
}
const NoPerms = new Discord.EmbedBuilder()
.setTitle("Invalid Permissions!")
.setDescription(
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
)
.setColor(supportbot.Embed.Colours.Warn);
if (!interaction.member.roles.cache.has(SupportStaff.id) && !interaction.member.roles.cache.has(Admin.id)) {
return interaction.reply({ embeds: [NoPerms] });
interaction.reply({ embeds: [ArchiveEmbed] });
interaction.message.edit({ components: [row] });
}
}
if (interaction.customId === "ticketunlock") {
if (interaction.channel.name.startsWith(supportbot.TicketPrefix)) {
interaction.message.fetch();
let Admin =
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.name === supportbot.Admin
) ||
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.id === supportbot.Admin
);
if (!interaction.member.roles.cache.has(Admin.id)) {
return await interaction.reply({
content: "You don't have permission to do that.",
ephemeral: true,
});
}
let all = interaction.channel.permissionOverwrites.cache;
await interaction.channel.setInvitable(enable);
let parent =
interaction.guild.channels.cache.find(
(c) => c.name === supportbot.UnlockTicketCategory
) ||
interaction.guild.channels.cache.find(
(c) => c.id === supportbot.UnlockTicketCategory
);
if (parent) {
await interaction.channel.setParent(parent.id);
}
const message = enable ? msgconfig.Ticket.EnableInvites : msgconfig.Ticket.DisableInvites;
const embed = new Discord.EmbedBuilder()
.setDescription(message)
.setColor(supportbot.Embed.Colours.General);
all.forEach((perm) => {
interaction.channel.permissionOverwrites.create(perm.id, {
VIEW_CHANNEL: true,
});
});
await interaction.channel.permissionOverwrites.create(Admin.id, {
VIEW_CHANNEL: true,
});
await interaction.reply({
embeds: [embed],
ephemeral: true,
});
}
await interaction.channel.permissionOverwrites.create(
interaction.guild.id,
{
VIEW_CHANNEL: false,
}
);
const CloseButton = new Discord.MessageButton()
.setCustomId("ticketclose")
.setLabel("Close")
.setStyle(supportbot.TicketCloseColour)
.setEmoji(supportbot.TicketCloseEmoji);
});
const LockButton = new Discord.MessageButton()
.setCustomId("ticketlock")
.setLabel("Lock")
.setStyle(supportbot.TicketLockColour)
.setEmoji(supportbot.TicketLockEmoji);
const TicketClaimButton = new Discord.MessageButton()
.setCustomId("ticketclaim")
.setLabel("Claim")
.setStyle(supportbot.TicketClaimColour)
.setEmoji(supportbot.TicketClaimEmoji);
const row = new Discord.MessageActionRow().addComponents(
CloseButton, LockButton, TicketClaimButton
);
const ArchiveEmbed = new Discord.MessageEmbed()
.setTitle("Unarchived")
.setDescription(`Unarchived ${interaction.channel.name}`)
.setColor(supportbot.SuccessColour);
interaction.reply({ embeds: [ArchiveEmbed] });
interaction.message.edit({ components: [row] });
}
}
if (interaction.customId === "ticketclaim") {
if (interaction.channel.name.startsWith(supportbot.TicketPrefix)) {
const Staff = await interaction.client.getRole(supportbot.Staff, interaction.guild);
interaction.message.fetch();
let User = interaction.guild.members.cache.get(interaction.user.id);
let Admin =
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.name === supportbot.Admin
) ||
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.id === supportbot.Admin
);
if (!interaction.member.roles.cache.has(Admin.id)) {
return await interaction.reply({
content: "You don't have permission to do that.",
ephemeral: true,
});
}
let all = interaction.channel.permissionOverwrites.cache;
const ticketUnclaimButton = new Discord.MessageButton()
.setCustomId("ticketunclaim")
.setLabel("Unclaim")
.setStyle(supportbot.TicketUnclaimColour)
.setEmoji(supportbot.TicketUnclaimEmoji);
const CloseButton = new Discord.MessageButton()
.setCustomId("ticketclose")
.setLabel("Close")
.setStyle(supportbot.TicketCloseColour)
.setEmoji(supportbot.TicketCloseEmoji);
const LockButton = new Discord.MessageButton()
.setCustomId("ticketlock")
.setLabel("Lock")
.setStyle(supportbot.TicketLockColour)
.setEmoji(supportbot.TicketLockEmoji);
const row = new Discord.MessageActionRow().addComponents(
CloseButton, LockButton, ticketUnclaimButton
);
const ArchiveEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.TicketClaimTitle)
.setDescription(supportbot.TicketClaimMessage + " <@" + interaction.user.id + ">")
.setColor(supportbot.EmbedColour);
interaction.reply({ embeds: [ArchiveEmbed]});
interaction.message.edit({ components: [row] });
await interaction.channel.permissionOverwrites.edit(Staff.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: false,
});
}
await interaction.channel.permissionOverwrites.edit(interaction.user.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
});
}
}
if (interaction.customId === "ticketunclaim") {
if (interaction.channel.name.startsWith(supportbot.TicketPrefix)) {
const Staff = await interaction.client.getRole(supportbot.Staff, interaction.guild);
interaction.message.fetch();
let User = interaction.guild.members.cache.get(interaction.user.id);
let Admin =
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.name === supportbot.Admin
) ||
interaction.guild.roles.cache.find(
(AdminUser) => AdminUser.id === supportbot.Admin
);
if (!interaction.member.roles.cache.has(Admin.id)) {
return await interaction.reply({
content: "You don't have permission to do that.",
ephemeral: true,
});
}
let all = interaction.channel.permissionOverwrites.cache;
const CloseButton = new Discord.MessageButton()
.setCustomId("ticketclose")
.setLabel("Close")
.setStyle(supportbot.TicketCloseColour)
.setEmoji(supportbot.TicketCloseEmoji);
const LockButton = new Discord.MessageButton()
.setCustomId("ticketlock")
.setLabel("Lock")
.setStyle(supportbot.TicketLockColour)
.setEmoji(supportbot.TicketLockEmoji);
const TicketClaimButton = new Discord.MessageButton()
.setCustomId("ticketclaim")
.setLabel("Claim")
.setStyle(supportbot.TicketClaimColour)
.setEmoji(supportbot.TicketClaimEmoji);
const row = new Discord.MessageActionRow().addComponents(
CloseButton, LockButton, TicketClaimButton
);
const ArchiveEmbed = new Discord.MessageEmbed()
.setTitle(supportbot.TicketUnclaimTitle)
.setDescription(supportbot.TicketUnclaimMessage + " <@" + interaction.user.id + ">")
.setColor(supportbot.EmbedColour);
interaction.reply({ embeds: [ArchiveEmbed]});
interaction.message.edit({ components: [row] });
await interaction.channel.permissionOverwrites.edit(Staff.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
});
}
await interaction.channel.permissionOverwrites.edit(interaction.user.id, {
VIEW_CHANNEL: true,
SEND_MESSAGES: true,
});
}
}
);
-166
View File
@@ -1,166 +0,0 @@
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const axios = require("axios");
const { OpenAI } = require('openai');
// Load configuration files with validation
function loadConfig(path) {
try {
return yaml.load(fs.readFileSync(path, "utf8"));
} catch (error) {
console.error(`Error loading config file at ${path}:`, error);
throw error;
}
}
const supportbotai = yaml.load(fs.readFileSync("./Configs/supportbot-ai.yml"));
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
// Validate configuration values
function validateConfig(config, keys) {
keys.forEach(key => {
if (!config[key]) {
throw new Error(`Missing configuration key: ${key}`);
}
});
}
const CHANNELS = [supportbotai.Channels.AIChannel];
// Initialize Discord client
const client = new Discord.Client({
intents: ['Guilds', 'GuildMembers', 'GuildMessages']
});
// Load custom Event structure
const Event = require("../Structures/Event.js");
// Initialize OpenAI client
const openai = new OpenAI({
apiKey: supportbotai.General.OpenAI_Key,
});
const PASTEBIN_API_KEY = supportbotai.General.PastebinAPI_Key;
const PASTEBIN_API_URL = supportbotai.General.PastebinAPI_URL;
// Function to create a paste on Pastebin
async function createPaste(content) {
try {
const response = await axios.post(PASTEBIN_API_URL, new URLSearchParams({
api_dev_key: PASTEBIN_API_KEY,
api_option: 'paste',
api_paste_code: content,
api_paste_private: 1, // 0 = public, 1 = unlisted, 2 = private
api_paste_expire_date: '1D', // Expire in 1 day
api_paste_format: 'text'
}));
return response.data;
} catch (error) {
console.error('Pastebin Error:', error);
throw error;
}
}
// Event handler for message creation
module.exports = new Event("messageCreate", async (client, message) => {
if (message.author.bot || !message.guild) return;
if (!CHANNELS.includes(message.channelId) && !message.mentions.users.has(client.user.id)) return;
if (supportbotai.Enabled) {
const sendTypingInterval = setInterval(() => {
message.channel.sendTyping();
}, 5000);
let conversation = [{
role: "system",
content: "SupportBot is your friendly neighbourhood support bot."
}];
let prevMessages = await message.channel.messages.fetch({ limit: 10 });
prevMessages = prevMessages.reverse().filter(msg => !msg.author.bot || msg.author.id === client.user.id);
prevMessages.forEach((msg) => {
const username = msg.author.username.replace(/\s+/g, '_').replace(/[^\w\s]/gi, '');
conversation.push({
role: msg.author.id === client.user.id ? "assistant" : "user",
name: username,
content: msg.content,
});
});
try {
const response = await openai.chat.completions.create({
model: supportbotai.General.Model,
messages: conversation,
max_tokens: supportbotai.General.Tokens,
});
clearInterval(sendTypingInterval);
if (response.choices && response.choices.length > 0) {
const replyContent = response.choices[0].message.content;
const SupportBotAI = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(replyContent)
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
if (replyContent.length > 2000) {
const pasteLink = await createPaste(replyContent);
const SupportBotAIPastebin = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.MessageTooLong.replace("{pastebin}", pasteLink))
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [SupportBotAIPastebin] });
} else {
message.reply({ embeds: [SupportBotAI] });
}
} else {
const SupportBotAIErrorResponse = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.ErrorResponse)
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [SupportBotAIErrorResponse], ephemeral: true });
}
} catch (error) {
clearInterval(sendTypingInterval);
const SupportBotAIErrorResponse = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.OpenAIError)
.setColor(supportbot.Embed.Colours.Error)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
console.error('OpenAI Error:', error);
message.reply({ embeds: [SupportBotAIErrorResponse], ephemeral: true });
}
}
if (supportbotai.Enabled === false) {
const AIDisabled = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.AIDisabled)
.setColor(supportbot.Embed.Colours.Error)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [AIDisabled], ephemeral: true })
return;
}
});
+148 -133
View File
@@ -4,11 +4,7 @@
const fs = require("fs");
const Discord = require("discord.js");
const { Client, GatewayIntentBits, ActivityType } = require('discord.js');
const client = new Discord.Client({intents: 32767})
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
@@ -16,149 +12,103 @@ const panelconfig = yaml.load(
fs.readFileSync("./Configs/ticket-panel.yml", "utf8")
);
const cmdconfig = yaml.load(
fs.readFileSync("./Configs/commands.yml", "utf8")
);
const msgconfig = yaml.load(
fs.readFileSync("./Configs/messages.yml", "utf8")
);
const Event = require("../Structures/Event.js");
let chan1 = client.channels.cache.get(panelconfig.Channel);
module.exports = new Event("ready", async (client, interaction) => {
const { getRole, getChannel, getCategory } = client;
client.user.setActivity(supportbot.BotActivity, {
type: supportbot.ActivityType,
url: supportbot.StreamingURL,
});
if (supportbot.Activity.Type === "Playing", "playing") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Playing }],
status: supportbot.Activity.Type,
});
}
if (supportbot.Activity.Type === "Watching", "watching") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Watching }],
status: supportbot.Activity.Type,
});
}
if (supportbot.Activity.Type === "Listening", "listening") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Listening }],
status: supportbot.Activity.Type,
});
}
if (supportbot.Activity.Type === "Competing", "competing") {
client.user.setPresence({
activities: [{ name: supportbot.Activity.Status, type: Discord.ActivityType.Competing }],
status: supportbot.Activity.Type,
});
}
console.log(`\u001b[32m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(`\u001b[36m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(`\u001b[91m`, `┏━━━┓╋╋╋╋╋╋╋╋╋╋╋╋╋┏┓┏━━┓╋╋╋┏┓`);
console.log(`\u001b[91m`, `┃┏━┓┃╋╋╋╋╋╋╋╋╋╋╋╋┏┛┗┫┏┓┃╋╋┏┛┗┓`);
console.log(`\u001b[91m`, `┃┗━━┳┓┏┳━━┳━━┳━━┳┻┓┏┫┗┛┗┳━┻┓┏┛`);
console.log(`\u001b[91m`, `┗━━┓┃┃┃┃┏┓┃┏┓┃┏┓┃┏┫┃┃┏━┓┃┏┓┃┃`);
console.log(`\u001b[91m`, `┃┗━┛┃┗┛┃┗┛┃┗┛┃┗┛┃┃┃┗┫┗━┛┃┗┛┃┗┓`);
console.log(`\u001b[91m`, `┗━━━┻━━┫┏━┫┏━┻━━┻┛┗━┻━━━┻━━┻━┛`);
console.log(`\u001b[91m`, `┗╋╋╋╋╋╋╋┃┃╋┃┃`);
console.log(`\u001b[91m`, `╋╋╋╋╋╋╋┗┛╋┗┛`);
console.log(` `);
console.log(`\u001b[31m`, `┏━━━┓╋╋╋╋╋╋╋╋╋╋╋╋╋┏┓┏━━┓╋╋╋┏┓`);
console.log(`\u001b[31m`, `┃┏━┓┃╋╋╋╋╋╋╋╋╋╋╋╋┏┛┗┫┏┓┃╋╋┏┛┗┓`);
console.log(`\u001b[31m`, `┃┗━━┳┓┏┳━━┳━━┳━━┳┻┓┏┫┗┛┗┳━┻┓┏┛`);
console.log(`\u001b[31m`, `┗━━┓┃┃┃┃┏┓┃┏┓┃┏┓┃┏┫┃┃┏━┓┃┏┓┃┃`);
console.log(`\u001b[31m`, `┃┗━┛┃┗┛┃┗┛┃┗┛┃┗┛┃┃┃┗┫┗━┛┃┗┛┃┗┓`);
console.log(`\u001b[31m`, `┗━━━┻━━┫┏━┫┏━┻━━┻┛┗━┻━━━┻━━┻━┛`);
console.log(`\u001b[31m`, `┗╋╋╋╋╋╋╋┃┃╋┃┃`);
console.log(`\u001b[31m`, `╋╋╋╋╋╋╋┗┛╋┗┛`);
console.log(` `);
console.log(`\u001b[32m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(`\u001b[36m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(` `);
console.log(
`\u001b[31m`,
`${supportbot.General.Name} | [${supportbot.SupportBot_Version}]`,
`\u001b[32m`,
`Connected to Discord`,
`\u001b[33m`,
`${supportbot.Name} | ${supportbot.SupportBot_Version}`,
`\u001b[36m`,
`Connected to Discord`
);
console.log(`\u001b[31m`, `SupportBot proudly created by Emerald Development`);
console.log(` `);
console.log(
`\u001b[31m`,
`Discord`,
`\u001b[32m`,
`https://dsc.gg/emerald-dev`,
);
console.log(
`\u001b[31m`,
`Website`,
`\u001b[32m`,
`https://emeraldsrv.com`,
);
console.log(
`\u001b[31m`,
`Marketplace`,
`\u001b[32m`,
`https://market.emeraldsrv.com`,
);
console.log(
`\u001b[31m`,
`Documentation`,
`\u001b[32m`,
`https://emeraldsrv.com/third-party`,
);
console.log(` `);
console.log(
`\u001b[31m`,
`Invite URL:`,
`\u001b[33m`,
`Invite to your server:`,
`\u001b[36m`,
`https://discord.com/api/oauth2/authorize?client_id=` +
client.user.id +
`&permissions=8&scope=bot%20applications.commands`
);
console.log(
`\u001b[33m`,
`Resources:`,
`\u001b[36m`,
`https://emeraldsrv.dev/resources`
);
console.log(
`\u001b[33m`,
`Documentation:`,
`\u001b[36m`,
`https://emeraldsrv.dev/wiki/supportbot`
);
console.log(
`\u001b[33m`,
`Discord:`,
`\u001b[36m`,
`https://emeraldsrv.dev/discord`
);
console.log(
`\u001b[33m`,
`Hosting:`,
`\u001b[36m`,
`https://emeraldsrv.dev/hosting`
);
console.log(` `);
console.log(`\u001b[32m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(`\u001b[37m`, `SupportBot proudly created by Emerald Services`);
console.log(` `);
console.log(`\u001b[31m`, `――――――――――――――――――――――――――――――――――――――――――――`);
const roles = [
supportbot.Roles.StaffMember.Admin,
supportbot.Roles.StaffMember.Staff,
supportbot.Roles.ModRoles.Blacklisted,
supportbot.Roles.ModRoles.Muted
supportbot.Admin,
supportbot.Staff,
supportbot.TicketBlackListRole,
];
supportbot.Departments.forEach((department) => roles.push(department.role));
if (supportbot.Roles.AutoRole.Role) roles.push(supportbot.Roles.AutoRole.Role);
const channels = [
supportbot.Suggestions.Channel,
supportbot.Ticket.Log.TicketLog,
supportbot.Ticket.Log.TranscriptLog,
panelconfig.Channel,
supportbot.Welcome.Channel,
supportbot.Leave.Channel,
supportbot.Translate.Log
];
if (supportbot.AutoRole) roles.push(supportbot.JoinRole);
const channels = [
supportbot.SuggestionChannel,
supportbot.TicketLog,
supportbot.TranscriptLog,
panelconfig.Channel,
supportbot.WelcomeChannel,
supportbot.LeaveChannel,
supportbot.TranslateLogChannel
];
//const categories = [supportbot.TicketCategory];
if (!channels) {
console.log("\u001b[31m", `[MISSING CHANNEL]`, `\u001b[37;1m`, `${channels}`, "\u001b[31m", `channel not found. Please check your config file.`);
return;
}
// else {
// console.log(`\u001b[32m`, `[CHANNEL LOCATED]`, `\u001b[37;1m`, `${channels}`, `\u001b[32;1m`, `channel has been found.`);
// }
const missingC = [];
const missingR = [];
const missingCat = [];
for (let c of channels) {
if ((c === supportbot.SuggestionChannel && supportbot.DisableSuggestionsChannel) || c === supportbot.TicketLog && supportbot.DisableTicketLogChannel) {
continue;
}
const find = await getChannel(c, client.guilds.cache.first());
if (!find) missingC.push(c);
}
for (let r of roles) {
const find = await getRole(r, client.guilds.cache.first());
if (!find) missingR.push(r);
@@ -170,33 +120,98 @@ module.exports = new Event("ready", async (client, interaction) => {
if (missingR.length > 0) {
console.log(
"\u001b[31m",
`[MISSING CONFIGURATION]`,
"\u001b[33m",
`The following Roles could not be found in your server.\n`, `\u001b[31m`, `[${missingR.join(
`[WARN] The following Roles could not be found! Please check your configs!\n${missingR.join(
", "
)}]`, `\n `,
)}`
);
}
if (missingC.length > 0) {
console.log(
"\u001b[31m",
`[MISSING CONFIGURATION]`,
"\u001b[33m",
`The following Channels could not be found in your server.\n`, `\u001b[31m`, `[${missingC.join(
`[WARN] The following Channels could not be found! Please check your configs!\n${missingC.join(
", "
)}]`, `\n `
)}`
);
}
if (missingCat.length > 0) {
console.log(
"\u001b[31m",
`[MISSING CONFIGURATION]`,
"\u001b[33m",
`The following Categories could not be found in your server.\n`, `\u001b[31m`, `[${missingCat.join(
`[WARN] The following Categories could not be found! Please check your configs!\n${missingCat.join(
", "
)}]`, `\n `,
)}`
);
}
});
if (panelconfig.TicketPanel) {
let chan1 = await client.getChannel(
panelconfig.Channel,
client.guilds.cache.first()
);
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 = JSON.parse(
fs.readFileSync("./Data/ticket-panel-id.json", "utf8")
);
chan1.messages.fetch(panelid.TicketPanelID).catch(async () => {
let embed = new Discord.MessageEmbed()
.setTitle(panelconfig.PanelTitle)
.setColor(panelconfig.PanelColour)
.setFooter({
text: supportbot.EmbedFooter,
iconURL: interaction.user.displayAvatarURL(),
});
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;
button = supportbot.Departments.map((x) =>
new Discord.MessageButton()
.setCustomId("department-" + supportbot.Departments.indexOf(x))
.setLabel(x.title)
.setStyle(x.color)
.setEmoji(x.emoji)
);
let row = new Discord.MessageActionRow().addComponents(button);
await chan1
.send({
embeds: [embed],
components: [row],
})
.then((r) => {
let data = {
id: panelid.id,
TicketPanelID: r.id,
};
fs.writeFileSync(
"./Data/ticket-panel-id.json",
JSON.stringify(data),
"utf8"
);
})
.catch((e) => {
console.log("Raw: " + e);
});
});
}
});
+3 -16
View File
@@ -1,6 +1,6 @@
<h1 align="center">
<br>
<a href="https://github.com/Emerald-Services/SupportBot"><img src="https://i.imgur.com/cuadAYv.png"></a>
<a href="https://github.com/Emerald-Services/SupportBot"><img src="https://i.imgur.com/tzi3d7Q.png"></a>
<br>
SupportBot
<br>
@@ -24,22 +24,10 @@
<img src="https://img.shields.io/github/downloads/Emerald-Services/SupportBot/total?style=for-the-badge" alt="shield.png">
</a>
## Supported Versions
| SupportBot | Node.JS | Discord.JS | Supported |
|------------|---------|------------|------------|
| 8.x | 20.x | 14.x. | ✅ Yes
| 7.7.3 | 16.x | 13.x. | ✅ Yes
| 7.x | 16.x | 13.x. | ❌ No
| 6.x | 14.x | 13.x. | ❌ No
| 5.x | 12.x | 13.x. | ❌ No
| 4.x | 11.x | 13.x. | ❌ No
| Older | 10.x | 13.x. | ❌ No
</div>
<p align="center">
<a href="https://emeraldsrv.com/">Website</a>
<a href="https://emeraldsrv.dev/">Website</a>
•
<a href="https://github.com/Emerald-Services/SupportBot/wiki">Wiki</a>
<br>
@@ -60,7 +48,7 @@ SupportBot is an Open-Source discord bot built with [discord.js](https://github.
## Support
<a href="https://emeraldsrv.com/discord">
<a href="https://emeraldsrv.dev/discord">
<img alt="Discord" src="https://img.shields.io/discord/597779408295821323?logo=discord&logoColor=white&style=for-the-badge">
</a>
@@ -72,7 +60,6 @@ Released under the [MIT](https://opensource.org/licenses/MIT) license.
## Third-Party
- [Official addons repository](https://github.com/Emerald-Services/Addons/)
- [Syphers Addons](https://github.com/SypherRed/SB_Addons_Unofficial)
- [BuiltByBit](https://builtbybit.com/supportbot)
- [Polymart](https://polymart.org/resource/supportbot-1-discord-ticket-bot.518)
+54 -107
View File
@@ -1,156 +1,101 @@
// C:\Users\ollie\Documents\GitHub\SupportBot\Structures\Client.js
// SupportBot | Emerald Services
// Client Structure
const fs = require("fs");
const Discord = require("discord.js");
const { GatewayIntentBits, Partials } = require('discord.js');
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
const Discord = require("discord.js");
const intents = new Discord.Intents(32767);
const yaml = require("js-yaml");
const supportbot = yaml.load(
fs.readFileSync("./Configs/supportbot.yml", "utf8")
);
class Client extends Discord.Client {
constructor() {
super({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildMessages
],
partials: [Partials.Channel]
});
super({ intents });
this.commands = new Discord.Collection();
}
async getChannel(channel, guild) {
if (!channel) return null; // Add check for undefined channel
return guild.channels.cache.find(
(c) =>
(c.type === Discord.ChannelType.GuildText || c.type === Discord.ChannelType.GuildNews) &&
(c.id === channel || (c.name && c.name.toLowerCase() === channel.toLowerCase()))
(c.type === "GUILD_TEXT" || c.type === "GUILD_NEWS") &&
(c.id === channel || c.name.toLowerCase() === channel.toLowerCase())
);
}
async getRole(role, guild) {
if (!role) return null; // Add check for undefined role
return guild.roles.cache.find(
(r) => r.id === role || (r.name && r.name.toLowerCase() === role.toLowerCase())
(r) => r.id === role || r.name.toLowerCase() === role.toLowerCase()
);
}
async getCategory(category, guild) {
if (!category) return null; // Add check for undefined category
return guild.channels.cache.find(
(c) =>
c.type === Discord.ChannelType.GuildCategory &&
(c.id === category || (c.name && c.name.toLowerCase() === category.toLowerCase()))
c.type === "GUILD_CATEGORY" &&
(c.id === category || c.name.toLowerCase() === category.toLowerCase())
);
}
async start(token) {
let tempCommandFiles = fs.readdirSync("./Commands").filter((file) => file.endsWith(".js"));
var tempCommandFiles = fs.readdirSync("./Commands").filter((file) => file.endsWith(".js"));
if (cmdconfig.Suggestion.Enabled === false) {
if (supportbot.DisableSuggestions) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "suggest.js");
}
if (cmdconfig.Help.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "help.js");
}
if (cmdconfig.Info.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "info.js");
}
if (cmdconfig.OpenTicket.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "ticket.js");
}
if (cmdconfig.CloseTicket.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "close.js");
}
if (cmdconfig.Embed.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "embed.js");
}
if (cmdconfig.Translate.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "translate.js");
}
if (cmdconfig.UserInfo.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "userinfo.js");
}
if (cmdconfig.Ping.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
}
if (cmdconfig.Ping.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
}
if (supportbot.Ticket.ClaimTickets.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "ticketstats.js");
}
const commandFiles = tempCommandFiles;
const addonFiles = fs
.readdirSync("./Addons")
.filter((file) => file.endsWith(".js"));
const addons = addonFiles.map((file) => {
let addon = require(`../Addons/${file}`);
addon.name = file.split(".")[0];
return addon;
});
const commands = commandFiles.map((file) => require(`../Commands/${file}`));
// Commands
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
commands.forEach((cmd) => {
console.log(`\u001b[32m`, `[CMD]`, `\u001b[37;1m`, `${cmd.name}`, `\u001b[32;1m`, "Loaded");
console.log(`\u001b[31;1m`, `${cmd.name}`, `\u001b[32;1m`, "Loaded");
this.commands.set(cmd.name, cmd);
});
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
// Addons
console.log(" ");
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
if (supportbot.General.Addons.Enabled) {
const addonFiles = fs.readdirSync("./Addons").filter((file) => file.endsWith(".js"));
const addons = addonFiles.map((file) => {
let addon = require(`../Addons/${file}`);
addon.name = file.split(".")[0];
return addon;
addons.forEach((addon) => {
console.log(
`\u001b[33m`,
`[ADDON]`,
`\u001b[31;1m`,
`${addon.name}`,
`\u001b[32;1m`,
"Loaded"
);
addon.commands?.forEach((command) => {
this.commands.set(command.name, command);
});
// Addons
console.log(" ");
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
addons.forEach((addon) => {
console.log(
`\u001b[32m`,
`[ADDON]`,
`\u001b[37;1m`,
`${addon.name}`,
`\u001b[32;1m`,
"Loaded"
);
addon.commands?.forEach((command) => {
this.commands.set(command.name, command);
});
addon.events?.forEach((event) => {
this.on(event.event, (...args) => event.run(this, ...args));
});
addon.events?.forEach((event) => {
this.on(event.event, (...args) => event.run(this, ...args));
});
});
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
}
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
// Slash Commands
this.once("ready", async () => {
await this.guilds.cache.first()?.commands.set(this.commands);
console.log(
"\u001b[32m",
`[SUCCESS]`,
`\u001b[37;1m`,
`\u001b[32;1m`,
`Slash Commands Registered for ${this.guilds.cache.first().name}`
);
});
@@ -158,11 +103,13 @@ class Client extends Discord.Client {
console.log(" ");
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
fs.readdirSync("./Events").filter((file) => file.endsWith(".js")).forEach((file) => {
const event = require(`../Events/${file}`);
console.log(`\u001b[32m`, `[EVENT]`, `\u001b[37;1m`, `${event.event}`, `\u001b[32;1m`, "Loaded");
this.on(event.event, (...args) => event.run(this, ...args));
});
fs.readdirSync("./Events")
.filter((file) => file.endsWith(".js"))
.forEach((file) => {
const event = require(`../Events/${file}`);
console.log(`\u001b[31;1m`, `${event.event}`, `\u001b[32;1m`, "Loaded");
this.on(event.event, (...args) => event.run(this, ...args));
});
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
if (process.argv[2] !== "test") {
+2 -23
View File
@@ -18,27 +18,6 @@ const supportbot = yaml.load(
);
const Client = require("./Structures/Client.js");
const client = new Client({
intents: ['Guilds', 'GuildMembers', 'GuildMessages']
});
client.start(supportbot.General.Token);
const client = new Client({});
client.start(supportbot.Token);
+5 -8
View File
@@ -1,11 +1,11 @@
{
"name": "supportbot",
"version": "8.0.1",
"version": "7.7.3",
"description": "SupportBot is an open-sourced support system for discord. It's completely free to use with high amounts of customization to match your own brand.",
"main": "index.js",
"scripts": {
"setup": "npm i && node index.js",
"start": "node index.js"
"start": "npm i && node index.js",
"test": "node index.js test"
},
"repository": {
"type": "git",
@@ -19,11 +19,8 @@
"homepage": "https://github.com/Emerald-Services/SupportBot#readme",
"dependencies": {
"@vitalets/google-translate-api": "^8.0.0",
"axios": "^1.7.2",
"chatgpt": "^5.2.5",
"discord.js": "^14.13.0",
"discord.js": "^13.6.0",
"js-yaml": "^4.1.0",
"moment": "^2.29.3",
"openai": "^4.50.0"
"moment": "^2.29.3"
}
}