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

|
<h1 align="center">
|
||||||
|
<br>
|
||||||
|
<a href="https://github.com/Emerald-Services/SupportBot"><img src="https://i.imgur.com/cuadAYv.png"></a>
|
||||||
|
<br>
|
||||||
|
SupportBot
|
||||||
|
<br>
|
||||||
|
</h1>
|
||||||
|
|
||||||
## What is SupportBot?
|
<div align="center">
|
||||||
|
|
||||||
|
<a href="https://opensource.org/licenses/MIT">
|
||||||
|
<img src="https://img.shields.io/badge/license-MIT-green?style=for-the-badge" alt="shield.png">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<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">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<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">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a href="https://github.com/Emerald-Services/SupportBot/releases">
|
||||||
|
<img src="https://img.shields.io/github/downloads/Emerald-Services/SupportBot/total?style=for-the-badge" alt="shield.png">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
| SupportBot | Node.JS | Discord.JS | Supported |
|
||||||
|
|------------|---------|------------|------------|
|
||||||
|
| 8.x | 20.x | 14.x. | ✅ Yes
|
||||||
|
| 7.7.3 | 16.x | 13.x. | ✅ Yes
|
||||||
|
| 7.x | 16.x | 13.x. | ❌ No
|
||||||
|
| 6.x | 14.x | 13.x. | ❌ No
|
||||||
|
| 5.x | 12.x | 13.x. | ❌ No
|
||||||
|
| 4.x | 11.x | 13.x. | ❌ No
|
||||||
|
| Older | 10.x | 13.x. | ❌ No
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://emeraldsrv.com/">Website</a>
|
||||||
|
•
|
||||||
|
<a href="https://github.com/Emerald-Services/SupportBot/wiki">Wiki</a>
|
||||||
|
<br>
|
||||||
|
<a href="#about">About</a>
|
||||||
|
•
|
||||||
|
<a href="#support">Support</a>
|
||||||
|
•
|
||||||
|
<a href="#license">License</a>
|
||||||
|
•
|
||||||
|
<a href="https://github.com/Emerald-Services/SupportBot/wiki/Third-Party-Developer">Third-Party</a>
|
||||||
|
•
|
||||||
|
<a href="#contributors">Contributors</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
SupportBot is an Open-Source discord bot built with [discord.js](https://github.com/discordjs/discord.js). It's primarily focused to help servers organise and manage their support system in a unique way with full customisation to match your brand.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
<a href="https://emeraldsrv.com/discord">
|
||||||
|
<img alt="Discord" src="https://img.shields.io/discord/597779408295821323?logo=discord&logoColor=white&style=for-the-badge">
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Released under the [MIT](https://opensource.org/licenses/MIT) license.
|
||||||
|
|
||||||
|
|
||||||
|
## Third-Party
|
||||||
|
|
||||||
|
- [Official addons repository](https://github.com/Emerald-Services/Addons/)
|
||||||
|
- [Syphers Addons](https://github.com/SypherRed/SB_Addons_Unofficial)
|
||||||
|
- [BuiltByBit](https://builtbybit.com/supportbot)
|
||||||
|
- [Polymart](https://polymart.org/resource/supportbot-1-discord-ticket-bot.518)
|
||||||
|
|
||||||
|
|
||||||
|
## Contributors
|
||||||
|
|
||||||
|
<a href="https://github.com/Emerald-Services/SupportBot/graphs/contributors">
|
||||||
|
<img src="https://contrib.rocks/image?repo=Emerald-Services/SupportBot">
|
||||||
|
</a>
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## Quick Links
|
|
||||||
|
|
||||||
**|** [Discord](https://emeraldsrv.dev/discord) **|**
|
|
||||||
[Hosting](https://emeraldsrv.dev/hosting) **|**
|
|
||||||
[Documentation](https://emeraldsrv.dev/wiki/supportbot) **|**
|
|
||||||
[Download via MC-Market](https://www.mc-market.org/resources/8940/) **|**
|
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
Use this section to tell people about which versions of your project are
|
||||||
|
currently being supported with security updates.
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 7.7.2 | :white_check_mark: |
|
||||||
|
| 7.7.1 | :white_check_mark: |
|
||||||
|
| < 4.0 | :x: |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
Use this section to tell people how to report a vulnerability.
|
||||||
|
|
||||||
|
Tell them where to go, how often they can expect to get an update on a
|
||||||
|
reported vulnerability, what to expect if the vulnerability is accepted or
|
||||||
|
declined, etc.
|
||||||
+108
-55
@@ -1,101 +1,156 @@
|
|||||||
|
// C:\Users\ollie\Documents\GitHub\SupportBot\Structures\Client.js
|
||||||
|
|
||||||
// SupportBot | Emerald Services
|
// SupportBot | Emerald Services
|
||||||
// Client Structure
|
// Client Structure
|
||||||
|
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
|
||||||
const Discord = require("discord.js");
|
const Discord = require("discord.js");
|
||||||
const intents = new Discord.Intents(32767);
|
const { GatewayIntentBits, Partials } = require('discord.js');
|
||||||
|
|
||||||
const yaml = require("js-yaml");
|
const yaml = require("js-yaml");
|
||||||
const supportbot = yaml.load(
|
|
||||||
fs.readFileSync("./Configs/supportbot.yml", "utf8")
|
const supportbot = yaml.load(fs.readFileSync("./Configs/supportbot.yml", "utf8"));
|
||||||
);
|
const cmdconfig = yaml.load(fs.readFileSync("./Configs/commands.yml", "utf8"));
|
||||||
|
|
||||||
class Client extends Discord.Client {
|
class Client extends Discord.Client {
|
||||||
constructor() {
|
constructor() {
|
||||||
super({ intents });
|
super({
|
||||||
|
intents: [
|
||||||
|
GatewayIntentBits.Guilds,
|
||||||
|
GatewayIntentBits.GuildMembers,
|
||||||
|
GatewayIntentBits.GuildMessages
|
||||||
|
],
|
||||||
|
partials: [Partials.Channel]
|
||||||
|
});
|
||||||
|
|
||||||
this.commands = new Discord.Collection();
|
this.commands = new Discord.Collection();
|
||||||
}
|
}
|
||||||
|
|
||||||
async getChannel(channel, guild) {
|
async getChannel(channel, guild) {
|
||||||
|
if (!channel) return null; // Add check for undefined channel
|
||||||
return guild.channels.cache.find(
|
return guild.channels.cache.find(
|
||||||
(c) =>
|
(c) =>
|
||||||
(c.type === "GUILD_TEXT" || c.type === "GUILD_NEWS") &&
|
(c.type === Discord.ChannelType.GuildText || c.type === Discord.ChannelType.GuildNews) &&
|
||||||
(c.id === channel || c.name.toLowerCase() === channel.toLowerCase())
|
(c.id === channel || (c.name && c.name.toLowerCase() === channel.toLowerCase()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRole(role, guild) {
|
async getRole(role, guild) {
|
||||||
|
if (!role) return null; // Add check for undefined role
|
||||||
return guild.roles.cache.find(
|
return guild.roles.cache.find(
|
||||||
(r) => r.id === role || r.name.toLowerCase() === role.toLowerCase()
|
(r) => r.id === role || (r.name && r.name.toLowerCase() === role.toLowerCase())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCategory(category, guild) {
|
async getCategory(category, guild) {
|
||||||
|
if (!category) return null; // Add check for undefined category
|
||||||
return guild.channels.cache.find(
|
return guild.channels.cache.find(
|
||||||
(c) =>
|
(c) =>
|
||||||
c.type === "GUILD_CATEGORY" &&
|
c.type === Discord.ChannelType.GuildCategory &&
|
||||||
(c.id === category || c.name.toLowerCase() === category.toLowerCase())
|
(c.id === category || (c.name && c.name.toLowerCase() === category.toLowerCase()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async start(token) {
|
async start(token) {
|
||||||
var tempCommandFiles = fs.readdirSync("./Commands").filter((file) => file.endsWith(".js"));
|
let tempCommandFiles = fs.readdirSync("./Commands").filter((file) => file.endsWith(".js"));
|
||||||
|
|
||||||
if (supportbot.DisableSuggestions) {
|
if (cmdconfig.Suggestion.Enabled === false) {
|
||||||
tempCommandFiles = tempCommandFiles.filter(item => item !== "suggest.js");
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "suggest.js");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.Help.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "help.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.Info.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "info.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.OpenTicket.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "ticket.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.CloseTicket.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "close.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.Embed.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "embed.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.Translate.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "translate.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.UserInfo.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "userinfo.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.Ping.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmdconfig.Ping.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "Ping.js");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (supportbot.Ticket.ClaimTickets.Enabled === false) {
|
||||||
|
tempCommandFiles = tempCommandFiles.filter(item => item !== "ticketstats.js");
|
||||||
|
}
|
||||||
|
|
||||||
const commandFiles = tempCommandFiles;
|
const commandFiles = tempCommandFiles;
|
||||||
|
|
||||||
const addonFiles = fs
|
|
||||||
.readdirSync("./Addons")
|
|
||||||
.filter((file) => file.endsWith(".js"));
|
|
||||||
|
|
||||||
const addons = addonFiles.map((file) => {
|
|
||||||
let addon = require(`../Addons/${file}`);
|
|
||||||
addon.name = file.split(".")[0];
|
|
||||||
return addon;
|
|
||||||
});
|
|
||||||
|
|
||||||
const commands = commandFiles.map((file) => require(`../Commands/${file}`));
|
const commands = commandFiles.map((file) => require(`../Commands/${file}`));
|
||||||
|
|
||||||
// Commands
|
// Commands
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
|
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
|
||||||
|
|
||||||
commands.forEach((cmd) => {
|
commands.forEach((cmd) => {
|
||||||
console.log(`\u001b[31;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 ▬▬▬▬▬▬▬");
|
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Commands ▬▬▬▬▬▬▬");
|
||||||
// Addons
|
|
||||||
console.log(" ");
|
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
|
||||||
|
|
||||||
addons.forEach((addon) => {
|
if (supportbot.General.Addons.Enabled) {
|
||||||
console.log(
|
const addonFiles = fs.readdirSync("./Addons").filter((file) => file.endsWith(".js"));
|
||||||
`\u001b[33m`,
|
|
||||||
`[ADDON]`,
|
|
||||||
`\u001b[31;1m`,
|
|
||||||
`${addon.name}`,
|
|
||||||
`\u001b[32;1m`,
|
|
||||||
"Loaded"
|
|
||||||
);
|
|
||||||
addon.commands?.forEach((command) => {
|
|
||||||
this.commands.set(command.name, command);
|
|
||||||
});
|
|
||||||
addon.events?.forEach((event) => {
|
|
||||||
this.on(event.event, (...args) => event.run(this, ...args));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
const addons = addonFiles.map((file) => {
|
||||||
|
let addon = require(`../Addons/${file}`);
|
||||||
|
addon.name = file.split(".")[0];
|
||||||
|
return addon;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Addons
|
||||||
|
console.log(" ");
|
||||||
|
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
||||||
|
|
||||||
|
addons.forEach((addon) => {
|
||||||
|
console.log(
|
||||||
|
`\u001b[32m`,
|
||||||
|
`[ADDON]`,
|
||||||
|
`\u001b[37;1m`,
|
||||||
|
`${addon.name}`,
|
||||||
|
`\u001b[32;1m`,
|
||||||
|
"Loaded"
|
||||||
|
);
|
||||||
|
addon.commands?.forEach((command) => {
|
||||||
|
this.commands.set(command.name, command);
|
||||||
|
});
|
||||||
|
addon.events?.forEach((event) => {
|
||||||
|
this.on(event.event, (...args) => event.run(this, ...args));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Addons ▬▬▬▬▬▬▬");
|
||||||
|
}
|
||||||
|
|
||||||
// Slash Commands
|
// 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);
|
||||||
console.log(
|
console.log(
|
||||||
`\u001b[32;1m`,
|
"\u001b[32m",
|
||||||
|
`[SUCCESS]`,
|
||||||
|
`\u001b[37;1m`,
|
||||||
`Slash Commands Registered for ${this.guilds.cache.first().name}`
|
`Slash Commands Registered for ${this.guilds.cache.first().name}`
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -103,13 +158,11 @@ class Client extends Discord.Client {
|
|||||||
console.log(" ");
|
console.log(" ");
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
|
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
|
||||||
|
|
||||||
fs.readdirSync("./Events")
|
fs.readdirSync("./Events").filter((file) => file.endsWith(".js")).forEach((file) => {
|
||||||
.filter((file) => file.endsWith(".js"))
|
const event = require(`../Events/${file}`);
|
||||||
.forEach((file) => {
|
console.log(`\u001b[32m`, `[EVENT]`, `\u001b[37;1m`, `${event.event}`, `\u001b[32;1m`, "Loaded");
|
||||||
const event = require(`../Events/${file}`);
|
this.on(event.event, (...args) => event.run(this, ...args));
|
||||||
console.log(`\u001b[31;1m`, `${event.event}`, `\u001b[32;1m`, "Loaded");
|
});
|
||||||
this.on(event.event, (...args) => event.run(this, ...args));
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
|
console.log(`\u001b[34;1m`, "▬▬▬▬▬▬▬ Events ▬▬▬▬▬▬▬");
|
||||||
if (process.argv[2] !== "test") {
|
if (process.argv[2] !== "test") {
|
||||||
|
|||||||
@@ -18,6 +18,27 @@ const supportbot = yaml.load(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const Client = require("./Structures/Client.js");
|
const Client = require("./Structures/Client.js");
|
||||||
const client = new Client({});
|
const client = new Client({
|
||||||
|
intents: ['Guilds', 'GuildMembers', 'GuildMessages']
|
||||||
|
});
|
||||||
|
|
||||||
|
client.start(supportbot.General.Token);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
client.start(supportbot.Token);
|
|
||||||
Generated
-1146
File diff suppressed because it is too large.
Load diff
+8
-5
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "supportbot",
|
"name": "supportbot",
|
||||||
"version": "7.7b",
|
"version": "8.0.1",
|
||||||
"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.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "npm i && node index.js",
|
"setup": "npm i && node index.js",
|
||||||
"test": "node index.js test"
|
"start": "node index.js"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@@ -19,8 +19,11 @@
|
|||||||
"homepage": "https://github.com/Emerald-Services/SupportBot#readme",
|
"homepage": "https://github.com/Emerald-Services/SupportBot#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vitalets/google-translate-api": "^8.0.0",
|
"@vitalets/google-translate-api": "^8.0.0",
|
||||||
"discord.js": "^13.6.0",
|
"axios": "^1.7.2",
|
||||||
|
"chatgpt": "^5.2.5",
|
||||||
|
"discord.js": "^14.13.0",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"moment": "^2.29.3"
|
"moment": "^2.29.3",
|
||||||
|
"openai": "^4.50.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user