Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
753f432c95 | ||
|
|
c824bc51b2 | ||
|
|
39ee540b55 | ||
|
|
903b214051 | ||
|
|
ac0daf5fe7 | ||
|
|
80e38a07e9 | ||
|
|
d2598e09f7 | ||
|
|
28aab47150 | ||
|
|
81bda67ae4 | ||
|
|
25bbd1ff85 | ||
|
|
164d695a5f | ||
|
|
57e4a3e77c | ||
|
|
a6ac532b2b | ||
|
|
4f14722e14 | ||
|
|
9a6eece7a1 | ||
|
|
fd65d0a9a7 | ||
|
|
48500fe8a4 |
No files matched your search
@@ -0,0 +1,26 @@
|
|||||||
|
const Discord = require("discord.js");
|
||||||
|
const fs = require("fs");
|
||||||
|
const yaml = require("js-yaml");
|
||||||
|
const { Command } = require('../Structures/Addon.js'); // Adjust the path as needed
|
||||||
|
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
||||||
|
|
||||||
|
module.exports = new Command({
|
||||||
|
name: "addon",
|
||||||
|
description: "This is a sample addon!",
|
||||||
|
options: [],
|
||||||
|
permissions: ["Administrator"],
|
||||||
|
|
||||||
|
async run(interaction) {
|
||||||
|
let disableCommand = true;
|
||||||
|
|
||||||
|
const PingEmbed = new Discord.EmbedBuilder()
|
||||||
|
.setDescription(
|
||||||
|
`This is a sample addon.\n\nPong! \`${interaction.client.ws.ping} ms\``
|
||||||
|
)
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
|
interaction.reply({
|
||||||
|
embeds: [PingEmbed],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
# Contributor Covenant Code of Conduct
|
|
||||||
|
|
||||||
## Our Pledge
|
|
||||||
|
|
||||||
We as members, contributors, and leaders pledge to make participation in our
|
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
|
||||||
identity and expression, level of experience, education, socio-economic status,
|
|
||||||
nationality, personal appearance, race, religion, or sexual identity
|
|
||||||
and orientation.
|
|
||||||
|
|
||||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
|
||||||
diverse, inclusive, and healthy community.
|
|
||||||
|
|
||||||
## Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to a positive environment for our
|
|
||||||
community include:
|
|
||||||
|
|
||||||
* Demonstrating empathy and kindness toward other people
|
|
||||||
* Being respectful of differing opinions, viewpoints, and experiences
|
|
||||||
* Giving and gracefully accepting constructive feedback
|
|
||||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
|
||||||
and learning from the experience
|
|
||||||
* Focusing on what is best not just for us as individuals, but for the
|
|
||||||
overall community
|
|
||||||
|
|
||||||
Examples of unacceptable behavior include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery, and sexual attention or
|
|
||||||
advances of any kind
|
|
||||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or email
|
|
||||||
address, without their explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
## Enforcement Responsibilities
|
|
||||||
|
|
||||||
Community leaders are responsible for clarifying and enforcing our standards of
|
|
||||||
acceptable behavior and will take appropriate and fair corrective action in
|
|
||||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
|
||||||
or harmful.
|
|
||||||
|
|
||||||
Community leaders have the right and responsibility to remove, edit, or reject
|
|
||||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
|
||||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
|
||||||
decisions when appropriate.
|
|
||||||
|
|
||||||
## Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies within all community spaces, and also applies when
|
|
||||||
an individual is officially representing the community in public spaces.
|
|
||||||
Examples of representing our community include using an official e-mail address,
|
|
||||||
posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event.
|
|
||||||
|
|
||||||
## Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported to the community leaders responsible for enforcement at
|
|
||||||
our discord.
|
|
||||||
All complaints will be reviewed and investigated promptly and fairly.
|
|
||||||
|
|
||||||
All community leaders are obligated to respect the privacy and security of the
|
|
||||||
reporter of any incident.
|
|
||||||
|
|
||||||
## Enforcement Guidelines
|
|
||||||
|
|
||||||
Community leaders will follow these Community Impact Guidelines in determining
|
|
||||||
the consequences for any action they deem in violation of this Code of Conduct:
|
|
||||||
|
|
||||||
### 1. Correction
|
|
||||||
|
|
||||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
|
||||||
unprofessional or unwelcome in the community.
|
|
||||||
|
|
||||||
**Consequence**: A private, written warning from community leaders, providing
|
|
||||||
clarity around the nature of the violation and an explanation of why the
|
|
||||||
behavior was inappropriate. A public apology may be requested.
|
|
||||||
|
|
||||||
### 2. Warning
|
|
||||||
|
|
||||||
**Community Impact**: A violation through a single incident or series
|
|
||||||
of actions.
|
|
||||||
|
|
||||||
**Consequence**: A warning with consequences for continued behavior. No
|
|
||||||
interaction with the people involved, including unsolicited interaction with
|
|
||||||
those enforcing the Code of Conduct, for a specified period of time. This
|
|
||||||
includes avoiding interactions in community spaces as well as external channels
|
|
||||||
like social media. Violating these terms may lead to a temporary or
|
|
||||||
permanent ban.
|
|
||||||
|
|
||||||
### 3. Temporary Ban
|
|
||||||
|
|
||||||
**Community Impact**: A serious violation of community standards, including
|
|
||||||
sustained inappropriate behavior.
|
|
||||||
|
|
||||||
**Consequence**: A temporary ban from any sort of interaction or public
|
|
||||||
communication with the community for a specified period of time. No public or
|
|
||||||
private interaction with the people involved, including unsolicited interaction
|
|
||||||
with those enforcing the Code of Conduct, is allowed during this period.
|
|
||||||
Violating these terms may lead to a permanent ban.
|
|
||||||
|
|
||||||
### 4. Permanent Ban
|
|
||||||
|
|
||||||
**Community Impact**: Demonstrating a pattern of violation of community
|
|
||||||
standards, including sustained inappropriate behavior, harassment of an
|
|
||||||
individual, or aggression toward or disparagement of classes of individuals.
|
|
||||||
|
|
||||||
**Consequence**: A permanent ban from any sort of public interaction within
|
|
||||||
the community.
|
|
||||||
|
|
||||||
## Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
|
||||||
version 2.0, available at
|
|
||||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
|
||||||
|
|
||||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
|
||||||
enforcement ladder](https://github.com/mozilla/diversity).
|
|
||||||
|
|
||||||
[homepage]: https://www.contributor-covenant.org
|
|
||||||
|
|
||||||
For answers to common questions about this code of conduct, see the FAQ at
|
|
||||||
https://www.contributor-covenant.org/faq. Translations are available at
|
|
||||||
https://www.contributor-covenant.org/translations.
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
# Contributing
|
|
||||||
|
|
||||||
When contributing to this repository, please first discuss the change you wish to make via issue,
|
|
||||||
email, or any other method with the owners of this repository before making a change.
|
|
||||||
|
|
||||||
Please note we have a code of conduct, please follow it in all your interactions with the project.
|
|
||||||
|
|
||||||
## Pull Request Process
|
|
||||||
|
|
||||||
1. Ensure any install or build dependencies are removed before the end of the layer when doing a
|
|
||||||
build.
|
|
||||||
2. Update the README.md with details of changes to the interface, this includes new environment
|
|
||||||
variables, exposed ports, useful file locations and container parameters.
|
|
||||||
3. Increase the version numbers in any examples files and the README.md to the new version that this
|
|
||||||
Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
|
|
||||||
4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you
|
|
||||||
do not have permission to do that, you may request the second reviewer to merge it for you.
|
|
||||||
|
|
||||||
## Code of Conduct
|
|
||||||
|
|
||||||
### Our Pledge
|
|
||||||
|
|
||||||
In the interest of fostering an open and welcoming environment, we as
|
|
||||||
contributors and maintainers pledge to making participation in our project and
|
|
||||||
our community a harassment-free experience for everyone, regardless of age, body
|
|
||||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
|
||||||
nationality, personal appearance, race, religion, or sexual identity and
|
|
||||||
orientation.
|
|
||||||
|
|
||||||
### Our Standards
|
|
||||||
|
|
||||||
Examples of behavior that contributes to creating a positive environment
|
|
||||||
include:
|
|
||||||
|
|
||||||
* Using welcoming and inclusive language
|
|
||||||
* Being respectful of differing viewpoints and experiences
|
|
||||||
* Gracefully accepting constructive criticism
|
|
||||||
* Focusing on what is best for the community
|
|
||||||
* Showing empathy towards other community members
|
|
||||||
|
|
||||||
Examples of unacceptable behavior by participants include:
|
|
||||||
|
|
||||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
|
||||||
advances
|
|
||||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
|
||||||
* Public or private harassment
|
|
||||||
* Publishing others' private information, such as a physical or electronic
|
|
||||||
address, without explicit permission
|
|
||||||
* Other conduct which could reasonably be considered inappropriate in a
|
|
||||||
professional setting
|
|
||||||
|
|
||||||
### Our Responsibilities
|
|
||||||
|
|
||||||
Project maintainers are responsible for clarifying the standards of acceptable
|
|
||||||
behavior and are expected to take appropriate and fair corrective action in
|
|
||||||
response to any instances of unacceptable behavior.
|
|
||||||
|
|
||||||
Project maintainers have the right and responsibility to remove, edit, or
|
|
||||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
|
||||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
|
||||||
permanently any contributor for other behaviors that they deem inappropriate,
|
|
||||||
threatening, offensive, or harmful.
|
|
||||||
|
|
||||||
### Scope
|
|
||||||
|
|
||||||
This Code of Conduct applies both within project spaces and in public spaces
|
|
||||||
when an individual is representing the project or its community. Examples of
|
|
||||||
representing a project or community include using an official project e-mail
|
|
||||||
address, posting via an official social media account, or acting as an appointed
|
|
||||||
representative at an online or offline event. Representation of a project may be
|
|
||||||
further defined and clarified by project maintainers.
|
|
||||||
|
|
||||||
### Enforcement
|
|
||||||
|
|
||||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
|
||||||
reported by contacting the project team at [INSERT EMAIL ADDRESS]. All
|
|
||||||
complaints will be reviewed and investigated and will result in a response that
|
|
||||||
is deemed necessary and appropriate to the circumstances. The project team is
|
|
||||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
|
||||||
Further details of specific enforcement policies may be posted separately.
|
|
||||||
|
|
||||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
|
||||||
faith may face temporary or permanent repercussions as determined by other
|
|
||||||
members of the project's leadership.
|
|
||||||
|
|
||||||
### Attribution
|
|
||||||
|
|
||||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
|
||||||
available at [http://contributor-covenant.org/version/1/4][version]
|
|
||||||
|
|
||||||
[homepage]: http://contributor-covenant.org
|
|
||||||
[version]: http://contributor-covenant.org/version/1/4/
|
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const {
|
||||||
|
EmbedBuilder,
|
||||||
|
ApplicationCommandOptionType,
|
||||||
|
ApplicationCommandType,
|
||||||
|
ActionRowBuilder,
|
||||||
|
ButtonBuilder,
|
||||||
|
ButtonStyle,
|
||||||
|
ChannelType,
|
||||||
|
} = 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";
|
||||||
|
|
||||||
|
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)
|
||||||
|
.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 {
|
||||||
|
// 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);
|
||||||
|
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: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
// 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(
|
||||||
|
"%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],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
+19
-50
@@ -2,15 +2,9 @@ const fs = require("fs");
|
|||||||
const Discord = require("discord.js");
|
const Discord = require("discord.js");
|
||||||
const yaml = require("js-yaml");
|
const yaml = require("js-yaml");
|
||||||
|
|
||||||
const supportbot = yaml.load(
|
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
||||||
fs.readFileSync("./Configs/supportbot.yml", "utf8")
|
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
||||||
);
|
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
|
||||||
const cmdconfig = yaml.load(
|
|
||||||
fs.readFileSync("./Configs/commands.yml", "utf8")
|
|
||||||
);
|
|
||||||
const msgconfig = yaml.load(
|
|
||||||
fs.readFileSync("./Configs/messages.yml", "utf8")
|
|
||||||
);
|
|
||||||
|
|
||||||
const Command = require("../Structures/Command.js");
|
const Command = require("../Structures/Command.js");
|
||||||
|
|
||||||
@@ -35,28 +29,25 @@ module.exports = new Command({
|
|||||||
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
|
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
|
||||||
|
|
||||||
if (!SupportStaff || !Admin)
|
if (!SupportStaff || !Admin)
|
||||||
return interaction.reply(
|
return interaction.reply("Some roles seem to be missing!\nPlease check for errors when starting the bot.");
|
||||||
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
|
|
||||||
);
|
|
||||||
|
|
||||||
const NoPerms = new Discord.EmbedBuilder()
|
const NoPerms = new Discord.EmbedBuilder()
|
||||||
.setTitle("Invalid Permissions!")
|
.setTitle("Invalid Permissions!")
|
||||||
.setDescription(
|
.setDescription(`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``)
|
||||||
`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``
|
|
||||||
)
|
|
||||||
.setColor(supportbot.Embed.Colours.Warn);
|
.setColor(supportbot.Embed.Colours.Warn);
|
||||||
|
|
||||||
if (
|
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] });
|
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()
|
const NotTicketChannel = new Discord.EmbedBuilder()
|
||||||
.setTitle("Invalid Channel!")
|
.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);
|
.setColor(supportbot.Embed.Colours.Warn);
|
||||||
|
|
||||||
return interaction.reply({ embeds: [NotTicketChannel], ephemeral: true });
|
return interaction.reply({ embeds: [NotTicketChannel], ephemeral: true });
|
||||||
@@ -81,15 +72,14 @@ module.exports = new Command({
|
|||||||
const CloseButton = new Discord.ButtonBuilder()
|
const CloseButton = new Discord.ButtonBuilder()
|
||||||
.setCustomId("confirmCloseTicket")
|
.setCustomId("confirmCloseTicket")
|
||||||
.setLabel(supportbot.Ticket.Close.Confirmation_Button)
|
.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);
|
const row = new Discord.ActionRowBuilder().addComponents(CloseButton);
|
||||||
|
|
||||||
const CloseTicketRequest = new Discord.EmbedBuilder()
|
const CloseTicketRequest = new Discord.EmbedBuilder()
|
||||||
.setTitle(`**${supportbot.Ticket.Close.Title}**`)
|
.setTitle(`**${supportbot.Ticket.Close.Title}**`)
|
||||||
.setDescription(
|
.setDescription(`${msgconfig.Ticket.ConfirmClose}`)
|
||||||
`${msgconfig.Ticket.ConfirmClose}`
|
|
||||||
)
|
|
||||||
.setColor(supportbot.Embed.Colours.General);
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
await interaction.followUp({
|
await interaction.followUp({
|
||||||
@@ -116,10 +106,9 @@ async function handleCloseTicket(interaction, reason, ticket, TicketData) {
|
|||||||
|
|
||||||
let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
let tickets = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
let tUser = interaction.client.users.cache.get(ticket.user);
|
let tUser = interaction.client.users.cache.get(ticket.user);
|
||||||
let transcriptChannel = await getChannel(supportbot.Ticket.Log.TranscriptLog, interaction.guild);
|
let transcriptChannel = await getChannel(supportbot.Ticket.Log.TicketDataLog, interaction.guild);
|
||||||
let logChannel = await getChannel(supportbot.Ticket.Log.TicketLog, interaction.guild);
|
|
||||||
|
|
||||||
if (!transcriptChannel || !logChannel)
|
if (!transcriptChannel)
|
||||||
return interaction.followUp("Some Channels seem to be missing!");
|
return interaction.followUp("Some Channels seem to be missing!");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -133,22 +122,8 @@ async function handleCloseTicket(interaction, reason, ticket, TicketData) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const transcriptEmbed = new Discord.EmbedBuilder()
|
const transcriptEmbed = new Discord.EmbedBuilder()
|
||||||
.setTitle(supportbot.Ticket.Log.TranscriptTitle)
|
.setTitle(msgconfig.TicketLog.Title)
|
||||||
.setColor(supportbot.Embed.Colours.General)
|
.setColor(msgconfig.TicketLog.Colour)
|
||||||
.setFooter({
|
|
||||||
text: supportbot.Embed.Footer,
|
|
||||||
iconURL: interaction.user.displayAvatarURL(),
|
|
||||||
})
|
|
||||||
.addFields(
|
|
||||||
{ name: "Ticket", value: `${interaction.channel.name} (${interaction.channel.id})` },
|
|
||||||
{ name: "User", value: `${tUser?.username || "N/A"}#${tUser?.discriminator || "N/A"} (${tUser?.id || ticket.user})` },
|
|
||||||
{ name: "Closed By", value: interaction.user.tag },
|
|
||||||
{ name: "Reason", value: reason }
|
|
||||||
);
|
|
||||||
|
|
||||||
const logEmbed = new Discord.EmbedBuilder()
|
|
||||||
.setTitle(supportbot.Ticket.Log.TicketLog_Title)
|
|
||||||
.setColor(supportbot.Embed.Colours.General)
|
|
||||||
.setFooter({
|
.setFooter({
|
||||||
text: supportbot.Embed.Footer,
|
text: supportbot.Embed.Footer,
|
||||||
iconURL: interaction.user.displayAvatarURL(),
|
iconURL: interaction.user.displayAvatarURL(),
|
||||||
@@ -262,12 +237,6 @@ async function handleCloseTicket(interaction, reason, ticket, TicketData) {
|
|||||||
</html>
|
</html>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
if (!supportbot.Ticket.Log.DisableTicketLogChannel) {
|
|
||||||
await logChannel.send({ embeds: [logEmbed] }).catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let file = new Discord.AttachmentBuilder(
|
let file = new Discord.AttachmentBuilder(
|
||||||
Buffer.from(html),
|
Buffer.from(html),
|
||||||
{ name: fileName }
|
{ name: fileName }
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const {
|
||||||
|
EmbedBuilder,
|
||||||
|
ApplicationCommandOptionType,
|
||||||
|
ApplicationCommandType,
|
||||||
|
ChannelType,
|
||||||
|
} = 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 forcefully add",
|
||||||
|
type: ApplicationCommandOptionType.User,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
permissions: cmdconfig.ForceAddUser.Permission,
|
||||||
|
|
||||||
|
async run(interaction) {
|
||||||
|
const userToAdd = interaction.options.getUser("user");
|
||||||
|
const ticketChannel = interaction.channel;
|
||||||
|
const ticketDataPath = "./Data/TicketData.json";
|
||||||
|
|
||||||
|
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)
|
||||||
|
.setColor(supportbot.Embed.Colours.Error);
|
||||||
|
|
||||||
|
return interaction.reply({
|
||||||
|
embeds: [onlyInTicket],
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
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);
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
+10
-21
@@ -1,17 +1,9 @@
|
|||||||
// SupportBot | Emerald Services
|
|
||||||
// Help Command
|
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const Discord = require("discord.js");
|
const Discord = require("discord.js");
|
||||||
const yaml = require("js-yaml");
|
const yaml = require("js-yaml");
|
||||||
|
|
||||||
const supportbot = yaml.load(
|
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
||||||
fs.readFileSync("./Configs/supportbot.yml", "utf8")
|
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
||||||
);
|
|
||||||
|
|
||||||
const cmdconfig = yaml.load(
|
|
||||||
fs.readFileSync("./Configs/commands.yml", "utf8")
|
|
||||||
);
|
|
||||||
|
|
||||||
const Command = require("../Structures/Command.js");
|
const Command = require("../Structures/Command.js");
|
||||||
|
|
||||||
@@ -32,11 +24,17 @@ module.exports = new Command({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch all commands from the client's commands collection
|
// Separate regular commands and addon commands
|
||||||
let botCommands = "";
|
let botCommands = "";
|
||||||
|
let addonCommands = "";
|
||||||
|
|
||||||
interaction.client.commands.forEach((command) => {
|
interaction.client.commands.forEach((command) => {
|
||||||
if (command.permissions) {
|
if (command.permissions) {
|
||||||
botCommands += `\`${command.name}\` `;
|
if (command.addon) {
|
||||||
|
addonCommands += `\`${command.name}\` `;
|
||||||
|
} else {
|
||||||
|
botCommands += `\`${command.name}\` `;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -51,15 +49,6 @@ module.exports = new Command({
|
|||||||
inline: false,
|
inline: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Conditionally add Addons section
|
|
||||||
if (supportbot.General.Addons.Enabled) {
|
|
||||||
HelpEmbed1.addFields({
|
|
||||||
name: "🛠️ Addons\n",
|
|
||||||
value: "No addons available.",
|
|
||||||
inline: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
HelpEmbed1.setFooter({
|
HelpEmbed1.setFooter({
|
||||||
text: supportbot.Embed.Footer,
|
text: supportbot.Embed.Footer,
|
||||||
iconURL: interaction.user.displayAvatarURL(),
|
iconURL: interaction.user.displayAvatarURL(),
|
||||||
|
|||||||
@@ -0,0 +1,324 @@
|
|||||||
|
const { EmbedBuilder, ModalBuilder, TextInputBuilder, TextInputStyle, ApplicationCommandType, ActionRowBuilder, ButtonBuilder, ButtonStyle, ApplicationCommandOptionType } = require("discord.js");
|
||||||
|
const fs = require("fs");
|
||||||
|
const yaml = require("js-yaml");
|
||||||
|
|
||||||
|
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
||||||
|
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
||||||
|
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
|
||||||
|
|
||||||
|
const Command = require("../Structures/Command.js");
|
||||||
|
|
||||||
|
const clockedInUsers = new Set();
|
||||||
|
|
||||||
|
// 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 => {
|
||||||
|
if (field.name === 'Clocked In Status') {
|
||||||
|
field.value = clockedIn ? '✅ Clocked In' : '❌ Clocked Out';
|
||||||
|
}
|
||||||
|
return field;
|
||||||
|
});
|
||||||
|
return profileEmbed;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new Command({
|
||||||
|
name: cmdconfig.Profile.Command,
|
||||||
|
description: cmdconfig.Profile.Description,
|
||||||
|
type: ApplicationCommandType.ChatInput,
|
||||||
|
permissions: cmdconfig.Profile.Permission,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: 'user',
|
||||||
|
description: 'The user to view the profile of',
|
||||||
|
type: ApplicationCommandOptionType.User,
|
||||||
|
required: false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
async run(interaction) {
|
||||||
|
await interaction.deferReply({ ephemeral: true }); // Acknowledge the interaction immediately
|
||||||
|
|
||||||
|
const userOption = interaction.options.getUser('user');
|
||||||
|
const viewingUser = userOption || interaction.user;
|
||||||
|
const viewingUserId = viewingUser.id;
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (!Staff || !Admin) {
|
||||||
|
return interaction.editReply({
|
||||||
|
content: "Some roles seem to be missing!\nPlease check for errors when starting the bot.",
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const isStaff = user.roles.cache.has(Staff.id) || user.roles.cache.has(Admin.id);
|
||||||
|
const isOwnProfile = interactionUserId === viewingUserId;
|
||||||
|
|
||||||
|
const profilePath = `./Data/Profiles/${viewingUserId}.json`;
|
||||||
|
let profileData;
|
||||||
|
|
||||||
|
if (fs.existsSync(profilePath)) {
|
||||||
|
profileData = JSON.parse(fs.readFileSync(profilePath, "utf8"));
|
||||||
|
} else {
|
||||||
|
profileData = {
|
||||||
|
bio: "",
|
||||||
|
timezone: "",
|
||||||
|
clockedIn: false
|
||||||
|
};
|
||||||
|
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
const { bio, timezone, clockedIn } = profileData;
|
||||||
|
|
||||||
|
let profileEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(`${viewingUser.username}'s Profile`)
|
||||||
|
.setColor(supportbot.Embed.Colours.General)
|
||||||
|
.setThumbnail(viewingUser.displayAvatarURL())
|
||||||
|
.addFields(
|
||||||
|
{ name: 'Bio', value: bio || 'No bio set.', inline: false },
|
||||||
|
{ name: 'Timezone', value: timezone || 'No timezone set.', inline: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isStaff) {
|
||||||
|
profileEmbed.addFields({ name: 'Clocked In Status', value: clockedIn ? '✅ Clocked In' : '❌ Clocked Out', inline: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const buttonRow = new ActionRowBuilder();
|
||||||
|
if (isOwnProfile) {
|
||||||
|
buttonRow.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('editProfile')
|
||||||
|
.setLabel('Edit Profile')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isStaff) {
|
||||||
|
buttonRow.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('clockInOut')
|
||||||
|
.setLabel(clockedIn ? 'Clock Out' : 'Clock In')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isStaff && supportbot.Ticket.ClaimTickets.Enabled) {
|
||||||
|
buttonRow.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('viewTicketStats')
|
||||||
|
.setLabel('View Ticket Stats')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.editReply({ embeds: [profileEmbed], components: buttonRow.components.length > 0 ? [buttonRow] : [] });
|
||||||
|
|
||||||
|
const filter = i => (
|
||||||
|
['editProfile', 'clockInOut', 'viewTicketStats', 'showOpenTickets', 'backToStats', 'backToProfile'].includes(i.customId)
|
||||||
|
&& i.user.id === interactionUserId
|
||||||
|
);
|
||||||
|
|
||||||
|
const collector = interaction.channel.createMessageComponentCollector({ filter, time: 60000 });
|
||||||
|
|
||||||
|
collector.on('collect', async i => {
|
||||||
|
if (i.customId === 'editProfile') {
|
||||||
|
const modal = new ModalBuilder()
|
||||||
|
.setCustomId('editProfileModal')
|
||||||
|
.setTitle('Edit Profile')
|
||||||
|
.addComponents(
|
||||||
|
new ActionRowBuilder().addComponents(
|
||||||
|
new TextInputBuilder()
|
||||||
|
.setCustomId('bio')
|
||||||
|
.setLabel('Bio')
|
||||||
|
.setStyle(TextInputStyle.Paragraph)
|
||||||
|
.setPlaceholder('Enter your bio')
|
||||||
|
.setValue(String(bio))
|
||||||
|
.setRequired(false)
|
||||||
|
),
|
||||||
|
new ActionRowBuilder().addComponents(
|
||||||
|
new TextInputBuilder()
|
||||||
|
.setCustomId('timezone')
|
||||||
|
.setLabel('Timezone')
|
||||||
|
.setStyle(TextInputStyle.Short)
|
||||||
|
.setPlaceholder('Enter your timezone')
|
||||||
|
.setValue(String(timezone))
|
||||||
|
.setRequired(false)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await i.showModal(modal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.customId === 'clockInOut') {
|
||||||
|
profileData.clockedIn = !profileData.clockedIn;
|
||||||
|
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
|
||||||
|
profileEmbed = updateClockedInStatus(profileEmbed, profileData.clockedIn);
|
||||||
|
|
||||||
|
if (profileData.clockedIn) {
|
||||||
|
clockedInUsers.add(viewingUserId);
|
||||||
|
} else {
|
||||||
|
clockedInUsers.delete(viewingUserId);
|
||||||
|
}
|
||||||
|
|
||||||
|
const updatedButtonRow = new ActionRowBuilder()
|
||||||
|
.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('editProfile')
|
||||||
|
.setLabel('Edit Profile')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isStaff) {
|
||||||
|
updatedButtonRow.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('clockInOut')
|
||||||
|
.setLabel(profileData.clockedIn ? 'Clock Out' : 'Clock In')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (supportbot.Ticket.ClaimTickets.Enabled) {
|
||||||
|
updatedButtonRow.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('viewTicketStats')
|
||||||
|
.setLabel('View Ticket Stats')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await i.update({ embeds: [profileEmbed], components: [updatedButtonRow] });
|
||||||
|
|
||||||
|
let clockedinout = new EmbedBuilder()
|
||||||
|
.setTitle(profileData.clockedIn ? 'Clocked In!' : 'Clocked Out!')
|
||||||
|
.setDescription(profileData.clockedIn ? 'You have successfully clocked in.' : 'You have successfully clocked out.')
|
||||||
|
.setColor(supportbot.Embed.Colours.General)
|
||||||
|
|
||||||
|
await interaction.followUp({ embeds: [clockedinout], ephemeral: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.customId === 'viewTicketStats') {
|
||||||
|
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
|
const ticketsClaimed = TicketData.tickets.filter(t => t.claimedBy === viewingUserId);
|
||||||
|
const ticketsOpen = ticketsClaimed.filter(t => t.open);
|
||||||
|
const totalTickets = ticketsClaimed.length;
|
||||||
|
|
||||||
|
let totalResponseTime = 0;
|
||||||
|
let responseCount = 0;
|
||||||
|
|
||||||
|
ticketsClaimed.forEach(ticket => {
|
||||||
|
if (ticket.claimedAt && ticket.createdAt) {
|
||||||
|
const responseTime = new Date(ticket.claimedAt) - new Date(ticket.createdAt);
|
||||||
|
totalResponseTime += responseTime;
|
||||||
|
responseCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const averageResponseTime = responseCount ? totalResponseTime / responseCount : 0;
|
||||||
|
const averageResponseTimeMinutes = Math.round(averageResponseTime / 60000);
|
||||||
|
|
||||||
|
const statsEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(msgconfig.TicketStats.Title)
|
||||||
|
.setDescription(`> Ticket stats for <@${viewingUserId}>`)
|
||||||
|
.setColor(supportbot.Embed.Colours.General)
|
||||||
|
.addFields(
|
||||||
|
{ name: msgconfig.TicketStats.OpenTickets, value: `${ticketsOpen.length}`, inline: true },
|
||||||
|
{ name: msgconfig.TicketStats.TotalTickets, value: `${totalTickets}`, inline: true },
|
||||||
|
{ name: msgconfig.TicketStats.ResponseTime, value: `${averageResponseTimeMinutes} minutes`, inline: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
const statsButtonRow = new ActionRowBuilder()
|
||||||
|
.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('showOpenTickets')
|
||||||
|
.setLabel('Show Open Tickets')
|
||||||
|
.setStyle(ButtonStyle.Secondary),
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('backToProfile')
|
||||||
|
.setLabel('Back to Profile')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
|
||||||
|
await i.update({ embeds: [statsEmbed], components: [statsButtonRow] });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.customId === 'showOpenTickets') {
|
||||||
|
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
|
const ticketsOpen = TicketData.tickets.filter(t => t.claimedBy === viewingUserId && t.open);
|
||||||
|
|
||||||
|
const openTicketsEmbed = new EmbedBuilder()
|
||||||
|
.setTitle('Active Tickets')
|
||||||
|
.setDescription(ticketsOpen.map(t => `<#${t.id}>`).join('\n') || 'No active tickets.')
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
|
const openTicketsButtonRow = new ActionRowBuilder()
|
||||||
|
.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('backToStats')
|
||||||
|
.setLabel('Back to Stats')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
|
||||||
|
await i.update({ embeds: [openTicketsEmbed], components: [openTicketsButtonRow] });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.customId === 'backToStats') {
|
||||||
|
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
|
const ticketsClaimed = TicketData.tickets.filter(t => t.claimedBy === viewingUserId);
|
||||||
|
const ticketsOpen = ticketsClaimed.filter(t => t.open);
|
||||||
|
const totalTickets = ticketsClaimed.length;
|
||||||
|
|
||||||
|
let totalResponseTime = 0;
|
||||||
|
let responseCount = 0;
|
||||||
|
|
||||||
|
ticketsClaimed.forEach(ticket => {
|
||||||
|
if (ticket.claimedAt && ticket.createdAt) {
|
||||||
|
const responseTime = new Date(ticket.claimedAt) - new Date(ticket.createdAt);
|
||||||
|
totalResponseTime += responseTime;
|
||||||
|
responseCount++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const averageResponseTime = responseCount ? totalResponseTime / responseCount : 0;
|
||||||
|
const averageResponseTimeMinutes = Math.round(averageResponseTime / 60000);
|
||||||
|
|
||||||
|
const statsEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(msgconfig.TicketStats.Title)
|
||||||
|
.setDescription(`> Ticket stats for <@${viewingUserId}>`)
|
||||||
|
.setColor(supportbot.Embed.Colours.General)
|
||||||
|
.addFields(
|
||||||
|
{ name: msgconfig.TicketStats.OpenTickets, value: `${ticketsOpen.length}`, inline: true },
|
||||||
|
{ name: msgconfig.TicketStats.TotalTickets, value: `${totalTickets}`, inline: true },
|
||||||
|
{ name: msgconfig.TicketStats.ResponseTime, value: `${averageResponseTimeMinutes} minutes`, inline: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
const statsButtonRow = new ActionRowBuilder()
|
||||||
|
.addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('showOpenTickets')
|
||||||
|
.setLabel('Show Open Tickets')
|
||||||
|
.setStyle(ButtonStyle.Secondary),
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId('backToProfile')
|
||||||
|
.setLabel('Back to Profile')
|
||||||
|
.setStyle(ButtonStyle.Secondary)
|
||||||
|
);
|
||||||
|
|
||||||
|
await i.update({ embeds: [statsEmbed], components: [statsButtonRow] });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i.customId === 'backToProfile') {
|
||||||
|
await i.update({ embeds: [profileEmbed], components: buttonRow.components.length > 0 ? [buttonRow] : [] });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports.clockedInUsers = clockedInUsers;
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
const fs = require("fs");
|
||||||
|
const {
|
||||||
|
EmbedBuilder,
|
||||||
|
ApplicationCommandOptionType,
|
||||||
|
ApplicationCommandType,
|
||||||
|
ChannelType,
|
||||||
|
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 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)
|
||||||
|
.setColor(supportbot.Embed.Colours.Error);
|
||||||
|
|
||||||
|
return interaction.reply({
|
||||||
|
embeds: [onlyInTicket],
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 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) {
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@@ -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 });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
+402
-240
@@ -8,7 +8,7 @@ const {
|
|||||||
ButtonBuilder,
|
ButtonBuilder,
|
||||||
StringSelectMenuBuilder,
|
StringSelectMenuBuilder,
|
||||||
StringSelectMenuOptionBuilder,
|
StringSelectMenuOptionBuilder,
|
||||||
GuildMemberRoleManager,
|
ButtonStyle,
|
||||||
} = require("discord.js");
|
} = require("discord.js");
|
||||||
const yaml = require("js-yaml");
|
const yaml = require("js-yaml");
|
||||||
|
|
||||||
@@ -20,6 +20,177 @@ const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
|
|||||||
const Command = require("../Structures/Command.js");
|
const Command = require("../Structures/Command.js");
|
||||||
const TicketNumberID = require("../Structures/TicketID.js");
|
const TicketNumberID = require("../Structures/TicketID.js");
|
||||||
|
|
||||||
|
async function getClockedInUsers(guild) {
|
||||||
|
const clockedInUsers = new Set();
|
||||||
|
|
||||||
|
const profilesDir = './Data/Profiles';
|
||||||
|
const profileFiles = fs.readdirSync(profilesDir);
|
||||||
|
|
||||||
|
for (const file of profileFiles) {
|
||||||
|
const profileData = JSON.parse(fs.readFileSync(`${profilesDir}/${file}`, "utf8"));
|
||||||
|
if (profileData.clockedIn) {
|
||||||
|
const userId = file.replace('.json', '');
|
||||||
|
const member = await guild.members.fetch(userId);
|
||||||
|
if (member) clockedInUsers.add(member.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return clockedInUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function assignTicketToUser(ticketChannel, Staff, Admin, interaction, attempts = 0) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
const clockedInUsers = await getClockedInUsers(interaction.guild);
|
||||||
|
|
||||||
|
if (clockedInUsers.size === 0 || attempts >= 2) {
|
||||||
|
const claimChannel = await interaction.guild.channels.cache.get(supportbot.Ticket.ClaimTickets.Channel);
|
||||||
|
if (claimChannel) {
|
||||||
|
const claimEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
|
||||||
|
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage)
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
|
const claimButton = new ButtonBuilder()
|
||||||
|
.setCustomId(`claimticket-${ticketChannel.id}`)
|
||||||
|
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle || 'Claim Ticket')
|
||||||
|
.setStyle(ButtonStyle.Primary);
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder().addComponents(claimButton);
|
||||||
|
|
||||||
|
const claimMessage = await claimChannel.send({
|
||||||
|
content: `<@&${Staff.id}> <@&${Admin.id}>`,
|
||||||
|
embeds: [claimEmbed],
|
||||||
|
components: [row],
|
||||||
|
});
|
||||||
|
|
||||||
|
const filter = i => i.customId === `claimticket-${ticketChannel.id}` && i.member.roles.cache.has(Staff.id);
|
||||||
|
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
|
||||||
|
|
||||||
|
collector.on('collect', async i => {
|
||||||
|
await ticketChannel.send({ content: `<@${i.user.id}> has claimed the ticket.` });
|
||||||
|
});
|
||||||
|
|
||||||
|
collector.on('end', async collected => {
|
||||||
|
if (collected.size === 0) {
|
||||||
|
await claimMessage.delete();
|
||||||
|
|
||||||
|
await claimChannel.send({
|
||||||
|
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)],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
console.error("Claim channel not found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const clockedInArray = Array.from(clockedInUsers);
|
||||||
|
const assignedUserId = clockedInArray[Math.floor(Math.random() * clockedInArray.length)];
|
||||||
|
const assignedUser = await interaction.guild.members.fetch(assignedUserId);
|
||||||
|
|
||||||
|
const claimEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
|
||||||
|
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage.replace('%user%', interaction.user.id))
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
|
const claimButton = new ButtonBuilder()
|
||||||
|
.setCustomId(`claimticket-${ticketChannel.id}`)
|
||||||
|
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle || 'Claim Ticket')
|
||||||
|
.setStyle(ButtonStyle.Primary);
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder().addComponents(claimButton);
|
||||||
|
|
||||||
|
const claimChannel = await interaction.guild.channels.cache.get(supportbot.Ticket.ClaimTickets.Channel);
|
||||||
|
if (!claimChannel) {
|
||||||
|
console.error("Claim channel not found");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const claimMessage = await claimChannel.send({
|
||||||
|
content: `${assignedUser}`,
|
||||||
|
embeds: [claimEmbed],
|
||||||
|
components: [row],
|
||||||
|
});
|
||||||
|
|
||||||
|
const filter = i => i.customId === `claimticket-${ticketChannel.id}` && i.user.id === assignedUserId;
|
||||||
|
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
|
||||||
|
|
||||||
|
collector.on('collect', async i => {
|
||||||
|
await ticketChannel.send({ content: `<@${assignedUserId}>` }).then(msg => setTimeout(() => msg.delete(), 5000));
|
||||||
|
});
|
||||||
|
|
||||||
|
collector.on('end', async collected => {
|
||||||
|
if (collected.size === 0) {
|
||||||
|
await claimMessage.delete();
|
||||||
|
|
||||||
|
if (attempts >= 1) {
|
||||||
|
await claimChannel.send({
|
||||||
|
content: `No one claimed the ticket. Tagging roles: <@&${Staff.id}> <@&${Admin.id}>`,
|
||||||
|
embeds: [new EmbedBuilder().setDescription(`Ticket is still unclaimed: <#${ticketChannel.id}>`).setColor(supportbot.Embed.Colours.Warn)],
|
||||||
|
});
|
||||||
|
|
||||||
|
const claimEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
|
||||||
|
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage)
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
|
const claimButton = new ButtonBuilder()
|
||||||
|
.setCustomId(`claimticket-${ticketChannel.id}`)
|
||||||
|
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle)
|
||||||
|
.setEmoji(supportbot.Ticket.ClaimTickets.ButtonEmoji)
|
||||||
|
.setStyle(ButtonStyle.Primary);
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder().addComponents(claimButton);
|
||||||
|
|
||||||
|
const claimMessage = await claimChannel.send({
|
||||||
|
embeds: [claimEmbed],
|
||||||
|
components: [row],
|
||||||
|
});
|
||||||
|
|
||||||
|
const filter = i => i.customId === `claimticket-${ticketChannel.id}` && i.member.roles.cache.has(Staff.id);
|
||||||
|
const collector = claimMessage.createMessageComponentCollector({ filter, time: 120000 });
|
||||||
|
|
||||||
|
collector.on('collect', async i => {
|
||||||
|
console.log(`Ticket ${ticketChannel.id} claimed by user ${i.user.id}`);
|
||||||
|
await ticketChannel.member.add(i.user.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
collector.on('end', async collected => {
|
||||||
|
if (collected.size === 0) {
|
||||||
|
console.log(`No one claimed the ticket (${ticketChannel.id}), notifying all staff`);
|
||||||
|
await claimMessage.delete();
|
||||||
|
|
||||||
|
await claimChannel.send({
|
||||||
|
content: `No one claimed the ticket. Tagging roles: <@&${Staff.id}> <@&${Admin.id}>`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
const ReassigningEmbed = new EmbedBuilder()
|
||||||
|
.setTitle(msgconfig.Ticket.ClaimTickets.ReassigningTitle)
|
||||||
|
.setDescription(msgconfig.Ticket.ClaimTickets.ReassigningMessage.replace('%user%', assignedUserId))
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
|
await claimChannel.send({ embeds: [ReassigningEmbed], components: [] });
|
||||||
|
await assignTicketToUser(ticketChannel, Staff, Admin, interaction, attempts + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return assignedUserId;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in assignTicketToUser function:", error);
|
||||||
|
if (error instanceof CombinedError) {
|
||||||
|
console.error("CombinedError details:", error.errors);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = new Command({
|
module.exports = new Command({
|
||||||
name: cmdconfig.OpenTicket.Command,
|
name: cmdconfig.OpenTicket.Command,
|
||||||
description: cmdconfig.OpenTicket.Description,
|
description: cmdconfig.OpenTicket.Description,
|
||||||
@@ -34,275 +205,266 @@ module.exports = new Command({
|
|||||||
permissions: cmdconfig.OpenTicket.Permission,
|
permissions: cmdconfig.OpenTicket.Permission,
|
||||||
|
|
||||||
async run(interaction) {
|
async run(interaction) {
|
||||||
let department = interaction.customId?.split("-")[1] || null;
|
try {
|
||||||
let TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
let TicketReason = null;
|
||||||
const { getRole, getChannel } = interaction.client;
|
if (supportbot.Ticket.TicketReason) {
|
||||||
let User = interaction.guild.members.cache.get(interaction.user.id);
|
TicketReason = interaction.reason || null; // Retrieve the reason from the interaction object
|
||||||
|
}
|
||||||
|
|
||||||
if (
|
let TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
supportbot.Ticket.TicketsPerUser &&
|
const { getRole, getChannel } = interaction.client;
|
||||||
TicketData.tickets.filter((t) => t.user === interaction.user.id && t.open).length >= supportbot.Ticket.TicketsPerUser
|
let User = interaction.guild.members.cache.get(interaction.user.id);
|
||||||
) {
|
|
||||||
return interaction.reply({
|
if (
|
||||||
embeds: [
|
supportbot.Ticket.TicketsPerUser &&
|
||||||
{
|
TicketData.tickets.filter((t) => t.user === interaction.user.id && t.open).length >= supportbot.Ticket.TicketsPerUser
|
||||||
title: "Too Many Tickets!",
|
) {
|
||||||
description: `You can't have more than ${supportbot.Ticket.TicketsPerUser} open tickets!`,
|
return interaction.reply({
|
||||||
color: supportbot.Embed.Colours.Warn,
|
embeds: [
|
||||||
},
|
{
|
||||||
],
|
title: "Too Many Tickets!",
|
||||||
ephemeral: true,
|
description: `You can't have more than ${supportbot.Ticket.TicketsPerUser} open tickets!`,
|
||||||
});
|
color: supportbot.Embed.Colours.Warn,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (User.roles.cache.has(supportbot.Roles.ModRoles.Blacklisted)) {
|
||||||
|
return interaction.reply({
|
||||||
|
content: msgconfig.Ticket.Blacklisted,
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (User.roles.cache.has(supportbot.Roles.ModRoles.Muted)) {
|
||||||
|
return interaction.reply({
|
||||||
|
content: msgconfig.Ticket.Muted,
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let ticketNumberID = await TicketNumberID.pad();
|
||||||
|
const TicketSubject = TicketReason || msgconfig.Ticket.InvalidSubject;
|
||||||
|
|
||||||
|
const TicketExists = new EmbedBuilder()
|
||||||
|
.setTitle("Ticket Exists!")
|
||||||
|
.setDescription(msgconfig.Ticket.TicketExists);
|
||||||
|
|
||||||
|
if (
|
||||||
|
await interaction.guild.channels.cache.find(
|
||||||
|
(ticketChannel) => ticketChannel.name === `${supportbot.Ticket.Channel}${ticketNumberID}`
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return await interaction.reply({
|
||||||
|
embeds: [TicketExists],
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
|
||||||
|
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
|
||||||
|
if (!Staff || !Admin)
|
||||||
|
return interaction.reply({
|
||||||
|
content: "Some roles seem to be missing!\nPlease check for errors when starting the bot.",
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
let ticketChannel;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (User.roles.cache.has(supportbot.Roles.ModRoles.Blacklisted)) {
|
// Save ticket data
|
||||||
return interaction.reply({
|
TicketData.tickets.push({
|
||||||
content: msgconfig.Ticket.Blacklisted,
|
id: ticketChannel.id,
|
||||||
ephemeral: true,
|
name: ticketChannel.name,
|
||||||
});
|
user: interaction.user.id,
|
||||||
}
|
number: ticketNumberID,
|
||||||
|
reason: TicketSubject,
|
||||||
if (User.roles.cache.has(supportbot.Roles.ModRoles.Muted)) {
|
open: true,
|
||||||
return interaction.reply({
|
subUsers: [],
|
||||||
content: msgconfig.Ticket.Muted,
|
createdAt: new Date().toISOString(),
|
||||||
ephemeral: true,
|
claimedAt: null,
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let ticketNumberID = await TicketNumberID.pad();
|
|
||||||
const TicketSubject = interaction.options?.getString("reason") || msgconfig.Ticket.InvalidSubject;
|
|
||||||
|
|
||||||
const TicketExists = new EmbedBuilder()
|
|
||||||
.setTitle("Ticket Exists!")
|
|
||||||
.setDescription(msgconfig.Ticket.TicketExists);
|
|
||||||
|
|
||||||
if (
|
|
||||||
await interaction.guild.channels.cache.find(
|
|
||||||
(ticketChannel) => ticketChannel.name === `${supportbot.Ticket.Channel}${ticketNumberID}`
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return await interaction.reply({
|
|
||||||
embeds: [TicketExists],
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const Staff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
|
|
||||||
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
|
|
||||||
|
|
||||||
if (!Staff || !Admin)
|
|
||||||
return interaction.reply({
|
|
||||||
content: "Some roles seem to be missing!\nPlease check for errors when starting the bot.",
|
|
||||||
ephemeral: true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const TicketCategory = interaction.guild.channels.cache.find(
|
fs.writeFileSync(
|
||||||
(c) => c.name === supportbot.Ticket.TicketCategory || c.id === supportbot.Ticket.TicketCategory
|
"./Data/TicketData.json",
|
||||||
);
|
JSON.stringify(TicketData, null, 4),
|
||||||
|
(err) => {
|
||||||
const channel = await getChannel(supportbot.Ticket.TicketCategory, interaction.guild);
|
if (err) console.error(err);
|
||||||
const ticketChannel = await channel.threads.create({
|
}
|
||||||
name: `${supportbot.Ticket.Channel}${ticketNumberID}`,
|
|
||||||
type: ChannelType.PrivateThread,
|
|
||||||
parent: TicketCategory,
|
|
||||||
autoArchiveDuration: 60,
|
|
||||||
reason: 'support ticket',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (supportbot.Ticket.ClaimTickets.Enabled === false) {
|
|
||||||
const InvStaff = await ticketChannel.send(`<@&${Staff.id}> <@&${Admin.id}>`)
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
InvStaff.delete();
|
|
||||||
}, 2000)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TICKET CLAIMING SYSTEM [START]
|
|
||||||
|
|
||||||
if (supportbot.Ticket.ClaimTickets.Enabled) {
|
|
||||||
const InvStaff1 = await ticketChannel.send(`<@&${Admin.id}>`)
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
InvStaff1.delete();
|
|
||||||
}, 2000)
|
|
||||||
|
|
||||||
const claimChannel = await getChannel(
|
|
||||||
supportbot.Ticket.ClaimTickets.Channel,
|
|
||||||
interaction.guild
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const claimEmbed = new EmbedBuilder()
|
// Notify the user that the ticket was created
|
||||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimTitle)
|
const CreatedTicket = new EmbedBuilder()
|
||||||
.setDescription(msgconfig.Ticket.ClaimTickets.ClaimMessage
|
.setDescription(
|
||||||
.replace('%user%', interaction.user.id)
|
msgconfig.Ticket.TicketCreatedAlert.replace(/%ticketauthor%/g, interaction.user.id)
|
||||||
)
|
.replace(/%ticketid%/g, ticketChannel.id)
|
||||||
.setColor(supportbot.Embed.Colours.General);
|
.replace(/%ticketusername%/g, interaction.user.username)
|
||||||
|
.replace(/%ticketreason%/g, TicketSubject)
|
||||||
|
)
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
await interaction.reply({ embeds: [CreatedTicket], ephemeral: true });
|
||||||
|
|
||||||
const claimButton = new ButtonBuilder()
|
// Create the ticket message
|
||||||
.setCustomId(`claimticket-${ticketChannel.id}`)
|
const TicketMessage = new EmbedBuilder()
|
||||||
.setLabel(supportbot.Ticket.ClaimTickets.ButtonTitle)
|
.setAuthor({
|
||||||
.setStyle(supportbot.Ticket.ClaimTickets.Button);
|
name: msgconfig.Ticket.TicketAuthorTitle.replace(/%ticketauthor%/g, interaction.user.id)
|
||||||
|
.replace(/%ticketid%/g, ticketChannel.id)
|
||||||
|
.replace(/%ticketusername%/g, interaction.user.username),
|
||||||
|
iconURL: interaction.user.displayAvatarURL(),
|
||||||
|
})
|
||||||
|
.setTitle(
|
||||||
|
msgconfig.Ticket.TicketTitle.replace(/%ticketauthor%/g, interaction.user.id)
|
||||||
|
.replace(/%ticketid%/g, ticketChannel.id)
|
||||||
|
.replace(/%ticketusername%/g, interaction.user.username)
|
||||||
|
)
|
||||||
|
.setDescription(
|
||||||
|
msgconfig.Ticket.TicketMessage.replace(/%ticketauthor%/g, interaction.user.id)
|
||||||
|
.replace(/%ticketid%/g, ticketChannel.id)
|
||||||
|
.replace(/%ticketusername%/g, interaction.user.username)
|
||||||
|
.replace(/%ticketreason%/g, TicketSubject)
|
||||||
|
)
|
||||||
|
.setColor(supportbot.Embed.Colours.General);
|
||||||
|
|
||||||
const row = new ActionRowBuilder().addComponents(claimButton);
|
// Add reason field if ticket reason is enabled
|
||||||
|
if (supportbot.Ticket.TicketReason && TicketReason) {
|
||||||
await claimChannel.send({
|
TicketMessage.addFields(
|
||||||
content: `<@&${Staff.id}>`,
|
{ name: "Reason", value: TicketReason, inline: false }
|
||||||
embeds: [claimEmbed],
|
);
|
||||||
components: [row]
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// TICKET CLAIMING SYSTEM [END]
|
|
||||||
|
|
||||||
if (!department) {
|
|
||||||
await ticketChannel.members.add(interaction.user.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
TicketData.tickets.push({
|
|
||||||
id: ticketChannel.id,
|
|
||||||
name: ticketChannel.name,
|
|
||||||
user: interaction.user.id,
|
|
||||||
number: ticketNumberID,
|
|
||||||
reason: TicketSubject,
|
|
||||||
open: true,
|
|
||||||
subUsers: [],
|
|
||||||
createdAt: new Date().toISOString(),
|
|
||||||
claimedAt: null, // Will be updated when claimed
|
|
||||||
});
|
|
||||||
|
|
||||||
fs.writeFileSync(
|
|
||||||
"./Data/TicketData.json",
|
|
||||||
JSON.stringify(TicketData, null, 4),
|
|
||||||
(err) => {
|
|
||||||
if (err) console.error(err);
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
const CreatedTicket = new EmbedBuilder()
|
// Create the control panel
|
||||||
.setDescription(
|
const SelectMenus = new StringSelectMenuBuilder()
|
||||||
msgconfig.Ticket.TicketCreatedAlert.replace(/%ticketauthor%/g, interaction.user.id)
|
|
||||||
.replace(/%ticketid%/g, ticketChannel.id)
|
|
||||||
.replace(/%ticketusername%/g, interaction.user.username)
|
|
||||||
)
|
|
||||||
.setColor(supportbot.Embed.Colours.General);
|
|
||||||
await interaction.reply({ embeds: [CreatedTicket], ephemeral: true });
|
|
||||||
|
|
||||||
if (supportbot.Ticket.AllowMentions) {
|
|
||||||
await ticketChannel.send(`${interaction.user}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const TicketMessage = new EmbedBuilder()
|
|
||||||
.setAuthor({
|
|
||||||
name: msgconfig.Ticket.TicketAuthorTitle.replace(/%ticketauthor%/g, interaction.user.id)
|
|
||||||
.replace(/%ticketid%/g, ticketChannel.id)
|
|
||||||
.replace(/%ticketusername%/g, interaction.user.username),
|
|
||||||
iconURL: interaction.user.displayAvatarURL(),
|
|
||||||
})
|
|
||||||
.setTitle(
|
|
||||||
msgconfig.Ticket.TicketTitle.replace(/%ticketauthor%/g, interaction.user.id)
|
|
||||||
.replace(/%ticketid%/g, ticketChannel.id)
|
|
||||||
.replace(/%ticketusername%/g, interaction.user.username)
|
|
||||||
)
|
|
||||||
.setDescription(
|
|
||||||
msgconfig.Ticket.TicketMessage.replace(/%ticketauthor%/g, interaction.user.id)
|
|
||||||
.replace(/%ticketid%/g, ticketChannel.id)
|
|
||||||
.replace(/%ticketusername%/g, interaction.user.username)
|
|
||||||
)
|
|
||||||
.setColor(supportbot.Embed.Colours.General);
|
|
||||||
|
|
||||||
const SelectMenus = new StringSelectMenuBuilder()
|
|
||||||
.setCustomId("ticketcontrolpanel")
|
.setCustomId("ticketcontrolpanel")
|
||||||
.setPlaceholder("Ticket Control Panel")
|
.setPlaceholder("Ticket Control Panel")
|
||||||
.addOptions(
|
.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()
|
new StringSelectMenuOptionBuilder()
|
||||||
.setLabel("Close")
|
.setLabel("Close")
|
||||||
.setDescription("Close the ticket.")
|
.setDescription("Close the ticket.")
|
||||||
.setEmoji(supportbot.SelectMenus.Tickets.CloseEmoji)
|
.setEmoji(supportbot.SelectMenus.Tickets.CloseEmoji)
|
||||||
.setValue("ticketclose"),
|
.setValue("ticketclose"),
|
||||||
new StringSelectMenuOptionBuilder()
|
new StringSelectMenuOptionBuilder()
|
||||||
.setLabel("Enable Invites")
|
.setLabel("Archive")
|
||||||
.setDescription("Enable invites.")
|
.setDescription("Archive the ticket.")
|
||||||
.setEmoji(supportbot.SelectMenus.Tickets.EnableInvitesEmoji)
|
.setEmoji(supportbot.SelectMenus.Tickets.ArchiveEmoji)
|
||||||
.setValue("enableinvites"),
|
.setValue("archiveticket"),
|
||||||
|
...(supportbot.Ticket.TicketType === "threads" ? [
|
||||||
|
new StringSelectMenuOptionBuilder()
|
||||||
|
.setLabel("Lock Ticket")
|
||||||
|
.setDescription("Lock the ticket.")
|
||||||
|
.setEmoji(supportbot.SelectMenus.Tickets.LockEmoji)
|
||||||
|
.setValue("lockticket")
|
||||||
|
] : []),
|
||||||
new StringSelectMenuOptionBuilder()
|
new StringSelectMenuOptionBuilder()
|
||||||
.setLabel("Disable Invites")
|
.setLabel("Rename Ticket")
|
||||||
.setDescription("Disable invites.")
|
.setDescription("Rename the ticket.")
|
||||||
.setEmoji(supportbot.SelectMenus.Tickets.DisableInvitesEmoji)
|
.setEmoji(supportbot.SelectMenus.Tickets.RenameEmoji)
|
||||||
.setValue("disableinvites"),
|
.setValue("renameticket")
|
||||||
);
|
);
|
||||||
|
|
||||||
const row2 = new ActionRowBuilder().addComponents(SelectMenus);
|
if (supportbot.Ticket.TicketType === "threads") {
|
||||||
|
SelectMenus.addOptions(
|
||||||
if (!department) {
|
new StringSelectMenuOptionBuilder()
|
||||||
try {
|
.setLabel("Enable Invites")
|
||||||
let buttons = supportbot.Departments.map((x) =>
|
.setDescription("Enable invites.")
|
||||||
new ButtonBuilder()
|
.setEmoji(supportbot.SelectMenus.Tickets.EnableInvitesEmoji)
|
||||||
.setCustomId("Department" + supportbot.Departments.indexOf(x))
|
.setValue("enableinvites"),
|
||||||
.setLabel(x.title)
|
new StringSelectMenuOptionBuilder()
|
||||||
.setStyle(x.color)
|
.setLabel("Disable Invites")
|
||||||
.setEmoji(x.emoji)
|
.setDescription("Disable invites.")
|
||||||
);
|
.setEmoji(supportbot.SelectMenus.Tickets.DisableInvitesEmoji)
|
||||||
|
.setValue("disableinvites"),
|
||||||
if (supportbot.Ticket.AllowMentions) {
|
);
|
||||||
await ticketChannel.send("<@&" + supportbot.Ticket.RoleMention + ">");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const row = new ActionRowBuilder().addComponents(buttons);
|
const row2 = new ActionRowBuilder().addComponents(SelectMenus);
|
||||||
const m = await ticketChannel.send({
|
|
||||||
embeds: [TicketMessage],
|
|
||||||
components: [row2],
|
|
||||||
});
|
|
||||||
|
|
||||||
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) {
|
|
||||||
console.error("An error occurred while handling collector:", error);
|
|
||||||
}
|
|
||||||
return await ticketChannel.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error sending message:", error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await ticketChannel.send({
|
await ticketChannel.send({
|
||||||
embeds: [TicketMessage],
|
embeds: [TicketMessage],
|
||||||
components: [row2],
|
components: [row2],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error in run method:", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -35,8 +35,13 @@ module.exports = new Command({
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const channelName = panelconfig.Channel;
|
const { getChannel } = interaction.client;
|
||||||
const channel = interaction.guild.channels.cache.find(ch => ch.name === channelName);
|
|
||||||
|
const channel = await getChannel(
|
||||||
|
supportbot.Ticket.TicketHome,
|
||||||
|
interaction.guild
|
||||||
|
);
|
||||||
|
|
||||||
if (!channel) {
|
if (!channel) {
|
||||||
console.log(`[TICKET PANEL] ${channelName} channel not found. Please check your config file.`);
|
console.log(`[TICKET PANEL] ${channelName} channel not found. Please check your config file.`);
|
||||||
return interaction.reply({
|
return interaction.reply({
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
const { EmbedBuilder, ApplicationCommandType } = require("discord.js");
|
|
||||||
const fs = require("fs");
|
|
||||||
const yaml = require("js-yaml");
|
|
||||||
|
|
||||||
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
|
||||||
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
|
||||||
const msgconfig = yaml.load(fs.readFileSync("./Configs/messages.yml", "utf8"));
|
|
||||||
|
|
||||||
const Command = require("../Structures/Command.js");
|
|
||||||
|
|
||||||
module.exports = new Command({
|
|
||||||
name: cmdconfig.TicketStats.Command,
|
|
||||||
description: cmdconfig.TicketStats.Description,
|
|
||||||
type: ApplicationCommandType.ChatInput,
|
|
||||||
permissions: ["SendMessages"], // Adjust permissions as needed
|
|
||||||
|
|
||||||
async run(interaction) {
|
|
||||||
|
|
||||||
if (supportbot.Ticket.ClaimTickets.Enabled) {
|
|
||||||
|
|
||||||
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
|
||||||
const userId = interaction.user.id;
|
|
||||||
|
|
||||||
const ticketsClaimed = TicketData.tickets.filter(t => t.claimedBy === userId);
|
|
||||||
const ticketsOpen = ticketsClaimed.filter(t => t.open);
|
|
||||||
const totalTickets = ticketsClaimed.length;
|
|
||||||
|
|
||||||
let totalResponseTime = 0;
|
|
||||||
let responseCount = 0;
|
|
||||||
|
|
||||||
ticketsClaimed.forEach(ticket => {
|
|
||||||
if (ticket.claimedAt && ticket.createdAt) {
|
|
||||||
const responseTime = new Date(ticket.claimedAt) - new Date(ticket.createdAt);
|
|
||||||
totalResponseTime += responseTime;
|
|
||||||
responseCount++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const averageResponseTime = responseCount ? totalResponseTime / responseCount : 0;
|
|
||||||
const averageResponseTimeMinutes = Math.round(averageResponseTime / 60000); // Convert to minutes
|
|
||||||
|
|
||||||
const statsEmbed = new EmbedBuilder()
|
|
||||||
.setTitle(msgconfig.TicketStats.Title)
|
|
||||||
.setDescription(`> Ticket stats for <@${interaction.user.id}>`)
|
|
||||||
.setColor(supportbot.Embed.Colours.General)
|
|
||||||
.addFields(
|
|
||||||
{ name: msgconfig.TicketStats.OpenTickets, value: `${ticketsOpen.length}`, inline: true },
|
|
||||||
{ name: msgconfig.TicketStats.TotalTickets, value: `${totalTickets}`, inline: true },
|
|
||||||
{ name: msgconfig.TicketStats.ResponseTime, value: `${averageResponseTimeMinutes} minutes`, inline: false }
|
|
||||||
);
|
|
||||||
|
|
||||||
await interaction.reply({ embeds: [statsEmbed], ephemeral: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@@ -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 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 text = await interaction.options.getString("text"); // Grab the text to translate by the user
|
||||||
let translatelog = await getChannel(
|
let translatelog = await getChannel(
|
||||||
supportbot.Translate.Log,
|
supportbot.Translate.TranslateLog,
|
||||||
interaction.guild
|
interaction.guild
|
||||||
); // Grab the set logging channel for translations
|
); // Grab the set logging channel for translations
|
||||||
|
|
||||||
|
|||||||
@@ -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/
|
|
||||||
**/
|
|
||||||
+29
-11
@@ -13,18 +13,14 @@
|
|||||||
#
|
#
|
||||||
# Command Configuration
|
# Command Configuration
|
||||||
|
|
||||||
|
# If you don't want to mess with this configuration, You can manage commands via Discord Settings the Intregations.
|
||||||
|
|
||||||
Help:
|
Help:
|
||||||
Command: "help"
|
Command: "help"
|
||||||
Description: "Get a list of all the commands."
|
Description: "Get a list of all the commands."
|
||||||
Permission: ["SendMessages"]
|
Permission: ["SendMessages"]
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
EnableAI:
|
|
||||||
Command: "enableai"
|
|
||||||
Description: "Talk with SupportBot"
|
|
||||||
Permission: ["SendMessages"]
|
|
||||||
Enabled: true
|
|
||||||
|
|
||||||
Info:
|
Info:
|
||||||
Command: "info"
|
Command: "info"
|
||||||
Description: "Get information about the **ServerName**."
|
Description: "Get information about the **ServerName**."
|
||||||
@@ -37,9 +33,9 @@ TicketPanel:
|
|||||||
Permission: ["Administrator"]
|
Permission: ["Administrator"]
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
TicketStats:
|
Profile:
|
||||||
Command: "ticketstats"
|
Command: "profile"
|
||||||
Description: "Shows staff members their ticket statistics"
|
Description: "Shows the profile for a discord member."
|
||||||
Permission: ["SendMessages"]
|
Permission: ["SendMessages"]
|
||||||
# Command is automatically disabled when the TicketClaims is disabled.
|
# Command is automatically disabled when the TicketClaims is disabled.
|
||||||
|
|
||||||
@@ -49,9 +45,21 @@ OpenTicket:
|
|||||||
Permission: ["SendMessages"]
|
Permission: ["SendMessages"]
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
Add:
|
AddUser:
|
||||||
Command: "add"
|
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"]
|
Permission: ["SendMessages"]
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
@@ -91,6 +99,16 @@ Ping:
|
|||||||
Permission: ["SendMessages"]
|
Permission: ["SendMessages"]
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
# ---------------------------------------
|
||||||
|
# Bot Administrator Commands
|
||||||
|
# ---------------------------------------
|
||||||
|
|
||||||
|
Settings:
|
||||||
|
Command: "settings"
|
||||||
|
Description: "Update bot settings."
|
||||||
|
Permission: ["Administrator"]
|
||||||
|
Enabled: true
|
||||||
|
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
# Command Description Configuration
|
# Command Description Configuration
|
||||||
# ---------------------------------------
|
# ---------------------------------------
|
||||||
|
|||||||
+101
-36
@@ -17,14 +17,14 @@ Info:
|
|||||||
Title: "About Us"
|
Title: "About Us"
|
||||||
Description: "SupportBot is an open-sourced support system for discord. It's completely free to use with high amounts of customization to match your own brand."
|
Description: "SupportBot is an open-sourced support system for discord. It's completely free to use with high amounts of customization to match your own brand."
|
||||||
Button: "Visit Site"
|
Button: "Visit Site"
|
||||||
URL: "https://emeraldsrv.com"
|
URL: "https://docs.emeraldsrv.com"
|
||||||
Colour: "#f74343"
|
Colour: "#f74343"
|
||||||
|
|
||||||
Welcome:
|
Welcome:
|
||||||
Embed:
|
Embed:
|
||||||
Colour: "#f74343"
|
Colour: "#f74343"
|
||||||
Title: "Welcome to ServerName"
|
Title: "Welcome to ServerName"
|
||||||
Message: "> :smile: %joined_user% has just landed!"
|
Message: ":smile: %joined_user% has just landed!"
|
||||||
Thumbnail: "BOT"
|
Thumbnail: "BOT"
|
||||||
|
|
||||||
ImageEnabled: false
|
ImageEnabled: false
|
||||||
@@ -34,7 +34,7 @@ Leave:
|
|||||||
Embed:
|
Embed:
|
||||||
Colour: "#f74343"
|
Colour: "#f74343"
|
||||||
Title: "Goodbye!"
|
Title: "Goodbye!"
|
||||||
Message: "> :slight_frown: %joined_user% has recently dropped out!"
|
Message: ":slight_frown: %joined_user% has recently dropped out!"
|
||||||
Thumbnail: "BOT"
|
Thumbnail: "BOT"
|
||||||
|
|
||||||
ImageEnabled: false
|
ImageEnabled: false
|
||||||
@@ -42,8 +42,8 @@ Leave:
|
|||||||
|
|
||||||
Suggestions:
|
Suggestions:
|
||||||
Sent_Title: "Suggestion Sent!"
|
Sent_Title: "Suggestion Sent!"
|
||||||
Sent: "> :white_check_mark: **You have successfully sent a suggestion.**"
|
Sent: ":white_check_mark: **You have successfully sent a suggestion.**"
|
||||||
NoSelfVote: "> :x: **You cannot vote on your own suggestion.**"
|
NoSelfVote: ":x: **You cannot vote on your own suggestion.**"
|
||||||
RemoveVoteButton: "Remove Vote"
|
RemoveVoteButton: "Remove Vote"
|
||||||
|
|
||||||
Ticket:
|
Ticket:
|
||||||
@@ -56,47 +56,44 @@ Ticket:
|
|||||||
|
|
||||||
TicketAuthorTitle: "%ticketusername%'s Ticket"
|
TicketAuthorTitle: "%ticketusername%'s Ticket"
|
||||||
TicketTitle: "Support 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"
|
TicketThumbnail: "https://images.emojiterra.com/google/android-pie/512px/1f39f.png"
|
||||||
TicketCreatedAlert: "> :ticket: Ticked Created: <#%ticketid%>"
|
TicketCreatedAlert: ":ticket: Ticked Created: <#%ticketid%>"
|
||||||
TicketExists: "> ❌ Ticket already exists"
|
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
|
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
|
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."
|
TicketArchived: ":white_check_mark: Ticket archived."
|
||||||
EnableInvites: "> 🔓 Invites have been enabled for this ticket."
|
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:
|
# Available Placeholders:
|
||||||
|
|
||||||
# <@%user%> - Tags the user who was added to the ticket.
|
# <@%user%> - Tags the user who was added to the ticket.
|
||||||
|
|
||||||
AddUserToTicket_Title: "➕ Add User!"
|
Blacklisted: ":x: You are not allowed to open a ticket"
|
||||||
AddUserToTicket: "> To add a user to this ticket, Tag them."
|
Muted: ":x: You are `Muted` and therefore not allowed to open any tickets"
|
||||||
|
InvalidSubject: "No Reason Provided!"
|
||||||
|
|
||||||
RemovedUserFromTicket_Title: "➖ Removed User!"
|
ConfirmClose: "Please confirm closing the ticket by clicking the button below."
|
||||||
RemovedUserFromTicket: "> <@%user%> has been `Removed` from this ticket"
|
CloseTimeout: "Ticket close confirmation timed out."
|
||||||
|
|
||||||
Blacklisted: "> :x: You are not allowed to open a ticket"
|
RenamedSuccess: "🏷️ Ticket renamed successfully!"
|
||||||
Muted: "> :x: You are `Muted` and therefore not allowed to open any tickets"
|
|
||||||
InvalidSubject: "> No Reason Provided!"
|
|
||||||
|
|
||||||
TranscriptSavedMessage: "📝 **Transcript Saved!**"
|
|
||||||
TicketLockMessage: "❌ **Ticket Locked!**"
|
|
||||||
TicketDeleteMessage: "⚠ **Ticket Deleting!**"
|
|
||||||
|
|
||||||
ClosingTicket: "> :warning: You have requested to close your support ticket."
|
|
||||||
ConfirmClose: "> Please confirm closing the ticket by clicking the button below."
|
|
||||||
CloseTimeout: "> Ticket close confirmation timed out."
|
|
||||||
|
|
||||||
ClaimTickets:
|
ClaimTickets:
|
||||||
ClaimTitle: "Incoming Support Request!"
|
ClaimTitle: "Incoming Support Request!"
|
||||||
ClaimMessage: "> A new ticket has been created by <@!%user%>. Click the button below to claim this ticket."
|
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_Edit: "<#%channel%> was claimed by <@!%user%>."
|
||||||
|
|
||||||
ClaimedTitle: "Ticket Claimed!"
|
ClaimedTitle: "Ticket Claimed!"
|
||||||
Claimed: "> You have successfully claimed this ticket. <#%channel%>"
|
Claimed: "You have successfully claimed this ticket. <#%channel%>"
|
||||||
NoPermsToClaimTitle: "Error, no permissions!"
|
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...**"
|
||||||
|
|
||||||
TicketStats:
|
TicketStats:
|
||||||
OpenTickets: "✅ Open Tickets"
|
OpenTickets: "✅ Open Tickets"
|
||||||
@@ -105,12 +102,80 @@ TicketStats:
|
|||||||
|
|
||||||
Title: "Your Ticket Stats"
|
Title: "Your Ticket Stats"
|
||||||
|
|
||||||
|
TicketLog:
|
||||||
|
Title: "Ticket Log"
|
||||||
|
Colour: "#0cc559"
|
||||||
|
|
||||||
|
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%."
|
||||||
|
|
||||||
|
# Added Message for inside the ticket, this informs everyone inside the ticket that the user has been added.
|
||||||
|
Added_Title: "User Added"
|
||||||
|
Added_Description: "Successfully added **%username%** to the ticket."
|
||||||
|
|
||||||
|
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:
|
Error:
|
||||||
IncorrectPerms: "> :x: **Err!** You do not have the correct permissions to use this."
|
IncorrectPerms: ":x: **Err!** You do not have the correct permissions to use this."
|
||||||
InvalidChannel: "> :x: **Err!** Channel not found. Please create it!"
|
InvalidChannel: ":x: **Err!** Channel not found. Please create it!"
|
||||||
UserNotFound: "> :x: **Err!** This user doesn't exist, Are they in this server?"
|
UserNotFound: ":x: **Err!** This user doesn't exist, Are they in this server?"
|
||||||
NoValidTicket: "> :warning: You cannot execute this command here."
|
NoValidTicket: ":warning: You cannot execute this command here."
|
||||||
TicketExists: "> :warning: This ticket cannot be opened, It already exists!"
|
TicketExists: ":warning: This ticket cannot be opened, It already exists!"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,12 @@ Enabled: true
|
|||||||
General:
|
General:
|
||||||
Name: "SupportBot AI"
|
Name: "SupportBot AI"
|
||||||
# What would you like to call your AI
|
# What would you like to call your AI
|
||||||
Model: "gpt-4o"
|
Model: "gpt-4o-mini"
|
||||||
# You can see a list of OpenAI Models here: https://platform.openai.com/docs/models
|
# You can see a list of OpenAI Models here: https://platform.openai.com/docs/models
|
||||||
|
|
||||||
Tokens: 400
|
Tokens: 400
|
||||||
# Max tokens you can set is 400
|
# Max tokens you can set is 400
|
||||||
# For more information about tokens, go to https://openai.com/api/pricing/
|
# For more information about tokens, go to https://openai.com/api/pricing/
|
||||||
|
|
||||||
OpenAI_Key: "OPEN_AI_API_KEY"
|
OpenAI_Key: "OPEN_AI_API_KEY"
|
||||||
# To create an OpenAI API key, go to https://platform.openai.com/api-keys
|
# To create an OpenAI API key, go to https://platform.openai.com/api-keys
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ General:
|
|||||||
PastebinAPI_URL: "https://pastebin.com/api/api_post.php"
|
PastebinAPI_URL: "https://pastebin.com/api/api_post.php"
|
||||||
|
|
||||||
Channels:
|
Channels:
|
||||||
AIChannel: "0000000000000000000"
|
AIChannel: "AI_BOT_CHANNEL"
|
||||||
# This is the channel where AI will respond in without needing to mention the bot.
|
# This is the channel where AI will respond in without needing to mention the bot.
|
||||||
|
|
||||||
Embed:
|
Embed:
|
||||||
|
|||||||
+72
-46
@@ -11,7 +11,7 @@
|
|||||||
# Official Documentation: https://github.com/Emerald-Services/SupportBot/wiki
|
# Official Documentation: https://github.com/Emerald-Services/SupportBot/wiki
|
||||||
# Third-Party Documentation: COMING SOON
|
# Third-Party Documentation: COMING SOON
|
||||||
|
|
||||||
SupportBot_Version: "v8.0"
|
SupportBot_Version: "v8.2"
|
||||||
# Do not change the version number
|
# Do not change the version number
|
||||||
|
|
||||||
# -------------------------
|
# -------------------------
|
||||||
@@ -24,7 +24,7 @@ General:
|
|||||||
# To get your Discord Bot Token, Go to https://discord.com/developers/applications
|
# To get your Discord Bot Token, Go to https://discord.com/developers/applications
|
||||||
|
|
||||||
Addons:
|
Addons:
|
||||||
Enabled: false
|
Enabled: true
|
||||||
|
|
||||||
# -------------------------
|
# -------------------------
|
||||||
# Activity
|
# Activity
|
||||||
@@ -37,6 +37,8 @@ Activity:
|
|||||||
StreamingURL: "https://www.twitch.tv/YOUR_TWITCH_NAME"
|
StreamingURL: "https://www.twitch.tv/YOUR_TWITCH_NAME"
|
||||||
# Set The Type to "Streaming" for a streaming status!
|
# Set The Type to "Streaming" for a streaming status!
|
||||||
|
|
||||||
|
# You can update the activity via Discord using: /settings
|
||||||
|
|
||||||
# -------------------------
|
# -------------------------
|
||||||
# Embeds
|
# Embeds
|
||||||
# -------------------------
|
# -------------------------
|
||||||
@@ -57,15 +59,15 @@ Embed:
|
|||||||
Roles:
|
Roles:
|
||||||
AutoRole:
|
AutoRole:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Role: "Member"
|
Role: "ROLE_ID"
|
||||||
|
|
||||||
StaffMember:
|
StaffMember:
|
||||||
Staff: "Staff"
|
Staff: "STAFF_ROLE_ID"
|
||||||
Admin: "Admin"
|
Admin: "ADMIN_ROLE_ID"
|
||||||
|
|
||||||
ModRoles:
|
ModRoles:
|
||||||
Muted: "Muted"
|
Muted: "MUTED_ROLE_ID"
|
||||||
Blacklisted: "Blacklisted"
|
Blacklisted: "BLACKLISTED_ROLE_ID"
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
# System Messages
|
# System Messages
|
||||||
@@ -73,18 +75,18 @@ Roles:
|
|||||||
|
|
||||||
Welcome:
|
Welcome:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Channel: "🚨┃join-leave-logs"
|
Channel: "WELCOME_CHANNEL_ID"
|
||||||
|
|
||||||
Leave:
|
Leave:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
Channel: "🚨┃join-leave-logs"
|
Channel: "LEAVE_CHANNEL_ID"
|
||||||
|
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
# Suggestions
|
# Suggestions
|
||||||
# ----------------------------
|
# ----------------------------
|
||||||
|
|
||||||
Suggestions:
|
Suggestions:
|
||||||
Channel: "📗┃suggestions"
|
Channel: "SUGGEST_CHANNEL_ID"
|
||||||
UpvoteEmoji: "✅"
|
UpvoteEmoji: "✅"
|
||||||
DownvoteEmoji: "❌"
|
DownvoteEmoji: "❌"
|
||||||
|
|
||||||
@@ -119,8 +121,23 @@ Suggestions:
|
|||||||
# -------------------------
|
# -------------------------
|
||||||
|
|
||||||
Ticket:
|
Ticket:
|
||||||
TicketCategory: "📗┃tickets" #Where tickets normally go with the /ticket command
|
TicketType: "channels" # Choose how you want tickets to be created.
|
||||||
# This is the channel name for the ticket threads to be created, NOT A DISCORD CATEGORY!
|
# Options:
|
||||||
|
# channels - Tickets will be created as channels in the
|
||||||
|
# threads - Tickets will be created as threads through the "TicketHome"
|
||||||
|
|
||||||
|
# For TicketType "Threads"
|
||||||
|
TicketHome: "TICKETHOME_CHANNEL_ID"
|
||||||
|
# What is TicketHome?
|
||||||
|
# - Channel where the Ticket creation panel is sent.
|
||||||
|
# - Channel where ticket threads are made. (only if ticket threads is enabled above.)
|
||||||
|
|
||||||
|
# For TicketType "Channels"
|
||||||
|
TicketChannelsCategory: "TICKET_CATEGORY_ID" # if Type is set to channels
|
||||||
|
TicketChannelsCategory2: "BACKUP_TICKET_CATEGORY_ID" # This will be used if the first category has reached the max channel limit.
|
||||||
|
TicketArchiveCategory: "ARCHIVE_TICKET_CATEGORY_ID"
|
||||||
|
|
||||||
|
# ---
|
||||||
|
|
||||||
Channel: "ticket-" # The prefix for ticket channel names
|
Channel: "ticket-" # The prefix for ticket channel names
|
||||||
TicketsPerUser: 100
|
TicketsPerUser: 100
|
||||||
@@ -134,47 +151,50 @@ Ticket:
|
|||||||
# Set to true to allow all staff to access the ticket
|
# Set to true to allow all staff to access the ticket
|
||||||
|
|
||||||
Log:
|
Log:
|
||||||
TicketLog: "🚨┃ticket-data"
|
TicketDataLog: "TICKET_LOG_ID"
|
||||||
TicketLog_Title: "Ticket Closed"
|
TickeDataTitle: "Ticket Data"
|
||||||
DisableTicketLogChannel: false
|
|
||||||
|
|
||||||
TranscriptLog: "🚨┃ticket-data"
|
|
||||||
TranscriptTitle: "Ticket Transcript"
|
|
||||||
|
|
||||||
Close:
|
Close:
|
||||||
StaffOnly: true
|
StaffOnly: true
|
||||||
# Set to false is anyone is able to close a ticket.
|
# Set to false is anyone is able to close a ticket.
|
||||||
|
|
||||||
Confirmation_Button: "Confirm Close"
|
Confirmation_Button: "Confirm Close"
|
||||||
|
Confirmation_Emoji: "🗑️"
|
||||||
|
Confirmation_Style: "2"
|
||||||
|
|
||||||
Title: "Are you sure you want to close this ticket?"
|
Title: "Are you sure you want to close this ticket?"
|
||||||
|
|
||||||
Invites:
|
|
||||||
StaffOnly: true
|
|
||||||
|
|
||||||
ClaimTickets:
|
|
||||||
Enabled: true
|
|
||||||
Channel: "1249723473757077624"
|
|
||||||
# Channel name or Channel ID
|
|
||||||
|
|
||||||
ButtonTitle: "Claim Ticket"
|
|
||||||
Button: "1"
|
|
||||||
|
|
||||||
# Available Button Styles
|
# Available Button Styles
|
||||||
# 1 - Blurple
|
# 1 - Blurple
|
||||||
# 2 - Grey
|
# 2 - Grey
|
||||||
# 3 - Green
|
# 3 - Green
|
||||||
# 4 - Red
|
# 4 - Red
|
||||||
|
|
||||||
|
Invites:
|
||||||
|
StaffOnly: true
|
||||||
|
|
||||||
# -------------------------
|
ClaimTickets:
|
||||||
# Departments - NOT IN THIS UPDATE
|
Enabled: true
|
||||||
# -------------------------
|
Channel: "CLAIM_TICKETS_CHANNEL_ID"
|
||||||
|
# Channel name or Channel ID
|
||||||
|
|
||||||
|
ClaimAcceptTime: 120000
|
||||||
|
# How long the assigned user has to accept the ticket before it gets re-assigned to someone else.
|
||||||
|
# 120000 = 2 Minutes
|
||||||
|
# 180000 = 3 Minutes
|
||||||
|
# 240000 = 4 Minutes
|
||||||
|
# 300000 = 5 Minutes
|
||||||
|
# Time in Mliseconds
|
||||||
|
|
||||||
Departments:
|
ButtonTitle: "Claim Ticket"
|
||||||
- title: "Create Ticket"
|
ButtonEmoji: "🎫"
|
||||||
role: "Staff"
|
Button: "1"
|
||||||
color: "2"
|
|
||||||
emoji: "🎫"
|
# Available Button Styles
|
||||||
category: "TICKETS"
|
# 1 - Blurple
|
||||||
|
# 2 - Grey
|
||||||
|
# 3 - Green
|
||||||
|
# 4 - Red
|
||||||
|
|
||||||
# -------------------------
|
# -------------------------
|
||||||
# Buttons
|
# Buttons
|
||||||
@@ -184,13 +204,20 @@ Buttons:
|
|||||||
ClaimEmoji: "🧑💻"
|
ClaimEmoji: "🧑💻"
|
||||||
ClaimStyle: "1"
|
ClaimStyle: "1"
|
||||||
|
|
||||||
|
Unarchive: "Unarchive Ticket"
|
||||||
|
Unarchive_Emoji: "♻️"
|
||||||
|
Unarchive_Style: "2"
|
||||||
|
|
||||||
|
Unlock: "Unlock Ticket"
|
||||||
|
Unlock_Emoji: "🔓"
|
||||||
|
Unlock_Style: "2"
|
||||||
|
|
||||||
# Available Button Styles
|
# Available Button Styles
|
||||||
# 1 - Blurple
|
# 1 - Blurple
|
||||||
# 2 - Grey
|
# 2 - Grey
|
||||||
# 3 - Green
|
# 3 - Green
|
||||||
# 4 - Red
|
# 4 - Red
|
||||||
|
|
||||||
|
|
||||||
# -------------------------
|
# -------------------------
|
||||||
# Select Menus
|
# Select Menus
|
||||||
# -------------------------
|
# -------------------------
|
||||||
@@ -198,19 +225,18 @@ Buttons:
|
|||||||
SelectMenus:
|
SelectMenus:
|
||||||
Tickets:
|
Tickets:
|
||||||
PanelEmoji: "⚙️"
|
PanelEmoji: "⚙️"
|
||||||
|
|
||||||
CloseEmoji: "🗑️"
|
CloseEmoji: "🗑️"
|
||||||
ArchiveEmoji: "♻️"
|
ArchiveEmoji: "♻️"
|
||||||
LockTicketEmoji: "🔒"
|
LockEmoji: "🔐"
|
||||||
UnLockTicketEmoji: "🔓"
|
RenameEmoji: "🏷️"
|
||||||
EnableInvitesEmoji: "🔒"
|
|
||||||
DisableInvitesEmoji: "🔓"
|
|
||||||
AddUserEmoji: "➕"
|
|
||||||
RemoveUserEmoji: "➖"
|
|
||||||
|
|
||||||
|
EnableInvitesEmoji: "📤"
|
||||||
|
DisableInvitesEmoji: "📥"
|
||||||
|
|
||||||
# -------------------------
|
# -------------------------
|
||||||
# Misc
|
# Misc
|
||||||
# -------------------------
|
# -------------------------
|
||||||
|
|
||||||
Translate:
|
Translate:
|
||||||
Log: "🚨┃logs"
|
TranslateLog: "TRANSLATE_LOG_ID"
|
||||||
@@ -20,9 +20,6 @@ Panel: true
|
|||||||
# Ticket Panel Message Configuration #2b2d31
|
# Ticket Panel Message Configuration #2b2d31
|
||||||
# ----------------------------------------
|
# ----------------------------------------
|
||||||
|
|
||||||
Channel: "📗┃tickets"
|
|
||||||
# The channel used to create the ticket panel, Use command /ticketpanel to generate it.
|
|
||||||
|
|
||||||
PanelTitle: "SupportBot"
|
PanelTitle: "SupportBot"
|
||||||
PanelColour: "#0cc559"
|
PanelColour: "#0cc559"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -1,3 +1 @@
|
|||||||
{
|
{}
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"tickets": [
|
"tickets": [
|
||||||
{}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"bio": "",
|
||||||
|
"timezone": "",
|
||||||
|
"clockedIn": false
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"id": 0,
|
"id": 0,
|
||||||
"TicketPanelID": "0000000000000000000"
|
"TicketPanelID": "0000000000000000000"
|
||||||
}
|
}
|
||||||
+20
-19
@@ -19,7 +19,8 @@ const msgconfig = yaml.load(
|
|||||||
module.exports = new Event("guildMemberAdd", async (client, member, interaction, guild) => {
|
module.exports = new Event("guildMemberAdd", async (client, member, interaction, guild) => {
|
||||||
|
|
||||||
if (supportbot.Welcome.Enabled) {
|
if (supportbot.Welcome.Enabled) {
|
||||||
const WelcomeChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.Welcome.Channel)
|
const WelcomeChannel = member.guild.channels.cache.get(supportbot.Welcome.Channel) ||
|
||||||
|
member.guild.channels.cache.find(channel => channel.name === supportbot.Welcome.Channel);
|
||||||
|
|
||||||
const WelcomeEmbed = new Discord.EmbedBuilder()
|
const WelcomeEmbed = new Discord.EmbedBuilder()
|
||||||
.setColor(msgconfig.Welcome.Embed.Colour)
|
.setColor(msgconfig.Welcome.Embed.Colour)
|
||||||
@@ -27,29 +28,29 @@ module.exports = new Event("guildMemberAdd", async (client, member, interaction,
|
|||||||
.setDescription(msgconfig.Welcome.Embed.Message.replace(/%joined_user%/g, member.user))
|
.setDescription(msgconfig.Welcome.Embed.Message.replace(/%joined_user%/g, member.user))
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
if (msgconfig.Welcome.Embed.Thumbnail === "BOT") {
|
if (msgconfig.Welcome.Embed.Thumbnail === "BOT") {
|
||||||
WelcomeEmbed.setThumbnail(client.user.displayAvatarURL())
|
WelcomeEmbed.setThumbnail(client.user.displayAvatarURL())
|
||||||
}
|
} else if (msgconfig.Welcome.Embed.Thumbnail === "USER") {
|
||||||
|
WelcomeEmbed.setThumbnail(member.user.displayAvatarURL())
|
||||||
|
}
|
||||||
|
|
||||||
if (msgconfig.Welcome.Embed.Thumbnail === "USER") {
|
if (msgconfig.Welcome.Embed.ImageEnabled) {
|
||||||
WelcomeEmbed.setThumbnail(member.user.displayAvatarURL())
|
WelcomeEmbed.setImage(msgconfig.Welcome.Embed.ImageURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msgconfig.Welcome.Embed.ImageEnabled) {
|
if (WelcomeChannel) {
|
||||||
WelcomeEmbed.setImage(msgconfig.Welcome.Embed.ImageURL)
|
WelcomeChannel.send({ embeds: [WelcomeEmbed] });
|
||||||
}
|
}
|
||||||
|
|
||||||
WelcomeChannel.send({
|
if (supportbot.Roles.AutoRole.Enabled) {
|
||||||
embeds: [WelcomeEmbed]
|
const role = member.guild.roles.cache.get(supportbot.Roles.AutoRole.Role) ||
|
||||||
})
|
member.guild.roles.cache.find(role => role.name === supportbot.Roles.AutoRole.Role);
|
||||||
|
if (role) {
|
||||||
if (supportbot.Roles.AutoRole.Enabled) {
|
|
||||||
var role = member.guild.roles.cache.find(role => role.name === supportbot.Roles.AutoRole.Role);
|
|
||||||
member.roles.add(role);
|
member.roles.add(role);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
console.log(`\u001b[32m`, `[+]`, `\u001b[33m`, `${member.user.username} joined the server!`)
|
|
||||||
|
|
||||||
|
console.log(`\u001b[32m`, `[+]`, `\u001b[33m`, `${member.user.username} joined the server!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
+16
-16
@@ -19,32 +19,32 @@ const msgconfig = yaml.load(
|
|||||||
module.exports = new Event("guildMemberRemove", async (client, member, interaction, guild) => {
|
module.exports = new Event("guildMemberRemove", async (client, member, interaction, guild) => {
|
||||||
|
|
||||||
if (supportbot.Leave.Enabled) {
|
if (supportbot.Leave.Enabled) {
|
||||||
const LeaveChannel = member.guild.channels.cache.find(channel => channel.name === supportbot.Leave.Channel)
|
const LeaveChannel = member.guild.channels.cache.get(supportbot.Leave.Channel) ||
|
||||||
|
member.guild.channels.cache.find(channel => channel.name === supportbot.Leave.Channel);
|
||||||
|
|
||||||
const LeaveEmbed = new Discord.EmbedBuilder()
|
const LeaveEmbed = new Discord.EmbedBuilder()
|
||||||
.setColor(msgconfig.Leave.Embed.Colour)
|
.setColor(msgconfig.Leave.Embed.Colour)
|
||||||
.setTitle(msgconfig.Leave.Embed.Title)
|
.setTitle(msgconfig.Leave.Embed.Title)
|
||||||
.setDescription(msgconfig.Leave.Embed.Message.replace(/%joined_user%/g, member.user))
|
.setDescription(msgconfig.Leave.Embed.Message.replace(/%left_user%/g, member.user))
|
||||||
.setTimestamp();
|
.setTimestamp();
|
||||||
|
|
||||||
if (msgconfig.Leave.Embed.Thumbnail === "BOT") {
|
if (msgconfig.Leave.Embed.Thumbnail === "BOT") {
|
||||||
LeaveEmbed.setThumbnail(client.user.displayAvatarURL())
|
LeaveEmbed.setThumbnail(client.user.displayAvatarURL());
|
||||||
}
|
} else if (msgconfig.Leave.Embed.Thumbnail === "USER") {
|
||||||
|
LeaveEmbed.setThumbnail(member.user.displayAvatarURL());
|
||||||
|
}
|
||||||
|
|
||||||
if (msgconfig.Leave.Embed.Thumbnail === "USER") {
|
if (msgconfig.Leave.Embed.ImageEnabled) {
|
||||||
LeaveEmbed.setThumbnail(member.user.displayAvatarURL())
|
LeaveEmbed.setImage(msgconfig.Leave.Embed.ImageURL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msgconfig.Leave.Embed.ImageEnabled) {
|
|
||||||
LeaveEmbed.setImage(msgconfig.Leave.Embed.ImageURL)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (LeaveChannel) {
|
||||||
LeaveChannel.send({
|
LeaveChannel.send({
|
||||||
embeds: [LeaveEmbed]
|
embeds: [LeaveEmbed]
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
console.log(`\u001b[31m`, `[-]`, `\u001b[33m`, `${member.user.username} left the server!`)
|
console.log(`\u001b[31m`, `[-]`, `\u001b[33m`, `${member.user.username} left the server!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
+480
-67
@@ -16,7 +16,8 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports = new Event("interactionCreate", async (client, interaction) => {
|
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(
|
const command = client.commands.find(
|
||||||
(cmd) => cmd.name.toLowerCase() === interaction.commandName
|
(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;
|
if (interaction.user.bot || !interaction.guild) return;
|
||||||
|
|
||||||
const NotValid = new Discord.EmbedBuilder()
|
const NotValid = new Discord.EmbedBuilder()
|
||||||
.setDescription(`:x: \`Invalid Command\` `)
|
.setDescription(`:x: \`Invalid Command\``)
|
||||||
.setColor(supportbot.Embed.Colours.Error);
|
.setColor(supportbot.Embed.Colours.Error);
|
||||||
|
|
||||||
if (!command)
|
if (!command)
|
||||||
return interaction.reply({
|
return interaction.reply({
|
||||||
embeds: [NotValid],
|
embeds: [NotValid],
|
||||||
|
ephemeral: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const permission = interaction.member.permissions.has(command.permissions);
|
const permission = interaction.member.permissions.has(command.permissions);
|
||||||
@@ -43,40 +45,238 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
if (!permission)
|
if (!permission)
|
||||||
return interaction.reply({
|
return interaction.reply({
|
||||||
embeds: [ValidPerms],
|
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.customId === "renameTicketModal") {
|
||||||
|
const newTicketName = interaction.fields.getTextInputValue("renameTicket");
|
||||||
|
|
||||||
|
// Fixing the ticketChannelId extraction and lookup
|
||||||
|
const ticketChannelId = interaction.channel.id;
|
||||||
|
|
||||||
|
let ticketChannel;
|
||||||
|
if (supportbot.Ticket.TicketType === "threads") {
|
||||||
|
ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
|
||||||
|
} else if (supportbot.Ticket.TicketType === "channels") {
|
||||||
|
ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ticketChannel) {
|
||||||
|
return interaction.reply({
|
||||||
|
content: "Ticket channel not found.",
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await ticketChannel.setName(newTicketName);
|
||||||
|
|
||||||
|
const renamedsuccess = new Discord.EmbedBuilder()
|
||||||
|
.setDescription(msgconfig.Ticket.RenamedSuccess)
|
||||||
|
.setColor(supportbot.Embed.Colours.Success);
|
||||||
|
|
||||||
|
return interaction.reply({
|
||||||
|
embeds: [renamedsuccess],
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error renaming the ticket:", error);
|
||||||
|
return interaction.reply({
|
||||||
|
content: "There was an error renaming the ticket.",
|
||||||
|
ephemeral: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (interaction.isStringSelectMenu()) {
|
if (interaction.isStringSelectMenu()) {
|
||||||
if (interaction.customId === "ticketcontrolpanel") {
|
if (interaction.customId === "ticketcontrolpanel") {
|
||||||
const selectedOption = interaction.values[0];
|
const selectedOption = interaction.values[0];
|
||||||
const { getRole, getChannel } = interaction.client;
|
const { getRole, getChannel } = interaction.client;
|
||||||
switch (selectedOption) {
|
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":
|
case "ticketclose":
|
||||||
const closeCommand = client.commands.get(cmdconfig.CloseTicket.Command);
|
const closeCommand = client.commands.get(cmdconfig.CloseTicket.Command);
|
||||||
if (closeCommand) {
|
if (closeCommand) {
|
||||||
closeCommand.run(interaction);
|
await closeCommand.run(interaction);
|
||||||
} else {
|
} else {
|
||||||
console.error("[X] Close Command Not Found");
|
console.error("[X] Close Command Not Found");
|
||||||
}
|
}
|
||||||
break;
|
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],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (supportbot.Ticket.TicketType === "threads") {
|
||||||
|
await interaction.channel.setArchived(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportbot.Ticket.TicketType === "channels") {
|
||||||
|
const { getRole, getChannel } = interaction.client;
|
||||||
|
await interaction.channel.setParent(supportbot.Ticket.TicketArchiveCategory);
|
||||||
|
|
||||||
|
const ticketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
|
const ticketInfo = ticketData.tickets.find(t => t.id === interaction.channel.id);
|
||||||
|
|
||||||
|
if (ticketInfo) {
|
||||||
|
const user = interaction.guild.members.cache.get(ticketInfo.user) || ticketInfo.user;
|
||||||
|
const claimedBy = interaction.guild.members.cache.get(ticketInfo.claimedBy) || ticketInfo.claimedBy;
|
||||||
|
const Admin = await interaction.guild.roles.fetch(supportbot.Roles.StaffMember.Admin);
|
||||||
|
const Staff = await interaction.guild.roles.fetch(supportbot.Roles.StaffMember.Staff);
|
||||||
|
|
||||||
|
if (user && user.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(user.id, {
|
||||||
|
ViewChannel: false,
|
||||||
|
SendMessages: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportbot.ClaimTickets === true) {
|
||||||
|
if (claimedBy && claimedBy.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(claimedBy.id, {
|
||||||
|
ViewChannel: true,
|
||||||
|
SendMessages: true,
|
||||||
|
ReadMessageHistory: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportbot.ClaimTickets === false) {
|
||||||
|
if (Staff && Staff.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(claimedBy.id, {
|
||||||
|
ViewChannel: true,
|
||||||
|
SendMessages: true,
|
||||||
|
ReadMessageHistory: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Admin && Admin.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(Admin.id, {
|
||||||
|
ViewChannel: true,
|
||||||
|
SendMessages: true,
|
||||||
|
ReadMessageHistory: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.channel.permissionOverwrites.edit(interaction.guild.roles.everyone.id, {
|
||||||
|
ViewChannel: false,
|
||||||
|
SendMessages: false,
|
||||||
|
ReadMessageHistory: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "lockticket":
|
||||||
|
const lockembed = new Discord.EmbedBuilder()
|
||||||
|
.setDescription(msgconfig.Ticket.TicketLocked)
|
||||||
|
.setColor(supportbot.Embed.Colours.Success);
|
||||||
|
|
||||||
|
const unlockButton = new Discord.ButtonBuilder()
|
||||||
|
.setCustomId("unlockTicket")
|
||||||
|
.setLabel(supportbot.Buttons.Tickets.Unlock)
|
||||||
|
.setEmoji(supportbot.Buttons.Tickets.Unlock_Emoji)
|
||||||
|
.setStyle(supportbot.Buttons.Tickets.Unlock_Style);
|
||||||
|
|
||||||
|
const LockedOptions = new Discord.ActionRowBuilder()
|
||||||
|
.addComponents(unlockButton);
|
||||||
|
|
||||||
|
await interaction.channel.send({
|
||||||
|
embeds: [lockembed],
|
||||||
|
components: [LockedOptions],
|
||||||
|
ephemeral: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (supportbot.Ticket.TicketType === "threads") {
|
||||||
|
await interaction.channel.setLocked(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "unlockTicket":
|
||||||
|
const unlockEmbed = new Discord.EmbedBuilder()
|
||||||
|
.setDescription(msgconfig.Ticket.TicketUnlocked)
|
||||||
|
.setColor(supportbot.Embed.Colours.Success);
|
||||||
|
|
||||||
|
await interaction.channel.send({
|
||||||
|
embeds: [unlockEmbed],
|
||||||
|
ephemeral: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (supportbot.Ticket.TicketType === "threads") {
|
||||||
|
await interaction.channel.setLocked(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case "enableinvites":
|
case "enableinvites":
|
||||||
await handleInvites(interaction, true);
|
await handleInvites(interaction, true);
|
||||||
break;
|
break;
|
||||||
@@ -84,37 +284,163 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
case "disableinvites":
|
case "disableinvites":
|
||||||
await handleInvites(interaction, false);
|
await handleInvites(interaction, false);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case "renameticket":
|
||||||
|
const modal = new Discord.ModalBuilder()
|
||||||
|
.setCustomId("renameTicketModal")
|
||||||
|
.setTitle("Rename Channel")
|
||||||
|
.addComponents(
|
||||||
|
new Discord.ActionRowBuilder()
|
||||||
|
.addComponents(
|
||||||
|
new Discord.TextInputBuilder()
|
||||||
|
.setCustomId("renameTicket")
|
||||||
|
.setLabel("New Channel Name")
|
||||||
|
.setStyle(Discord.TextInputStyle.Short)
|
||||||
|
.setRequired(true)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await interaction.showModal(modal);
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (interaction.isButton()) {
|
if (interaction.isButton()) {
|
||||||
if (interaction.customId === 'createticket') {
|
if (interaction.customId === "unarchiveTicket") {
|
||||||
try {
|
|
||||||
const cmd = client.commands.get(cmdconfig.OpenTicket.Command);
|
if (supportbot.Ticket.TicketType === "threads") {
|
||||||
if (!cmd) return;
|
await interaction.channel.setArchived(false);
|
||||||
cmd.run(interaction);
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error("Error executing the ticket command:", error);
|
if (supportbot.Ticket.TicketType === "channels") {
|
||||||
await interaction.reply({
|
const { getRole, getChannel } = interaction.client;
|
||||||
content: "An error occurred while creating the ticket.",
|
await interaction.channel.setParent(supportbot.Ticket.TicketChannelsCategory);
|
||||||
ephemeral: true,
|
|
||||||
});
|
const ticketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
|
const ticketInfo = ticketData.tickets.find(t => t.id === interaction.channel.id);
|
||||||
|
|
||||||
|
if (ticketInfo) {
|
||||||
|
const user = interaction.guild.members.cache.get(ticketInfo.user) || ticketInfo.user;
|
||||||
|
const claimedBy = interaction.guild.members.cache.get(ticketInfo.claimedBy) || ticketInfo.claimedBy;
|
||||||
|
const Admin = await interaction.guild.roles.fetch(supportbot.Roles.StaffMember.Admin);
|
||||||
|
const Staff = await interaction.guild.roles.fetch(supportbot.Roles.StaffMember.Staff);
|
||||||
|
|
||||||
|
if (user && user.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(user.id, {
|
||||||
|
ViewChannel: true,
|
||||||
|
SendMessages: true,
|
||||||
|
ReadMessageHistory: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportbot.ClaimTickets === true) {
|
||||||
|
if (claimedBy && claimedBy.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(claimedBy.id, {
|
||||||
|
ViewChannel: true,
|
||||||
|
SendMessages: true,
|
||||||
|
ReadMessageHistory: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportbot.ClaimTickets === false) {
|
||||||
|
if (Staff && Staff.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(claimedBy.id, {
|
||||||
|
ViewChannel: true,
|
||||||
|
SendMessages: true,
|
||||||
|
ReadMessageHistory: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Admin && Admin.id) {
|
||||||
|
await interaction.channel.permissionOverwrites.edit(Admin.id, {
|
||||||
|
ViewChannel: true,
|
||||||
|
SendMessages: true,
|
||||||
|
ReadMessageHistory: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.channel.permissionOverwrites.edit(interaction.guild.roles.everyone.id, {
|
||||||
|
ViewChannel: false,
|
||||||
|
SendMessages: false,
|
||||||
|
ReadMessageHistory: 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") {
|
if (interaction.customId === "openticket") {
|
||||||
try {
|
if (supportbot.Ticket.TicketReason) {
|
||||||
const cmd = client.commands.get(cmdconfig.OpenTicket);
|
const modal = new Discord.ModalBuilder()
|
||||||
if (!cmd) return;
|
.setCustomId("ticketReasonModal")
|
||||||
cmd.run(interaction);
|
.setTitle("Ticket Reason")
|
||||||
} catch (error) {
|
.addComponents(
|
||||||
console.error(error);
|
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-')) {
|
if (interaction.customId.startsWith("claimticket-")) {
|
||||||
const ticketChannelId = interaction.customId.split('-')[1];
|
const ticketChannelId = interaction.customId.split("-")[1];
|
||||||
const ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
|
const ticketChannel = interaction.guild.channels.cache.get(ticketChannelId);
|
||||||
if (!ticketChannel) {
|
if (!ticketChannel) {
|
||||||
return interaction.reply({
|
return interaction.reply({
|
||||||
@@ -144,7 +470,7 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
const NoPermsClaim = new Discord.EmbedBuilder()
|
const NoPermsClaim = new Discord.EmbedBuilder()
|
||||||
.setTitle(msgconfig.Ticket.ClaimTickets.NoPermsToClaimTitle)
|
.setTitle(msgconfig.Ticket.ClaimTickets.NoPermsToClaimTitle)
|
||||||
.setDescription(
|
.setDescription(
|
||||||
msgconfig.Ticket.ClaimTickets.NoPermsToClaim.replace('%channel%', ticketChannel.name)
|
msgconfig.Ticket.ClaimTickets.NoPermsToClaim.replace("%channel%", ticketChannel.name)
|
||||||
)
|
)
|
||||||
.setColor(supportbot.Embed.Colours.Error);
|
.setColor(supportbot.Embed.Colours.Error);
|
||||||
|
|
||||||
@@ -155,12 +481,32 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const pingclaimedstaff = await ticketChannel.send(`<@${interaction.user.id}>`);
|
const pingclaimedstaff = await ticketChannel.send(`<@${interaction.user.id}>`);
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
pingclaimedstaff.delete();
|
pingclaimedstaff.delete();
|
||||||
}, 2000)
|
}, 2000);
|
||||||
|
|
||||||
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
const TicketData = JSON.parse(fs.readFileSync("./Data/TicketData.json", "utf8"));
|
||||||
const ticketIndex = TicketData.tickets.findIndex((t) => t.id === ticketChannelId);
|
const ticketIndex = TicketData.tickets.findIndex((t) => t.id === ticketChannelId);
|
||||||
@@ -174,13 +520,13 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
const claimedEmbed = new Discord.EmbedBuilder(claimMessage.embeds[0].data)
|
const claimedEmbed = new Discord.EmbedBuilder(claimMessage.embeds[0].data)
|
||||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
|
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
|
||||||
.setDescription(
|
.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);
|
.setColor(supportbot.Embed.Colours.Success);
|
||||||
|
|
||||||
const successfullyClaimed = new Discord.EmbedBuilder()
|
const successfullyClaimed = new Discord.EmbedBuilder()
|
||||||
.setTitle(msgconfig.Ticket.ClaimTickets.ClaimedTitle)
|
.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);
|
.setColor(supportbot.Embed.Colours.Success);
|
||||||
|
|
||||||
await claimMessage.edit({ embeds: [claimedEmbed], components: [] });
|
await claimMessage.edit({ embeds: [claimedEmbed], components: [] });
|
||||||
@@ -191,36 +537,41 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SUGGESTION INTERACTIONS [START]
|
// 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];
|
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 userId = interaction.user.id;
|
||||||
const hasUpvoted = suggestion.upvotes.includes(userId);
|
const hasUpvoted = suggestion.upvotes.includes(userId);
|
||||||
const hasDownvoted = suggestion.downvotes.includes(userId);
|
const hasDownvoted = suggestion.downvotes.includes(userId);
|
||||||
|
|
||||||
if (interaction.customId === 'upvote') {
|
if (interaction.customId === "upvote") {
|
||||||
if (hasUpvoted) {
|
if (hasUpvoted) {
|
||||||
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
|
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
|
||||||
} else {
|
} else {
|
||||||
suggestion.upvotes.push(userId);
|
suggestion.upvotes.push(userId);
|
||||||
if (hasDownvoted) {
|
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) {
|
if (hasDownvoted) {
|
||||||
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
|
suggestion.downvotes = suggestion.downvotes.filter((id) => id !== userId);
|
||||||
} else {
|
} else {
|
||||||
suggestion.downvotes.push(userId);
|
suggestion.downvotes.push(userId);
|
||||||
if (hasUpvoted) {
|
if (hasUpvoted) {
|
||||||
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
|
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (interaction.customId === 'removevote') {
|
} else if (interaction.customId === "removevote") {
|
||||||
suggestion.upvotes = suggestion.upvotes.filter(id => id !== userId);
|
suggestion.upvotes = suggestion.upvotes.filter((id) => id !== userId);
|
||||||
suggestion.downvotes = suggestion.downvotes.filter(id => id !== userId);
|
suggestion.downvotes = suggestion.downvotes.filter((id) => id !== userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeFileSync("./Data/SuggestionData.json", JSON.stringify(suggestions, null, 2));
|
fs.writeFileSync("./Data/SuggestionData.json", JSON.stringify(suggestions, null, 2));
|
||||||
@@ -228,25 +579,36 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
const upvoteCount = suggestion.upvotes.length;
|
const upvoteCount = suggestion.upvotes.length;
|
||||||
const downvoteCount = suggestion.downvotes.length;
|
const downvoteCount = suggestion.downvotes.length;
|
||||||
|
|
||||||
const updatedEmbed = new Discord.EmbedBuilder(interaction.message.embeds[0].data)
|
const updatedEmbed = new Discord.EmbedBuilder(interaction.message.embeds[0].data).setFields([
|
||||||
.setFields([
|
{ name: "Suggestion", value: suggestion.suggestion, inline: true },
|
||||||
{ name: 'Suggestion', value: suggestion.suggestion, inline: true },
|
{ name: "From", value: `<@${suggestion.author}>` },
|
||||||
{ name: 'From', value: `<@${suggestion.author}>` },
|
{
|
||||||
{ name: `${supportbot.Suggestions.UpvoteEmoji} ${supportbot.Suggestions.UpvoteTitle}`, value: `${upvoteCount}`, inline: true },
|
name: `${supportbot.Suggestions.UpvoteEmoji} ${supportbot.Suggestions.UpvoteTitle}`,
|
||||||
{ name: `${supportbot.Suggestions.DownvoteEmoji} ${supportbot.Suggestions.DownvoteTitle}`, value: `${downvoteCount}`, inline: true }
|
value: `${upvoteCount}`,
|
||||||
]);
|
inline: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: `${supportbot.Suggestions.DownvoteEmoji} ${supportbot.Suggestions.DownvoteTitle}`,
|
||||||
|
value: `${downvoteCount}`,
|
||||||
|
inline: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
await interaction.update({ embeds: [updatedEmbed] });
|
await interaction.update({ embeds: [updatedEmbed] });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleInvites(interaction, enable) {
|
async function handleInvites(interaction, enable) {
|
||||||
if (supportbot.Ticket.Invites.StaffOnly) {
|
if (supportbot.Ticket.Invites.StaffOnly) {
|
||||||
|
const { getRole, getChannel } = interaction.client;
|
||||||
const SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
|
const SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
|
||||||
const Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
|
const 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.");
|
return interaction.reply(
|
||||||
|
"Some roles seem to be missing!\nPlease check for errors when starting the bot."
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const NoPerms = new Discord.EmbedBuilder()
|
const NoPerms = new Discord.EmbedBuilder()
|
||||||
@@ -256,7 +618,10 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
)
|
)
|
||||||
.setColor(supportbot.Embed.Colours.Warn);
|
.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] });
|
return interaction.reply({ embeds: [NoPerms] });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -264,9 +629,7 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
await interaction.channel.setInvitable(enable);
|
await interaction.channel.setInvitable(enable);
|
||||||
|
|
||||||
const message = enable ? msgconfig.Ticket.EnableInvites : msgconfig.Ticket.DisableInvites;
|
const message = enable ? msgconfig.Ticket.EnableInvites : msgconfig.Ticket.DisableInvites;
|
||||||
const embed = new Discord.EmbedBuilder()
|
const embed = new Discord.EmbedBuilder().setDescription(message).setColor(supportbot.Embed.Colours.General);
|
||||||
.setDescription(message)
|
|
||||||
.setColor(supportbot.Embed.Colours.General);
|
|
||||||
|
|
||||||
await interaction.reply({
|
await interaction.reply({
|
||||||
embeds: [embed],
|
embeds: [embed],
|
||||||
@@ -274,5 +637,55 @@ module.exports = new Event("interactionCreate", async (client, interaction) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Modal submission handler for editing profile
|
||||||
|
if (interaction.type === Discord.InteractionType.ModalSubmit && interaction.customId === "editProfileModal") {
|
||||||
|
const userId = interaction.user.id;
|
||||||
|
const profilePath = `./Data/Profiles/${userId}.json`;
|
||||||
|
|
||||||
|
let profileData;
|
||||||
|
if (fs.existsSync(profilePath)) {
|
||||||
|
profileData = JSON.parse(fs.readFileSync(profilePath, "utf8"));
|
||||||
|
} else {
|
||||||
|
profileData = {
|
||||||
|
bio: "",
|
||||||
|
timezone: "",
|
||||||
|
clockedIn: false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const newBio = interaction.fields.getTextInputValue("bio");
|
||||||
|
const newTimezone = interaction.fields.getTextInputValue("timezone");
|
||||||
|
|
||||||
|
profileData.bio = newBio;
|
||||||
|
profileData.timezone = newTimezone;
|
||||||
|
|
||||||
|
fs.writeFileSync(profilePath, JSON.stringify(profileData, null, 2));
|
||||||
|
|
||||||
|
const updatedProfileEmbed = new Discord.EmbedBuilder()
|
||||||
|
.setTitle(`${interaction.user.username}'s Profile`)
|
||||||
|
.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 }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (profileData.clockedIn !== undefined) {
|
||||||
|
updatedProfileEmbed.addFields({
|
||||||
|
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,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
+27
-84
@@ -26,7 +26,7 @@ const msgconfig = yaml.load(
|
|||||||
|
|
||||||
const Event = require("../Structures/Event.js");
|
const Event = require("../Structures/Event.js");
|
||||||
|
|
||||||
let chan1 = client.channels.cache.get(panelconfig.Channel);
|
let chan1 = client.channels.cache.get(supportbot.Ticket.TicketHome);
|
||||||
|
|
||||||
module.exports = new Event("ready", async (client, interaction) => {
|
module.exports = new Event("ready", async (client, interaction) => {
|
||||||
const { getRole, getChannel, getCategory } = client;
|
const { getRole, getChannel, getCategory } = client;
|
||||||
@@ -59,7 +59,7 @@ module.exports = new Event("ready", async (client, interaction) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`\u001b[32m`, `――――――――――――――――――――――――――――――――――――――――――――`);
|
console.log(`\u001b[33m`, `――――――――――――――――――――――――――――――――――――――――――――`);
|
||||||
console.log(` `);
|
console.log(` `);
|
||||||
console.log(`\u001b[31m`, `┏━━━┓╋╋╋╋╋╋╋╋╋╋╋╋╋┏┓┏━━┓╋╋╋┏┓`);
|
console.log(`\u001b[31m`, `┏━━━┓╋╋╋╋╋╋╋╋╋╋╋╋╋┏┓┏━━┓╋╋╋┏┓`);
|
||||||
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(`\u001b[31m`, `╋╋╋╋╋╋╋┗┛╋┗┛`);
|
console.log(`\u001b[31m`, `╋╋╋╋╋╋╋┗┛╋┗┛`);
|
||||||
console.log(` `);
|
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(` `);
|
||||||
console.log(
|
console.log(`\u001b[33m`, `――――――――――――――――― [Links] ――――――――――――――――――`);
|
||||||
`\u001b[31m`,
|
console.log("\u001b[32m", "Discord: https://dsc.gg/emerald-dev");
|
||||||
`${supportbot.General.Name} | [${supportbot.SupportBot_Version}]`,
|
console.log("\u001b[32m", "Website: https://emeraldsrv.com");
|
||||||
`\u001b[32m`,
|
console.log("\u001b[32m", "Community: https://community.emeraldsrv.com");
|
||||||
`Connected to Discord`,
|
console.log("\u001b[32m", "Documentation: https://docs.emeraldsrv.com");
|
||||||
);
|
|
||||||
|
|
||||||
console.log(`\u001b[31m`, `SupportBot proudly created by Emerald Development`);
|
|
||||||
|
|
||||||
console.log(` `);
|
console.log(` `);
|
||||||
|
console.log(`\u001b[33m`, `――――――――――――――――― [Invite] ――――――――――――――――――`);
|
||||||
console.log(
|
console.log("\u001b[32m", `Invite URL: https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=8&scope=bot%20applications.commands`);
|
||||||
`\u001b[31m`,
|
|
||||||
`Discord`,
|
|
||||||
`\u001b[32m`,
|
|
||||||
`https://dsc.gg/emerald-dev`,
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`\u001b[31m`,
|
|
||||||
`Website`,
|
|
||||||
`\u001b[32m`,
|
|
||||||
`https://emeraldsrv.com`,
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`\u001b[31m`,
|
|
||||||
`Marketplace`,
|
|
||||||
`\u001b[32m`,
|
|
||||||
`https://market.emeraldsrv.com`,
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(
|
|
||||||
`\u001b[31m`,
|
|
||||||
`Documentation`,
|
|
||||||
`\u001b[32m`,
|
|
||||||
`https://emeraldsrv.com/third-party`,
|
|
||||||
);
|
|
||||||
|
|
||||||
console.log(` `);
|
console.log(` `);
|
||||||
|
console.log(`\u001b[33m`, `――――――――――――――――― [Config Check] ――――――――――――――――――`);
|
||||||
console.log(
|
console.log("\u001b[32m", "Config initialization...");
|
||||||
`\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`, `――――――――――――――――――――――――――――――――――――――――――――`);
|
|
||||||
|
|
||||||
const roles = [
|
const roles = [
|
||||||
supportbot.Roles.StaffMember.Admin,
|
supportbot.Roles.StaffMember.Admin,
|
||||||
@@ -132,15 +94,13 @@ module.exports = new Event("ready", async (client, interaction) => {
|
|||||||
supportbot.Roles.ModRoles.Muted
|
supportbot.Roles.ModRoles.Muted
|
||||||
];
|
];
|
||||||
|
|
||||||
supportbot.Departments.forEach((department) => roles.push(department.role));
|
|
||||||
|
|
||||||
if (supportbot.Roles.AutoRole.Role) roles.push(supportbot.Roles.AutoRole.Role);
|
if (supportbot.Roles.AutoRole.Role) roles.push(supportbot.Roles.AutoRole.Role);
|
||||||
|
|
||||||
const channels = [
|
const channels = [
|
||||||
supportbot.Suggestions.Channel,
|
supportbot.Suggestions.Channel,
|
||||||
supportbot.Ticket.Log.TicketLog,
|
supportbot.Ticket.Log.TicketLog,
|
||||||
supportbot.Ticket.Log.TranscriptLog,
|
supportbot.Ticket.Log.TranscriptLog,
|
||||||
panelconfig.Channel,
|
supportbot.Ticket.TicketHome,
|
||||||
supportbot.Welcome.Channel,
|
supportbot.Welcome.Channel,
|
||||||
supportbot.Leave.Channel,
|
supportbot.Leave.Channel,
|
||||||
supportbot.Translate.Log
|
supportbot.Translate.Log
|
||||||
@@ -168,35 +128,18 @@ module.exports = new Event("ready", async (client, interaction) => {
|
|||||||
// if (!find) missingCat.push(cat);
|
// if (!find) missingCat.push(cat);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (missingR.length > 0) {
|
const missingRoles = await Promise.all(roles.map(role => getRole(role, client.guilds.cache.first())));
|
||||||
console.log(
|
const missingChannels = await Promise.all(channels.map(channel => getChannel(channel, client.guilds.cache.first())));
|
||||||
"\u001b[31m",
|
|
||||||
`[MISSING CONFIGURATION]`,
|
if (missingRoles.some(role => !role)) {
|
||||||
"\u001b[33m",
|
console.log("\u001b[31m", `Missing roles in your server configuration: ${missingRoles.filter(role => !role).join(', ')}`);
|
||||||
`The following Roles could not be found in your server.\n`, `\u001b[31m`, `[${missingR.join(
|
|
||||||
", "
|
|
||||||
)}]`, `\n `,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (missingC.length > 0) {
|
if (missingChannels.some(channel => !channel)) {
|
||||||
console.log(
|
console.log("\u001b[31m", `Missing channels in your server configuration: ${missingChannels.filter(channel => !channel).join(', ')}`);
|
||||||
"\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 `,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("\u001b[32m", "Configs initialized, No problems were detected.");
|
||||||
|
console.log(` `);
|
||||||
|
|
||||||
});
|
});
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2022 Emerald Services
|
Copyright (c) 2024 Emerald Services
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -13,11 +13,11 @@
|
|||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://github.com/discordjs">
|
<a href="https://github.com/discordjs">
|
||||||
<img src="https://img.shields.io/badge/discord.js-v13.6.x-blue.svg?style=for-the-badge&logo=javascript.svg" alt="shield.png">
|
<img src="https://img.shields.io/badge/DISCORD.JS%20-%20v14-blue?style=for-the-badge" alt="shield.png">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://github.com/nodejs/node">
|
<a href="https://github.com/nodejs/node">
|
||||||
<img src="https://img.shields.io/badge/node.js-v16.14.x-green.svg?style=for-the-badge&logo=node" alt="shield.png">
|
<img src="https://img.shields.io/badge/NODE.JS%20-%20v20.x-green?style=for-the-badge" alt="shield.png">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="https://github.com/Emerald-Services/SupportBot/releases">
|
<a href="https://github.com/Emerald-Services/SupportBot/releases">
|
||||||
@@ -84,5 +84,13 @@ Released under the [MIT](https://opensource.org/licenses/MIT) license.
|
|||||||
<img src="https://contrib.rocks/image?repo=Emerald-Services/SupportBot">
|
<img src="https://contrib.rocks/image?repo=Emerald-Services/SupportBot">
|
||||||
</a>
|
</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:
|
||||||
|
|
||||||
|
[]([https://repl.it/github/ItsNyoty/iki](https://repl.it/github/Emerald-Services/SupportBot
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+7
-1
@@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
// SupportBot | Emerald Services
|
// SupportBot | Emerald Services
|
||||||
// Addon Structure
|
// Addon Structure
|
||||||
|
|
||||||
class Command {
|
class Command {
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
this.name = options.name;
|
this.name = options.name;
|
||||||
@@ -10,7 +10,13 @@ class Command {
|
|||||||
this.run = options.run;
|
this.run = options.run;
|
||||||
this.defaultPermission = true;
|
this.defaultPermission = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Method to dynamically update options
|
||||||
|
setOptions(options) {
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Event {
|
class Event {
|
||||||
constructor(event, run) {
|
constructor(event, run) {
|
||||||
this.event = event;
|
this.event = event;
|
||||||
|
|||||||
+40
-25
@@ -1,12 +1,8 @@
|
|||||||
// C:\Users\ollie\Documents\GitHub\SupportBot\Structures\Client.js
|
|
||||||
|
|
||||||
// SupportBot | Emerald Services
|
|
||||||
// Client Structure
|
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
const Discord = require("discord.js");
|
const Discord = require("discord.js");
|
||||||
const { GatewayIntentBits, Partials } = require('discord.js');
|
const { GatewayIntentBits, Partials } = require('discord.js');
|
||||||
const yaml = require("js-yaml");
|
const yaml = require("js-yaml");
|
||||||
|
const { Command, Event } = require('./Addon.js'); // Adjust the path as needed
|
||||||
|
|
||||||
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
||||||
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
||||||
@@ -89,39 +85,52 @@ class Client extends Discord.Client {
|
|||||||
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmdconfig.Ping.Enabled === false) {
|
if (cmdconfig.AddUser.Enabled === false) {
|
||||||
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "addUser.js");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (supportbot.Ticket.ClaimTickets.Enabled === false) {
|
if (cmdconfig.RemoveUser.Enabled === false) {
|
||||||
tempCommandFiles = tempCommandFiles.filter(item => item !== "ticketstats.js");
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.Settings.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "settings.js");
|
||||||
|
}
|
||||||
|
|
||||||
const commandFiles = tempCommandFiles;
|
const commandFiles = tempCommandFiles;
|
||||||
const commands = commandFiles.map((file) => require(`../Commands/${file}`));
|
const commands = commandFiles.map((file) => require(`../Commands/${file}`));
|
||||||
|
|
||||||
// Commands
|
// Load main commands
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
|
console.log(`\u001b[33m`, "――――――――――――――――――――――――――――――――――――――――――――");
|
||||||
|
|
||||||
commands.forEach((cmd) => {
|
commands.forEach((cmd) => {
|
||||||
console.log(`\u001b[32m`, `[CMD]`, `\u001b[37;1m`, `${cmd.name}`, `\u001b[32;1m`, "Loaded");
|
console.log(`\u001b[32m`, `[CMD]`, `\u001b[37;1m`, `${cmd.name}`, `\u001b[32;1m`, "Loaded");
|
||||||
this.commands.set(cmd.name, cmd);
|
this.commands.set(cmd.name, cmd);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
|
// Load addon commands and events
|
||||||
|
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
|
||||||
|
|
||||||
if (supportbot.General.Addons.Enabled) {
|
if (supportbot.General.Addons.Enabled) {
|
||||||
const addonFiles = fs.readdirSync("./Addons").filter((file) => file.endsWith(".js"));
|
const addonFiles = fs.readdirSync("./Addons").filter((file) => file.endsWith(".js"));
|
||||||
|
|
||||||
const addons = addonFiles.map((file) => {
|
const addons = addonFiles.map((file) => {
|
||||||
let addon = require(`../Addons/${file}`);
|
const addon = require(`../Addons/${file}`);
|
||||||
addon.name = file.split(".")[0];
|
addon.name = file.split(".")[0];
|
||||||
return addon;
|
return addon;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Addons
|
// Addons
|
||||||
console.log(" ");
|
console.log(" ");
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
||||||
|
|
||||||
addons.forEach((addon) => {
|
addons.forEach((addon) => {
|
||||||
console.log(
|
console.log(
|
||||||
@@ -132,18 +141,24 @@ class Client extends Discord.Client {
|
|||||||
`\u001b[32;1m`,
|
`\u001b[32;1m`,
|
||||||
"Loaded"
|
"Loaded"
|
||||||
);
|
);
|
||||||
addon.commands?.forEach((command) => {
|
|
||||||
this.commands.set(command.name, command);
|
if (addon instanceof Command) {
|
||||||
});
|
this.commands.set(addon.name, addon);
|
||||||
addon.events?.forEach((event) => {
|
}
|
||||||
this.on(event.event, (...args) => event.run(this, ...args));
|
|
||||||
});
|
if (addon.events && Array.isArray(addon.events)) {
|
||||||
|
addon.events.forEach((event) => {
|
||||||
|
if (event instanceof Event) {
|
||||||
|
this.on(event.event, (...args) => event.run(this, ...args));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slash Commands
|
// Register Slash Commands
|
||||||
|
|
||||||
this.once("ready", async () => {
|
this.once("ready", async () => {
|
||||||
await this.guilds.cache.first()?.commands.set(this.commands);
|
await this.guilds.cache.first()?.commands.set(this.commands);
|
||||||
@@ -156,7 +171,7 @@ class Client extends Discord.Client {
|
|||||||
});
|
});
|
||||||
|
|
||||||
console.log(" ");
|
console.log(" ");
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
|
console.log(`\u001b[33m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
|
||||||
|
|
||||||
fs.readdirSync("./Events").filter((file) => file.endsWith(".js")).forEach((file) => {
|
fs.readdirSync("./Events").filter((file) => file.endsWith(".js")).forEach((file) => {
|
||||||
const event = require(`../Events/${file}`);
|
const event = require(`../Events/${file}`);
|
||||||
@@ -164,7 +179,7 @@ class Client extends Discord.Client {
|
|||||||
this.on(event.event, (...args) => event.run(this, ...args));
|
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") {
|
if (process.argv[2] !== "test") {
|
||||||
await this.login(token);
|
await this.login(token);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Generated
+1671
File diff suppressed because it is too large.
Load diff
+4
-1
@@ -18,12 +18,15 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/Emerald-Services/SupportBot#readme",
|
"homepage": "https://github.com/Emerald-Services/SupportBot#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@paypal/checkout-server-sdk": "^1.0.3",
|
||||||
"@vitalets/google-translate-api": "^8.0.0",
|
"@vitalets/google-translate-api": "^8.0.0",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"chatgpt": "^5.2.5",
|
"chatgpt": "^5.2.5",
|
||||||
"discord.js": "^14.13.0",
|
"discord.js": "^14.13.0",
|
||||||
|
"js": "^0.1.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"moment": "^2.29.3",
|
"moment": "^2.29.3",
|
||||||
"openai": "^4.50.0"
|
"ms": "^2.1.3",
|
||||||
|
"openai": "^4.50.0",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user