Merge pull request #262 from ZynerOrg/dev

2022.5.0
This commit is contained in:
Axel Olausson Holtenäs 2022-05-20 23:05:55 +02:00 committed by GitHub
commit 3603a5c0b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
116 changed files with 1965 additions and 1731 deletions

View file

@ -1,5 +1,16 @@
version = 1 version = 1
[[analyzers]]
name = "javascript"
enabled = true
[[analyzers]] [[analyzers]]
name = "shell" name = "shell"
enabled = true enabled = true
[[transformers]]
name = "standardjs"
enabled = true
[[transformers]]
name = "prettier"

View file

@ -7,54 +7,50 @@ This document entails the privacy policy and agreement that you accept when addi
This privacy policy applies to **Xyter**#7721 (949998000401436673) This privacy policy applies to **Xyter**#7721 (949998000401436673)
### Terminology ### Terminology
* **Server Manager** - Anyone who has the ability to add a bot to a server or configure the bot for the server. This is usually an administrator or moderator
* **Server Member** - Anyone who is a member of server to which one of the bots has been added
* **Service User** - Anyone who authorizes an application (logs in) for a scope that provides additional information
- **Server Manager** - Anyone who has the ability to add a bot to a server or configure the bot for the server. This is usually an administrator or moderator
- **Server Member** - Anyone who is a member of server to which one of the bots has been added
- **Service User** - Anyone who authorizes an application (logs in) for a scope that provides additional information
### Data Collected By Command ### Data Collected By Command
The following items may be collected and stored when intentionally provided by a user (usually by means of a command). This data will not be collected automatically. When providing data in this way, you forego any rights to the content of the data provided.
* Server configurations (/settings guild)
* Data and content for automated tasks (/shop roles)
* Locale (/settings user language)
* Reputation (/reputation give)
The following items may be collected and stored when intentionally provided by a user (usually by means of a command). This data will not be collected automatically. When providing data in this way, you forego any rights to the content of the data provided.
- Server configurations (/settings guild)
- Data and content for automated tasks (/shop roles)
- Locale (/settings user language)
- Reputation (/reputation give)
### Data Collected When Enabled ### Data Collected When Enabled
These items will be automatically collected if a bot is configured to perform certain actions by a server manager. These features are always opt-in, and thus this data will not be collected unless the corresponding feature is enabled. These items will be automatically collected if a bot is configured to perform certain actions by a server manager. These features are always opt-in, and thus this data will not be collected unless the corresponding feature is enabled.
* API Token & URL (/settings guild pterodactyl)
* Counters (/admin counter)
- API Token & URL (/settings guild pterodactyl)
- Counters (/admin counter)
### Data Collected Automatically ### Data Collected Automatically
This data may be collected automatically. This data is used to provide statistics or history data. For any bots that collect this data, it is necessary for features of said bot. This data may be collected automatically. This data is used to provide statistics or history data. For any bots that collect this data, it is necessary for features of said bot.
* Username ID (Unique identifier)
* Guild ID (Unique identifier)
* Any data needed for standard operation of Discord bots, such as server permissions
* Credits (/profile view)
* Points (/profile view)
* Levels (/profile view)
* Timestamps (Audit logs and all your data that we store)
- Username ID (Unique identifier)
- Guild ID (Unique identifier)
- Any data needed for standard operation of Discord bots, such as server permissions
- Credits (/profile view)
- Points (/profile view)
- Levels (/profile view)
- Timestamps (Audit logs and all your data that we store)
### Data Storage ### Data Storage
All stored data is kept on protected servers. While storage methods vary, most data is kept within password-protected databases such as [MongoDB Atlas](https://atlas.mongodb.com/). Please keep in mind that even with these protections, no data can ever be 100% secure. All efforts are taken to keep your data secure and private, but its absolute security cannot be guaranteed. All stored data is kept on protected servers. While storage methods vary, most data is kept within password-protected databases such as [MongoDB Atlas](https://atlas.mongodb.com/). Please keep in mind that even with these protections, no data can ever be 100% secure. All efforts are taken to keep your data secure and private, but its absolute security cannot be guaranteed.
### Feedback ### Feedback
Feedback on Xyter bot and service is appreciated. When you submit comments, suggestions, bug reports, and any other forms of feedback, you forego any rights to the content, title, or intent of the provided feedback. Additionally, the feedback may be utilized in any way. Feedback on Xyter bot and service is appreciated. When you submit comments, suggestions, bug reports, and any other forms of feedback, you forego any rights to the content, title, or intent of the provided feedback. Additionally, the feedback may be utilized in any way.
### Agreement ### Agreement
By adding Xyter bot to your server or using this bot or service in any way, you are consenting to the policies outlined in this document. In addition, you (the server manager) are agreeing to inform your members of the [Developer Terms of Service](https://discordapp.com/developers/docs/legal) and the contents of this document. If you, the server manager, do not agree to this document, you may remove the bot(s) from the server. If you, the server member, do not agree to this document, you may leave the server that contains the bot(s). If you, the service user, do not agree to this document, you may revoke authorization of the application(s) in your 'Authorized Apps' menu. By adding Xyter bot to your server or using this bot or service in any way, you are consenting to the policies outlined in this document. In addition, you (the server manager) are agreeing to inform your members of the [Developer Terms of Service](https://discordapp.com/developers/docs/legal) and the contents of this document. If you, the server manager, do not agree to this document, you may remove the bot(s) from the server. If you, the server member, do not agree to this document, you may leave the server that contains the bot(s). If you, the service user, do not agree to this document, you may revoke authorization of the application(s) in your 'Authorized Apps' menu.
Changes to This Privacy Policy Changes to This Privacy Policy

View file

@ -2,10 +2,10 @@
## Supported Versions ## Supported Versions
| Version | Supported | | Version | Supported |
| ------- | ------------------ | | ---------- | ------------------ |
| 2022.4.x | :white_check_mark: | | 2022.4.x | :white_check_mark: |
| < 2022.4.x | :x: | | < 2022.4.x | :x: |
## Reporting a Vulnerability ## Reporting a Vulnerability

View file

@ -1,3 +0,0 @@
files:
- source: /lang/en/*.json
translation: /lang/%two_letters_code%/%original_file_name%

View file

@ -1,3 +0,0 @@
{
"test":"test"
}

View file

@ -5,7 +5,7 @@
"main": "src/index.ts", "main": "src/index.ts",
"scripts": { "scripts": {
"test": "jest", "test": "jest",
"start": "nodemon | pino-pretty -i pid,hostname -t yyyy-mm-dd HH:MM:s", "start": "node .",
"prettier-format": "prettier \"src/**/*.ts\" --write", "prettier-format": "prettier \"src/**/*.ts\" --write",
"lint": "eslint ./src --ext .ts", "lint": "eslint ./src --ext .ts",
"prepare": "husky install" "prepare": "husky install"
@ -27,37 +27,43 @@
"email": "vermium@zyner.org" "email": "vermium@zyner.org"
}, },
"dependencies": { "dependencies": {
"@discordjs/builders": "^0.12.0", "@discordjs/builders": "^0.13.0",
"@discordjs/rest": "^0.4.0", "@discordjs/rest": "^0.4.0",
"axios": "^0.26.0", "@types/i18next-fs-backend": "^1.1.2",
"axios": "^0.27.2",
"chance": "^1.1.8", "chance": "^1.1.8",
"common": "^0.2.5", "common": "^0.2.5",
"crypto": "^1.0.1", "crypto": "^1.0.1",
"discord-api-types": "^0.31.0", "discord-api-types": "^0.33.0",
"discord.js": "^13.6.0", "discord.js": "^13.6.0",
"i18n": "^0.14.2",
"i18next": "^21.6.13", "i18next": "^21.6.13",
"i18next-async-backend": "^2.0.0",
"i18next-fs-backend": "^1.1.4",
"i18next-http-backend": "^1.4.0",
"i18next-resources-to-backend": "^1.0.0",
"mongoose": "^6.2.3", "mongoose": "^6.2.3",
"node-schedule": "^2.1.0", "node-schedule": "^2.1.0",
"ts-node": "^10.7.0", "ts-node": "^10.7.0",
"tsconfig-paths": "^3.14.1", "tsconfig-paths": "^4.0.0",
"typescript": "^4.6.3", "typescript": "^4.6.3",
"uuid": "^8.3.2", "uuid": "^8.3.2",
"winston-daily-rotate-file": "^4.6.1" "winston-daily-rotate-file": "^4.6.1"
}, },
"devDependencies": { "devDependencies": {
"@types/chance": "^1.1.3", "@types/chance": "^1.1.3",
"@types/node-schedule": "^1.3.2", "@types/node-schedule": "2.1.0",
"@types/uuid": "^8.3.4", "@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.15.0", "@typescript-eslint/eslint-plugin": "^5.15.0",
"@typescript-eslint/parser": "^5.15.0", "@typescript-eslint/parser": "^5.15.0",
"eslint": "8.13.0", "eslint": "8.15.0",
"eslint-config-airbnb-base": "15.0.0", "eslint-config-airbnb-base": "15.0.0",
"eslint-config-prettier": "8.5.0", "eslint-config-prettier": "8.5.0",
"eslint-plugin-import": "2.26.0", "eslint-plugin-import": "2.26.0",
"eslint-plugin-no-loops": "^0.3.0", "eslint-plugin-no-loops": "^0.3.0",
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"husky": "^7.0.0", "husky": "8.0.1",
"jest": "^27.5.1", "jest": "28.0.0",
"lint-staged": "^12.3.7", "lint-staged": "^12.3.7",
"prettier": "^2.6.0" "prettier": "^2.6.0"
}, },

View file

@ -8,13 +8,15 @@ import logger from "@logger";
import { url } from "@config/database"; import { url } from "@config/database";
export default async () => { export default async () => {
mongoose.connect(url).then(async (connection) => { await mongoose.connect(url).then(async (connection) => {
logger?.info(`Connected to database: ${connection.connection.name}`); logger.info(`Connected to database: ${connection.connection.name}`);
}); });
mongoose.connection.on("error", (error) => {
logger?.error(error); mongoose.connection.on("error", async (error) => {
logger.error(`${error}`);
}); });
mongoose.connection.on("warn", (warning) => {
logger?.warn(warning); mongoose.connection.on("warn", async (warning) => {
logger.warn(warning);
}); });
}; };

View file

