8.2
This commit is contained in:
1 parent
4f14722e14
commit
ac0daf5fe7
28 files changed
+929
-550
No files matched your search
+27
-3
@@ -6,6 +6,7 @@ const {
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
ChannelType,
|
||||
} = require("discord.js");
|
||||
const yaml = require("js-yaml");
|
||||
|
||||
@@ -34,8 +35,10 @@ module.exports = new Command({
|
||||
const ticketChannel = interaction.channel;
|
||||
const ticketDataPath = "./Data/TicketData.json";
|
||||
|
||||
// Check if the channel is a ticket thread
|
||||
if (!ticketChannel.isThread()) {
|
||||
if (
|
||||
(supportbot.Ticket.TicketType === "threads" && !ticketChannel.isThread()) ||
|
||||
(supportbot.Ticket.TicketType === "channels" && ticketChannel.type !== ChannelType.GuildText)
|
||||
) {
|
||||
const onlyInTicket = new EmbedBuilder()
|
||||
.setTitle(msgconfig.AddUser.NotInTicket_Title)
|
||||
.setDescription(msgconfig.AddUser.NotInTicket_Description)
|
||||
@@ -91,7 +94,16 @@ module.exports = new Command({
|
||||
collector.on("collect", async (i) => {
|
||||
if (i.customId === "accept_invite") {
|
||||
try {
|
||||
await ticketChannel.members.add(userToAdd.id);
|
||||
// Add user to thread or channel based on TicketType
|
||||
if (supportbot.Ticket.TicketType === "threads") {
|
||||
await ticketChannel.members.add(userToAdd.id); // For threads
|
||||
} else if (supportbot.Ticket.TicketType === "channels") {
|
||||
await ticketChannel.permissionOverwrites.create(userToAdd.id, {
|
||||
ViewChannel: true,
|
||||
SendMessages: true,
|
||||
ReadMessageHistory: true,
|
||||
}); // For channels
|
||||
}
|
||||
|
||||
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
|
||||
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
|
||||
@@ -110,6 +122,18 @@ module.exports = new Command({
|
||||
components: [],
|
||||
});
|
||||
|
||||
// Send the added user ticket message in the ticket channel
|
||||
|
||||
const addeduserTicket = new EmbedBuilder()
|
||||
.setTitle(msgconfig.AddUser.Added_Title)
|
||||
.setDescription(msgconfig.AddUser.Added_Description.replace('%username%', userToAdd.username))
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
await ticketChannel.send({
|
||||
embeds: [addeduserTicket],
|
||||
});
|
||||
|
||||
|
||||
const addedToTicketEmbed = new EmbedBuilder()
|
||||
.setTitle(msgconfig.AddUser.AddedToTicket_Title)
|
||||
.setDescription(msgconfig.AddUser.AddedToTicket_Description.replace(
|
||||
|
||||
+17
-49
@@ -2,15 +2,9 @@ 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 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");
|
||||
|
||||
@@ -35,28 +29,25 @@ module.exports = new Command({
|
||||
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."
|
||||
);
|
||||
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}\``
|
||||
)
|
||||
.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)
|
||||
)
|
||||
if (!interaction.member.roles.cache.has(SupportStaff.id) && !interaction.member.roles.cache.has(Admin.id))
|
||||
return interaction.reply({ embeds: [NoPerms] });
|
||||
}
|
||||
|
||||
if (interaction.channel.type !== Discord.ChannelType.PrivateThread) {
|
||||
// Check if it's a thread or channel based on config
|
||||
if (
|
||||
(supportbot.Ticket.TicketType === "threads" && interaction.channel.type !== Discord.ChannelType.PrivateThread) ||
|
||||
(supportbot.Ticket.TicketType === "channels" && interaction.channel.type !== Discord.ChannelType.GuildText)
|
||||
) {
|
||||
const NotTicketChannel = new Discord.EmbedBuilder()
|
||||
.setTitle("Invalid Channel!")
|
||||
.setDescription("This command can only be used in a ticket thread.")
|
||||
.setDescription(`This command can only be used in a ${supportbot.Ticket.TicketType === "threads" ? "ticket thread" : "ticket channel"}.`)
|
||||
.setColor(supportbot.Embed.Colours.Warn);
|
||||
|
||||
return interaction.reply({ embeds: [NotTicketChannel], ephemeral: true });
|
||||
@@ -88,9 +79,7 @@ module.exports = new Command({
|
||||
|
||||
const CloseTicketRequest = new Discord.EmbedBuilder()
|
||||
.setTitle(`**${supportbot.Ticket.Close.Title}**`)
|
||||
.setDescription(
|
||||
`${msgconfig.Ticket.ConfirmClose}`
|
||||
)
|
||||
.setDescription(`${msgconfig.Ticket.ConfirmClose}`)
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
await interaction.followUp({
|
||||
@@ -117,10 +106,9 @@ async function handleCloseTicket(interaction, reason, ticket, TicketData) {
|
||||
|
||||
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);
|
||||
let transcriptChannel = await getChannel(supportbot.Ticket.Log.TicketDataLog, interaction.guild);
|
||||
|
||||
if (!transcriptChannel || !logChannel)
|
||||
if (!transcriptChannel)
|
||||
return interaction.followUp("Some Channels seem to be missing!");
|
||||
|
||||
try {
|
||||
@@ -134,22 +122,8 @@ async function handleCloseTicket(interaction, reason, ticket, TicketData) {
|
||||
);
|
||||
|
||||
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)
|
||||
.setTitle(msgconfig.TicketLog.Title)
|
||||
.setColor(msgconfig.TicketLog.Colour)
|
||||
.setFooter({
|
||||
text: supportbot.Embed.Footer,
|
||||
iconURL: interaction.user.displayAvatarURL(),
|
||||
@@ -263,12 +237,6 @@ async function handleCloseTicket(interaction, reason, ticket, TicketData) {
|
||||
</html>
|
||||
`;
|
||||
|
||||
if (!supportbot.Ticket.Log.DisableTicketLogChannel) {
|
||||
await logChannel.send({ embeds: [logEmbed] }).catch((err) => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
|
||||
let file = new Discord.AttachmentBuilder(
|
||||
Buffer.from(html),
|
||||
{ name: fileName }
|
||||
|
||||
+51
-36
@@ -1,9 +1,9 @@
|
||||
// File: Commands/ForceAddUser.js
|
||||
const fs = require("fs");
|
||||
const {
|
||||
EmbedBuilder,
|
||||
ApplicationCommandOptionType,
|
||||
ApplicationCommandType,
|
||||
ChannelType,
|
||||
} = require("discord.js");
|
||||
const yaml = require("js-yaml");
|
||||
|
||||
@@ -20,7 +20,7 @@ module.exports = new Command({
|
||||
options: [
|
||||
{
|
||||
name: "user",
|
||||
description: "The user to add",
|
||||
description: "The user to forcefully add",
|
||||
type: ApplicationCommandOptionType.User,
|
||||
required: true,
|
||||
},
|
||||
@@ -28,34 +28,14 @@ module.exports = new Command({
|
||||
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()) {
|
||||
if (
|
||||
(supportbot.Ticket.TicketType === "threads" && !ticketChannel.isThread()) ||
|
||||
(supportbot.Ticket.TicketType === "channels" && ticketChannel.type !== ChannelType.GuildText)
|
||||
) {
|
||||
const onlyInTicket = new EmbedBuilder()
|
||||
.setTitle(msgconfig.ForceAddUser.NotInTicket_Title)
|
||||
.setDescription(msgconfig.ForceAddUser.NotInTicket_Description)
|
||||
@@ -68,7 +48,42 @@ module.exports = new Command({
|
||||
}
|
||||
|
||||
try {
|
||||
await ticketChannel.members.add(userToAdd.id);
|
||||
|
||||
if (supportbot.Ticket.TicketType === "threads") {
|
||||
try {
|
||||
// Explicitly ensure the bot is in the thread
|
||||
const botMember = await ticketChannel.members.fetch(interaction.client.user.id).catch(() => null);
|
||||
if (!botMember) {
|
||||
await ticketChannel.join();
|
||||
}
|
||||
|
||||
// Delay to ensure API has processed the bot's membership
|
||||
await new Promise(res => setTimeout(res, 1000));
|
||||
|
||||
// Attempt to add the user to the thread
|
||||
await ticketChannel.members.add(userToAdd.id);
|
||||
|
||||
console.log("User successfully added to the thread.");
|
||||
} catch (err) {
|
||||
console.error("Error adding user to the thread:", err.message);
|
||||
const errorEmbed = new EmbedBuilder()
|
||||
.setTitle(msgconfig.ForceAddUser.Error_Title)
|
||||
.setDescription(`An error occurred: ${err.message}`)
|
||||
.setColor(supportbot.Embed.Colours.Error);
|
||||
|
||||
return interaction.reply({
|
||||
embeds: [errorEmbed],
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
||||
} else if (supportbot.Ticket.TicketType === "channels") {
|
||||
await ticketChannel.permissionOverwrites.create(userToAdd.id, {
|
||||
ViewChannel: true,
|
||||
SendMessages: true,
|
||||
ReadMessageHistory: true,
|
||||
});
|
||||
}
|
||||
|
||||
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
|
||||
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
|
||||
@@ -79,10 +94,9 @@ module.exports = new Command({
|
||||
|
||||
const addedEmbed = new EmbedBuilder()
|
||||
.setTitle(msgconfig.ForceAddUser.Added_Title)
|
||||
.setDescription(msgconfig.ForceAddUser.Added_Description.replace(
|
||||
"%username%",
|
||||
userToAdd.username
|
||||
))
|
||||
.setDescription(
|
||||
msgconfig.ForceAddUser.Added_Description.replace("%username%", userToAdd.username)
|
||||
)
|
||||
.setColor(supportbot.Embed.Colours.Success);
|
||||
|
||||
await interaction.reply({
|
||||
@@ -92,16 +106,17 @@ module.exports = new Command({
|
||||
|
||||
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})`
|
||||
))
|
||||
.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);
|
||||
|
||||
|
||||
+4
-3
@@ -10,9 +10,9 @@ const Command = require("../Structures/Command.js");
|
||||
|
||||
const clockedInUsers = new Set();
|
||||
|
||||
async function getRole(roleName, guild) {
|
||||
return guild.roles.cache.find(role => role.name === roleName);
|
||||
}
|
||||
// async function getRole(roleName, guild) {
|
||||
// return guild.roles.cache.find(role => role.name === roleName);
|
||||
// }
|
||||
|
||||
function updateClockedInStatus(profileEmbed, clockedIn) {
|
||||
profileEmbed.data.fields = profileEmbed.data.fields.map(field => {
|
||||
@@ -47,6 +47,7 @@ module.exports = new Command({
|
||||
const interactionUserId = interaction.user.id;
|
||||
|
||||
const user = interaction.guild.members.cache.get(viewingUserId);
|
||||
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);
|
||||
|
||||
+20
-11
@@ -1,10 +1,9 @@
|
||||
// File path: Commands/RemoveUser.js
|
||||
|
||||
const fs = require("fs");
|
||||
const {
|
||||
EmbedBuilder,
|
||||
ApplicationCommandOptionType,
|
||||
ApplicationCommandType,
|
||||
ChannelType,
|
||||
ActionRowBuilder,
|
||||
ButtonBuilder,
|
||||
ButtonStyle,
|
||||
@@ -36,13 +35,13 @@ module.exports = new Command({
|
||||
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)
|
||||
|
||||
if (!SupportStaff || !Admin) {
|
||||
return interaction.reply(
|
||||
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
|
||||
);
|
||||
}
|
||||
|
||||
const NoPerms = new EmbedBuilder()
|
||||
const NoPerms = new EmbedBuilder()
|
||||
.setTitle("Invalid Permissions!")
|
||||
.setDescription(
|
||||
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
|
||||
@@ -50,17 +49,21 @@ module.exports = new Command({
|
||||
.setColor(supportbot.Embed.Colours.Warn);
|
||||
|
||||
if (
|
||||
!interaction.member.roles.cache.has(SupportStaff.id) &&
|
||||
!interaction.member.roles.cache.has(Admin.id)
|
||||
)
|
||||
!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()) {
|
||||
// Check if the channel is a ticket thread or text channel based on TicketType
|
||||
if (
|
||||
(supportbot.Ticket.TicketType === "threads" && !ticketChannel.isThread()) ||
|
||||
(supportbot.Ticket.TicketType === "channels" && ticketChannel.type !== ChannelType.GuildText)
|
||||
) {
|
||||
const onlyInTicket = new EmbedBuilder()
|
||||
.setTitle(msgconfig.RemoveUser.NotInTicket_Title)
|
||||
.setDescription(msgconfig.RemoveUser.NotInTicket_Description)
|
||||
@@ -73,8 +76,14 @@ module.exports = new Command({
|
||||
}
|
||||
|
||||
try {
|
||||
await ticketChannel.members.remove(userToRemove.id);
|
||||
// Remove user from thread or channel based on TicketType
|
||||
if (supportbot.Ticket.TicketType === "threads") {
|
||||
await ticketChannel.members.remove(userToRemove.id); // For threads
|
||||
} else if (supportbot.Ticket.TicketType === "channels") {
|
||||
await ticketChannel.permissionOverwrites.delete(userToRemove.id); // For channels
|
||||
}
|
||||
|
||||
// Update the ticket data
|
||||
const ticketData = JSON.parse(fs.readFileSync(ticketDataPath, "utf8"));
|
||||
const ticketIndex = ticketData.tickets.findIndex((t) => t.id === ticketChannel.id);
|
||||
if (ticketIndex !== -1) {
|
||||
|
||||
@@ -0,0 +1,235 @@
|
||||
const { Command } = require('../Structures/Addon.js');
|
||||
const Discord = require("discord.js");
|
||||
const fs = require("fs");
|
||||
const yaml = require("js-yaml");
|
||||
const path = require("path");
|
||||
|
||||
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
||||
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
||||
const settingsFilePath = path.resolve(__dirname, '../Data/settings.json');
|
||||
|
||||
function loadSettings() {
|
||||
try {
|
||||
if (fs.existsSync(settingsFilePath)) {
|
||||
const data = fs.readFileSync(settingsFilePath, 'utf8');
|
||||
return JSON.parse(data);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error reading settings file:", error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function saveSettings(settings) {
|
||||
try {
|
||||
fs.writeFileSync(settingsFilePath, JSON.stringify(settings, null, 2), 'utf8');
|
||||
} catch (error) {
|
||||
console.error("Error writing settings file:", error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = new Command({
|
||||
name: cmdconfig.Settings.Command,
|
||||
description: cmdconfig.Settings.Description,
|
||||
permissions: cmdconfig.Settings.Permission,
|
||||
options: [
|
||||
{
|
||||
name: 'setstatus',
|
||||
type: Discord.ApplicationCommandOptionType.Subcommand,
|
||||
description: 'Set the bot status',
|
||||
options: [
|
||||
{
|
||||
name: 'status',
|
||||
type: Discord.ApplicationCommandOptionType.String,
|
||||
description: 'Choose the bot status',
|
||||
required: true,
|
||||
choices: [
|
||||
{ name: 'Online 🟢', value: 'online' },
|
||||
{ name: 'Idle 🌙', value: 'idle' },
|
||||
{ name: 'Do Not Disturb ⛔', value: 'dnd' },
|
||||
{ name: 'Invisible 👻', value: 'invisible' }
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'setactivity',
|
||||
type: Discord.ApplicationCommandOptionType.Subcommand,
|
||||
description: 'Set the bot activity',
|
||||
options: [
|
||||
{
|
||||
name: 'type',
|
||||
type: Discord.ApplicationCommandOptionType.String,
|
||||
description: 'Choose the activity type',
|
||||
required: true,
|
||||
choices: [
|
||||
{ name: 'Playing 🎮', value: 'PLAYING' },
|
||||
{ name: 'Watching 👀', value: 'WATCHING' },
|
||||
{ name: 'Listening 🎧', value: 'LISTENING' },
|
||||
{ name: 'Competing 🏆', value: 'COMPETING' }
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
type: Discord.ApplicationCommandOptionType.String,
|
||||
description: 'The activity message',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'streammode',
|
||||
type: Discord.ApplicationCommandOptionType.Subcommand,
|
||||
description: 'Set the bot streaming status',
|
||||
options: [
|
||||
{
|
||||
name: 'toggle',
|
||||
type: Discord.ApplicationCommandOptionType.String,
|
||||
description: 'Turn streaming mode on or off',
|
||||
required: true,
|
||||
choices: [
|
||||
{ name: 'On', value: 'on' },
|
||||
{ name: 'Off', value: 'off' }
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'twitchurl',
|
||||
type: Discord.ApplicationCommandOptionType.String,
|
||||
description: 'Twitch stream URL (Required if turning on)',
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
name: 'setnickname',
|
||||
type: Discord.ApplicationCommandOptionType.Subcommand,
|
||||
description: 'Set the bot nickname',
|
||||
options: [
|
||||
{
|
||||
name: 'nickname',
|
||||
type: Discord.ApplicationCommandOptionType.String,
|
||||
description: 'The new nickname for the bot',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
async run(interaction) {
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
const settings = loadSettings();
|
||||
|
||||
if (subcommand === 'setstatus') {
|
||||
const status = interaction.options.getString('status');
|
||||
|
||||
try {
|
||||
interaction.client.user.setPresence({
|
||||
status: status,
|
||||
activities: interaction.client.user.presence.activities || [],
|
||||
});
|
||||
|
||||
settings.status = status;
|
||||
saveSettings(settings);
|
||||
|
||||
const embed = new Discord.EmbedBuilder()
|
||||
.setDescription(`Status set to **${status.charAt(0).toUpperCase() + status.slice(1)}**`)
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
return interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
} catch (error) {
|
||||
return interaction.reply({ content: `Failed to set status: ${error.message}`, ephemeral: true });
|
||||
}
|
||||
}
|
||||
|
||||
if (subcommand === 'setactivity') {
|
||||
const activityType = interaction.options.getString('type');
|
||||
const activityMessage = interaction.options.getString('message');
|
||||
|
||||
try {
|
||||
interaction.client.user.setPresence({
|
||||
activities: [{ name: activityMessage, type: Discord.ActivityType[activityType] }],
|
||||
status: interaction.client.user.presence.status || 'online',
|
||||
});
|
||||
|
||||
settings.activity = { type: activityType, message: activityMessage };
|
||||
saveSettings(settings);
|
||||
|
||||
const embed = new Discord.EmbedBuilder()
|
||||
.setDescription(`Activity set to **${activityType.toLowerCase()} ${activityMessage}**`)
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
return interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
} catch (error) {
|
||||
return interaction.reply({ content: `Failed to set activity: ${error.message}`, ephemeral: true });
|
||||
}
|
||||
} else if (subcommand === 'streammode') {
|
||||
const toggle = interaction.options.getString('toggle');
|
||||
const twitchUrl = interaction.options.getString('twitchurl');
|
||||
|
||||
if (toggle === 'on') {
|
||||
if (!twitchUrl) {
|
||||
return interaction.reply({ content: 'Please provide a Twitch URL to stream.', ephemeral: true });
|
||||
}
|
||||
|
||||
try {
|
||||
interaction.client.user.setPresence({
|
||||
activities: [{ name: 'Streaming', type: Discord.ActivityType.Streaming, url: twitchUrl }],
|
||||
status: 'online',
|
||||
});
|
||||
|
||||
settings.streaming = { active: true, url: twitchUrl };
|
||||
saveSettings(settings);
|
||||
|
||||
const embed = new Discord.EmbedBuilder()
|
||||
.setDescription(`**Streaming mode enabled!**\nStreaming: [Twitch](${twitchUrl})`)
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
return interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
} catch (error) {
|
||||
return interaction.reply({ content: `Failed to enable streaming mode: ${error.message}`, ephemeral: true });
|
||||
}
|
||||
} else if (toggle === 'off') {
|
||||
try {
|
||||
interaction.client.user.setPresence({
|
||||
activities: interaction.client.user.presence.activities.filter(a => a.type !== Discord.ActivityType.Streaming),
|
||||
status: settings.status || 'online',
|
||||
});
|
||||
|
||||
settings.streaming = { active: false };
|
||||
saveSettings(settings);
|
||||
|
||||
const embed = new Discord.EmbedBuilder()
|
||||
.setDescription(`**Streaming mode disabled!**`)
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
return interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
} catch (error) {
|
||||
return interaction.reply({ content: `Failed to disable streaming mode: ${error.message}`, ephemeral: true });
|
||||
}
|
||||
}
|
||||
} else if (subcommand === 'setnickname') {
|
||||
const nickname = interaction.options.getString('nickname');
|
||||
|
||||
try {
|
||||
const guild = interaction.guild;
|
||||
const botMember = guild.members.cache.get(interaction.client.user.id);
|
||||
await botMember.setNickname(nickname);
|
||||
|
||||
settings.nickname = nickname;
|
||||
saveSettings(settings);
|
||||
|
||||
const embed = new Discord.EmbedBuilder()
|
||||
.setDescription(`Bot nickname set to **${nickname}**`)
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
return interaction.reply({ embeds: [embed], ephemeral: true });
|
||||
} catch (error) {
|
||||
return interaction.reply({ content: `Failed to set nickname: ${error.message}`, ephemeral: true });
|
||||
}
|
||||
} else {
|
||||
return interaction.reply({ content: 'Invalid command usage.', ephemeral: true });
|
||||
}
|
||||
},
|
||||
});
|
||||
+113
-104
@@ -38,19 +38,16 @@ async function getClockedInUsers(guild) {
|
||||
}
|
||||
|
||||
async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, attempts = 0) {
|
||||
console.log(`Assigning ticket attempt ${attempts}`);
|
||||
|
||||
try {
|
||||
const clockedInUsers = await getClockedInUsers(interaction.guild);
|
||||
console.log(`Clocked in users: ${Array.from(clockedInUsers).join(', ')}`);
|
||||
|
||||
if (clockedInUsers.size === 0 || attempts >= 2) {
|
||||
console.log("No clocked in users or max attempts reached");
|
||||
const claimChannel = await interaction.guild.channels.cache.get(supportbot.Ticket.ClaimTickets.Channel);
|
||||
if (claimChannel) {
|
||||
const claimEmbed = new EmbedBuilder()
|
||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle || 'Default Claim Title')
|
||||
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage || 'Default Claim Message')
|
||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
|
||||
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage)
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
const claimButton = new ButtonBuilder()
|
||||
@@ -70,17 +67,15 @@ async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, atte
|
||||
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
|
||||
|
||||
collector.on('collect', async i => {
|
||||
console.log(`Ticket claimed by user ${i.user.id}`);
|
||||
await ticketChannel.send({ content: `<@${i.user.id}> has claimed the ticket.` });
|
||||
});
|
||||
|
||||
collector.on('end', async collected => {
|
||||
if (collected.size === 0) {
|
||||
console.log("No one claimed the ticket, notifying admins");
|
||||
await claimMessage.delete();
|
||||
|
||||
await claimChannel.send({
|
||||
content: `No one claimed the ticket. Tagging roles: <@&${Staff.id}> <@&${Admin.id}>`,
|
||||
content: `Ticket is still unclaimed. \nCC: [<@&${Staff.id}> <@&${Admin.id}]`,
|
||||
embeds: [new EmbedBuilder().setDescription(`Ticket is still unclaimed: <#${ticketChannel.id}>`).setColor(supportbot.Embed.Colours.Warn)],
|
||||
});
|
||||
}
|
||||
@@ -96,11 +91,10 @@ async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, atte
|
||||
const clockedInArray = Array.from(clockedInUsers);
|
||||
const assignedUserId = clockedInArray[Math.floor(Math.random() * clockedInArray.length)];
|
||||
const assignedUser = await interaction.guild.members.fetch(assignedUserId);
|
||||
console.log(`Assigned user: ${assignedUserId}`);
|
||||
|
||||
const claimEmbed = new EmbedBuilder()
|
||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle || 'Default Claim Title')
|
||||
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage.replace('%user%', interaction.user.id) || 'Default Claim Message')
|
||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
|
||||
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage.replace('%user%', interaction.user.id))
|
||||
.setColor(supportbot.Embed.Colours.General);
|
||||
|
||||
const claimButton = new ButtonBuilder()
|
||||
@@ -126,13 +120,11 @@ async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, atte
|
||||
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
|
||||
|
||||
collector.on('collect', async i => {
|
||||
console.log(`Ticket claimed by user ${i.user.id}`);
|
||||
await ticketChannel.send({ content: `<@${assignedUserId}>` });
|
||||
await ticketChannel.send({ content: `<@${assignedUserId}>` }).then(msg => setTimeout(() => msg.delete(), 5000));
|
||||
});
|
||||
|
||||
collector.on('end', async collected => {
|
||||
if (collected.size === 0) {
|
||||
console.log("No one claimed the ticket, attempting reassignment");
|
||||
await claimMessage.delete();
|
||||
|
||||
if (attempts >= 1) {
|
||||
@@ -141,7 +133,6 @@ async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, atte
|
||||
embeds: [new EmbedBuilder().setDescription(`Ticket is still unclaimed: <#${ticketChannel.id}>`).setColor(supportbot.Embed.Colours.Warn)],
|
||||
});
|
||||
|
||||
// Add a claim button for any staff member to click
|
||||
const claimEmbed = new EmbedBuilder()
|
||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
|
||||
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage)
|
||||
@@ -156,7 +147,6 @@ async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, atte
|
||||
const row = new ActionRowBuilder().addComponents(claimButton);
|
||||
|
||||
const claimMessage = await claimChannel.send({
|
||||
content: `<@&${Staff.id}> <@&${Admin.id}>`,
|
||||
embeds: [claimEmbed],
|
||||
components: [row],
|
||||
});
|
||||
@@ -281,31 +271,87 @@ module.exports = new Command({
|
||||
ephemeral: true,
|
||||
});
|
||||
|
||||
const TicketCategory = interaction.guild.channels.cache.find(
|
||||
(c) => c.name === supportbot.Ticket.TicketCategory || c.id === supportbot.Ticket.TicketCategory
|
||||
);
|
||||
let ticketChannel;
|
||||
|
||||
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.TicketType === "threads") {
|
||||
const TicketHome = interaction.guild.channels.cache.find(
|
||||
(c) => c.name === supportbot.Ticket.TicketHome || c.id === supportbot.Ticket.TicketHome
|
||||
);
|
||||
|
||||
const channel = await getChannel(supportbot.Ticket.TicketHome, interaction.guild);
|
||||
ticketChannel = await channel.threads.create({
|
||||
name: `${supportbot.Ticket.Channel}${ticketNumberID}`,
|
||||
type: ChannelType.PrivateThread,
|
||||
parent: TicketHome,
|
||||
autoArchiveDuration: 60,
|
||||
reason: 'support ticket',
|
||||
});
|
||||
} else if (supportbot.Ticket.TicketType === "channels") {
|
||||
const category = interaction.guild.channels.cache.find(
|
||||
(c) => c.name === supportbot.Ticket.TicketChannelsCategory || c.id === supportbot.Ticket.TicketChannelsCategory
|
||||
);
|
||||
|
||||
if (!category) {
|
||||
return interaction.reply({
|
||||
content: "The ticket category does not exist!",
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
|
||||
ticketChannel = await interaction.guild.channels.create({
|
||||
name: `${supportbot.Ticket.Channel}${ticketNumberID}`,
|
||||
type: ChannelType.GuildText,
|
||||
parent: category.id,
|
||||
reason: 'support ticket',
|
||||
});
|
||||
|
||||
// Move to secondary category if the primary one is full
|
||||
if (category.children.size >= 50) {
|
||||
const secondaryCategory = interaction.guild.channels.cache.find(
|
||||
(c) => c.name === supportbot.Ticket.TicketChannelsCategory2 || c.id === supportbot.Ticket.TicketChannelsCategory2
|
||||
);
|
||||
|
||||
if (secondaryCategory) {
|
||||
await ticketChannel.setParent(secondaryCategory.id);
|
||||
} else {
|
||||
return interaction.reply({
|
||||
content: "The secondary ticket category does not exist!",
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Assign ticket to a user if claiming tickets is enabled
|
||||
if (supportbot.Ticket.ClaimTickets.Enabled) {
|
||||
const assignedUserId = await assignTicketToUser(ticketChannel, Staff, Admin, interaction);
|
||||
if (!assignedUserId) {
|
||||
const claimChannel = await interaction.guild.channels.cache.get(supportbot.Ticket.ClaimTickets.Channel);
|
||||
await claimChannel.send(`<@&${Staff.id}> <@&${Admin.id}>`);
|
||||
}
|
||||
}
|
||||
|
||||
// Add user to the ticket channel
|
||||
await ticketChannel.members.add(interaction.user.id);
|
||||
if (supportbot.Ticket.TicketType === "threads") {
|
||||
await ticketChannel.members.add(interaction.user.id);
|
||||
|
||||
} else if (supportbot.Ticket.TicketType === "channels") {
|
||||
|
||||
await ticketChannel.permissionOverwrites.create(interaction.user.id, {
|
||||
ViewChannel: true,
|
||||
SendMessages: true,
|
||||
ReadMessageHistory: true,
|
||||
});
|
||||
|
||||
await ticketChannel.permissionOverwrites.create(Admin, {
|
||||
ViewChannel: true,
|
||||
SendMessages: true,
|
||||
ReadMessageHistory: true,
|
||||
});
|
||||
|
||||
await ticketChannel.permissionOverwrites.create(interaction.guild.roles.everyone, {
|
||||
ViewChannel: false,
|
||||
});
|
||||
}
|
||||
|
||||
// Save ticket data
|
||||
TicketData.tickets.push({
|
||||
id: ticketChannel.id,
|
||||
@@ -368,92 +414,55 @@ module.exports = new Command({
|
||||
|
||||
// Create the control panel
|
||||
const SelectMenus = new StringSelectMenuBuilder()
|
||||
.setCustomId("ticketcontrolpanel")
|
||||
.setPlaceholder("Ticket Control Panel")
|
||||
.addOptions(
|
||||
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"),
|
||||
.setCustomId("ticketcontrolpanel")
|
||||
.setPlaceholder("Ticket Control Panel")
|
||||
.addOptions(
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel("Close")
|
||||
.setDescription("Close the ticket.")
|
||||
.setEmoji(supportbot.SelectMenus.Tickets.CloseEmoji)
|
||||
.setValue("ticketclose"),
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel("Archive")
|
||||
.setDescription("Archive the ticket.")
|
||||
.setEmoji(supportbot.SelectMenus.Tickets.ArchiveEmoji)
|
||||
.setValue("archiveticket"),
|
||||
...(supportbot.Ticket.TicketType === "threads" ? [
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel("Lock Ticket")
|
||||
.setDescription("Lock the ticket.")
|
||||
.setEmoji(supportbot.SelectMenus.Tickets.LockEmoji)
|
||||
.setValue("lockticket"),
|
||||
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"),
|
||||
);
|
||||
.setValue("lockticket")
|
||||
] : []),
|
||||
new StringSelectMenuOptionBuilder()
|
||||
.setLabel("Rename Ticket")
|
||||
.setDescription("Rename the ticket.")
|
||||
.setEmoji(supportbot.SelectMenus.Tickets.RenameEmoji)
|
||||
.setValue("renameticket")
|
||||
);
|
||||
|
||||
if (supportbot.Ticket.TicketType === "threads") {
|
||||
SelectMenus.addOptions(
|
||||
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"),
|
||||
);
|
||||
}
|
||||
|
||||
const row2 = new ActionRowBuilder().addComponents(SelectMenus);
|
||||
|
||||
// Send the ticket message and control panel
|
||||
await ticketChannel.send({
|
||||
embeds: [TicketMessage],
|
||||
components: [row2],
|
||||
});
|
||||
|
||||
// Handle department selection if not specified
|
||||
if (!department) {
|
||||
try {
|
||||
const buttons = supportbot.Departments.map((x, index) =>
|
||||
new ButtonBuilder()
|
||||
.setCustomId("Department" + index)
|
||||
.setLabel(x.title)
|
||||
.setStyle(x.color)
|
||||
.setEmoji(x.emoji)
|
||||
);
|
||||
|
||||
const row = new ActionRowBuilder().addComponents(buttons);
|
||||
|
||||
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 in run method:", error);
|
||||
}
|
||||
|
||||
@@ -35,8 +35,13 @@ module.exports = new Command({
|
||||
});
|
||||
}
|
||||
|
||||
const channelName = panelconfig.Channel;
|
||||
const channel = interaction.guild.channels.cache.find(ch => ch.name === channelName);
|
||||
const { getChannel } = interaction.client;
|
||||
|
||||
const channel = await getChannel(
|
||||
supportbot.Ticket.TicketHome,
|
||||
interaction.guild
|
||||
);
|
||||
|
||||
if (!channel) {
|
||||
console.log(`[TICKET PANEL] ${channelName} channel not found. Please check your config file.`);
|
||||
return interaction.reply({
|
||||
|
||||
@@ -71,7 +71,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.Translate.TranslateLog,
|
||||
interaction.guild
|
||||
); // Grab the set logging channel for translations
|
||||
|
||||
|
||||
Reference in new issue
Block a user