Compare commits

..
8 Commits
Author SHA1 Message Date
1tzEmerald 81bda67ae4 Merge pull request #172 from Emerald-Services/1tzemerald-patch-3
Update supportbot.yml
2024-07-30 17:58:41 +01:00
1tzEmerald 25bbd1ff85 Update supportbot.yml 2024-07-30 17:58:01 +01:00
1tzEmerald 164d695a5f Merge pull request #171 from Emerald-Services/1tzemerald-patch-2
Create 0000000000000000.json
2024-07-30 17:57:33 +01:00
1tzEmerald 57e4a3e77c Create 0000000000000000.json 2024-07-30 17:57:12 +01:00
1tzEmerald a6ac532b2b Merge pull request #169 from Emerald-Services/dev
8.0.1 Dev -> Release Branch
2024-07-30 17:47:13 +01:00
1tzEmerald 4f14722e14 8.0.1 Update 2024-07-30 17:45:35 +01:00
1tzEmerald 9a6eece7a1 v8.1 2024-07-09 22:49:49 +01:00
ItsNyoty 48500fe8a4 Update README.md 2024-07-03 13:42:46 +02:00
26 changed files with 2572 additions and 825 deletions

No files matched your search

+193
View File
@@ -0,0 +1,193 @@
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
} = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.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.AddUser.Command,
description: cmdconfig.AddUser.Description,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "user",
description: "The user to add",
type: ApplicationCommandOptionType.User,
required: true,
},
],
permissions: cmdconfig.AddUser.Permission,
async run(interaction) {
const userToAdd = interaction.options.getUser("user");
const ticketChannel = interaction.channel;
const ticketDataPath = "./Data/TicketData.json";
// Check if the channel is a ticket thread
if (!ticketChannel.isThread()) {
const onlyInTicket = new EmbedBuilder()
.setTitle(msgconfig.AddUser.NotInTicket_Title)
.setDescription(msgconfig.AddUser.NotInTicket_Description)
.setColor(supportbot.Embed.Colours.Error);
return interaction.reply({
embeds: [onlyInTicket],
ephemeral: true,
});
}
const ticketInviteEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Invite_Title)
.setDescription(msgconfig.AddUser.Invite_Description.replace("%username%", userToAdd.username))
.setColor(supportbot.Embed.Colours.General);
await interaction.reply({
embeds: [ticketInviteEmbed],
ephemeral: true,
});
try {
const dmEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.DM_Title)
.setDescription(msgconfig.AddUser.DM_Description.replace("%channelname%", ticketChannel.name))
.setColor(supportbot.Embed.Colours.General);
const acceptButton = new ButtonBuilder()
.setCustomId("accept_invite")
.setLabel(msgconfig.AddUser.Accept_Label)
.setEmoji("✅")
.setStyle(ButtonStyle.Primary);
const rejectButton = new ButtonBuilder()
.setCustomId("reject_invite")
.setLabel(msgconfig.AddUser.Reject_Label)
.setEmoji("❌")
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder().addComponents(acceptButton, rejectButton);
const dmMessage = await userToAdd.send({
embeds: [dmEmbed],
components: [row],
});
const filter = (i) => i.user.id === userToAdd.id;
const collector = dmMessage.createMessageComponentCollector({
filter,
time: 60000,
});
collector.on("collect", async (i) => {
if (i.customId === "accept_invite") {
try {
await ticketChannel.members.add(userToAdd.id);
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
if (ticketIndex !== -1) {
ticketData.tickets[ticketIndex].subUsers.push(userToAdd.id);
fs.writeFileSync(ticketDataPath, JSON.stringify(ticketData, null, 4));
}
const acceptedEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Accepted_Title)
.setDescription(msgconfig.AddUser.Accepted_Message)
.setColor(supportbot.Embed.Colours.Success);
await i.update({
embeds: [acceptedEmbed],
components: [],
});
const addedToTicketEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.AddedToTicket_Title)
.setDescription(msgconfig.AddUser.AddedToTicket_Description.replace(
"%channel_link%",
`[${ticketChannel.name}](https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id})`
))
.setColor(supportbot.Embed.Colours.General);
const ticketLinkButton = new ButtonBuilder()
.setLabel(msgconfig.AddUser.ViewTicket_Label)
.setURL(`https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id}`)
.setStyle(ButtonStyle.Link);
await userToAdd.send({
embeds: [addedToTicketEmbed],
components: [new ActionRowBuilder().addComponents(ticketLinkButton)],
});
} catch (err) {
console.error("Error adding user to the ticket:", err);
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Error_Title)
.setDescription(msgconfig.AddUser.Error_Adding)
.setColor(supportbot.Embed.Colours.Error);
await i.update({
embeds: [errorEmbed],
components: [],
});
}
} else {
const declinedEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Declined_Title)
.setDescription(msgconfig.AddUser.Declined_Message)
.setColor(supportbot.Embed.Colours.Error);
await i.update({
embeds: [declinedEmbed],
components: [],
});
}
});
collector.on("end", (collected) => {
if (collected.size === 0) {
userToAdd.send({
embeds: [
new EmbedBuilder()
.setTitle(msgconfig.AddUser.NoResponse_Title)
.setDescription(msgconfig.AddUser.NoResponse_Message)
.setColor(supportbot.Embed.Colours.Warning),
],
});
}
});
} catch (error) {
if (error.code === 50007) {
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.DM_Error_Title)
.setDescription(msgconfig.AddUser.DM_Error_Description.replace("%username%", userToAdd.username))
.setColor(supportbot.Embed.Colours.Error);
await ticketChannel.send({
embeds: [errorEmbed],
});
} else {
console.error("Error sending DM:", error);
const unexpectedErrorEmbed = new EmbedBuilder()
.setTitle(msgconfig.AddUser.Unexpected_Error_Title)
.setDescription(msgconfig.AddUser.Unexpected_Error_Description.replace("%error%", error.message))
.setColor(supportbot.Embed.Colours.Error);
await ticketChannel.send({
embeds: [unexpectedErrorEmbed],
});
}
}
},
});
+2 -1
View File
@@ -81,7 +81,8 @@ module.exports = new Command({
const CloseButton = new Discord.ButtonBuilder()
.setCustomId("confirmCloseTicket")
.setLabel(supportbot.Ticket.Close.Confirmation_Button)
.setStyle(Discord.ButtonStyle.Danger);
.setEmoji(supportbot.Ticket.Close.Confirmation_Emoji)
.setStyle(supportbot.Ticket.Close.Confirmation_Style);
const row = new Discord.ActionRowBuilder().addComponents(CloseButton);
+119
View File
@@ -0,0 +1,119 @@
// File: Commands/ForceAddUser.js
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
} = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.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.ForceAddUser.Command,
description: cmdconfig.ForceAddUser.Description,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "user",
description: "The user to add",
type: ApplicationCommandOptionType.User,
required: true,
},
],
permissions: cmdconfig.ForceAddUser.Permission,
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)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new 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] });
const userToAdd = interaction.options.getUser("user");
const ticketChannel = interaction.channel;
const ticketDataPath = "./Data/TicketData.json";
if (!ticketChannel.isThread()) {
const onlyInTicket = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.NotInTicket_Title)
.setDescription(msgconfig.ForceAddUser.NotInTicket_Description)
.setColor(supportbot.Embed.Colours.Error);
return interaction.reply({
embeds: [onlyInTicket],
ephemeral: true,
});
}
try {
await ticketChannel.members.add(userToAdd.id);
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
if (ticketIndex !== -1) {
ticketData.tickets[ticketIndex].subUsers.push(userToAdd.id);
fs.writeFileSync(ticketDataPath, JSON.stringify(ticketData, null, 4));
}
const addedEmbed = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.Added_Title)
.setDescription(msgconfig.ForceAddUser.Added_Description.replace(
"%username%",
userToAdd.username
))
.setColor(supportbot.Embed.Colours.Success);
await interaction.reply({
embeds: [addedEmbed],
ephemeral: true,
});
const addedToTicketEmbed = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.AddedToTicket_Title)
.setDescription(msgconfig.ForceAddUser.AddedToTicket_Description.replace(
"%channel_link%",
`[${ticketChannel.name}](https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id})`
))
.setColor(supportbot.Embed.Colours.General);
await userToAdd.send({
embeds: [addedToTicketEmbed],
});
} catch (err) {
console.error("Error adding user to the ticket:", err);
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.ForceAddUser.Error_Title)
.setDescription(msgconfig.ForceAddUser.Error_Adding)
.setColor(supportbot.Embed.Colours.Error);
await interaction.reply({
embeds: [errorEmbed],
ephemeral: true,
});
}
},
});
-79
View File
@@ -1,79 +0,0 @@
const fs = require("fs");
const Discord = require("discord.js");
const yaml = require("js-yaml");
const generateImage = require('../Structures/generateImage.js');
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
const Command = require("../Structures/Command.js");
module.exports = new Command({
name: "image",
description: "Create an image through SupportBot AI",
type: Discord.ApplicationCommandType.ChatInput,
options: [
{
name: "prompt",
description: "The prompt to generate an image from",
type: Discord.ApplicationCommandOptionType.String,
required: true,
},
{
name: "negativeprompt",
description: "The negative prompt to exclude from the image",
type: Discord.ApplicationCommandOptionType.String,
required: false,
},
{
name: "cfgscale",
description: "The cfg scale for the image generation",
type: Discord.ApplicationCommandOptionType.Number,
required: false,
}
],
permissions: "SendMessages",
async run(interaction) {
const prompt = interaction.options.getString("prompt");
const negativePrompt = interaction.options.getString("negativeprompt") || "";
const cfgScale = interaction.options.getNumber("cfgscale") || 7.5; // Default value
try {
const imageUrl = await generateImage(prompt, negativePrompt, cfgScale);
const ImageEmbed = new Discord.EmbedBuilder()
.setTitle("Generated Image")
.setDescription(`Here is the image generated for your prompt: "${prompt}"`)
.setImage(imageUrl)
.setColor(supportbot.Embed.Colours.General)
.setFooter({
text: supportbot.Embed.Footer,
iconURL: interaction.user.displayAvatarURL(),
});
if (!interaction.replied) {
await interaction.reply({
ephemeral: true,
embeds: [ImageEmbed],
});
} else {
await interaction.followUp({
ephemeral: true,
embeds: [ImageEmbed],
});
}
} catch (error) {
console.error('Error generating image:', error);
if (!interaction.replied) {
await interaction.reply({
ephemeral: true,
content: `An error occurred while generating the image: ${error.message}. Please try again later.`,
});
} else {
await interaction.followUp({
ephemeral: true,
content: `An error occurred while generating the image: ${error.message}. Please try again later.`,
});
}
}
},
});
+3 -3
View File
@@ -25,10 +25,10 @@ function updateClockedInStatus(profileEmbed, clockedIn) {
}
module.exports = new Command({
name: 'profile',
description: 'Show user profile',
name: cmdconfig.Profile.Command,
description: cmdconfig.Profile.Description,
type: ApplicationCommandType.ChatInput,
permissions: ["SendMessages"],
permissions: cmdconfig.Profile.Permission,
options: [
{
name: 'user',
+125
View File
@@ -0,0 +1,125 @@
// File path: Commands/RemoveUser.js
const fs = require("fs");
const {
EmbedBuilder,
ApplicationCommandOptionType,
ApplicationCommandType,
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
} = require("discord.js");
const yaml = require("js-yaml");
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.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.RemoveUser.Command,
description: cmdconfig.RemoveUser.Description,
type: ApplicationCommandType.ChatInput,
options: [
{
name: "user",
description: "The user to remove",
type: ApplicationCommandOptionType.User,
required: true,
},
],
permissions: cmdconfig.RemoveUser.Permission,
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)
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
const NoPerms = new 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] });
const userToRemove = interaction.options.getUser("user");
const ticketChannel = interaction.channel;
const ticketDataPath = "./Data/TicketData.json";
// Check if the channel is a ticket thread
if (!ticketChannel.isThread()) {
const onlyInTicket = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.NotInTicket_Title)
.setDescription(msgconfig.RemoveUser.NotInTicket_Description)
.setColor(supportbot.Embed.Colours.Error);
return interaction.reply({
embeds: [onlyInTicket],
ephemeral: true,
});
}
try {
await ticketChannel.members.remove(userToRemove.id);
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
if (ticketIndex !== -1) {
const subUsers = ticketData.tickets[ticketIndex].subUsers;
const userIndex = subUsers.indexOf(userToRemove.id);
if (userIndex !== -1) {
subUsers.splice(userIndex, 1);
fs.writeFileSync(ticketDataPath, JSON.stringify(ticketData, null, 4));
}
}
const removedEmbed = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.Removed_Title)
.setDescription(msgconfig.RemoveUser.Removed_Message)
.setColor(supportbot.Embed.Colours.Success);
await interaction.reply({
embeds: [removedEmbed],
ephemeral: true,
});
const removedFromTicketEmbed = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.RemovedFromTicket_Title)
.setDescription(msgconfig.RemoveUser.RemovedFromTicket_Description.replace(
"%channel_link%",
`[${ticketChannel.name}](https://discord.com/channels/${ticketChannel.guild.id}/${ticketChannel.id})`
))
.setColor(supportbot.Embed.Colours.General);
await userToRemove.send({
embeds: [removedFromTicketEmbed],
});
} catch (err) {
console.error("Error removing user from the ticket:", err);
const errorEmbed = new EmbedBuilder()
.setTitle(msgconfig.RemoveUser.Error_Title)
.setDescription(msgconfig.RemoveUser.Error_Removing)
.setColor(supportbot.Embed.Colours.Error);
await interaction.reply({
embeds: [errorEmbed],
ephemeral: true,
});
}
},
});
+62 -52
View File
@@ -8,7 +8,7 @@ const {
ButtonBuilder,
StringSelectMenuBuilder,
StringSelectMenuOptionBuilder,
ButtonStyle
ButtonStyle,
} = require("discord.js");
const yaml = require("js-yaml");
@@ -22,7 +22,7 @@ const TicketNumberID = require("../Structures/TicketID.js");
async function getClockedInUsers(guild) {
const clockedInUsers = new Set();
const profilesDir = './Data/Profiles';
const profileFiles = fs.readdirSync(profilesDir);
@@ -201,10 +201,6 @@ async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, atte
}
}
module.exports = new Command({
name: cmdconfig.OpenTicket.Command,
description: cmdconfig.OpenTicket.Description,
@@ -220,7 +216,11 @@ module.exports = new Command({
async run(interaction) {
try {
let department = interaction.customId?.split("-")[1] || null;
let TicketReason = null;
if (supportbot.Ticket.TicketReason) {
TicketReason = interaction.reason || null; // Retrieve the reason from the interaction object
}
let TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const { getRole, getChannel } = interaction.client;
let User = interaction.guild.members.cache.get(interaction.user.id);
@@ -256,7 +256,7 @@ module.exports = new Command({
}
let ticketNumberID = await TicketNumberID.pad();
const TicketSubject = interaction.options?.getString("reason") || msgconfig.Ticket.InvalidSubject;
const TicketSubject = TicketReason || msgconfig.Ticket.InvalidSubject;
const TicketExists = new EmbedBuilder()
.setTitle("Ticket Exists!")
@@ -304,9 +304,7 @@ module.exports = new Command({
}
// Add user to the ticket channel
if (!department) {
await ticketChannel.members.add(interaction.user.id);
}
await ticketChannel.members.add(interaction.user.id);
// Save ticket data
TicketData.tickets.push({
@@ -335,6 +333,7 @@ module.exports = new Command({
msgconfig.Ticket.TicketCreatedAlert.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
.replace(/%ticketreason%/g, TicketSubject)
)
.setColor(supportbot.Embed.Colours.General);
await interaction.reply({ embeds: [CreatedTicket], ephemeral: true });
@@ -356,29 +355,37 @@ module.exports = new Command({
msgconfig.Ticket.TicketMessage.replace(/%ticketauthor%/g, interaction.user.id)
.replace(/%ticketid%/g, ticketChannel.id)
.replace(/%ticketusername%/g, interaction.user.username)
.replace(/%ticketreason%/g, TicketSubject)
)
.setColor(supportbot.Embed.Colours.General);
// Add reason field if ticket reason is enabled
if (supportbot.Ticket.TicketReason && TicketReason) {
TicketMessage.addFields(
{ name: "Reason", value: TicketReason, inline: false }
);
}
// Create the control panel
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("Archive")
.setDescription("Acrhive the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.ArchiveEmoji)
.setValue("archiveticket"),
new StringSelectMenuOptionBuilder()
.setLabel("Lock Ticket")
.setDescription("Lock the ticket.")
.setEmoji(supportbot.SelectMenus.Tickets.LockEmoji)
.setValue("lockticket"),
new StringSelectMenuOptionBuilder()
.setLabel("Enable Invites")
.setDescription("Enable invites.")
@@ -399,11 +406,12 @@ module.exports = new Command({
components: [row2],
});
// Handle department selection if not specified
if (!department) {
try {
let buttons = supportbot.Departments.map((x) =>
const buttons = supportbot.Departments.map((x, index) =>
new ButtonBuilder()
.setCustomId("Department" + supportbot.Departments.indexOf(x))
.setCustomId("Department" + index)
.setLabel(x.title)
.setStyle(x.color)
.setEmoji(x.emoji)
@@ -411,37 +419,39 @@ module.exports = new Command({
const row = new ActionRowBuilder().addComponents(buttons);
try {
const filter = (i) => i.user.id === interaction.user.id;
await m.awaitMessageComponent({
filter,
max: 1,
componentType: "BUTTON",
time: supportbot.Ticket.Timeout * 60000,
});
} catch (e) {
if (e.code === "COLLECTOR_ERROR") {
try {
let ticket = TicketData.tickets.findIndex((t) => t.id === ticketChannel.id);
TicketData.tickets[ticket].open = false;
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(TicketData, null, 4),
(err) => {
if (err) console.error(err);
}
);
interaction.user.send(
"Your ticket has timed out. Please open a new one, and select a department."
);
} catch (error) {return assignedUserId;
console.error("An error occurred while handling collector:", error);
}
return await ticketChannel.delete();
const message = await ticketChannel.send({
content: "Please select a department:",
components: [row],
});
const filter = (i) => i.user.id === interaction.user.id;
await message.awaitMessageComponent({
filter,
max: 1,
componentType: "BUTTON",
time: supportbot.Ticket.Timeout * 60000,
});
} catch (e) {
if (e.code === "COLLECTOR_ERROR") {
try {
const ticket = TicketData.tickets.findIndex((t) => t.id === ticketChannel.id);
TicketData.tickets[ticket].open = false;
fs.writeFileSync(
"./Data/TicketData.json",
JSON.stringify(TicketData, null, 4),
(err) => {
if (err) console.error(err);
}
);
await 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);
}
await ticketChannel.delete();
}
} catch (error) {
console.error("Error sending message:", error);
}
}
} catch (error) {
-137
View File
@@ -1,137 +0,0 @@
// SupportBot | Emerald Services
// User Info Command
const fs = require("fs");
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")
);
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,
options: [
{
type: Discord.ApplicationCommandOptionType.User,
name: "user",
description: "The user you want to get info about.",
required: true,
}, // The user input
],
permissions: cmdconfig.UserInfo.Permission,
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);
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
)
return interaction.reply({ embeds: [NoPerms] });
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()
.setTitle("User Not Found!")
.setDescription(
`${msgconfig.Error.UserNotFound}\n\nTry Again:\`/${cmdconfig.UserInfoCommand} <@!User_ID> or @User\``
)
.setColor(supportbot.ErrorColour);
if (!user) return interaction.reply({ embeds: [UserNotExist] });
// Flags a user/bot can have
const flags = {
DISCORD_EMPLOYEE: 'Discord Employee',
DISCORD_PARTNER: 'Discord Partner',
BUGHUNTER_LEVEL_1: 'Bug Hunter (Level 1)',
BUGHUNTER_LEVEL_2: 'Bug Hunter (Level 2)',
HYPESQUAD_EVENTS: 'HypeSquad Events',
HOUSE_BRAVERY: 'House of Bravery',
HOUSE_BRILLIANCE: 'House of Brilliance',
HOUSE_BALANCE: 'House of Balance',
EARLY_SUPPORTER: 'Early Supporter',
TEAM_USER: 'Team User',
SYSTEM: 'System',
VERIFIED_BOT: 'Verified Bot',
VERIFIED_DEVELOPER: 'Verified Bot Developer'
};
// Status message with icon
let status = {
online: "🟢Online",
idle: "🟡Idle",
dnd: "🔴Do Not Disturb",
offline: "⚫Offline"
};
const userFlags = user.flags.toArray();
// Embed containing the userinfo
let userembed = new Discord.EmbedBuilder()
.setTitle(`User Info for User: ${user.tag}`)
.setThumbnail(member.displayAvatarURL({ dynamic: true, size: 512 }))
.setColor(member.roles.highest.hexColor)
.addFields(
{ name: "Name:", value: `${user.tag}\n<@${member.id}>`, inline: true },
{ name: "ID:", value: `${member.id}`, inline: true },
{ name: "Is Bot:", value: user.bot ? "Yes" : "No", inline: true },
{ name: "House/Badge:", value: `${userFlags.length ? userFlags.map(flag => flags[flag]).join("\n") : "None"}`, inline: true },
{ name: "Current Status:", value: `${status[member.presence ? member.presence.status : "offline"]}`, inline: true },
{ name: "Avatar URL:", value: `[Click Here](${member.displayAvatarURL()})`, inline: true },
{ name: "\u200b", value: "\u200b", inline: false}
)
.addFields(
{ name: "Creation Date:", value: `${moment(user.createdAt).format("MMMM Do YYYY, h:mm:ss a")}\n> ${moment(user.createdAt).startOf("day").fromNow()}`, inline: true },
{ name: "Joined Date:", value: `${moment(member.joinedAt).format("MMMM Do YYYY, h:mm:ss a")}\n> ${moment(member.joinedAt).startOf("day").fromNow()}`, inline: true },
{ name: "Roles Total:", value: `${member.roles.cache.size -1}`, inline: false },
{ 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 })
.setTimestamp();
// Send embed [userembed]
await interaction.reply({ embeds: [userembed] }).catch((err) => console.error("An error has occured: ", err));
},
})
/**
* @INFO
* UserInfo command by Sypher#3415 | 321332200668790786
* @INFO
* Solely created for SupportBot | https://github.com/Emerald-Services/SupportBot/
**/
+17 -11
View File
@@ -19,12 +19,6 @@ Help:
Permission: ["SendMessages"]
Enabled: true
EnableAI:
Command: "enableai"
Description: "Talk with SupportBot"
Permission: ["SendMessages"]
Enabled: true
Info:
Command: "info"
Description: "Get information about the **ServerName**."
@@ -37,9 +31,9 @@ TicketPanel:
Permission: ["Administrator"]
Enabled: true
TicketStats:
Command: "ticketstats"
Description: "Shows staff members their ticket statistics"
Profile:
Command: "profile"
Description: "Shows the profile for a discord member."
Permission: ["SendMessages"]
# Command is automatically disabled when the TicketClaims is disabled.
@@ -49,9 +43,21 @@ OpenTicket:
Permission: ["SendMessages"]
Enabled: true
Add:
AddUser:
Command: "add"
Description: "Add a user to the ticket."
Description: "Add a user to a support ticket."
Permission: ["SendMessages"]
Enabled: true
ForceAddUser:
Command: "forceadd"
Description: "Add a user to a support ticket by bypassing the invite system."
Permission: ["SendMessages"]
Enabled: true
RemoveUser:
Command: "remove"
Description: "Remove a user from a support ticket."
Permission: ["SendMessages"]
Enabled: true
+90 -33
View File
@@ -24,7 +24,7 @@ Welcome:
Embed:
Colour: "#f74343"
Title: "Welcome to ServerName"
Message: "> :smile: %joined_user% has just landed!"
Message: ":smile: %joined_user% has just landed!"
Thumbnail: "BOT"
ImageEnabled: false
@@ -34,7 +34,7 @@ Leave:
Embed:
Colour: "#f74343"
Title: "Goodbye!"
Message: "> :slight_frown: %joined_user% has recently dropped out!"
Message: ":slight_frown: %joined_user% has recently dropped out!"
Thumbnail: "BOT"
ImageEnabled: false
@@ -42,8 +42,8 @@ Leave:
Suggestions:
Sent_Title: "Suggestion Sent!"
Sent: "> :white_check_mark: **You have successfully sent a suggestion.**"
NoSelfVote: "> :x: **You cannot vote on your own suggestion.**"
Sent: ":white_check_mark: **You have successfully sent a suggestion.**"
NoSelfVote: ":x: **You cannot vote on your own suggestion.**"
RemoveVoteButton: "Remove Vote"
Ticket:
@@ -56,50 +56,47 @@ Ticket:
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."
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
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."
TicketArchived: ":white_check_mark: Ticket archived."
TicketUnarchived: ":white_check_mark: Ticket unarchived."
TicketLocked: ":lock: Ticket is locked."
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!"
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."
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%>."
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%>"
Claimed: "You have successfully claimed this ticket. <#%channel%>"
NoPermsToClaimTitle: "Error, no permissions!"
NoPermsToClaim: "> :x: **Err!** You do not permissions to claim this ticket."
NoPermsToClaim: ":x: **Err!** You do not permissions to claim this ticket."
ReassigningTitle: "Reassigning!..."
ReassigningMessage: "> <@%user%> did not claim the ticket. **Reassigning...**"
ReassigningMessage: "<@%user%> did not claim the ticket. **Reassigning...**"
TicketStats:
OpenTickets: "✅ Open Tickets"
@@ -108,12 +105,72 @@ TicketStats:
Title: "Your Ticket Stats"
AddUser:
NotInTicket_Title: "Ticket Invitation"
NotInTicket_Description: "This command can only be used within a ticket thread."
Invite_Title: "User Invited"
Invite_Description: "%username% has been invited to join the ticket."
DM_Title: "Ticket Invitation"
DM_Description: "You have been invited to join the ticket %channelname%. Do you accept?"
Accept_Label: "Accept"
Reject_Label: "Reject"
ViewTicket_Label: "Go to Ticket"
Accepted_Title: "Invitation Accepted"
Accepted_Message: "You have been added to the ticket."
AddedToTicket_Title: "Added to Ticket"
AddedToTicket_Description: "You have been added to the ticket %channel_link%."
Declined_Title: "Invitation Declined"
Declined_Message: "You have declined the invitation."
NoResponse_Title: "No Response"
NoResponse_Message: "You did not respond in time. Please contact staff if you wish to join the ticket."
Error_Title: "Error"
Error_Adding: "There was an error adding you to the ticket. Please try again."
DM_Error_Title: "Error"
DM_Error_Description: "Unable to send a DM to %username%. Please ensure your DMs are enabled."
Unexpected_Error_Title: "Error"
Unexpected_Error_Description: "An unexpected error occurred: %error%"
RemoveUser:
NotInTicket_Title: "Error"
NotInTicket_Description: "This command can only be used in ticket threads."
Removed_Title: "User Removed"
Removed_Message: "The user has been successfully removed from the ticket."
RemovedFromTicket_Title: "Removed from Ticket"
RemovedFromTicket_Description: "You have been removed from the ticket channel %channel_link%."
Error_Title: "Error"
Error_Removing: "There was an error removing the user from the ticket."
ForceAddUser:
NotInTicket_Title: "Not a Ticket"
NotInTicket_Description: "This command can only be used within a ticket thread."
Added_Title: "User Added"
Added_Description: "Successfully added %username% to the ticket."
AddedToTicket_Title: "You have been added to a Ticket"
AddedToTicket_Description: "You have been added to the ticket channel [%channel_link%]."
Error_Title: "Error"
Error_Adding: "There was an error adding the user to the ticket."
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!"
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!"
+2 -3
View File
@@ -16,12 +16,11 @@ General:
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 KEY"
OpenAI_Key: "OPEN_AI_KEY_HERE"
# To create an OpenAI API key, go to https://platform.openai.com/api-keys
PastebinAPI_Key: "PASTEBIN KEY"
PastebinAPI_Key: "PASTEBIN_API_KEY_HERE"
# You can get your Pastebin API Key from https://pastebin.com
PastebinAPI_URL: "https://pastebin.com/api/api_post.php"
+26 -7
View File
@@ -20,7 +20,7 @@ SupportBot_Version: "v8.0.1"
General:
Name: "SupportBot"
Token: "BOT TOKEN HERE"
Token: "BOT_TOKEN_HERE"
# To get your Discord Bot Token, Go to https://discord.com/developers/applications
Addons:
@@ -145,11 +145,22 @@ Ticket:
StaffOnly: true
# Set to false is anyone is able to close a ticket.
Confirmation_Button: "Confirm Close"
Confirmation_Emoji: "🗑️"
Confirmation_Style: "2"
Title: "Are you sure you want to close this ticket?"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
# 3 - Green
# 4 - Red
Invites:
StaffOnly: true
LockedTickets:
Channel: "1267856939275124809"
ClaimTickets:
Enabled: true
Channel: "1249723473757077624"
@@ -188,6 +199,15 @@ Buttons:
ClaimEmoji: "🧑‍💻"
ClaimStyle: "1"
Unarchive: "Unarchive Ticket"
Unarchive_Emoji: "♻️"
Unarchive_Style: "2"
Unlock: "Unlock Ticket"
Unlock_Emoji: "🔓"
Unlock_Style: "2"
# Available Button Styles
# 1 - Blurple
# 2 - Grey
@@ -202,14 +222,13 @@ Buttons:
SelectMenus:
Tickets:
PanelEmoji: "⚙️"
CloseEmoji: "🗑️"
ArchiveEmoji: "♻️"
LockTicketEmoji: "🔒"
UnLockTicketEmoji: "🔓"
EnableInvitesEmoji: "🔒"
DisableInvitesEmoji: "🔓"
AddUserEmoji: "➕"
RemoveUserEmoji: "➖"
LockEmoji: "🔐"
EnableInvitesEmoji: "📤"
DisableInvitesEmoji: "📥"
# -------------------------
+1 -7
View File
@@ -1,7 +1 @@
{
"419821884431925260": {
"bio": "Hi",
"timezone": "",
"isClockedIn": false
}
}
{}
-5
View File
@@ -1,5 +0,0 @@
{
"clockedIn": true,
"bio": "Hi",
"timezone": "GMT"
}
-5
View File
@@ -1,5 +0,0 @@
{
"bio": "This is the most W bio",
"timezone": "cst",
"clockedIn": false
}
+1 -3
View File
@@ -1,3 +1 @@
[
"419821884431925260"
]
{}
+1 -16
View File
@@ -1,16 +1 @@
{
"1250864227460186240": {
"suggestion": "hi",
"author": "419821884431925260",
"upvotes": [
"419821884431925260"
],
"downvotes": []
},
"1250900161958248533": {
"suggestion": "blob",
"author": "419821884431925260",
"upvotes": [],
"downvotes": []
}
}
{}
+1 -180
View File
@@ -1,184 +1,5 @@
{
"tickets": [
{},
{
"id": "1253862843053510687",
"name": "ticket-0021",
"user": "419821884431925260",
"number": "0021",
"reason": "> No Reason Provided!",
"open": true,
"subUsers": [],
"createdAt": "2024-06-22T00:03:18.227Z",
"claimedAt": null
},
{
"id": "1253863588012232727",
"name": "ticket-0022",
"user": "419821884431925260",
"number": "0022",
"reason": "> No Reason Provided!",
"open": true,
"subUsers": [],
"createdAt": "2024-06-22T00:06:16.126Z",
"claimedAt": "2024-06-22T00:09:12.693Z",
"claimedBy": "419821884431925260"
},
{
"id": "1255499438483574847",
"name": "ticket-0023",
"user": "419821884431925260",
"number": "0023",
"reason": "> No Reason Provided!",
"open": true,
"subUsers": [],
"createdAt": "2024-06-26T12:26:35.729Z",
"claimedAt": null
},
{
"id": "1255500796355678229",
"name": "ticket-0024",
"user": "419821884431925260",
"number": "0024",
"reason": "> No Reason Provided!",
"open": true,
"subUsers": [],
"createdAt": "2024-06-26T12:31:56.888Z",
"claimedAt": "2024-06-26T12:32:41.240Z",
"claimedBy": "419821884431925260"
},
{
"id": "1255501873386094603",
"name": "ticket-0025",
"user": "419821884431925260",
"number": "0025",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-06-26T12:36:13.810Z",
"claimedAt": null
},
{
"id": "1255508653906198709",
"name": "ticket-0026",
"user": "419821884431925260",
"number": "0026",
"reason": "> No Reason Provided!",
"open": true,
"subUsers": [],
"createdAt": "2024-06-26T13:03:10.321Z",
"claimedAt": null
},
{
"id": "1256299016023572572",
"name": "ticket-0027",
"user": "419821884431925260",
"number": "0027",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-06-28T17:23:50.113Z",
"claimedAt": null
},
{
"id": "1256300956824633426",
"name": "ticket-0028",
"user": "419821884431925260",
"number": "0028",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-06-28T17:31:31.454Z",
"claimedAt": null
},
{
"id": "1256302271461986507",
"name": "ticket-0029",
"user": "419821884431925260",
"number": "0029",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-06-28T17:36:44.673Z",
"claimedAt": null
},
{
"id": "1256303116505317457",
"name": "ticket-0030",
"user": "419821884431925260",
"number": "0030",
"reason": "> No Reason Provided!",
"open": true,
"subUsers": [],
"createdAt": "2024-06-28T17:40:06.292Z",
"claimedAt": null
},
{
"id": "1257775687562166304",
"name": "ticket-0031",
"user": "419821884431925260",
"number": "0031",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-07-02T19:11:33.760Z",
"claimedAt": null
},
{
"id": "1257776136843427841",
"name": "ticket-0032",
"user": "419821884431925260",
"number": "0032",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-07-02T19:13:20.641Z",
"claimedAt": null
},
{
"id": "1257777774483996795",
"name": "ticket-0033",
"user": "419821884431925260",
"number": "0033",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-07-02T19:19:51.116Z",
"claimedAt": null
},
{
"id": "1257778630600167535",
"name": "ticket-0034",
"user": "419821884431925260",
"number": "0034",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-07-02T19:23:15.328Z",
"claimedAt": null
},
{
"id": "1257780259374366841",
"name": "ticket-0035",
"user": "419821884431925260",
"number": "0035",
"reason": "> No Reason Provided!",
"open": false,
"subUsers": [],
"createdAt": "2024-07-02T19:29:43.607Z",
"claimedAt": null
},
{
"id": "1257782171389657180",
"name": "ticket-0036",
"user": "419821884431925260",
"number": "0036",
"reason": "> No Reason Provided!",
"open": true,
"subUsers": [],
"createdAt": "2024-07-02T19:37:19.467Z",
"claimedAt": "2024-07-02T19:43:12.873Z",
"claimedBy": "419821884431925260"
}
{}
]
}
@@ -2,4 +2,4 @@
"bio": "",
"timezone": "",
"clockedIn": false
}
}
+2 -2
View File
@@ -1,4 +1,4 @@
{
"id": 37,
"TicketPanelID": "1250863985335472312"
"id": 0,
"TicketPanelID": "000000000000000000"
}
+216 -76
View File
@@ -16,7 +16,8 @@ try {
}
module.exports = new Event("interactionCreate", async (client, interaction) => {
if (interaction.type == Discord.InteractionType.ApplicationCommand) {
if (interaction.type === Discord.InteractionType.ApplicationCommand) {
const command = client.commands.find(
(cmd) => cmd.name.toLowerCase() === interaction.commandName
);
@@ -24,12 +25,13 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
if (interaction.user.bot || !interaction.guild) return;
const NotValid = new Discord.EmbedBuilder()
.setDescription(`:x: \`Invalid Command\` `)
.setDescription(`:x: \`Invalid Command\``)
.setColor(supportbot.Embed.Colours.Error);
if (!command)
return interaction.reply({
embeds: [NotValid],
ephemeral: true,
});
const permission = interaction.member.permissions.has(command.permissions);
@@ -43,8 +45,50 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
if (!permission)
return interaction.reply({
embeds: [ValidPerms],
ephemeral: true,
});
command.run(interaction);
try {
if (command.name === cmdconfig.OpenTicket.Command && supportbot.Ticket.TicketReason) {
const modal = new Discord.ModalBuilder()
.setCustomId("ticketReasonModal")
.setTitle("Ticket Reason")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("reasonInput")
.setLabel("Reason")
.setStyle(Discord.TextInputStyle.Paragraph)
.setRequired(true)
)
);
await interaction.showModal(modal);
} else {
console.log("\u001b[32m", "[Executed]", "\u001b[37;1m", `${interaction.user.username} has executed ${command.name}`);
await command.run(interaction);
}
} catch (error) {
console.error("Error executing command:", error);
await interaction.reply({
content: "An error occurred while executing the command.",
ephemeral: true,
});
}
}
if (interaction.isModalSubmit()) {
if (interaction.customId === "ticketReasonModal") {
const reason = interaction.fields.getTextInputValue("reasonInput");
interaction.customId = `createticket-${reason}`;
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
if (cmd) {
interaction.reason = reason; // Attach the reason to the interaction object
await cmd.run(interaction);
} else {
console.error("Command not found.");
}
}
}
if (interaction.isStringSelectMenu()) {
@@ -52,31 +96,60 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
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);
await closeCommand.run(interaction);
} else {
console.error("[X] Close Command Not Found");
}
break;
case "archiveticket":
const arcembed = new Discord.EmbedBuilder()
.setDescription(msgconfig.Ticket.TicketArchived)
.setColor(supportbot.Embed.Colours.Success);
const CloseButton = new Discord.ButtonBuilder()
.setCustomId("confirmCloseTicket")
.setLabel(supportbot.Ticket.Close.Confirmation_Button)
.setEmoji(supportbot.Ticket.Close.Confirmation_Emoji)
.setStyle(supportbot.Ticket.Close.Confirmation_Style);
const unarchiveButton = new Discord.ButtonBuilder()
.setCustomId("unarchiveTicket")
.setLabel(supportbot.Buttons.Tickets.Unarchive)
.setEmoji(supportbot.Buttons.Tickets.Unarchive_Emoji)
.setStyle(supportbot.Buttons.Tickets.Unarchive_Style);
const ArchivedOptions = new Discord.ActionRowBuilder()
.addComponents(CloseButton, unarchiveButton);
await interaction.channel.send({
embeds: [arcembed],
components: [ArchivedOptions],
});
await interaction.channel.setArchived(true);
break;
case "lockticket":
const lockembed = new Discord.EmbedBuilder()
.setDescription(msgconfig.Ticket.TicketLocked)
.setColor(supportbot.Embed.Colours.Success);
await interaction.channel.send({
embeds: [lockembed],
components: [],
ephemeral: true,s
});
await interaction.channel.setLocked(true);
break;
case "enableinvites":
await handleInvites(interaction, true);
break;
@@ -89,32 +162,80 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
}
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 === "unarchiveTicket") {
await interaction.channel.setArchived(false);
const unrcembed = new Discord.EmbedBuilder()
.setDescription(msgconfig.Ticket.TicketUnarchived)
.setColor(supportbot.Embed.Colours.Success);
await interaction.update({
embeds: [unrcembed],
components: [],
});
}
if (interaction.customId === "createticket") {
if (supportbot.Ticket.TicketReason) {
const modal = new Discord.ModalBuilder()
.setCustomId("ticketReasonModal")
.setTitle("Ticket Reason")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("reasonInput")
.setLabel("Reason")
.setStyle(Discord.TextInputStyle.Paragraph)
.setRequired(true)
)
);
await interaction.showModal(modal);
} else {
try {
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
if (!cmd) return;
await 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") {
try {
const cmd = client.commands.get(cmdconfig.OpenTicket);
if (!cmd) return;
cmd.run(interaction);
} catch (error) {
console.error(error);
if (supportbot.Ticket.TicketReason) {
const modal = new Discord.ModalBuilder()
.setCustomId("ticketReasonModal")
.setTitle("Ticket Reason")
.addComponents(
new Discord.ActionRowBuilder().addComponents(
new Discord.TextInputBuilder()
.setCustomId("reasonInput")
.setLabel("Reason")
.setStyle(Discord.TextInputStyle.Paragraph)
.setRequired(true)
)
);
await interaction.showModal(modal);
} else {
try {
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
if (!cmd) return;
await cmd.run(interaction);
} catch (error) {
console.error(error);
}
}
}
if (interaction.customId.startsWith('claimticket-')) {
const ticketChannelId = interaction.customId.split('-')[1];
if (interaction.customId.startsWith("claimticket-")) {
const ticketChannelId = interaction.customId.split("-")[1];
const ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
if (!ticketChannel) {
return interaction.reply({
@@ -144,7 +265,7 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
const NoPermsClaim = new Discord.EmbedBuilder()
.setTitle(msgconfig.Ticket.ClaimTickets.NoPermsToClaimTitle)
.setDescription(
msgconfig.Ticket.ClaimTickets.NoPermsToClaim.replace('%channel%', ticketChannel.name)
msgconfig.Ticket.ClaimTickets.NoPermsToClaim.replace("%channel%", ticketChannel.name)
)
.setColor(supportbot.Embed.Colours.Error);
@@ -160,7 +281,7 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
setTimeout(() => {
pingclaimedstaff.delete();
}, 2000)
}, 2000);
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
const ticketIndex = TicketData.tickets.findIndex((t) => t.id === ticketChannelId);
@@ -174,13 +295,13 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
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)
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))
.setDescription(msgconfig.Ticket.ClaimTickets.Claimed.replace("%channel%", ticketChannel.id))
.setColor(supportbot.Embed.Colours.Success);
await claimMessage.edit({ embeds: [claimedEmbed], components: [] });
@@ -191,36 +312,41 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
}
// SUGGESTION INTERACTIONS [START]
if (interaction.customId === 'upvote' || interaction.customId === 'downvote' || interaction.customId === 'removevote') {
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 });
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 (interaction.customId === "upvote") {
if (hasUpvoted) {
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
} else {
suggestion.upvotes.push(userId);
if (hasDownvoted) {
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
suggestion.downvotes = suggestion.downvotes.filter((id) => id !== userId);
}
}
} else if (interaction.customId === 'downvote') {
} else if (interaction.customId === "downvote") {
if (hasDownvoted) {
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
suggestion.downvotes = suggestion.downvotes.filter((id) => id !== userId);
} else {
suggestion.downvotes.push(userId);
if (hasUpvoted) {
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
}
}
} else if (interaction.customId === 'removevote') {
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
} 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));
@@ -228,13 +354,20 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
const upvoteCount = suggestion.upvotes.length;
const downvoteCount = suggestion.downvotes.length;
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 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,
},
]);
await interaction.update({ embeds: [updatedEmbed] });
}
@@ -242,11 +375,14 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
async function handleInvites(interaction, enable) {
if (supportbot.Ticket.Invites.StaffOnly) {
const { getRole, getChannel } = interaction.client;
const SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
const 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.");
return interaction.reply(
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
);
}
const NoPerms = new Discord.EmbedBuilder()
@@ -256,7 +392,10 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
)
.setColor(supportbot.Embed.Colours.Warn);
if (!interaction.member.roles.cache.has(SupportStaff.id) && !interaction.member.roles.cache.has(Admin.id)) {
if (
!interaction.member.roles.cache.has(SupportStaff.id) &&
!interaction.member.roles.cache.has(Admin.id)
) {
return interaction.reply({ embeds: [NoPerms] });
}
}
@@ -264,9 +403,7 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
await interaction.channel.setInvitable(enable);
const message = enable ? msgconfig.Ticket.EnableInvites : msgconfig.Ticket.DisableInvites;
const embed = new Discord.EmbedBuilder()
.setDescription(message)
.setColor(supportbot.Embed.Colours.General);
const embed = new Discord.EmbedBuilder().setDescription(message).setColor(supportbot.Embed.Colours.General);
await interaction.reply({
embeds: [embed],
@@ -275,7 +412,7 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
}
// Modal submission handler for editing profile
if (interaction.type === Discord.InteractionType.ModalSubmit && interaction.customId === 'editProfileModal') {
if (interaction.type === Discord.InteractionType.ModalSubmit && interaction.customId === "editProfileModal") {
const userId = interaction.user.id;
const profilePath = `./Data/Profiles/${userId}.json`;
@@ -286,13 +423,13 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
profileData = {
bio: "",
timezone: "",
clockedIn: false
clockedIn: false,
};
}
try {
const newBio = interaction.fields.getTextInputValue('bio');
const newTimezone = interaction.fields.getTextInputValue('timezone');
const newBio = interaction.fields.getTextInputValue("bio");
const newTimezone = interaction.fields.getTextInputValue("timezone");
profileData.bio = newBio;
profileData.timezone = newTimezone;
@@ -304,22 +441,25 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
.setColor(supportbot.Embed.Colours.General)
.setThumbnail(interaction.user.displayAvatarURL())
.addFields(
{ name: 'Bio', value: newBio || 'No bio set.', inline: false },
{ name: 'Timezone', value: newTimezone || 'No timezone set.', inline: true }
{ name: "Bio", value: newBio || "No bio set.", inline: false },
{ name: "Timezone", value: newTimezone || "No timezone set.", inline: true }
);
if (profileData.clockedIn !== undefined) {
updatedProfileEmbed.addFields({
name: 'Clocked In Status',
value: profileData.clockedIn ? '✅ Clocked In' : '❌ Clocked Out',
inline: true
name: "Clocked In Status",
value: profileData.clockedIn ? "✅ Clocked In" : "❌ Clocked Out",
inline: true,
});
}
await interaction.reply({ embeds: [updatedProfileEmbed], ephemeral: true });
} catch (error) {
console.error("Failed to update profile data: ", error);
await interaction.reply({ content: "There was an error while updating your profile. Please try again later.", ephemeral: true });
await interaction.reply({
content: "There was an error while updating your profile. Please try again later.",
ephemeral: true,
});
}
}
});
+64 -116
View File
@@ -18,7 +18,6 @@ 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 => {
@@ -69,150 +68,99 @@ 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);
if (supportbotai.Enabled) {
let conversation = [{
role: "system",
content: `SupportBot is your friendly neighbourhood support bot. Current date and time: ${new Date().toLocaleString()}.
The bot uses a modular command handler where commands are loaded dynamically from the './Commands' directory. Each command has a name, description, and execute method.
The main Client class structure:
- Commands are loaded from the './Commands/' directory.
- Configs are loaded from the './Configs/' directory if enabled.
- Events are loaded from the './Events/' directory.
- Addons are loaded from the './Addons/' directory if enabled.
Example of a command structure:
{
module.exports = new Command({
name: cmdconfig.Ping.Command,
description: cmdconfig.Ping.Description,
options: [],
permissions: cmdconfig.Ping.Permission,
)}
}
const sendTypingInterval = setInterval(() => {
message.channel.sendTyping();
}, 5000);
You can find more information about the commands and configuration files in the 'Configs' and 'Commands' directories.
let conversation = [{
role: "system",
content: "SupportBot is your friendly neighbourhood support bot."
}];
All commands are loaded into the bot at startup from ./Events/ready.js and ./Client.js.
let prevMessages = await message.channel.messages.fetch({ limit: 10 });
prevMessages = prevMessages.reverse().filter(msg => !msg.author.bot || msg.author.id === client.user.id);
If someone asks you to do something, you can use the 'assist' command to have the bot respond, For example: "Can I speak to a support agent?", You would respond by opening a ticket which is the /Commands/ticket.js file or you can tell them to create a ticket in the channel defined as supportbot.Ticket.
prevMessages.forEach((msg) => {
const username = msg.author.username.replace(/\s+/g, '_').replace(/[^\w\s]/gi, '');
You can find the source code for the bot at https://github.com/EmeraldServices/SupportBot.
conversation.push({
role: msg.author.id === client.user.id ? "assistant" : "user",
name: username,
content: msg.content,
});
});
You then need to understand how the bot works. Interactions are handled by the ./Events/interactionCreate.js file.
Commands are filtered based on configuration settings and loaded into the bot at startup.
Xiled Gaming Network (XGN) is a gaming community that typically offers various services and activities for gamers.
Xiled Gaming Network (XGN) has 4 divisions, Team Xiled International (TXI), The XiledOnes (TXO), Dealers of Death (DOD), Psychotic Solutions (PS)
Xiled Gaming Network (XGN) can be found at https://officialxgn.gg/handbook/, This is where you can the code of conduct, policies and other important information for members.
You can join XGN with the discord - discord.gg/xgn
You can apply to join the XGN Clan - join.officialxgn.gg
You can find the founders of XGN under the history section of the handbook. https://officialxgn.gg/handbook/.
`
}];
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,
});
try {
const response = await openai.chat.completions.create({
model: supportbotai.General.Model,
messages: conversation,
max_tokens: supportbotai.General.Tokens,
});
clearInterval(sendTypingInterval);
clearInterval(sendTypingInterval);
if (response.choices && response.choices.length > 0) {
const replyContent = response.choices[0].message.content;
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.toLowerCase().startsWith("generate image:")) {
const prompt = replyContent.substring(15).trim();
const imageUrl = await generateImage(prompt);
if (replyContent.length > 2000) {
const pasteLink = await createPaste(replyContent);
const SupportBotAIImage = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(`Here is the image generated for your prompt: "${prompt}"`)
.setImage(imageUrl)
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [SupportBotAIImage] });
} else {
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()
const SupportBotAIPastebin = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.ErrorResponse)
.setDescription(supportbotai.Messages.MessageTooLong.replace("{pastebin}", pasteLink))
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [SupportBotAIErrorResponse], ephemeral: true });
message.reply({ embeds: [SupportBotAIPastebin] });
} else {
message.reply({ embeds: [SupportBotAI] });
}
} catch (error) {
clearInterval(sendTypingInterval);
} else {
const SupportBotAIErrorResponse = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.OpenAIError)
.setColor(supportbot.Embed.Colours.Error)
.setDescription(supportbotai.Messages.ErrorResponse)
.setColor(supportbotai.Embed.Color)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
console.error('OpenAI Error:', error);
message.reply({ embeds: [SupportBotAIErrorResponse], ephemeral: true });
}
}
} catch (error) {
clearInterval(sendTypingInterval);
if (!supportbotai.Enabled) {
const AIDisabled = new Discord.EmbedBuilder()
const SupportBotAIErrorResponse = new Discord.EmbedBuilder()
.setAuthor({ name: supportbotai.General.Name, iconURL: client.user.displayAvatarURL() })
.setDescription(supportbotai.Messages.AIDisabled)
.setDescription(supportbotai.Messages.OpenAIError)
.setColor(supportbot.Embed.Colours.Error)
.setFooter({ text: supportbotai.Embed.Footer, iconURL: message.author.displayAvatarURL() })
.setTimestamp();
message.reply({ embeds: [AIDisabled], ephemeral: true });
return;
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;
}
});
+25 -80
View File
@@ -59,7 +59,7 @@ module.exports = new Event("ready", async (client, interaction) => {
});
}
console.log(`\u001b[32m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(`\u001b[33m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(` `);
console.log(`\u001b[31m`, `┏━━━┓╋╋╋╋╋╋╋╋╋╋╋╋╋┏┓┏━━┓╋╋╋┏┓`);
console.log(`\u001b[31m`, `┃┏━┓┃╋╋╋╋╋╋╋╋╋╋╋╋┏┛┗┫┏┓┃╋╋┏┛┗┓`);
@@ -70,60 +70,22 @@ module.exports = new Event("ready", async (client, interaction) => {
console.log(`\u001b[31m`, `┗╋╋╋╋╋╋╋┃┃╋┃┃`);
console.log(`\u001b[31m`, `╋╋╋╋╋╋╋┗┛╋┗┛`);
console.log(` `);
console.log(`\u001b[32m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(`\u001b[33m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(` `);
console.log(`\u001b[33m`, `${supportbot.General.Name} | [${supportbot.SupportBot_Version}]`, `\u001b[32m`, `Connected to Discord`,);
console.log("\u001b[32m", "SupportBot created by Emerald Development ");
console.log(` `);
console.log(
`\u001b[31m`,
`${supportbot.General.Name} | [${supportbot.SupportBot_Version}]`,
`\u001b[32m`,
`Connected to Discord`,
);
console.log(`\u001b[31m`, `SupportBot proudly created by Emerald Development`);
console.log(`\u001b[33m`, `――――――――――――――――― [Links] ――――――――――――――――――`);
console.log("\u001b[32m", "Discord: https://dsc.gg/emerald-dev");
console.log("\u001b[32m", "Website: https://emeraldsrv.com");
console.log("\u001b[32m", "Community: https://community.emeraldsrv.com");
console.log("\u001b[32m", "Documentation: https://docs.emeraldsrv.com");
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(`\u001b[33m`, `――――――――――――――――― [Invite] ――――――――――――――――――`);
console.log("\u001b[32m", `Invite URL: https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=8&scope=bot%20applications.commands`);
console.log(` `);
console.log(
`\u001b[31m`,
`Invite URL:`,
`\u001b[36m`,
`https://discord.com/api/oauth2/authorize?client_id=` +
client.user.id +
`&permissions=8&scope=bot%20applications.commands`
);
console.log(` `);
console.log(`\u001b[32m`, `――――――――――――――――――――――――――――――――――――――――――――`);
console.log(`\u001b[33m`, `――――――――――――――――― [Config Check] ――――――――――――――――――`);
console.log("\u001b[32m", "Config initialization...");
const roles = [
supportbot.Roles.StaffMember.Admin,
@@ -168,35 +130,18 @@ module.exports = new Event("ready", async (client, interaction) => {
// if (!find) missingCat.push(cat);
// }
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(
", "
)}]`, `\n `,
);
const missingRoles = await Promise.all(roles.map(role => getRole(role, client.guilds.cache.first())));
const missingChannels = await Promise.all(channels.map(channel => getChannel(channel, client.guilds.cache.first())));
if (missingRoles.some(role => !role)) {
console.log("\u001b[31m", `Missing roles in your server configuration: ${missingRoles.filter(role => !role).join(', ')}`);
}
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(
", "
)}]`, `\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(
", "
)}]`, `\n `,
);
if (missingChannels.some(channel => !channel)) {
console.log("\u001b[31m", `Missing channels in your server configuration: ${missingChannels.filter(channel => !channel).join(', ')}`);
}
console.log("\u001b[32m", "Configs initialized, No problems were detected.");
console.log(` `);
});
+8
View File
@@ -84,5 +84,13 @@ Released under the [MIT](https://opensource.org/licenses/MIT) license.
<img src="https://contrib.rocks/image?repo=Emerald-Services/SupportBot">
</a>
## Hosting
You can use our [Pterodactyl egg](https://github.com/Emerald-Services/Pterodactyl-Egg) to host it on your own panel. We currently don't offer hosting for you, altough we might add this in the future.
If you don't know how to install pterodactyl, you could always host it on replit:
[![Run on Repl.it](https://repl.it/badge/github/ItsNyoty/IKI-bot)]([https://repl.it/github/ItsNyoty/iki](https://repl.it/github/Emerald-Services/SupportBot
)
+20 -8
View File
@@ -85,15 +85,27 @@ class Client extends Discord.Client {
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
}
if (supportbot.Ticket.ClaimTickets.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "ticketstats.js");
if (cmdconfig.AddUser.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "addUser.js");
}
if (cmdconfig.RemoveUser.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "removeUser.js");
}
if (cmdconfig.ForceAddUser.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "forceaddUser.js");
}
if (cmdconfig.Profile.Enabled === false) {
tempCommandFiles = tempCommandFiles.filter(item => item !== "Profile.js");
}
const commandFiles = tempCommandFiles;
const commands = commandFiles.map((file) => require(`../Commands/${file}`));
// Load main commands
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
console.log(`\u001b[33m`, "――――――――――――――――――――――――――――――――――――――――――――");
commands.forEach((cmd) => {
console.log(`\u001b[32m`, `[CMD]`, `\u001b[37;1m`, `${cmd.name}`, `\u001b[32;1m`, "Loaded");
@@ -101,7 +113,7 @@ class Client extends Discord.Client {
});
// Load addon commands and events
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
if (supportbot.General.Addons.Enabled) {
const addonFiles = fs.readdirSync("./Addons").filter((file) => file.endsWith(".js"));
@@ -114,7 +126,7 @@ class Client extends Discord.Client {
// Addons
console.log(" ");
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
addons.forEach((addon) => {
console.log(
@@ -139,7 +151,7 @@ class Client extends Discord.Client {
}
});
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
}
// Register Slash Commands
@@ -155,7 +167,7 @@ class Client extends Discord.Client {
});
console.log(" ");
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
fs.readdirSync("./Events").filter((file) => file.endsWith(".js")).forEach((file) => {
const event = require(`../Events/${file}`);
@@ -163,7 +175,7 @@ class Client extends Discord.Client {
this.on(event.event, (...args) => event.run(this, ...args));
});
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
if (process.argv[2] !== "test") {
await this.login(token);
} else {
+1593
View File
File diff suppressed because it is too large. Load diff