@ -1,3 +1,4 @@
import { ColorResolvable } from "discord.js";
import { Schema, model } from "mongoose"; import { Schema, model } from "mongoose";
interface IGuild { interface IGuild {
@ -10,6 +11,13 @@ interface IGuild {
minimumLength: number; minimumLength: number;
workTimeout: number; workTimeout: number;
}; };
embeds: {
successColor: ColorResolvable;
waitColor: ColorResolvable;
errorColor: ColorResolvable;
footerIcon: string;
footerText: string;
};
shop: { roles: { status: boolean; pricePerHour: number } }; shop: { roles: { status: boolean; pricePerHour: number } };
points: { points: {
status: boolean; status: boolean;
@ -61,6 +69,28 @@ const guildSchema = new Schema<IGuild>(
default: 900000, default: 900000,
}, },
}, },
embeds: {
successColor: {
type: String,
default: "#22bb33",
},
waitColor: {
type: String,
default: "#f0ad4e",
},
errorColor: {
type: String,
default: "#bb2124",
},
footerText: {
type: String,
default: "https://github.com/ZynerOrg/xyter",
},
footerIcon: {
type: String,
default: "https://github.com/ZynerOrg.png",
},
},
shop: { shop: {
roles: { roles: {
status: { status: {

View file

@ -7,13 +7,14 @@ import fetchGuild from "@helpers/fetchGuild";
import logger from "@logger"; import logger from "@logger";
export default { export default {
name: "guildCreate",
async execute(guild: Guild) { async execute(guild: Guild) {
const { client } = guild; const { client } = guild;
logger?.verbose(`Added to guild: ${guild.name} (${guild.id})`); logger?.silly(`Added to guild: ${guild.name} (${guild.id})`);
await fetchGuild(guild); await fetchGuild(guild);
await updatePresence(client); await updatePresence(client);
logger.silly(`guildCreate: ${guild}`);
}, },
}; };

View file

@ -7,13 +7,14 @@ import dropGuild from "@helpers/dropGuild";
import logger from "@logger"; import logger from "@logger";
export default { export default {
name: "guildDelete",
async execute(guild: Guild) { async execute(guild: Guild) {
const { client } = guild; const { client } = guild;
logger?.verbose(`Deleted from guild: ${guild.name} (${guild.id})`); logger?.silly(`Deleted from guild: ${guild.name} (${guild.id})`);
await dropGuild(guild); await dropGuild(guild);
await updatePresence(client); await updatePresence(client);
logger.silly(`guildDelete: ${guild}`);
}, },
}; };

View file

@ -3,10 +3,14 @@ import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { footerText, footerIcon, successColor } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
export default { export default {
execute: async (member: GuildMember) => { execute: async (member: GuildMember) => {
const { footerText, footerIcon, successColor } = await getEmbedConfig(
member.guild
);
const guildData = await guildSchema.findOne({ guildId: member.guild.id }); const guildData = await guildSchema.findOne({ guildId: member.guild.id });
const { client } = member; const { client } = member;
@ -20,24 +24,35 @@ export default {
if (channel === null) return; if (channel === null) return;
(channel as TextChannel).send({ (channel as TextChannel)
embeds: [ .send({
new MessageEmbed() embeds: [
.setColor(successColor) new MessageEmbed()
.setAuthor({ .setColor(successColor)
name: "Member Joined", .setAuthor({
iconURL: member.user.displayAvatarURL(), name: "Member Joined",
}) iconURL: member.user.displayAvatarURL(),
.setDescription(`${member.user} ${member.user.tag}`) })
.addFields([ .setDescription(`${member.user} ${member.user.tag}`)
{ name: "Account Age", value: `${member.user.createdAt}` }, .addFields([
]) { name: "Account Age", value: `${member.user.createdAt}` },
.setTimestamp() ])
.setFooter({ .setTimestamp()
text: footerText, .setFooter({
iconURL: footerIcon, text: footerText,
}), iconURL: footerIcon,
], }),
}); ],
})
.then(async () => {
logger.info(
`Audit log sent for event guildMemberAdd in guild ${member.guild.name} (${member.guild.id})`
);
})
.catch(async () => {
logger.error(
`Audit log failed to send for event guildMemberAdd in guild ${member.guild.name} (${member.guild.id})`
);
});
}, },
}; };

View file

@ -9,11 +9,10 @@ import joinMessage from "../guildMemberAdd/joinMessage";
import audits from "../guildMemberAdd/audits"; import audits from "../guildMemberAdd/audits";
export default { export default {
name: "guildMemberAdd",
async execute(member: GuildMember) { async execute(member: GuildMember) {
const { client, user, guild } = member; const { client, user, guild } = member;
logger?.verbose( logger?.silly(
`New member: ${user.tag} (${user.id}) added to guild: ${guild.name} (${guild.id})` `New member: ${user.tag} (${user.id}) added to guild: ${guild.name} (${guild.id})`
); );

View file

@ -1,13 +1,14 @@
import logger from "@logger";
import { GuildMember, MessageEmbed, TextChannel } from "discord.js"; import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { footerText, footerIcon, successColor } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
export default { export default {
execute: async (member: GuildMember) => { execute: async (member: GuildMember) => {
logger.info(member); const { footerText, footerIcon, successColor } = await getEmbedConfig(
member.guild
);
const guildData = await guildSchema.findOne({ guildId: member.guild.id }); const guildData = await guildSchema.findOne({ guildId: member.guild.id });

View file

@ -3,10 +3,14 @@ import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { footerText, footerIcon, errorColor } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
export default { export default {
execute: async (member: GuildMember) => { execute: async (member: GuildMember) => {
const { footerText, footerIcon, errorColor } = await getEmbedConfig(
member.guild
);
const guildData = await guildSchema.findOne({ guildId: member.guild.id }); const guildData = await guildSchema.findOne({ guildId: member.guild.id });
const { client } = member; const { client } = member;
@ -20,21 +24,32 @@ export default {
if (channel === null) return; if (channel === null) return;
(channel as TextChannel).send({ (channel as TextChannel)
embeds: [ .send({
new MessageEmbed() embeds: [
.setColor(errorColor) new MessageEmbed()
.setAuthor({ .setColor(errorColor)
name: "Member Left", .setAuthor({
iconURL: member.user.displayAvatarURL(), name: "Member Left",
}) iconURL: member.user.displayAvatarURL(),
.setDescription(`${member.user} ${member.user.tag}`) })
.setTimestamp() .setDescription(`${member.user} ${member.user.tag}`)
.setFooter({ .setTimestamp()
text: footerText, .setFooter({
iconURL: footerIcon, text: footerText,
}), iconURL: footerIcon,
], }),
}); ],
})
.then(async () => {
logger.info(
`Audit log sent for event guildMemberRemove in guild ${member.guild.name} (${member.guild.id})`
);
})
.catch(async () => {
logger.error(
`Audit log failed to send for event guildMemberRemove in guild ${member.guild.name} (${member.guild.id})`
);
});
}, },
}; };

View file

@ -9,11 +9,10 @@ import leaveMessage from "./leaveMessage";
import audits from "./audits"; import audits from "./audits";
export default { export default {
name: "guildMemberRemove",
async execute(member: GuildMember) { async execute(member: GuildMember) {
const { client, user, guild } = member; const { client, user, guild } = member;
logger?.verbose( logger?.silly(
`Removed member: ${user.tag} (${user.id}) from guild: ${guild.name} (${guild.id})` `Removed member: ${user.tag} (${user.id}) from guild: ${guild.name} (${guild.id})`
); );

View file

@ -1,13 +1,14 @@
import logger from "@logger";
import { GuildMember, MessageEmbed, TextChannel } from "discord.js"; import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { footerText, footerIcon, errorColor } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
export default { export default {
execute: async (member: GuildMember) => { execute: async (member: GuildMember) => {
logger.info(member); const { footerText, footerIcon, errorColor } = await getEmbedConfig(
member.guild
);
const guildData = await guildSchema.findOne({ guildId: member.guild.id }); const guildData = await guildSchema.findOne({ guildId: member.guild.id });

22
src/events/index.ts Normal file
View file

@ -0,0 +1,22 @@
// 3rd party dependencies
import mongoose from "mongoose";
// Dependencies
import logger from "@logger";
// Configuration
import { url } from "@config/database";
export default async () => {
await mongoose.connect(url).then(async (connection) => {
logger.info(`Connected to database: ${connection.connection.name}`);
});
mongoose.connection.on("error", async (error) => {
logger.error(`${error}`);
});
mongoose.connection.on("warn", async (warning) => {
logger.warn(warning);
});
};

View file

@ -3,7 +3,7 @@ import { Interaction, MessageEmbed, TextChannel } from "discord.js";
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { footerText, footerIcon, successColor } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
export default { export default {
execute: async (interaction: Interaction) => { execute: async (interaction: Interaction) => {
@ -11,6 +11,10 @@ export default {
if (interaction.guild === null) return; if (interaction.guild === null) return;
const { footerText, footerIcon, successColor } = await getEmbedConfig(
interaction.guild
);
const guildData = await guildSchema.findOne({ const guildData = await guildSchema.findOne({
guildId: interaction.guild.id, guildId: interaction.guild.id,
}); });
@ -26,23 +30,34 @@ export default {
if (channel === null) return; if (channel === null) return;
(channel as TextChannel).send({ (channel as TextChannel)
embeds: [ .send({
new MessageEmbed() embeds: [
.setColor(successColor) new MessageEmbed()
.setDescription( .setColor(successColor)
` .setDescription(
`
**Interaction created by** ${interaction.user.username} **in** ${interaction.channel} **Interaction created by** ${interaction.user.username} **in** ${interaction.channel}
` `
) )
.setThumbnail(interaction.user.displayAvatarURL()) .setThumbnail(interaction.user.displayAvatarURL())
.addFields([{ name: "Event", value: "interactionCreate" }]) .addFields([{ name: "Event", value: "interactionCreate" }])
.setTimestamp() .setTimestamp()
.setFooter({ .setFooter({
text: footerText, text: footerText,
iconURL: footerIcon, iconURL: footerIcon,
}), }),
], ],
}); })
.then(async () => {
logger.info(
`Audit log sent for event interactionCreate in guild ${interaction?.guild?.name} (${interaction?.guild?.id})`
);
})
.catch(async () => {
logger.error(
`Audit log failed to send for event interactionCreate in guild ${interaction?.guild?.name} (${interaction?.guild?.id})`
);
});
}, },
}; };

View file

@ -3,27 +3,88 @@ import { CommandInteraction, MessageEmbed } from "discord.js";
import logger from "@logger"; import logger from "@logger";
import { errorColor, footerText, footerIcon } from "@config/embed"; import deferReply from "@root/helpers/deferReply";
import getEmbedConfig from "@helpers/getEmbedConfig";
import getCommandMetadata from "@helpers/getCommandMetadata";
export default async (interaction: CommandInteraction) => { export default async (interaction: CommandInteraction) => {
if (!interaction.isCommand()) return; if (!interaction.isCommand()) return;
if (interaction.guild == null) return;
const { client, guild, commandName, user } = interaction; const { errorColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);
const { client, guild, commandName, user, memberPermissions } = interaction;
const currentCommand = client.commands.get(commandName); const currentCommand = client.commands.get(commandName);
if (!currentCommand) return;
await interaction.deferReply({ ephemeral: true }); if (currentCommand == null) {
logger.silly(`Command ${commandName} not found`);
}
const metadata = await getCommandMetadata(interaction, currentCommand);
await deferReply(interaction, metadata.ephemeral || false);
if (
metadata.permissions &&
metadata.guildOnly &&
!memberPermissions?.has(metadata.permissions)
) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:x:] Permission")
.setDescription(`You do not have the permission to manage the bot.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (metadata.guildOnly) {
if (!guild) {
logger.debug(`Guild is null`);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setDescription("This command is only available for guild")
.setColor(errorColor)
.setTimestamp(new Date())
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
}
if (metadata.dmOnly) {
if (guild) {
logger.silly(`Guild exist`);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setDescription("This command is only available in DM.")
.setColor(errorColor)
.setTimestamp(new Date())
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
}
await currentCommand await currentCommand
.execute(interaction) .execute(interaction)
.then(async () => { .then(async () => {
return logger?.verbose( return logger?.silly(
`Command: ${commandName} executed in guild: ${guild?.name} (${guild?.id}) by user: ${user?.tag} (${user?.id})` `Command: ${commandName} executed in guild: ${guild?.name} (${guild?.id}) by user: ${user?.tag} (${user?.id})`
); );
}) })
.catch(async (error: any) => { .catch(async (error: any) => {
logger?.error(error); logger?.error(`${error}`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [

View file

@ -7,11 +7,10 @@ import logger from "@logger";
import audits from "./audits"; import audits from "./audits";
export default { export default {
name: "interactionCreate",
async execute(interaction: CommandInteraction) { async execute(interaction: CommandInteraction) {
const { guild, id } = interaction; const { guild, id } = interaction;
logger?.verbose( logger?.silly(
`New interaction: ${id} in guild: ${guild?.name} (${guild?.id})` `New interaction: ${id} in guild: ${guild?.name} (${guild?.id})`
); );

View file

@ -2,7 +2,6 @@ import { Message } from "discord.js";
import modules from "@events/messageCreate/modules"; import modules from "@events/messageCreate/modules";
export default { export default {
name: "messageCreate",
async execute(message: Message) { async execute(message: Message) {
await modules.credits.execute(message); await modules.credits.execute(message);
await modules.points.execute(message); await modules.points.execute(message);

View file

@ -23,7 +23,7 @@ export default {
}); });
if (counter === null) { if (counter === null) {
logger.verbose( logger.silly(
`No counter found for guild ${guildId} and channel ${channelId}` `No counter found for guild ${guildId} and channel ${channelId}`
); );
return; return;
@ -33,7 +33,7 @@ export default {
lastMessage?.author.id === author.id && lastMessage?.author.id === author.id &&
channel.id === counter.channelId channel.id === counter.channelId
) { ) {
logger.verbose( logger.silly(
`${author.username} sent the last message therefor not allowing again.` `${author.username} sent the last message therefor not allowing again.`
); );
await message.delete(); await message.delete();
@ -41,7 +41,7 @@ export default {
} }
if (content !== counter.word) { if (content !== counter.word) {
logger.verbose( logger.silly(
`Counter word ${counter.word} does not match message ${content}` `Counter word ${counter.word} does not match message ${content}`
); );
@ -53,7 +53,7 @@ export default {
await counter await counter
.save() .save()
.then(async () => { .then(async () => {
logger.verbose( logger.silly(
`Counter for guild ${guildId} and channel ${channelId} is now ${counter.counter}` `Counter for guild ${guildId} and channel ${channelId} is now ${counter.counter}`
); );
}) })
@ -64,7 +64,7 @@ export default {
); );
}); });
logger.verbose( logger.silly(
`Counter word ${counter.word} was found in message ${content} from ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})` `Counter word ${counter.word} was found in message ${content} from ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})`
); );
}, },

View file

@ -30,7 +30,7 @@ export default {
const timeout = await timeouts.findOne(timeoutData); const timeout = await timeouts.findOne(timeoutData);
if (timeout) { if (timeout) {
logger.verbose( logger.silly(
`User ${userId} in guild ${guildId} is on timeout 2022-04-14-13-51-00` `User ${userId} in guild ${guildId} is on timeout 2022-04-14-13-51-00`
); );
return; return;
@ -41,7 +41,7 @@ export default {
await userData await userData
.save() .save()
.then(async () => { .then(async () => {
logger.verbose( logger.silly(
`User ${userId} in guild ${guildId} has ${userData.credits} credits` `User ${userId} in guild ${guildId} has ${userData.credits} credits`
); );
}) })
@ -55,7 +55,7 @@ export default {
await timeouts await timeouts
.create(timeoutData) .create(timeoutData)
.then(async () => { .then(async () => {
logger.verbose( logger.silly(
`Timeout 2022-04-14-13-51-00 for user ${userId} in guild ${guildId} has been created` `Timeout 2022-04-14-13-51-00 for user ${userId} in guild ${guildId} has been created`
); );
}) })
@ -70,7 +70,7 @@ export default {
await timeouts await timeouts
.deleteOne(timeoutData) .deleteOne(timeoutData)
.then(async () => { .then(async () => {
logger.verbose( logger.silly(
`Timeout 2022-04-14-13-51-00 for user ${userId} in guild ${guildId} has been deleted` `Timeout 2022-04-14-13-51-00 for user ${userId} in guild ${guildId} has been deleted`
); );
}) })

View file

@ -30,7 +30,7 @@ export default {
const timeout = await timeouts.findOne(timeoutData); const timeout = await timeouts.findOne(timeoutData);
if (timeout) { if (timeout) {
logger.verbose( logger.silly(
`User ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id} is on timeout 2022-04-14-14-15-00` `User ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id} is on timeout 2022-04-14-14-15-00`
); );
return; return;
@ -41,7 +41,7 @@ export default {
await userData await userData
.save() .save()
.then(async () => { .then(async () => {
logger.verbose( logger.silly(
`Successfully saved user ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})` `Successfully saved user ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})`
); );
}) })
@ -52,14 +52,14 @@ export default {
); );
}); });
logger.verbose( logger.silly(
`User ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id}) has ${userData.points} points` `User ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id}) has ${userData.points} points`
); );
await timeouts await timeouts
.create(timeoutData) .create(timeoutData)
.then(async () => { .then(async () => {
logger.verbose( logger.silly(
`Successfully created timeout for user ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})` `Successfully created timeout for user ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})`
); );
}) })
@ -74,7 +74,7 @@ export default {
await timeouts await timeouts
.deleteOne(timeoutData) .deleteOne(timeoutData)
.then(async () => { .then(async () => {
logger.verbose( logger.silly(
`Successfully deleted timeout 2022-04-14-14-15-00 for user ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})` `Successfully deleted timeout 2022-04-14-14-15-00 for user ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})`
); );
}) })

View file

@ -3,7 +3,7 @@ import { Message, MessageEmbed, TextChannel } from "discord.js";
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { footerText, footerIcon, successColor } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
export default { export default {
execute: async (message: Message) => { execute: async (message: Message) => {
@ -11,6 +11,10 @@ export default {
if (message.guild === null) return; if (message.guild === null) return;
const { footerText, footerIcon, successColor } = await getEmbedConfig(
message.guild
);
const guildData = await guildSchema.findOne({ const guildData = await guildSchema.findOne({
guildId: message.guild.id, guildId: message.guild.id,
}); });
@ -26,26 +30,37 @@ export default {
if (channel === null) return; if (channel === null) return;
(channel as TextChannel).send({ (channel as TextChannel)
embeds: [ .send({
new MessageEmbed() embeds: [
.setColor(successColor) new MessageEmbed()
.setAuthor({ .setColor(successColor)
name: message.author.username, .setAuthor({
iconURL: message.author.displayAvatarURL(), name: message.author.username,
}) iconURL: message.author.displayAvatarURL(),
.setDescription( })
` .setDescription(
`
**Message sent by** ${message.author} **deleted in** ${message.channel} **Message sent by** ${message.author} **deleted in** ${message.channel}
${message.content} ${message.content}
` `
) )
.setTimestamp() .setTimestamp()
.setFooter({ .setFooter({
text: footerText, text: footerText,
iconURL: footerIcon, iconURL: footerIcon,
}), }),
], ],
}); })
.then(async () => {
logger.info(
`Audit log sent for event messageDelete in guild ${message?.guild?.name} (${message?.guild?.id})`
);
})
.catch(async () => {
logger.error(
`Audit log failed to send for event messageDelete in guild ${message?.guild?.name} (${message?.guild?.id})`
);
});
}, },
}; };

View file

@ -3,7 +3,6 @@ import audits from "@events/messageDelete/audits";
import counter from "./modules/counter"; import counter from "./modules/counter";
export default { export default {
name: "messageDelete",
async execute(message: Message) { async execute(message: Message) {
await audits.execute(message); await audits.execute(message);
await counter(message); await counter(message);

View file

@ -14,7 +14,7 @@ export default async (message: Message) => {
}); });
if (counter === null) if (counter === null)
return logger?.verbose( return logger?.silly(
`No counter found for guild: ${guild?.name} (${guild?.id})` `No counter found for guild: ${guild?.name} (${guild?.id})`
); );
const { word } = counter; const { word } = counter;
@ -29,8 +29,8 @@ export default async (message: Message) => {
if (lastMessage.author.id === message.author.id) return; if (lastMessage.author.id === message.author.id) return;
channel?.send(`${author} said **${word}**.`); channel?.send(`${author} said **${word}**.`);
logger?.verbose(`${author} said ${word} in ${channel}`); logger?.silly(`${author} said ${word} in ${channel}`);
return logger?.verbose( return logger?.silly(
`User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) said the counter word: ${word}` `User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) said the counter word: ${word}`
); );
}; };

View file

@ -4,7 +4,7 @@ import { Message, MessageEmbed, TextChannel } from "discord.js";
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { footerText, footerIcon, successColor } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
export default { export default {
execute: async (oldMessage: Message, newMessage: Message) => { execute: async (oldMessage: Message, newMessage: Message) => {
@ -14,6 +14,10 @@ export default {
if (oldMessage.guild === null) return; if (oldMessage.guild === null) return;
if (newMessage.guild === null) return; if (newMessage.guild === null) return;
const { footerText, footerIcon, successColor } = await getEmbedConfig(
newMessage.guild
);
const guildData = await guildSchema.findOne({ const guildData = await guildSchema.findOne({
guildId: oldMessage.guild.id, guildId: oldMessage.guild.id,
}); });
@ -29,25 +33,36 @@ export default {
if (channel === null) return; if (channel === null) return;
(channel as TextChannel).send({ (channel as TextChannel)
embeds: [ .send({
new MessageEmbed() embeds: [
.setColor(successColor) new MessageEmbed()
.setAuthor({ .setColor(successColor)
name: newMessage.author.username, .setAuthor({
iconURL: newMessage.author.displayAvatarURL(), name: newMessage.author.username,
}) iconURL: newMessage.author.displayAvatarURL(),
.setDescription( })
` .setDescription(
`
**Message edited in** ${newMessage.channel} [jump to message](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.id}) **Message edited in** ${newMessage.channel} [jump to message](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.id})
` `
) )
.setTimestamp() .setTimestamp()
.setFooter({ .setFooter({
text: footerText, text: footerText,
iconURL: footerIcon, iconURL: footerIcon,
}), }),
], ],
}); })
.then(async () => {
logger.info(
`Audit log sent for event messageUpdate in guild ${newMessage?.guild?.name} (${newMessage?.guild?.id})`
);
})
.catch(async () => {
logger.error(
`Audit log failed to send for event messageUpdate in guild ${newMessage?.guild?.name} (${newMessage?.guild?.id})`
);
});
}, },
}; };

View file

@ -8,18 +8,16 @@ import counter from "./modules/counter";
import audits from "./audits"; import audits from "./audits";
export default { export default {
name: "messageUpdate",
async execute(oldMessage: Message, newMessage: Message) { async execute(oldMessage: Message, newMessage: Message) {
const { author, guild } = newMessage; const { author, guild } = newMessage;
await audits.execute(oldMessage, newMessage); await audits.execute(oldMessage, newMessage);
logger?.verbose( logger?.silly(
`Message update event fired by ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})` `Message update event fired by ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})`
); );
if (author?.bot) if (author?.bot) return logger?.silly(`Message update event fired by bot`);
return logger?.verbose(`Message update event fired by bot`);
await counter(newMessage); await counter(newMessage);
}, },

View file

@ -14,12 +14,12 @@ export default async (message: Message) => {
}); });
if (counter === null) if (counter === null)
return logger?.verbose( return logger?.silly(
`No counter found for guild: ${guild?.name} (${guild?.id})` `No counter found for guild: ${guild?.name} (${guild?.id})`
); );
const { word } = counter; const { word } = counter;
if (content === word) if (content === word)
return logger?.verbose( return logger?.silly(
`User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) said the counter word: ${word}` `User: ${author?.tag} (${author?.id}) in guild: ${guild?.name} (${guild?.id}) said the counter word: ${word}`
); );
@ -27,7 +27,7 @@ export default async (message: Message) => {
?.delete() ?.delete()
?.then(async () => { ?.then(async () => {
await channel?.send(`${author} said **${word}**.`); await channel?.send(`${author} said **${word}**.`);
logger?.verbose(`${author} said ${word} in ${channel}`); logger?.silly(`${author} said ${word} in ${channel}`);
}) })
?.catch(async (error: any) => { ?.catch(async (error: any) => {
logger?.error(error); logger?.error(error);

View file

@ -8,17 +8,16 @@ import deployCommands from "@handlers/deployCommands";
import devMode from "@handlers/devMode"; import devMode from "@handlers/devMode";
export default { export default {
name: "ready",
once: true, once: true,
async execute(client: Client) { async execute(client: Client) {
logger.info(`${client.user?.tag} (${client.user?.id}) is ready`); logger.info("Ready!");
await updatePresence(client); await updatePresence(client);
await devMode(client); await devMode(client);
await deployCommands(client); await deployCommands(client);
client.guilds?.cache.forEach((guild) => { client.guilds?.cache.forEach((guild) => {
logger.verbose( logger.silly(
`${client.user?.tag} (${client.user?.id}) is in guild: ${guild.name} (${guild.id}) with member count of ${guild.memberCount}` `${client.user?.tag} (${client.user?.id}) is in guild: ${guild.name} (${guild.id}) with member count of ${guild.memberCount}`
); );
}); });

View file

@ -12,22 +12,25 @@ export default async (client: Client) => {
} }
await Promise.all( await Promise.all(
plugins.map(async (pluginName) => { plugins.map(async (pluginName, index) => {
const plugin = await import(`../plugins/${pluginName}`); const plugin = await import(`../plugins/${pluginName}`);
await client?.commands?.set( await client.commands.set(
plugin?.default?.data?.name, plugin.default.builder.name,
plugin?.default plugin.default,
plugin.default.metadata
); );
logger.verbose(`Loaded plugin: ${pluginName}`); logger.verbose(
`Loaded plugin ${index + 1}/${plugins.length}: ${pluginName}`
);
}) })
) )
.then(async () => { .then(async () => {
logger.debug("Successfully loaded plugins."); logger.info(`Started all ${plugins.length} plugins.`);
}) })
.catch(async (err) => { .catch(async (err) => {
logger.error(err); logger.error(`${err}`);
}); });
}); });
}; };

View file

@ -12,17 +12,17 @@ export default async (client: Client) => {
await Promise.all( await Promise.all(
client.commands.map(async (pluginData: any) => { client.commands.map(async (pluginData: any) => {
pluginList.push(pluginData.data.toJSON()); pluginList.push(pluginData.builder.toJSON());
logger.verbose( logger.verbose(
`${pluginData.data.name} successfully pushed to plugin list.` `Plugin is ready for deployment: ${pluginData.builder.name}`
); );
}) })
) )
.then(async () => { .then(async () => {
logger.debug("Successfully pushed all plugins to plugin list."); logger.info("All plugins are ready to be deployed.");
}) })
.catch(async (error) => { .catch(async (error) => {
logger.error(error); logger.error(`${error}`);
}); });
const rest = new REST({ version: "9" }).setToken(token); const rest = new REST({ version: "9" }).setToken(token);
@ -32,10 +32,10 @@ export default async (client: Client) => {
body: pluginList, body: pluginList,
}) })
.then(async () => { .then(async () => {
logger.debug(`Successfully deployed plugins to Discord`); logger.info(`Successfully deployed plugins to Discord's API`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger.error(error); logger.error(`${error}`);
}); });
if (devMode) { if (devMode) {
@ -44,10 +44,10 @@ export default async (client: Client) => {
body: pluginList, body: pluginList,
}) })
.then(async () => .then(async () =>
logger.debug(`Successfully deployed guild plugins to Discord`) logger.info(`Successfully deployed guild plugins to Discord's API`)
) )
.catch(async (error) => { .catch(async (error) => {
logger.error(error); logger.error(`${error}`);
}); });
} }
}; };

View file

@ -9,11 +9,9 @@ import { devMode, guildId } from "@config/other";
export default async (client: Client) => { export default async (client: Client) => {
if (!devMode) { if (!devMode) {
return client?.application?.commands?.set([], guildId).then(async () => { return client?.application?.commands?.set([], guildId).then(async () => {
return logger.debug( return logger.verbose(`Development mode is disabled.`);
`Development commands disabled for guild: ${guildId}`
);
}); });
} }
return logger.debug(`Development commands enabled for guild: ${guildId}`); return logger.info(`Development mode is enabled.`);
}; };

View file

@ -4,7 +4,7 @@ import { secretKey, algorithm } from "@config/encryption";
const iv = crypto.randomBytes(16); const iv = crypto.randomBytes(16);
const encrypt = (text: any) => { const encrypt = (text: any): { iv: error; content: error } => {
const cipher = crypto.createCipheriv(algorithm, secretKey, iv); const cipher = crypto.createCipheriv(algorithm, secretKey, iv);
const encrypted = Buffer.concat([cipher.update(text), cipher.final()]); const encrypted = Buffer.concat([cipher.update(text), cipher.final()]);

View file

@ -9,27 +9,29 @@ export default async (client: Client) => {
} }
await Promise.all( await Promise.all(
events.map(async (eventName) => { events.map(async (eventName, index) => {
const event = await import(`../events/${eventName}`); const event = await import(`../events/${eventName}`);
logger.verbose(`Loaded event: ${eventName}`); logger.verbose(
`Loaded event ${index + 1}/${events.length}: ${eventName}`
);
if (event.once) { if (event.once) {
return client.once(event.default.name, async (...args) => return client.once(eventName, async (...args) =>
event.default.execute(...args) event.default.execute(...args)
); );
} }
return client.on(event.default.name, async (...args) => return client.on(eventName, async (...args) =>
event.default.execute(...args) event.default.execute(...args)
); );
}) })
) )
.then(async () => { .then(async () => {
logger.debug("Successfully loaded events."); logger.info(`Started all ${events.length} events.`);
}) })
.catch(async (err) => { .catch(async (err) => {
logger.error(err); logger.error(`${err}`);
}); });
}); });
}; };

View file

@ -5,7 +5,7 @@ import schedule from "node-schedule";
import logger from "@logger"; import logger from "@logger";
// Jobs // Jobs
import shopRoles from "@root/schedules/jobs/shopRoles"; import shopRoles from "@jobs/shopRoles";
export default async (client: Client) => { export default async (client: Client) => {
const expression = "*/5 * * * *"; const expression = "*/5 * * * *";

28
src/helpers/deferReply.ts Normal file
View file

@ -0,0 +1,28 @@
import { CommandInteraction, MessageEmbed } from "discord.js";
import getEmbedConfig from "@helpers/getEmbedConfig";
export default async (interaction: CommandInteraction, ephemeral: boolean) => {
if (interaction.guild == null) return;
await interaction.deferReply({
ephemeral,
});
const { waitColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);
await interaction.editReply({
embeds: [
new MessageEmbed()
.setFooter({
text: footerText,
iconURL: footerIcon,
})
.setTimestamp(new Date())
.setTitle("Processing your request")
.setColor(waitColor)
.setDescription("Please wait..."),
],
});
};

View file

@ -13,7 +13,7 @@ export default async (guild: Guild) => {
await guildSchema await guildSchema
.deleteMany({ guildId: guild.id }) .deleteMany({ guildId: guild.id })
.then(async () => { .then(async () => {
return logger?.verbose(`Deleted guild: ${guild.id}`); return logger?.silly(`Deleted guild: ${guild.id}`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error(`Error deleting guild: ${guild.id} - ${error}`); logger?.error(`Error deleting guild: ${guild.id} - ${error}`);
@ -22,7 +22,7 @@ export default async (guild: Guild) => {
await userSchema await userSchema
.deleteMany({ guildId: guild.id }) .deleteMany({ guildId: guild.id })
.then(async () => { .then(async () => {
logger?.verbose(`Deleted users for guild: ${guild.id} from database`); logger?.silly(`Deleted users for guild: ${guild.id} from database`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error(`Error deleting users for guild: ${guild.id} - ${error}`); logger?.error(`Error deleting users for guild: ${guild.id} - ${error}`);
@ -31,7 +31,7 @@ export default async (guild: Guild) => {
await apiSchema await apiSchema
.deleteMany({ guildId: guild.id }) .deleteMany({ guildId: guild.id })
.then(async () => { .then(async () => {
logger?.verbose(`Deleted apis for guild: ${guild.id} from database`); logger?.silly(`Deleted apis for guild: ${guild.id} from database`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error(`Error deleting apis for guild: ${guild.id} - ${error}`); logger?.error(`Error deleting apis for guild: ${guild.id} - ${error}`);
@ -40,7 +40,7 @@ export default async (guild: Guild) => {
await counterSchema await counterSchema
.deleteMany({ guildId: guild.id }) .deleteMany({ guildId: guild.id })
.then(async () => { .then(async () => {
logger?.verbose(`Deleted counters for guild: ${guild.id} from database`); logger?.silly(`Deleted counters for guild: ${guild.id} from database`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error( logger?.error(
@ -51,9 +51,7 @@ export default async (guild: Guild) => {
await shopRoleSchema await shopRoleSchema
.deleteMany({ guildId: guild.id }) .deleteMany({ guildId: guild.id })
.then(async () => { .then(async () => {
logger?.verbose( logger?.silly(`Deleted shop roles for guild: ${guild.id} from database`);
`Deleted shop roles for guild: ${guild.id} from database`
);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error( logger?.error(
@ -64,7 +62,7 @@ export default async (guild: Guild) => {
await timeoutSchema await timeoutSchema
.deleteMany({ guildId: guild.id }) .deleteMany({ guildId: guild.id })
.then(async () => { .then(async () => {
logger?.verbose(`Deleted timeouts for guild: ${guild.id} from database`); logger?.silly(`Deleted timeouts for guild: ${guild.id} from database`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error( logger?.error(

View file

@ -8,7 +8,7 @@ export default async (user: User, guild: Guild) => {
await userSchema await userSchema
.deleteOne({ userId: user.id, guildId: guild.id }) .deleteOne({ userId: user.id, guildId: guild.id })
.then(async () => { .then(async () => {
logger?.verbose(`Deleted user: ${user?.id} from guild: ${guild?.id}`); logger?.silly(`Deleted user: ${user?.id} from guild: ${guild?.id}`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error( logger?.error(

View file

@ -0,0 +1,9 @@
import { footerText, footerIcon } from "@config/embed";
import { MessageEmbed } from "discord.js";
export default new MessageEmbed()
.setFooter({
text: footerText,
iconURL: footerIcon,
})
.setTimestamp(new Date());

View file

@ -16,7 +16,7 @@ export default async (guild: Guild) => {
await newGuildObj await newGuildObj
.save() .save()
.then(async () => { .then(async () => {
logger?.verbose(`Created guild: ${guild.id}`); logger?.silly(`Created guild: ${guild.id}`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error(`Error creating guild: ${guild.id} - ${error}`); logger?.error(`Error creating guild: ${guild.id} - ${error}`);

View file

@ -22,7 +22,7 @@ export default async (user: User, guild: Guild) => {
await newUserObj await newUserObj
.save() .save()
.then(async () => { .then(async () => {
logger?.verbose(`Created user: ${user.id} for guild: ${guild.id}`); logger?.silly(`Created user: ${user.id} for guild: ${guild.id}`);
}) })
.catch(async (error) => { .catch(async (error) => {
logger?.error( logger?.error(

View file

@ -0,0 +1,12 @@
import { CommandInteraction } from "discord.js";
export default async (interaction: CommandInteraction, currentCommand: any) => {
const subcommand = interaction.options.getSubcommand();
const subcommandGroup = interaction.options.getSubcommandGroup(false);
if (!subcommandGroup) {
return currentCommand.modules[subcommand].metadata;
}
return currentCommand.modules[subcommandGroup].modules[subcommand].metadata;
};

View file

@ -0,0 +1,18 @@
import guildSchema from "@schemas/guild";
import { ColorResolvable, Guild } from "discord.js";
export default async (guild: Guild) => {
const guildConfig = await guildSchema.findOne({ guildId: guild.id });
if (guildConfig == null)
return {
successColor: "#22bb33" as ColorResolvable,
waitColor: "#f0ad4e" as ColorResolvable,
errorColor: "#bb2124" as ColorResolvable,
footerIcon: "https://github.com/ZynerOrg.png",
footerText: "https://github.com/ZynerOrg/xyter",
};
return guildConfig.embeds;
};

View file

@ -1,7 +1,7 @@
import logger from "@root/logger"; import logger from "@root/logger";
export default (count: number, noun: string, suffix?: string) => { export default (count: number, noun: string, suffix?: string): string => {
const result = `${count} ${noun}${count !== 1 ? suffix || "s" : ""}`; const result = `${count} ${noun}${count !== 1 ? suffix || "s" : ""}`;
logger?.verbose(`Pluralized ${count} to ${result}`); logger?.silly(`Pluralized ${count} to ${result}`);
return result; return result;
}; };

View file

@ -23,7 +23,7 @@ export default async function saveUser(data: any, data2: any) {
50 50
)}\n${`${_}\n${"=".repeat(50)}`}` )}\n${`${_}\n${"=".repeat(50)}`}`
) )
: logger?.verbose(`Saved user: ${data.id} (saveUser)`) : logger?.silly(`Saved user: ${data.id} (saveUser)`)
); );
if (data2) { if (data2) {
data2.save((_: any) => data2.save((_: any) =>
@ -33,7 +33,7 @@ export default async function saveUser(data: any, data2: any) {
50 50
)}\n${`${_}\n${"=".repeat(50)}`}` )}\n${`${_}\n${"=".repeat(50)}`}`
) )
: logger?.verbose(`Saved user: ${data2.id} (saveUser)`) : logger?.silly(`Saved user: ${data2.id} (saveUser)`)
); );
} }
}, },

View file

@ -3,6 +3,6 @@ import logger from "@logger";
export default function sleep(milliseconds: any) { export default function sleep(milliseconds: any) {
return new Promise((resolve) => { return new Promise((resolve) => {
setTimeout(resolve, milliseconds); setTimeout(resolve, milliseconds);
logger?.verbose(`Sleeping for ${milliseconds} milliseconds`); logger?.silly(`Sleeping for ${milliseconds} milliseconds`);
}); });
} }

View file

@ -10,5 +10,5 @@ export default async (client: Client) => {
activities: [{ type: "WATCHING", name: status }], activities: [{ type: "WATCHING", name: status }],
status: "online", status: "online",
}); });
logger?.verbose(`Updated client presence to: ${status}`); logger?.debug(`Updated client presence to: ${status}`);
}; };

View file

@ -4,25 +4,56 @@ import { token, intents } from "@config/discord";
import { Client } from "discord.js"; // discord.js import { Client } from "discord.js"; // discord.js
import locale from "@locale"; import database from "@root/events";
import database from "@database"; import schedules from "@handlers/schedules";
import schedules from "@schedules";
import events from "@handlers/events"; import events from "@handlers/events";
import commands from "@handlers/commands"; import commands from "@handlers/commands";
async function main() { // Main process that starts all other sub processes
const main = async () => {
// Initiate client object
const client = new Client({ const client = new Client({
intents, intents,
}); });
await locale(); // Start database manager
await database(); await database()
await schedules(client); .then(async () => {
await logger.silly("Database process started");
})
.catch(async (err) => {
await logger.error(`${err}`);
});
await commands(client); // Start schedule manager
await events(client); await schedules(client)
.then(async () => {
await logger.silly("Schedules process started");
})
.catch(async (err) => {
await logger.error(`${err}`);
});
// Start command handler
await commands(client)
.then(async () => {
await logger.silly("Commands process started");
})
.catch(async (err) => {
await logger.error(`${err}`);
});
// Start event handler
await events(client)
.then(async () => {
await logger.silly("Events process started");
})
.catch(async (err) => {
await logger.error(`${err}`);
});
// Authorize with Discord's API
await client.login(token); await client.login(token);
} };
main(); main()

View file

@ -55,18 +55,30 @@ export default async (client: Client) => {
const rRole = rMember.roles.cache.get(roleId); const rRole = rMember.roles.cache.get(roleId);
if (!rRole) { if (!rMember || !rRole) {
logger.error(`Role ${roleId} not found for shop role ${roleId}.`);
return;
}
if (!rMember) {
logger.error(`Member ${userId} not found for shop role ${roleId}.`); logger.error(`Member ${userId} not found for shop role ${roleId}.`);
await shopRoleSchema
.deleteOne({
userId,
roleId,
guildId,
})
.then(async () => {
logger.silly(
`Shop role document ${roleId} has been deleted from user ${userId}.`
);
})
.catch(async (error) => {
logger.error(
`Error deleting shop role document ${roleId} from user ${userId}.`,
error
);
});
return; return;
} }
if (new Date() > nextPayment) { if (new Date() > nextPayment) {
logger.verbose( logger.silly(
`Shop role ${roleId} is due for payment. Withdrawing credits from user ${userId}.` `Shop role ${roleId} is due for payment. Withdrawing credits from user ${userId}.`
); );
@ -79,23 +91,6 @@ export default async (client: Client) => {
if (!rMember) { if (!rMember) {
logger.error(`Member ${userId} not found for shop role ${roleId}.`); logger.error(`Member ${userId} not found for shop role ${roleId}.`);
await shopRoleSchema
.deleteOne({
userId,
roleId,
guildId,
})
.then(async () => {
logger.verbose(
`Shop role document ${roleId} has been deleted from user ${userId}.`
);
})
.catch(async (error) => {
logger.error(
`Error deleting shop role document ${roleId} from user ${userId}.`,
error
);
});
return; return;
} }
@ -114,7 +109,7 @@ export default async (client: Client) => {
await role await role
.save() .save()
.then(async () => { .then(async () => {
logger.verbose(`Shop role ${roleId} has been paid for.`); logger.silly(`Shop role ${roleId} has been paid for.`);
}) })
.catch(async (err) => { .catch(async (err) => {
logger.error( logger.error(
@ -123,7 +118,7 @@ export default async (client: Client) => {
); );
}); });
logger.verbose( logger.silly(
`Shop role ${roleId} has been paid for. Keeping role ${roleId} for user ${userId}.` `Shop role ${roleId} has been paid for. Keeping role ${roleId} for user ${userId}.`
); );
}) })

View file

@ -1,205 +0,0 @@
import i18next from "i18next";
import logger from "@logger";
export default async () => {
await i18next
.init({
lng: "en", // if you're using a language detector, do not define the lng option
// debug: true,
fallbackLng: "en",
resources: {
en: {
general: { not_available: "Not Available" },
commands: {
credits: {
general: {
credits_one: "{{count}} credit",
credits_other: "{{count}} credits",
},
addons: {
balance: { embed: { title: "Credits" } },
gift: { embed: { title: "Gift" } },
},
},
reputation: {
addons: {
give: {
version01: {
embed: {
title: ":medal: Reputation",
description:
"You have given reputation within the last day, you can not repute now!",
},
},
version02: {
embed: {
title: ":medal: Reputation",
description:
"You have given {{user}} a {{type}} reputation!",
},
},
version03: {
embed: {
title: ":medal: Reputation",
description: "You can not repute yourself.",
},
},
},
},
},
profile: {
addons: {
view: {
embed: {
title: "Profile",
reputation: "Reputation (Global)",
level: "Level (Guild)",
points: "Points (Guild)",
credits: "Credits (Guild)",
language_code: "Language Code (Global)",
},
},
settings: {
embed: {
title: "Profile",
description: "Following settings is set",
fields: { language: "Language" },
},
},
},
},
},
},
sv: {
general: { not_available: "Otillgänglig" },
commands: {
credits: {
general: {
credits_one: "{{count}} krona",
credits_other: "{{count}} kronor",
},
addons: {
balance: { embed: { title: "Krediter" } },
gift: { embed: { title: "Gåva" } },
},
},
reputation: {
addons: {
give: {
version01: {
embed: {
title: ":medal: Omdöme",
description:
"Du har redan gett omdöme inom den senaste dagen, du kan inte ge ett omdöme just nu!",
},
},
version02: {
embed: {
title: ":medal: Omdöme",
description: "Du har gett {{user}} ett {{type}} omdöme!",
},
},
version03: {
embed: {
title: ":medal: Omdöme",
description: "Du kan inte ge dig själv ett omdöme.",
},
},
},
},
},
profile: {
addons: {
view: {
embed: {
title: "Profil",
reputation: "Omdöme (Globalt)",
level: "Nivå (Server)",
points: "Poäng (Server)",
credits: "Krediter (Server)",
language_code: "Språkkod (Globalt)",
},
},
settings: {
embed: {
title: "Profil",
description: "Följande inställningar är satta",
fields: { language: "Språk" },
},
},
},
},
},
},
de: {
general: { not_available: "Nicht verfügbar" },
commands: {
credits: {
general: {
credits_one: "{{count}} Guthaben",
credits_other: "{{count}} Guthaben",
},
addons: {
balance: { embed: { title: "Guthaben" } },
gift: { embed: { title: "Geschenk" } },
},
},
reputation: {
addons: {
give: {
version01: {
embed: {
title: ":medal: Ruf",
description:
"Du hast dir am letzten Tag einen Ruf verschafft, den du jetzt nicht rühmen kannst!",
},
},
version02: {
embed: {
title: ":medal: Ruf",
description:
"Du hast {{user}} einen {{type}} Ruf gegeben!",
},
},
version03: {
embed: {
title: ":medal: Ruf",
description: "Du kannst dich nicht selbst rühmen.",
},
},
},
},
},
profile: {
addons: {
view: {
embed: {
title: "Profil",
reputation: "Ruf (Weltweit)",
level: "Level (Gilde)",
points: "Punkte (Gilde)",
credits: "Guthaben (Gilde)",
language_code: "Sprachcode (Weltweit)",
},
},
settings: {
embed: {
title: "Profile",
description: "Folgende Einstellungen werden vorgenommen",
fields: { language: "Sprache" },
},
},
},
},
},
},
},
})
.then(async () => {
logger.debug(`i18next initialized`);
})
.catch(async (error) => {
logger.error(`i18next failed to initialize: ${error}`);
});
};

View file

@ -3,24 +3,31 @@ import "winston-daily-rotate-file";
const { combine, timestamp, printf, colorize, align, json } = winston.format; const { combine, timestamp, printf, colorize, align, json } = winston.format;
export default winston.createLogger({ module.exports = {
level: process.env.LOG_LEVEL || "silly", // Logger initialized async-hronously
transports: [ logger: async () => {
new winston.transports.DailyRotateFile({ return winston.createLogger({
filename: "logs/combined-%DATE%.log", level: process.env.LOG_LEVEL || "silly",
datePattern: "YYYY-MM-DD", transports: [
maxFiles: "14d", new winston.transports.DailyRotateFile({
format: combine(timestamp(), json()), filename: "logs/combined-%DATE%.log",
}), datePattern: "YYYY-MM-DD",
new winston.transports.Console({ maxFiles: "14d",
format: combine( format: combine(timestamp(), json()),
colorize({ all: true }),
timestamp({
format: "YYYY-MM-DD HH:MM:ss",
}), }),
align(), new winston.transports.Console({
printf((info) => `[${info.timestamp}] ${info.level}: ${info.message}`) format: combine(
), colorize({ all: true }),
}), timestamp({
], format: "YYYY-MM-DD HH:MM:ss",
}); }),
align(),
printf(
(info) => `[${info.timestamp}] ${info.level}: ${info.message}`
)
),
}),
],
});
},
};

View file

@ -0,0 +1,64 @@
// Dependencies
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
// Modules
import modules from "./modules";
// Handlers
import logger from "@logger";
// Function
export default {
modules,
builder: new SlashCommandBuilder()
.setName("config")
.setDescription("Manage guild configurations.")
.addSubcommand(modules.pterodactyl.builder)
.addSubcommand(modules.credits.builder)
.addSubcommand(modules.points.builder)
.addSubcommand(modules.welcome.builder)
.addSubcommand(modules.audits.builder)
.addSubcommand(modules.shop.builder)
.addSubcommand(modules.embeds.builder),
async execute(interaction: CommandInteraction) {
// Destructure member
const { options } = interaction;
switch (options?.getSubcommand()) {
case "pterodactyl":
logger?.silly(`Subcommand is pterodactyl`);
return modules.pterodactyl.execute(interaction);
case "credits":
logger?.silly(`Subcommand is credits`);
return modules.credits.execute(interaction);
case "points":
logger?.silly(`Subcommand is points`);
return modules.points.execute(interaction);
case "welcome":
logger?.silly(`Subcommand is welcome`);
return modules.welcome.execute(interaction);
case "audits":
logger?.silly(`Subcommand is audits`);
return modules.audits.execute(interaction);
case "shop":
logger?.silly(`Subcommand is shop`);
return modules.shop.execute(interaction);
case "embeds":
logger?.silly(`Subcommand is shop`);
return modules.embeds.execute(interaction);
default:
logger?.silly(`Subcommand is not found`);
}
},
};

View file

@ -1,8 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction } from "discord.js"; import { CommandInteraction, Permissions } from "discord.js";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -14,7 +14,13 @@ import { ChannelType } from "discord-api-types/v10";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("audits") .setName("audits")
.setDescription("Audits") .setDescription("Audits")
@ -25,12 +31,16 @@ export default {
option option
.setName("channel") .setName("channel")
.setDescription("Channel for audit messages.") .setDescription("Channel for audit messages.")
.addChannelType(ChannelType.GuildText as number) .addChannelTypes(ChannelType.GuildText)
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure member if (interaction.guild == null) return;
const { options, guild } = interaction; const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);
const { guild, options } = interaction;
// Get options // Get options
const status = options?.getBoolean("status"); const status = options?.getBoolean("status");
@ -42,7 +52,7 @@ export default {
}); });
if (guildDB === null) { if (guildDB === null) {
return logger?.verbose(`Guild not found in database.`); return logger?.silly(`Guild not found in database.`);
} }
// Modify values // Modify values
@ -52,7 +62,7 @@ export default {
// Save guild // Save guild
await guildDB?.save()?.then(async () => { await guildDB?.save()?.then(async () => {
logger?.verbose(`Guild audits updated.`); logger?.silly(`Guild audits updated.`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -1,8 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction } from "discord.js"; import { CommandInteraction, Permissions } from "discord.js";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
//Handlers //Handlers
import logger from "@logger"; import logger from "@logger";
@ -13,7 +13,13 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("credits") .setName("credits")
.setDescription(`Credits`) .setDescription(`Credits`)
@ -45,9 +51,14 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure member if (interaction.guild == null) return;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure member
const { guild, options } = interaction; const { guild, options } = interaction;
if (guild == null) return;
// Get options // Get options
const status = options?.getBoolean("status"); const status = options?.getBoolean("status");
const rate = options?.getNumber("rate"); const rate = options?.getNumber("rate");
@ -62,7 +73,7 @@ export default {
}); });
if (guildDB === null) { if (guildDB === null) {
return logger?.verbose(`Guild is null`); return logger?.silly(`Guild is null`);
} }
// Modify values // Modify values
@ -80,7 +91,7 @@ export default {
// Save guild // Save guild
await guildDB?.save()?.then(async () => { await guildDB?.save()?.then(async () => {
logger?.verbose(`Guild saved`); logger?.silly(`Guild saved`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -0,0 +1,129 @@
// Dependencies
import { ColorResolvable, CommandInteraction, Permissions } from "discord.js";
//Handlers
import logger from "@logger";
// Models
import guildSchema from "@schemas/guild";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import getEmbedConfig from "@helpers/getEmbedConfig";
// Function
export default {
metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("embeds")
.setDescription(`Embeds`)
.addStringOption((option) =>
option
.setName("success-color")
.setDescription("No provided description")
)
.addStringOption((option) =>
option.setName("wait-color").setDescription("No provided description")
)
.addStringOption((option) =>
option.setName("error-color").setDescription("No provided description")
)
.addStringOption((option) =>
option.setName("footer-icon").setDescription("No provided description")
)
.addStringOption((option) =>
option.setName("footer-text").setDescription("No provided description")
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { guild, options } = interaction;
if (guild == null) return;
const embedConfig = await getEmbedConfig(guild);
if (embedConfig == null) return;
logger.info(embedConfig);
// Get options
const successColor = options?.getString("success-color") as ColorResolvable;
const waitColor = options?.getString("wait-color") as ColorResolvable;
const errorColor = options?.getString("error-color") as ColorResolvable;
const footerIcon = options?.getString("footer-icon");
const footerText = options?.getString("footer-text");
// Get guild object
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
if (guildDB === null) {
return logger?.silly(`Guild is null`);
}
// Modify values
guildDB.embeds.successColor =
successColor !== null ? successColor : guildDB?.embeds?.successColor;
guildDB.embeds.waitColor =
waitColor !== null ? waitColor : guildDB?.embeds?.waitColor;
guildDB.embeds.errorColor =
errorColor !== null ? errorColor : guildDB?.embeds?.errorColor;
guildDB.embeds.footerIcon =
footerIcon !== null ? footerIcon : guildDB?.embeds?.footerIcon;
guildDB.embeds.footerText =
footerText !== null ? footerText : guildDB?.embeds?.footerText;
// Save guild
await guildDB?.save()?.then(async () => {
logger?.silly(`Guild saved`);
return interaction?.editReply({
embeds: [
{
title: ":tools: Settings - Guild [Credits]",
description: `Credits settings updated.`,
color: successColor || embedConfig.successColor,
fields: [
{
name: "🤖 Success Color",
value: `${guildDB?.embeds?.successColor}`,
inline: true,
},
{
name: "📈 Wait Color",
value: `${guildDB?.embeds?.waitColor}`,
inline: true,
},
{
name: "📈 Error Color",
value: `${guildDB?.embeds?.errorColor}`,
inline: true,
},
{
name: "🔨 Footer Icon",
value: `${guildDB?.embeds?.footerIcon}`,
inline: true,
},
{
name: "⏰ Footer Text",
value: `${guildDB?.embeds?.footerText}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon || embedConfig.footerIcon,
text: footerText || embedConfig.footerText,
},
},
],
});
});
},
};

View file

@ -0,0 +1,9 @@
import audits from "@plugins/config/modules/audits";
import credits from "@plugins/config/modules/credits";
import points from "@plugins/config/modules/points";
import pterodactyl from "@plugins/config/modules/pterodactyl";
import shop from "@plugins/config/modules/shop";
import welcome from "@plugins/config/modules/welcome";
import embeds from "@plugins/config/modules/embeds";
export default { audits, credits, points, pterodactyl, shop, welcome, embeds };

View file

@ -1,8 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction } from "discord.js"; import { CommandInteraction, Permissions } from "discord.js";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -13,7 +13,13 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("points") .setName("points")
.setDescription("Points") .setDescription("Points")
@ -35,6 +41,11 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);
// Destructure member // Destructure member
const { options, guild } = interaction; const { options, guild } = interaction;
@ -50,7 +61,7 @@ export default {
}); });
if (guildDB === null) { if (guildDB === null) {
return logger?.verbose(`Guild not found in database.`); return logger?.silly(`Guild not found in database.`);
} }
// Modify values // Modify values
@ -63,7 +74,7 @@ export default {
// Save guild // Save guild
await guildDB?.save()?.then(async () => { await guildDB?.save()?.then(async () => {
logger?.verbose(`Guild points updated.`); logger?.silly(`Guild points updated.`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -1,8 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction } from "discord.js"; import { CommandInteraction, Permissions } from "discord.js";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -14,7 +14,13 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("pterodactyl") .setName("pterodactyl")
.setDescription("Controlpanel.gg") .setDescription("Controlpanel.gg")
@ -32,7 +38,10 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure member if (interaction.guild == null) return;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure member
const { options, guild } = interaction; const { options, guild } = interaction;
// Get options // Get options
@ -47,7 +56,7 @@ export default {
{ new: true, upsert: true } { new: true, upsert: true }
) )
.then(async () => { .then(async () => {
logger?.verbose(`Updated API credentials.`); logger?.silly(`Updated API credentials.`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -1,8 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction } from "discord.js"; import { CommandInteraction, Permissions } from "discord.js";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -10,11 +10,16 @@ import logger from "@logger";
// Models // Models
import guildSchema from "@schemas/guild"; import guildSchema from "@schemas/guild";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("shop") .setName("shop")
.setDescription("Shop") .setDescription("Shop")
@ -30,7 +35,10 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure member if (interaction.guild == null) return;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure member
const { options, guild } = interaction; const { options, guild } = interaction;
// Get options // Get options
@ -43,7 +51,7 @@ export default {
}); });
if (guildDB === null) { if (guildDB === null) {
return logger?.verbose(`Guild not found in database.`); return logger?.silly(`Guild not found in database.`);
} }
// Modify values // Modify values
@ -56,7 +64,7 @@ export default {
// Save guild // Save guild
await guildDB?.save()?.then(async () => { await guildDB?.save()?.then(async () => {
logger?.verbose(`Guild shop updated.`); logger?.silly(`Guild shop updated.`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -1,8 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction } from "discord.js"; import { CommandInteraction, Permissions } from "discord.js";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -14,7 +14,13 @@ import { ChannelType } from "discord-api-types/v10";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("welcome") .setName("welcome")
.setDescription("Welcome") .setDescription("Welcome")
@ -25,14 +31,16 @@ export default {
option option
.setName("join-channel") .setName("join-channel")
.setDescription("Channel for join messages.") .setDescription("Channel for join messages.")
.addChannelType(ChannelType.GuildText as number) .addChannelTypes(ChannelType.GuildText)
) )
.addChannelOption((option) => .addChannelOption((option) =>
option option
.setName("leave-channel") .setName("leave-channel")
.setDescription("Channel for leave messages.") .setDescription("Channel for leave messages.")
.addChannelType(ChannelType.GuildText as number) .addChannelTypes(ChannelType.GuildText)
) )
.addStringOption((option) => .addStringOption((option) =>
option option
.setName("leave-message") .setName("leave-message")
@ -45,7 +53,10 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure member if (interaction.guild == null) return;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
); // Destructure member
const { options, guild } = interaction; const { options, guild } = interaction;
// Get options // Get options
@ -61,7 +72,7 @@ export default {
}); });
if (guildDB === null) { if (guildDB === null) {
return logger?.verbose(`Guild not found in database.`); return logger?.silly(`Guild not found in database.`);
} }
// Modify values // Modify values
@ -83,7 +94,7 @@ export default {
// Save guild // Save guild
await guildDB?.save()?.then(async () => { await guildDB?.save()?.then(async () => {
logger?.verbose(`Guild welcome updated.`); logger?.silly(`Guild welcome updated.`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -1,25 +1,26 @@
// Dependencies
import { CommandInteraction } from "discord.js"; import { CommandInteraction } from "discord.js";
import { SlashCommandBuilder } from "@discordjs/builders"; import { SlashCommandBuilder } from "@discordjs/builders";
import logger from "@logger"; import logger from "@logger";
import modules from "@root/plugins/counters/modules"; import modules from "@plugins/counters/modules";
export default { export default {
metadata: { author: "Zyner" }, modules,
data: new SlashCommandBuilder()
builder: new SlashCommandBuilder()
.setName("counters") .setName("counters")
.setDescription("View guild counters") .setDescription("View guild counters")
.addSubcommand(modules.view.data),
.addSubcommand(modules.view.builder),
async execute(interaction: CommandInteraction) { async execute(interaction: CommandInteraction) {
const { options } = interaction; const { options } = interaction;
if (options?.getSubcommand() === "view") { if (options.getSubcommand() === "view") {
logger?.verbose(`Executing view subcommand`); logger.silly(`Executing view subcommand`);
return modules.view.execute(interaction); return modules.view.execute(interaction);
} }
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`); logger.silly(`Unknown subcommand ${options.getSubcommand()}`);
}, },
}; };

View file

@ -1,3 +1,3 @@
import view from "./view"; import view from "@plugins/counters/modules/view";
export default { view }; export default { view };

View file

@ -1,20 +1,15 @@
// Dependencies import getEmbedConfig from "@helpers/getEmbedConfig";
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10"; import { ChannelType } from "discord-api-types/v10";
import counterSchema from "@schemas/counter"; import counterSchema from "@schemas/counter";
// Configuration
import {
errorColor,
successColor,
footerText,
footerIcon,
} from "@config/embed";
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: { guildOnly: true, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("view") .setName("view")
.setDescription(`View a guild counter`) .setDescription(`View a guild counter`)
@ -25,14 +20,26 @@ export default {
`The channel that contains the counter you want to view` `The channel that contains the counter you want to view`
) )
.setRequired(true) .setRequired(true)
.addChannelType(ChannelType.GuildText as number) .addChannelTypes(ChannelType.GuildText)
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, guild } = interaction; const { options, guild } = interaction;
const discordChannel = options?.getChannel("channel"); const discordChannel = options?.getChannel("channel");
const embed = new MessageEmbed()
.setTitle("[:1234:] Counters (View)")
.setTimestamp(new Date())
.setFooter({
text: footerText,
iconURL: footerIcon,
});
const counter = await counterSchema?.findOne({ const counter = await counterSchema?.findOne({
guildId: guild?.id, guildId: guild?.id,
channelId: discordChannel?.id, channelId: discordChannel?.id,
@ -41,32 +48,20 @@ export default {
if (counter === null) { if (counter === null) {
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:1234:] Counters (View)")
.setDescription(`No counter found for channel ${discordChannel}!`) .setDescription(`No counter found for channel ${discordChannel}!`)
.setTimestamp(new Date()) .setColor(errorColor),
.setColor(errorColor)
.setFooter({
text: footerText,
iconURL: footerIcon,
}),
], ],
}); });
} }
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:1234:] Counters (View)")
.setDescription( .setDescription(
`Viewing counter for channel ${discordChannel} with count ${counter.counter}.` `Viewing counter for channel ${discordChannel}: ${counter.counter}!`
) )
.setTimestamp(new Date()) .setColor(successColor),
.setColor(successColor)
.setFooter({
text: footerText,
iconURL: footerIcon,
}),
], ],
}); });
}, },

View file

@ -1,44 +1,39 @@
// Dependencies
import { SlashCommandBuilder } from "@discordjs/builders"; import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js"; import { CommandInteraction } from "discord.js";
import logger from "@logger"; import logger from "@logger";
// Modules import modules from "@plugins/credits/modules";
import modules from "@root/plugins/credits/modules";
export default { export default {
metadata: { author: "Zyner" }, modules,
data: new SlashCommandBuilder()
builder: new SlashCommandBuilder()
.setName("credits") .setName("credits")
.setDescription("Manage your credits.") .setDescription("Manage your credits.")
.addSubcommand(modules.balance.data)
.addSubcommand(modules.gift.data) .addSubcommand(modules.balance.builder)
.addSubcommand(modules.top.data) .addSubcommand(modules.gift.builder)
.addSubcommand(modules.work.data), .addSubcommand(modules.top.builder)
.addSubcommand(modules.work.builder),
async execute(interaction: CommandInteraction) { async execute(interaction: CommandInteraction) {
const { options } = interaction; const { options } = interaction;
if (options?.getSubcommand() === "balance") { switch (options.getSubcommand()) {
logger?.verbose(`Executing balance subcommand`); case "balance":
return modules.balance.execute(interaction); await modules.balance.execute(interaction);
break;
case "gift":
await modules.gift.execute(interaction);
break;
case "top":
await modules.top.execute(interaction);
break;
case "work":
await modules.work.execute(interaction);
break;
default:
logger.silly(`Unknown subcommand ${options.getSubcommand()}`);
} }
if (options?.getSubcommand() === "gift") {
logger?.verbose(`Executing gift subcommand`);
return modules.gift.execute(interaction);
}
if (options?.getSubcommand() === "top") {
logger?.verbose(`Executing top command`);
return modules.top.execute(interaction);
}
if (options?.getSubcommand() === "work") {
logger?.verbose(`Executing work command`);
return modules.work.execute(interaction);
}
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`);
}, },
}; };

View file

@ -1,52 +1,42 @@
// Dependencies import getEmbedConfig from "@helpers/getEmbedConfig";
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import logger from "@logger"; import logger from "@logger";
// Configurations
import {
errorColor,
successColor,
footerText,
footerIcon,
} from "@config/embed";
// Helpers
import pluralize from "@helpers/pluralize";
import fetchUser from "@helpers/fetchUser"; import fetchUser from "@helpers/fetchUser";
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: { guildOnly: true, ephemeral: true },
return ( builder: (command: SlashCommandSubcommandBuilder) => {
command return command
.setName("balance") .setName("balance")
.setDescription(`View a user's balance`) .setDescription(`View a user's balance`)
.addUserOption((option) =>
// User option
.addUserOption((option) => .setName("user")
option .setDescription(`The user whose balance you want to view`)
.setName("user") );
.setDescription(`The user whose balance you want to view`)
)
);
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, user, guild } = interaction; const { options, user, guild } = interaction;
const discordUser = options?.getUser("user"); const discordUser = options.getUser("user");
const embed = new MessageEmbed()
.setTitle("[:dollar:] Balance")
.setTimestamp(new Date())
.setFooter({ text: footerText, iconURL: footerIcon });
if (guild === null) { if (guild === null) {
logger?.verbose(`Guild is null`); logger.silly(`Guild is null`);
return interaction?.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed.setDescription("Guild is not found").setColor(errorColor),
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(`You can only use this command in a guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
@ -54,50 +44,38 @@ export default {
const userObj = await fetchUser(discordUser || user, guild); const userObj = await fetchUser(discordUser || user, guild);
if (userObj === null) { if (userObj === null) {
logger?.verbose(`User not found`); logger.silly(`User not found`);
return interaction?.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Balance)") .setDescription(
.setDescription(`Could not find user ${discordUser || user}`) "User is not found. Please try again with a valid user."
.setTimestamp(new Date()) )
.setColor(errorColor) .setColor(errorColor),
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
if (userObj.credits === null) { if (userObj.credits === null) {
logger?.verbose(`User has no credits`); logger.silly(`User has no credits`);
return interaction?.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed.setDescription("Credits not found").setColor(errorColor),
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(`${discordUser || user} has no credits!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
logger?.verbose(`Found user ${discordUser || user}`); logger.silly(`Found user ${discordUser || user}`);
return interaction?.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Balance)")
.setDescription( .setDescription(
`${discordUser || user} has ${pluralize( `${discordUser || user} currently has ${userObj.credits} credits.`
userObj.credits,
`credit`
)}!`
) )
.setTimestamp(new Date()) .setColor(successColor),
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
}, },

View file

@ -2,12 +2,7 @@
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed } from "discord.js";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
errorColor,
successColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -21,7 +16,9 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("gift") .setName("gift")
.setDescription(`Gift a user credits`) .setDescription(`Gift a user credits`)
@ -42,38 +39,38 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, user, guild, client } = interaction; const { options, user, guild, client } = interaction;
const optionUser = options?.getUser("user"); const optionUser = options.getUser("user");
const optionAmount = options?.getInteger("amount"); const optionAmount = options.getInteger("amount");
const optionReason = options?.getString("reason"); const optionReason = options.getString("reason");
const embed = new MessageEmbed()
.setTitle("[:dollar:] Gift")
.setTimestamp(new Date())
.setFooter({ text: footerText, iconURL: footerIcon });
if (guild === null) { if (guild === null) {
logger?.verbose(`Guild is null`); logger.silly(`Guild is null`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed.setDescription("Guild is not found").setColor(errorColor),
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(`We can not find your guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
if (optionUser === null) { if (optionUser === null) {
logger?.verbose(`User not found`); logger.silly(`User not found`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)") .setDescription(`User is not found in this guild`)
.setDescription(`We can not find your requested user!`) .setColor(errorColor),
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
@ -85,170 +82,147 @@ export default {
const toUserDB = await fetchUser(optionUser, guild); const toUserDB = await fetchUser(optionUser, guild);
if (fromUserDB === null) { if (fromUserDB === null) {
logger?.verbose(`User not found`); logger.silly(`User not found`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)")
.setDescription( .setDescription(
`We can not find your requested from user in our database!` "You do not have any credits. Please write something in the chat to get some."
) )
.setTimestamp(new Date()) .setColor(errorColor),
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
if (toUserDB === null) { if (toUserDB === null) {
logger?.verbose(`User not found`); logger.silly(`User not found`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)")
.setDescription( .setDescription(
`We can not find your requested to user in our database!` "The user you want to gift credits to does not have any credits. Please wait until that user has typed something in the chat to get some."
) )
.setTimestamp(new Date()) .setColor(errorColor),
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
// If receiver is same as sender // If receiver is same as sender
if (optionUser?.id === user?.id) { if (optionUser.id === user.id) {
logger?.verbose(`User is same as sender`); logger.silly(`User is same as sender`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)") .setDescription(
.setDescription(`You can not pay yourself!`) "You can't gift credits to yourself. Please choose a different user."
.setTimestamp(new Date()) )
.setColor(errorColor) .setColor(errorColor),
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
// If amount is null // If amount is null
if (optionAmount === null) { if (optionAmount === null) {
logger?.verbose(`Amount is null`); logger.silly(`Amount is null`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)") .setDescription(
.setDescription(`We could not read your requested amount!`) "Please specify the amount of credits you want to gift."
.setTimestamp(new Date()) )
.setColor(errorColor) .setColor(errorColor),
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
// If amount is zero or below // If amount is zero or below
if (optionAmount <= 0) { if (optionAmount <= 0) {
logger?.verbose(`Amount is zero or below`); logger.silly(`Amount is zero or below`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)") .setDescription(
.setDescription(`You can't gift zero or below!`) "Please specify a valid amount of credits you want to gift."
.setTimestamp(new Date()) )
.setColor(errorColor) .setColor(errorColor),
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
// If user has below gifting amount // If user has below gifting amount
if (fromUserDB?.credits < optionAmount) { if (fromUserDB.credits < optionAmount) {
logger?.verbose(`User has below gifting amount`); logger.silly(`User has below gifting amount`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)")
.setDescription( .setDescription(
`You have insufficient credits. Your balance is ${fromUserDB?.credits}!` "You don't have enough credits to gift that amount. Please try again with a lower amount."
) )
.setTimestamp(new Date()) .setColor(errorColor),
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
// If toUserDB has no credits // If toUserDB has no credits
if (toUserDB === null) { if (toUserDB === null) {
logger?.verbose(`User has no credits`); logger.silly(`User has no credits`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)")
.setDescription( .setDescription(
`We can not find your requested to user in our database!` "The user you want to gift credits to does not have any credits. Please wait until that user has typed something in the chat to get some."
) )
.setTimestamp(new Date()) .setColor(errorColor),
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
// Withdraw amount from fromUserDB
fromUserDB.credits -= optionAmount;
// Deposit amount to toUserDB
toUserDB.credits += optionAmount;
// Save users // Save users
await saveUser(fromUserDB, toUserDB)?.then(async () => { await saveUser(fromUserDB, toUserDB).then(async () => {
// Get DM user object // Get DM user object
const dmUser = client?.users?.cache?.get(optionUser?.id); const dmUser = client.users.cache.get(optionUser.id);
if (dmUser == null) return;
// Send DM to user // Send DM to user
await dmUser await dmUser
?.send({ .send({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)")
.setDescription( .setDescription(
`You have received ${optionAmount} credits from ${ `${
user?.tag user.tag
} with reason ${ } has gifted you ${optionAmount} credits with reason: ${
optionReason ? ` with reason: ${optionReason}` : "" optionReason || "unspecified"
}!` }`
) )
.setTimestamp(new Date()) .setColor(successColor),
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}) })
.catch(async (error) => .catch(async (error) =>
logger?.error(`[Gift] Error sending DM to user: ${error}`) logger.error(`[Gift] Error sending DM to user: ${error}`)
); );
logger?.verbose( logger.silly(
`[Gift] Successfully gifted ${optionAmount} credits to ${optionUser?.tag}` `[Gift] Successfully gifted ${optionAmount} credits to ${optionUser.tag}`
); );
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Gift)")
.setDescription( .setDescription(
`Successfully gifted ${optionAmount} credits to ${optionUser?.tag}!` `Successfully gifted ${optionAmount} credits to ${
optionUser.tag
} with reason: ${optionReason || "unspecified"}`
) )
.setTimestamp(new Date()) .setColor(successColor),
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
}); });

View file

@ -1,6 +1,6 @@
import balance from "./balance"; import balance from "@plugins/credits/modules/balance";
import gift from "./gift"; import gift from "@plugins/credits/modules/gift";
import top from "./top"; import top from "@plugins/credits/modules/top";
import work from "./work"; import work from "@plugins/credits/modules/work";
export default { balance, gift, top, work }; export default { balance, gift, top, work };

View file

@ -1,48 +1,66 @@
// Dependencies import getEmbedConfig from "@helpers/getEmbedConfig";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import logger from "@logger";
import userSchema from "@schemas/user"; import userSchema, { IUser } from "@schemas/user";
// Configurations
import { successColor, footerText, footerIcon } from "@config/embed";
// Helpers
import pluralize from "@helpers/pluralize";
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: { guildOnly: true, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("top").setDescription(`View the top users`); return command.setName("top").setDescription(`View the top users`);
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Get all users in the guild if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { guild } = interaction;
const usersDB = await userSchema.find({ guildId: interaction?.guild?.id }); const embed = new MessageEmbed()
.setTitle("[:dollar:] Top")
.setTimestamp(new Date())
.setFooter({ text: footerText, iconURL: footerIcon });
if (guild === null) {
logger.silly(`Guild is null`);
return interaction.editReply({
embeds: [
embed
.setDescription(
"Guild is not found. Please try again with a valid guild."
)
.setColor(errorColor),
],
});
}
const usersDB = await userSchema.find({ guildId: guild.id });
const topTen = usersDB const topTen = usersDB
// Sort them after credits amount (ascending) // Sort them after credits amount (ascending)
.sort((a, b) => (a?.credits > b?.credits ? -1 : 1)) .sort((a, b) => (a.credits > b.credits ? -1 : 1))
// Return the top 10 // Return the top 10
.slice(0, 10); .slice(0, 10);
// Create entry object // Create entry object
const entry = (x: any, index: number) => const entry = (x: IUser, index: number) =>
`${index + 1}. <@${x?.userId}> - ${pluralize(x?.credits, "credit")}`; `${index + 1}. <@${x.userId}> - ${x.credits} credits`;
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Top)")
.setDescription( .setDescription(
`Top 10 users with the most credits. `Below are the top 10 users in this guild.
${topTen.map(entry).join("\n")}` ${topTen.map(entry).join("\n")}
`
) )
.setTimestamp(new Date()) .setColor(successColor),
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
}, },

View file

@ -4,7 +4,7 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import Chance from "chance"; import Chance from "chance";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -17,13 +17,25 @@ import fetchUser from "@helpers/fetchUser";
import fetchGuild from "@helpers/fetchGuild"; import fetchGuild from "@helpers/fetchGuild";
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("work").setDescription(`Work to earn credits`); return command.setName("work").setDescription(`Work to earn credits`);
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure member if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure member
const { guild, user } = interaction; const { guild, user } = interaction;
const embed = new MessageEmbed()
.setTitle("[:dollar:] Work")
.setTimestamp(new Date())
.setFooter({
text: footerText,
iconURL: footerIcon,
});
// Chance module // Chance module
const chance = new Chance(); const chance = new Chance();
@ -35,25 +47,22 @@ export default {
}); });
if (guild === null) { if (guild === null) {
return logger?.verbose(`Guild is null`); return logger?.silly(`Guild is null`);
} }
const guildDB = await fetchGuild(guild); const guildDB = await fetchGuild(guild);
// If user is not on timeout // If user is not on timeout
if (isTimeout) { if (isTimeout) {
logger?.verbose(`User ${user?.id} is on timeout`); logger?.silly(`User ${user?.id} is on timeout`);
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Work)")
.setDescription( .setDescription(
`You can not work while on timeout, please wait ${guildDB?.credits.workTimeout} seconds.` `You are on timeout, please wait ${guildDB?.credits.workTimeout} seconds.`
) )
.setTimestamp(new Date()) .setColor(errorColor),
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
@ -66,24 +75,21 @@ export default {
const userDB = await fetchUser(user, guild); const userDB = await fetchUser(user, guild);
if (userDB === null) { if (userDB === null) {
return logger?.verbose(`User not found`); return logger?.silly(`User not found`);
} }
userDB.credits += creditsEarned; userDB.credits += creditsEarned;
await userDB?.save()?.then(async () => { await userDB?.save()?.then(async () => {
logger?.verbose( logger?.silly(
`User ${userDB?.userId} worked and earned ${creditsEarned} credits` `User ${userDB?.userId} worked and earned ${creditsEarned} credits`
); );
return interaction.editReply({ return interaction.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:dollar:] Credits (Work)") .setDescription(`You worked and earned ${creditsEarned} credits.`)
.setDescription(`You worked and earned ${creditsEarned} credits`) .setColor(successColor),
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
}); });
@ -96,7 +102,7 @@ export default {
}); });
setTimeout(async () => { setTimeout(async () => {
logger?.verbose(`Removing timeout for user ${user?.id}`); logger?.silly(`Removing timeout for user ${user?.id}`);
// When timeout is out, remove it from the database // When timeout is out, remove it from the database
await timeoutSchema?.deleteOne({ await timeoutSchema?.deleteOne({

25
src/plugins/fun/index.ts Normal file
View file

@ -0,0 +1,25 @@
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
import logger from "@logger";
import modules from "@plugins/fun/modules";
export default {
modules,
builder: new SlashCommandBuilder()
.setName("fun")
.setDescription("Fun commands.")
.addSubcommand(modules.meme.builder),
async execute(interaction: CommandInteraction) {
const { options } = interaction;
if (options.getSubcommand() === "meme") {
await modules.meme.execute(interaction);
} else {
logger.silly(`Unknown subcommand ${options.getSubcommand()}`);
}
},
};

View file

@ -0,0 +1,5 @@
import meme from "@plugins/fun/modules/meme";
export default {
meme,
};

View file

@ -0,0 +1,41 @@
import getEmbedConfig from "@helpers/getEmbedConfig";
import axios from "axios";
import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import logger from "@logger";
export default {
metadata: { guildOnly: false, ephemeral: false },
builder: (command: SlashCommandSubcommandBuilder) => {
return command.setName("meme").setDescription("Get a meme from r/memes)");
},
execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { successColor, footerText, footerIcon } = await getEmbedConfig(
interaction.guild
);
await axios
.get("https://www.reddit.com/r/memes/random/.json")
.then(async (res) => {
const response = res.data[0].data.children;
const content = response[0].data;
const embed = new MessageEmbed()
.setTitle(content.title)
.setTimestamp(new Date())
.setImage(content.url)
.setFooter({
text: `👍 ${content.ups}︱👎 ${content.downs}\n${footerText}`,
iconURL: footerIcon,
})
.setColor(successColor);
return interaction.editReply({ embeds: [embed] });
})
.catch((error) => {
logger.error(`${error}`);
});
},
};

View file

@ -1,37 +0,0 @@
// Dependencies
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
import logger from "@logger";
// Modules
import moduleCreate from "./modules/create";
import moduleDelete from "./modules/delete";
// Function
export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("counters")
.setDescription("Manage guild counters.")
.addSubcommand(moduleCreate.data)
.addSubcommand(moduleDelete.data);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
if (options?.getSubcommand() === "create") {
logger?.verbose(`Executing create subcommand`);
return moduleCreate.execute(interaction);
}
if (options?.getSubcommand() === "delete") {
logger?.verbose(`Executing delete subcommand`);
return moduleDelete.execute(interaction);
}
logger?.verbose(`Unknown subcommand ${options?.getSubcommand()}`);
},
};

View file

@ -1,53 +0,0 @@
// Dependencies
import { CommandInteraction } from "discord.js";
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import logger from "@logger";
// Modules
import moduleGive from "./modules/give";
import moduleSet from "./modules/set";
import moduleTake from "./modules/take";
import moduleTransfer from "./modules/transfer";
// Function
export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("credits")
.setDescription("Manage the credits of a user.")
.addSubcommand(moduleGive.data)
.addSubcommand(moduleSet.data)
.addSubcommand(moduleTake.data)
.addSubcommand(moduleTransfer.data);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
if (options?.getSubcommand() === "give") {
logger?.verbose(`Executing give subcommand`);
return moduleGive.execute(interaction);
}
if (options?.getSubcommand() === "set") {
logger?.verbose(`Executing set subcommand`);
return moduleSet.execute(interaction);
}
if (options?.getSubcommand() === "take") {
logger?.verbose(`Executing take subcommand`);
return moduleTake.execute(interaction);
}
if (options?.getSubcommand() === "transfer") {
logger?.verbose(`Executing transfer subcommand`);
return moduleTransfer.execute(interaction);
}
logger?.verbose(`No subcommand found`);
},
};

View file

@ -1,54 +1,37 @@
//Dependencies //Dependencies
import { SlashCommandBuilder } from "@discordjs/builders"; import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction, Permissions, MessageEmbed } from "discord.js"; import { CommandInteraction } from "discord.js";
// Configurations
import { errorColor, footerText, footerIcon } from "@config/embed";
// Groups // Groups
import credits from "./groups/credits"; import modules from "@plugins/manage/modules";
import counters from "./groups/counters";
import logger from "@logger"; import logger from "@logger";
// Function // Function
export default { export default {
metadata: { author: "Zyner" }, modules,
data: new SlashCommandBuilder()
builder: new SlashCommandBuilder()
.setName("manage") .setName("manage")
.setDescription("Manage the bot.") .setDescription("Manage the bot.")
.addSubcommandGroup(counters.data) .addSubcommandGroup(modules.counters.builder)
.addSubcommandGroup(credits.data), .addSubcommandGroup(modules.credits.builder),
async execute(interaction: CommandInteraction) { async execute(interaction: CommandInteraction) {
// Destructure // Destructure
const { memberPermissions, options } = interaction; const { options } = interaction;
// Check permission
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage")
.setDescription(`You do not have the permission to manage the bot.`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (options?.getSubcommandGroup() === "credits") { if (options?.getSubcommandGroup() === "credits") {
logger?.verbose(`Subcommand group is credits`); logger?.silly(`Subcommand group is credits`);
return credits.execute(interaction); return modules.credits.execute(interaction);
} }
if (options?.getSubcommandGroup() === "counters") { if (options?.getSubcommandGroup() === "counters") {
logger?.verbose(`Subcommand group is counters`); logger?.silly(`Subcommand group is counters`);
return counters.execute(interaction); return modules.counters.execute(interaction);
} }
logger?.verbose(`Subcommand group is not credits or counters`); logger?.silly(`Subcommand group is not credits or counters`);
}, },
}; };

View file

@ -0,0 +1,39 @@
// Dependencies
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
import logger from "@logger";
// Modules
import modules from "./modules";
// Function
export default {
modules,
builder: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("counters")
.setDescription("Manage guild counters.")
.addSubcommand(modules.add.builder)
.addSubcommand(modules.remove.builder);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
if (options?.getSubcommand() === "add") {
logger?.silly(`Executing create subcommand`);
return modules.add.execute(interaction);
}
if (options?.getSubcommand() === "remove") {
logger?.silly(`Executing delete subcommand`);
return modules.remove.execute(interaction);
}
logger?.silly(`Unknown subcommand ${options?.getSubcommand()}`);
},
};

View file

@ -1,17 +1,11 @@
// Dependencies // Dependencies
import { MessageEmbed, CommandInteraction } from "discord.js"; import { MessageEmbed, CommandInteraction, Permissions } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10"; import { ChannelType } from "discord-api-types/v10";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "@logger"; import logger from "@logger";
// Models // Models
@ -19,16 +13,22 @@ import counterSchema from "@schemas/counter";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("create") .setName("add")
.setDescription("Add a counter to your guild.") .setDescription("Add a counter to your guild.")
.addChannelOption((option) => .addChannelOption((option) =>
option option
.setName("channel") .setName("channel")
.setDescription("The channel to send the counter to.") .setDescription("The channel to send the counter to.")
.setRequired(true) .setRequired(true)
.addChannelType(ChannelType.GuildText as number) .addChannelTypes(ChannelType.GuildText)
) )
.addStringOption((option) => .addStringOption((option) =>
option option
@ -43,12 +43,20 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, guild } = interaction; const { options, guild } = interaction;
const discordChannel = options?.getChannel("channel"); const discordChannel = options?.getChannel("channel");
const countingWord = options?.getString("word"); const countingWord = options?.getString("word");
const startValue = options?.getNumber("start"); const startValue = options?.getNumber("start");
const embed = new MessageEmbed()
.setTitle("[:toolbox:] Counters - Add")
.setTimestamp(new Date())
.setFooter({ text: footerText, iconURL: footerIcon });
const counter = await counterSchema?.findOne({ const counter = await counterSchema?.findOne({
guildId: guild?.id, guildId: guild?.id,
channelId: discordChannel?.id, channelId: discordChannel?.id,
@ -57,12 +65,9 @@ export default {
if (counter) { if (counter) {
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:toolbox:] Manage - Counters (Create)")
.setDescription(`A counter already exists for this channel.`) .setDescription(`A counter already exists for this channel.`)
.setTimestamp(new Date()) .setColor(errorColor),
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
@ -75,16 +80,15 @@ export default {
counter: startValue || 0, counter: startValue || 0,
}) })
.then(async () => { .then(async () => {
logger?.verbose(`Created counter`); logger?.silly(`Created counter`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:toolbox:] Manage - Counters (Create)") .setDescription(
.setDescription(`Created counter for ${discordChannel}`) `Successfully created counter for ${discordChannel?.name}.`
.setTimestamp(new Date()) )
.setColor(successColor) .setColor(successColor),
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
}); });

View file

@ -0,0 +1,4 @@
import add from "@plugins/manage/modules/counters/modules/add";
import remove from "@plugins/manage/modules/counters/modules/remove";
export default { add, remove };

View file

@ -1,13 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -19,39 +14,52 @@ import { ChannelType } from "discord-api-types/v10";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("delete") .setName("remove")
.setDescription(`Delete a counter from your guild.`) .setDescription(`Delete a counter from your guild.`)
.addChannelOption((option) => .addChannelOption((option) =>
option option
.setName("channel") .setName("channel")
.setDescription("The channel to delete the counter from.") .setDescription("The channel to delete the counter from.")
.setRequired(true) .setRequired(true)
.addChannelType(ChannelType.GuildText as number) .addChannelTypes(ChannelType.GuildText)
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, guild } = interaction; const { options, guild } = interaction;
const discordChannel = options?.getChannel("channel"); const discordChannel = options?.getChannel("channel");
const embed = new MessageEmbed()
.setTitle("[:toolbox:] Counters - Remove")
.setTimestamp(new Date())
.setFooter({ text: footerText, iconURL: footerIcon });
const counter = await counterSchema?.findOne({ const counter = await counterSchema?.findOne({
guildId: guild?.id, guildId: guild?.id,
channelId: discordChannel?.id, channelId: discordChannel?.id,
}); });
if (counter === null) { if (counter === null) {
logger?.verbose(`Counter is null`); logger?.silly(`Counter is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:toolbox:] Manage - Counters (Delete)") .setDescription(
.setDescription(`The counter for this channel does not exist.`) ":x: There is no counter in this channel. Please add a counter first."
.setTimestamp(new Date()) )
.setColor(errorColor) .setColor(errorColor),
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
} }
@ -62,16 +70,15 @@ export default {
channelId: discordChannel?.id, channelId: discordChannel?.id,
}) })
?.then(async () => { ?.then(async () => {
logger?.verbose(`Counter deleted`); logger?.silly(`Counter deleted`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
new MessageEmbed() embed
.setTitle("[:toolbox:] Manage - Counters (Delete)") .setDescription(
.setDescription(`The counter for this channel has been deleted.`) ":white_check_mark: Counter deleted successfully."
.setTimestamp(new Date()) )
.setColor(successColor) .setColor(successColor),
.setFooter({ text: footerText, iconURL: footerIcon }),
], ],
}); });
}) })

View file

@ -0,0 +1,43 @@
import { CommandInteraction } from "discord.js";
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import logger from "@logger";
import modules from "./modules";
export default {
modules,
builder: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("credits")
.setDescription("Manage the credits of a user.")
.addSubcommand(modules.give.builder)
.addSubcommand(modules.set.builder)
.addSubcommand(modules.take.builder)
.addSubcommand(modules.transfer.builder);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
switch (options.getSubcommand()) {
case "give":
logger.silly(`Executing give subcommand`);
return modules.give.execute(interaction);
case "set":
logger.silly(`Executing set subcommand`);
return modules.set.execute(interaction);
case "take":
logger.silly(`Executing take subcommand`);
return modules.take.execute(interaction);
case "transfer":
logger.silly(`Executing transfer subcommand`);
return modules.transfer.execute(interaction);
default:
logger.silly(`Unknown subcommand ${options.getSubcommand()}`);
}
},
};

View file

@ -1,14 +1,9 @@
// Dependencies // Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -21,7 +16,13 @@ import fetchUser from "@helpers/fetchUser";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("give") .setName("give")
.setDescription("Give credits to a user.") .setDescription("Give credits to a user.")
@ -39,7 +40,9 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure
const { guild, options } = interaction; const { guild, options } = interaction;
const discordReceiver = options?.getUser("user"); const discordReceiver = options?.getUser("user");
@ -47,7 +50,7 @@ export default {
// If amount option is null // If amount option is null
if (creditAmount === null) { if (creditAmount === null) {
logger?.verbose(`Amount is null`); logger?.silly(`Amount is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -63,7 +66,7 @@ export default {
// If amount is zero or below // If amount is zero or below
if (creditAmount <= 0) { if (creditAmount <= 0) {
logger?.verbose(`Amount is zero or below`); logger?.silly(`Amount is zero or below`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -78,7 +81,7 @@ export default {
} }
if (discordReceiver === null) { if (discordReceiver === null) {
logger?.verbose(`Discord receiver is null`); logger?.silly(`Discord receiver is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -92,7 +95,7 @@ export default {
}); });
} }
if (guild === null) { if (guild === null) {
logger?.verbose(`Guild is null`); logger?.silly(`Guild is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -109,7 +112,7 @@ export default {
const toUser = await fetchUser(discordReceiver, guild); const toUser = await fetchUser(discordReceiver, guild);
if (toUser === null) { if (toUser === null) {
logger?.verbose(`To user is null`); logger?.silly(`To user is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -141,7 +144,7 @@ export default {
// Save toUser // Save toUser
await toUser?.save()?.then(async () => { await toUser?.save()?.then(async () => {
logger?.verbose(`Saved toUser`); logger?.silly(`Saved toUser`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -0,0 +1,6 @@
import give from "@plugins/manage/modules/credits/modules/give";
import set from "@plugins/manage/modules/credits/modules/set";
import take from "@plugins/manage/modules/credits/modules/take";
import transfer from "@plugins/manage/modules/credits/modules/transfer";
export default { give, set, take, transfer };

View file

@ -1,13 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -20,7 +15,13 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("set") .setName("set")
.setDescription("Set the amount of credits a user has.") .setDescription("Set the amount of credits a user has.")
@ -38,6 +39,9 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild);
const { options, guild } = interaction; const { options, guild } = interaction;
const discordUser = options.getUser("user"); const discordUser = options.getUser("user");
@ -45,7 +49,7 @@ export default {
// If amount is null // If amount is null
if (creditAmount === null) { if (creditAmount === null) {
logger?.verbose(`Amount is null`); logger?.silly(`Amount is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -60,7 +64,7 @@ export default {
} }
if (discordUser === null) { if (discordUser === null) {
logger?.verbose(`User is null`); logger?.silly(`User is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -74,7 +78,7 @@ export default {
}); });
} }
if (guild === null) { if (guild === null) {
logger?.verbose(`Guild is null`); logger?.silly(`Guild is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -93,7 +97,7 @@ export default {
// If toUser does not exist // If toUser does not exist
if (toUser === null) { if (toUser === null) {
logger?.verbose(`User does not exist`); logger?.silly(`User does not exist`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -109,7 +113,7 @@ export default {
// If toUser.credits does not exist // If toUser.credits does not exist
if (toUser?.credits === null) { if (toUser?.credits === null) {
logger?.verbose(`User does not have any credits`); logger?.silly(`User does not have any credits`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -128,7 +132,7 @@ export default {
// Save toUser // Save toUser
await toUser?.save()?.then(async () => { await toUser?.save()?.then(async () => {
logger?.verbose(`Saved user`); logger?.silly(`Saved user`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -1,13 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -21,7 +16,13 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("take") .setName("take")
.setDescription("Take credits from a user.") .setDescription("Take credits from a user.")
@ -39,7 +40,9 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure
const { guild, options } = interaction; const { guild, options } = interaction;
// User option // User option
@ -50,7 +53,7 @@ export default {
// If amount is null // If amount is null
if (optionAmount === null) { if (optionAmount === null) {
logger?.verbose(`Amount is null`); logger?.silly(`Amount is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -66,7 +69,7 @@ export default {
// If amount is zero or below // If amount is zero or below
if (optionAmount <= 0) { if (optionAmount <= 0) {
logger?.verbose(`Amount is zero or below`); logger?.silly(`Amount is zero or below`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -81,7 +84,7 @@ export default {
} }
if (optionUser === null) { if (optionUser === null) {
logger?.verbose(`Discord receiver is null`); logger?.silly(`Discord receiver is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -95,7 +98,7 @@ export default {
}); });
} }
if (guild === null) { if (guild === null) {
logger?.verbose(`Guild is null`); logger?.silly(`Guild is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -114,7 +117,7 @@ export default {
// If toUser does not exist // If toUser does not exist
if (toUser === null) { if (toUser === null) {
logger?.verbose(`ToUser is null`); logger?.silly(`ToUser is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -130,7 +133,7 @@ export default {
// If toUser.credits does not exist // If toUser.credits does not exist
if (toUser?.credits === null) { if (toUser?.credits === null) {
logger?.verbose(`ToUser.credits is null`); logger?.silly(`ToUser.credits is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -149,7 +152,7 @@ export default {
// Save toUser // Save toUser
await toUser?.save()?.then(async () => { await toUser?.save()?.then(async () => {
logger?.verbose(`Saved toUser`); logger?.silly(`Saved toUser`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -1,13 +1,8 @@
// Dependencies // Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js"; import { CommandInteraction, MessageEmbed, Permissions } from "discord.js";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
@ -21,7 +16,13 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: {
guildOnly: true,
ephemeral: true,
permissions: [Permissions.FLAGS.MANAGE_GUILD],
},
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("transfer") .setName("transfer")
.setDescription("Transfer credits from one user to another.") .setDescription("Transfer credits from one user to another.")
@ -45,7 +46,9 @@ export default {
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure member if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure member
const { guild, options } = interaction; const { guild, options } = interaction;
// Get options // Get options
@ -55,7 +58,7 @@ export default {
// If amount is null // If amount is null
if (optionAmount === null) { if (optionAmount === null) {
logger?.verbose(`Amount is null`); logger?.silly(`Amount is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -70,7 +73,7 @@ export default {
} }
if (guild === null) { if (guild === null) {
logger?.verbose(`Guild is null`); logger?.silly(`Guild is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -84,7 +87,7 @@ export default {
}); });
} }
if (optionFromUser === null) { if (optionFromUser === null) {
logger?.verbose(`From user is null`); logger?.silly(`From user is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -98,7 +101,7 @@ export default {
}); });
} }
if (optionToUser === null) { if (optionToUser === null) {
logger?.verbose(`To user is null`); logger?.silly(`To user is null`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -120,7 +123,7 @@ export default {
// If toUser does not exist // If toUser does not exist
if (fromUser === null) { if (fromUser === null) {
logger?.verbose(`From user does not exist`); logger?.silly(`From user does not exist`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -138,7 +141,7 @@ export default {
// If toUser.credits does not exist // If toUser.credits does not exist
if (!fromUser?.credits) { if (!fromUser?.credits) {
logger?.verbose(`From user does not have credits`); logger?.silly(`From user does not have credits`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -156,7 +159,7 @@ export default {
// If toUser does not exist // If toUser does not exist
if (toUser === null) { if (toUser === null) {
logger?.verbose(`To user does not exist`); logger?.silly(`To user does not exist`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -174,7 +177,7 @@ export default {
// If toUser.credits does not exist // If toUser.credits does not exist
if (toUser?.credits === null) { if (toUser?.credits === null) {
logger?.verbose(`To user does not have credits`); logger?.silly(`To user does not have credits`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -198,7 +201,7 @@ export default {
// Save users // Save users
await saveUser(fromUser, toUser)?.then(async () => { await saveUser(fromUser, toUser)?.then(async () => {
logger?.verbose(`Saved users`); logger?.silly(`Saved users`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [

View file

@ -0,0 +1,4 @@
import counters from "@plugins/manage/modules/counters";
import credits from "@plugins/manage/modules/credits";
export default { counters, credits };

View file

@ -3,36 +3,28 @@ import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js"; import { CommandInteraction } from "discord.js";
// Modules // Modules
import view from "./modules/view"; import modules from "@plugins/profile/modules";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
// Function // Function
export default { export default {
metadata: { author: "Zyner" }, modules,
data: new SlashCommandBuilder()
builder: new SlashCommandBuilder()
.setName("profile") .setName("profile")
.setDescription("Check a profile.") .setDescription("Check a profile.")
.addSubcommand((subcommand) => .addSubcommand(modules.view.builder),
subcommand
.setName("view")
.setDescription("View a profile.")
.addUserOption((option) =>
option
.setName("target")
.setDescription("The profile you wish to view")
)
),
async execute(interaction: CommandInteraction) { async execute(interaction: CommandInteraction) {
const { options } = interaction; const { options } = interaction;
if (options?.getSubcommand() === "view") { if (options?.getSubcommand() === "view") {
logger?.verbose(`Executing view subcommand`); logger?.silly(`Executing view subcommand`);
return view(interaction); return modules.view.execute(interaction);
} }
logger?.verbose(`No subcommand found`); logger?.silly(`No subcommand found`);
}, },
}; };

View file

@ -0,0 +1,3 @@
import view from "@plugins/profile/modules/view";
export default { view };

View file

@ -2,74 +2,91 @@
import { CommandInteraction } from "discord.js"; import { CommandInteraction } from "discord.js";
// Configurations // Configurations
import { successColor, footerText, footerIcon } from "@config/embed"; import getEmbedConfig from "@helpers/getEmbedConfig";
// Models // Models
import fetchUser from "@helpers/fetchUser"; import fetchUser from "@helpers/fetchUser";
import logger from "@logger"; import logger from "@logger";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default async (interaction: CommandInteraction) => { export default {
// Destructure metadata: { guildOnly: true, ephemeral: false },
const { client, options, user, guild } = interaction;
// Target information builder: (command: SlashCommandSubcommandBuilder) => {
const target = options?.getUser("target"); return command
.setName("view")
.setDescription("View a profile.")
.addUserOption((option) =>
option.setName("target").setDescription("The profile you wish to view")
);
},
// Discord User Information execute: async (interaction: CommandInteraction) => {
const discordUser = await client?.users?.fetch( if (interaction.guild == null) return;
`${target ? target?.id : user?.id}` const { successColor, footerText, footerIcon } = await getEmbedConfig(
); interaction.guild
); // Destructure
const { client, options, user, guild } = interaction;
if (guild === null) { // Target information
return logger?.verbose(`Guild is null`); const target = options?.getUser("target");
}
// User Information // Discord User Information
const userObj = await fetchUser(discordUser, guild); const discordUser = await client?.users?.fetch(
`${target ? target?.id : user?.id}`
);
// Embed object if (guild === null) {
const embed = { return logger?.silly(`Guild is null`);
author: { }
name: `${discordUser?.username}#${discordUser?.discriminator}`,
icon_url: discordUser?.displayAvatarURL(), // User Information
}, const userObj = await fetchUser(discordUser, guild);
color: successColor,
fields: [ // Embed object
{ const embed = {
name: `:dollar: Credits`, author: {
value: `${userObj?.credits || "Not found"}`, name: `${discordUser?.username}#${discordUser?.discriminator}`,
inline: true, icon_url: discordUser?.displayAvatarURL(),
}, },
{ color: successColor,
name: `:squeeze_bottle: Level`, fields: [
value: `${userObj?.level || "Not found"}`, {
inline: true, name: `:dollar: Credits`,
value: `${userObj?.credits || "Not found"}`,
inline: true,
},
{
name: `:squeeze_bottle: Level`,
value: `${userObj?.level || "Not found"}`,
inline: true,
},
{
name: `:squeeze_bottle: Points`,
value: `${userObj?.points || "Not found"}`,
inline: true,
},
{
name: `:loudspeaker: Reputation`,
value: `${userObj?.reputation || "Not found"}`,
inline: true,
},
{
name: `:rainbow_flag: Language`,
value: `${userObj?.language || "Not found"}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
}, },
{ };
name: `:squeeze_bottle: Points`,
value: `${userObj?.points || "Not found"}`,
inline: true,
},
{
name: `:loudspeaker: Reputation`,
value: `${userObj?.reputation || "Not found"}`,
inline: true,
},
{
name: `:rainbow_flag: Language`,
value: `${userObj?.language || "Not found"}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Return interaction reply // Return interaction reply
return interaction?.editReply({ embeds: [embed] }); return interaction?.editReply({ embeds: [embed] });
},
}; };

View file

@ -3,27 +3,27 @@ import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js"; import { CommandInteraction } from "discord.js";
// Modules // Modules
import give from "./modules/give"; import modules from "./modules";
// Handlers // Handlers
import logger from "@logger"; import logger from "@logger";
// Function // Function
export default { export default {
metadata: { author: "Zyner" }, modules,
data: new SlashCommandBuilder() builder: new SlashCommandBuilder()
.setName("reputation") .setName("reputation")
.setDescription("Manage reputation.") .setDescription("Manage reputation.")
.addSubcommand(give.data), .addSubcommand(modules.give.builder),
async execute(interaction: CommandInteraction) { async execute(interaction: CommandInteraction) {
const { options } = interaction; const { options } = interaction;
if (options?.getSubcommand() === "give") { if (options?.getSubcommand() === "give") {
logger?.verbose(`Executing give subcommand`); logger?.silly(`Executing give subcommand`);
await give.execute(interaction); await modules.give.execute(interaction);
} }
logger?.verbose(`No subcommand found`); logger?.silly(`No subcommand found`);
}, },
}; };

View file

@ -2,12 +2,7 @@
import { CommandInteraction } from "discord.js"; import { CommandInteraction } from "discord.js";
// Configurations // Configurations
import { import getEmbedConfig from "@helpers/getEmbedConfig";
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
import { timeout } from "@config/reputation"; import { timeout } from "@config/reputation";
@ -21,7 +16,9 @@ import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function // Function
export default { export default {
data: (command: SlashCommandSubcommandBuilder) => { metadata: { guildOnly: true, ephemeral: true },
builder: (command: SlashCommandSubcommandBuilder) => {
return command return command
.setName("give") .setName("give")
.setDescription("Give reputation to a user") .setDescription("Give reputation to a user")
@ -36,12 +33,19 @@ export default {
.setName("type") .setName("type")
.setDescription("What type of reputation you want to repute") .setDescription("What type of reputation you want to repute")
.setRequired(true) .setRequired(true)
.addChoice("Positive", "positive") .addChoices(
.addChoice("Negative", "negative") { name: "Positive", value: "positive" },
{
name: "Negative",
value: "negative",
}
)
); );
}, },
execute: async (interaction: CommandInteraction) => { execute: async (interaction: CommandInteraction) => {
// Destructure if (interaction.guild == null) return;
const { errorColor, successColor, footerText, footerIcon } =
await getEmbedConfig(interaction.guild); // Destructure
const { options, user, guild } = interaction; const { options, user, guild } = interaction;
// Target option // Target option
@ -51,14 +55,14 @@ export default {
const optionType = options?.getString("type"); const optionType = options?.getString("type");
if (guild === null) { if (guild === null) {
return logger?.verbose(`Guild is null`); return logger?.silly(`Guild is null`);
} }
// User information // User information
const userObj = await fetchUser(user, guild); const userObj = await fetchUser(user, guild);
if (userObj === null) { if (userObj === null) {
return logger?.verbose(`User is null`); return logger?.silly(`User is null`);
} }
// Check if user has a timeout // Check if user has a timeout
@ -70,7 +74,7 @@ export default {
// If user is not on timeout // If user is not on timeout
if (isTimeout) { if (isTimeout) {
logger?.verbose(`User is on timeout`); logger?.silly(`User is on timeout`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -90,7 +94,7 @@ export default {
// Do not allow self reputation // Do not allow self reputation
if (optionTarget?.id === user?.id) { if (optionTarget?.id === user?.id) {
logger?.verbose(`User is trying to give reputation to self`); logger?.silly(`User is trying to give reputation to self`);
return interaction?.editReply({ return interaction?.editReply({
embeds: [ embeds: [
@ -110,21 +114,21 @@ export default {
// If type is positive // If type is positive
if (optionType === "positive") { if (optionType === "positive") {
logger?.verbose(`User is giving positive reputation`); logger?.silly(`User is giving positive reputation`);
userObj.reputation += 1; userObj.reputation += 1;
} }
// If type is negative // If type is negative
else if (optionType === "negative") { else if (optionType === "negative") {
logger?.verbose(`User is giving negative reputation`); logger?.silly(`User is giving negative reputation`);
userObj.reputation -= 1; userObj.reputation -= 1;
} }
// Save user // Save user
await userObj?.save()?.then(async () => { await userObj?.save()?.then(async () => {
logger?.verbose(`User reputation has been updated`); logger?.silly(`User reputation has been updated`);
await timeoutSchema?.create({ await timeoutSchema?.create({
guildId: guild?.id, guildId: guild?.id,
@ -149,7 +153,7 @@ export default {
}); });
setTimeout(async () => { setTimeout(async () => {
logger?.verbose(`Removing timeout`); logger?.silly(`Removing timeout`);
await timeoutSchema?.deleteOne({ await timeoutSchema?.deleteOne({
guildId: guild?.id, guildId: guild?.id,

View file

@ -0,0 +1,3 @@
import give from "@plugins/reputation/modules/give";
export default { give };

View file

@ -1,94 +0,0 @@
// Dependencies
import { Permissions, CommandInteraction } from "discord.js";
// Configurations
import { errorColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "@logger";
// Modules
import pterodactyl from "./modules/pterodactyl";
import credits from "./modules/credits";
import points from "./modules/points";
import welcome from "./modules/welcome";
import audits from "./modules/audits";
import shop from "./modules/shop";
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
// Function
export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("guild")
.setDescription("Guild settings.")
.addSubcommand(pterodactyl.data)
.addSubcommand(credits.data)
.addSubcommand(points.data)
.addSubcommand(welcome.data)
.addSubcommand(audits.data)
.addSubcommand(shop.data);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { memberPermissions, options } = interaction;
// Check permission
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
logger?.verbose(`User does not have permission to execute command.`);
return interaction?.editReply({
embeds: [
{
title: ":tools: Settings - Guild",
color: errorColor,
description: "You do not have permission to use this command.",
timestamp: new Date(),
footer: {
iconURL: footerIcon as string,
text: footerText as string,
},
},
],
});
}
if (options?.getSubcommand() === "pterodactyl") {
logger?.verbose(`Executing pterodactyl subcommand`);
return pterodactyl.execute(interaction);
}
if (options?.getSubcommand() === "credits") {
logger?.verbose(`Executing credits subcommand`);
return credits.execute(interaction);
}
if (options?.getSubcommand() === "points") {
logger?.verbose(`Executing points subcommand`);
return points.execute(interaction);
}
if (options?.getSubcommand() === "welcome") {
logger?.verbose(`Executing welcome subcommand`);
return welcome.execute(interaction);
}
if (options?.getSubcommand() === "audits") {
logger?.verbose(`Executing audit subcommand`);
return audits.execute(interaction);
}
if (options?.getSubcommand() === "shop") {
logger?.verbose(`Executing shop subcommand`);
return shop.execute(interaction);
}
logger?.verbose(`No subcommand found`);
},
};

View file

@ -1,38 +0,0 @@
// Dependencies
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
// Groups
import guildGroup from "./guild";
import userGroup from "./user";
// Handlers
import logger from "@logger";
// Function
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("settings")
.setDescription("Manage settings.")
.addSubcommandGroup(guildGroup.data)
.addSubcommandGroup(userGroup.data),
async execute(interaction: CommandInteraction) {
const { options } = interaction;
if (options.getSubcommandGroup() === "guild") {
logger.verbose(`Executing guild subcommand`);
return guildGroup.execute(interaction);
}
if (options.getSubcommandGroup() === "user") {
logger.verbose(`Executing user subcommand`);
return userGroup.execute(interaction);
}
logger.verbose(`No subcommand group found`);
},
};

View file

@ -1,41 +0,0 @@
// Dependencies
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
// Handlers
import logger from "@logger";
// Modules
import appearance from "./modules/appearance";
// Function
export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("user")
.setDescription("User settings.")
.addSubcommand((command) =>
command
.setName("appearance")
.setDescription("User appearance settings.")
.addStringOption((option) =>
option
.setName("language")
.setDescription("Set the language.")
.addChoice("English", "en")
.addChoice("Swedish", "sv")
)
);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
if (options?.getSubcommand() === "appearance") {
logger?.verbose(`Executing appearance subcommand`);
await appearance(interaction);
}
logger?.verbose(`No subcommand found`);
},
};

View file

@ -1,61 +0,0 @@
// Dependencies
import { CommandInteraction } from "discord.js";
// Configurations
import { successColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "@logger";
// Models
import fetchUser from "@helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { options, user, guild } = interaction;
// Get options
const language = options?.getString("language");
if (guild === null) {
return logger?.verbose(`Guild is null`);
}
// Get user object
const userDB = await fetchUser(user, guild);
if (userDB === null) {
return logger?.verbose(`User is null`);
}
// Modify values
userDB.language = language !== null ? language : userDB?.language;
// Save guild
await userDB?.save()?.then(async () => {
logger?.verbose(`Updated user language.`);
return interaction?.editReply({
embeds: [
{
title: ":hammer: Settings - User [Appearance]",
description: "Successfully updated user settings.",
color: successColor,
fields: [
{
name: "🏳️‍🌈 Language",
value: `${userDB?.language}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
},
],
});
});
};

View file

@ -3,37 +3,35 @@ import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js"; import { CommandInteraction } from "discord.js";
// Modules // Modules
import pterodactyl from "./modules/pterodactyl"; import modules from "./modules";
// Groups
import roles from "./roles";
// Handlers // Handlers
import logger from "../../logger"; import logger from "../../logger";
// Function // Function
export default { export default {
metadata: { author: "Zyner" }, modules,
data: new SlashCommandBuilder()
builder: new SlashCommandBuilder()
.setName("shop") .setName("shop")
.setDescription("Shop for credits and custom roles.") .setDescription("Shop for credits and custom roles.")
.addSubcommand(pterodactyl.data) .addSubcommand(modules.pterodactyl.builder)
.addSubcommandGroup(roles.data), .addSubcommandGroup(modules.roles.builder),
async execute(interaction: CommandInteraction) { async execute(interaction: CommandInteraction) {
const { options } = interaction; const { options } = interaction;
if (options?.getSubcommand() === "pterodactyl") { if (options?.getSubcommand() === "pterodactyl") {
logger.verbose(`Executing pterodactyl subcommand`); logger.silly(`Executing pterodactyl subcommand`);
return pterodactyl.execute(interaction); return modules.pterodactyl.execute(interaction);
} }
if (options?.getSubcommandGroup() === "roles") { if (options?.getSubcommandGroup() === "roles") {
logger?.verbose(`Subcommand group is roles`); logger?.silly(`Subcommand group is roles`);
return roles.execute(interaction); return modules.roles.execute(interaction);
} }
logger?.verbose(`No subcommand found.`); logger?.silly(`No subcommand found.`);
}, },
}; };

View file

@ -0,0 +1,4 @@
import pterodactyl from "@plugins/shop/modules/pterodactyl";
import roles from "@plugins/shop/modules/roles";
export default { pterodactyl, roles };

Some files were not shown because too many files have changed in this diff Show more