Merge pull request #218 from ZynerOrg/restyled/dev

Restyle Major rewritten structure & grammar
This commit is contained in:
Axel Olausson Holtenäs 2022-04-13 21:36:51 +02:00 committed by GitHub
commit 5c5b525667
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
117 changed files with 3107 additions and 2851 deletions

View file

@ -1,5 +1,6 @@
# Custom Dictionary Words
Controlpanel
cpgg
dagen
discordjs
Följande
@ -11,6 +12,7 @@ inom
inställningar
inte
Krediter
multistream
Nivå
omdöme
Omdöme

View file

@ -1,10 +1,9 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'bug'
assignees: ''
title: ""
labels: "bug"
assignees: "VermiumSifell"
---
**Describe the bug**
@ -12,6 +11,7 @@ A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
@ -23,16 +23,10 @@ A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Environment (please complete the following information):**
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
- Commit: [git rev-parse HEAD]
- Branch: [git branch --show-current]
**Additional context**
Add any other context about the problem here.

6
.gitignore vendored
View file

@ -4,6 +4,12 @@ node_modules
config.json
package-lock.json
**/config/*.ts
!**/config/index.ts
!**/config/example.*.ts
# Logs
logs
*.log

View file

@ -39,14 +39,17 @@
"discord.js": "^13.6.0",
"dotenv": "^16.0.0",
"i18next": "^21.6.13",
"module-alias": "^2.2.2",
"mongoose": "^6.2.3",
"node-schedule": "^2.1.0",
"pino": "^7.0.0-rc.9",
"pino-pretty": "^7.6.1",
"quick.db": "^7.1.3",
"ts-node": "^10.7.0",
"tsconfig-paths": "^3.14.1",
"typescript": "^4.6.3",
"uuid": "^8.3.2"
"uuid": "^8.3.2",
"winston-daily-rotate-file": "^4.6.1"
},
"devDependencies": {
"@types/chance": "^1.1.3",

View file

@ -1,34 +0,0 @@
// Dependencies
import { CommandInteraction } from "discord.js";
// Handlers
import logger from "../../../handlers/logger";
// Modules
import add from "./modules/add";
import remove from "./modules/remove";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options, guild, user, commandName } = interaction;
// Module - Add
if (options?.getSubcommand() === "add") {
// Execute Module - Add
return add(interaction);
}
// Module - Remove
else if (options?.getSubcommand() === "remove") {
// Execute Module - Remove
return remove(interaction);
}
// Log debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
};

View file

@ -1,99 +0,0 @@
// Dependencies
import { ColorResolvable, CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Models
import counterSchema from "../../../../helpers/database/models/counterSchema";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options, guild, user } = interaction;
// Channel option
const optionChannel = options?.getChannel("channel");
// Word option
const optionWord = options?.getString("word");
// Start option
const optionStart = options?.getNumber("start");
if (optionChannel?.type !== "GUILD_TEXT") {
// Return interaction reply
return interaction?.editReply({
embeds: [
{
title: ":toolbox: Admin - Counters [Add]" as string,
description:
"That channel is not supported, it needs to be a text channel." as string,
timestamp: new Date(),
color: config?.colors?.error as ColorResolvable,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
},
],
});
}
const counterExist = await counterSchema?.findOne({
guildId: guild?.id,
channelId: optionChannel?.id,
optionWord,
});
if (!counterExist) {
await counterSchema?.create({
guildId: guild?.id,
channelId: optionChannel?.id,
optionWord,
counter: optionStart || 0,
});
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} added ${optionChannel?.id} as a counter using word "${optionWord}" for counting.`
);
// Return interaction reply
return interaction?.editReply({
embeds: [
{
title: ":toolbox: Admin - Counters [Add]" as string,
description: `${optionChannel} is now counting when hearing word ${optionWord} and it starts at number ${
optionStart || 0
}.`,
timestamp: new Date(),
color: config?.colors?.success as ColorResolvable,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
},
],
});
}
// Return interaction reply
return interaction?.editReply({
embeds: [
{
title: ":toolbox: Admin - Counters [Add]" as string,
description: `${optionChannel} is already a counting channel.`,
timestamp: new Date(),
color: config?.colors?.error as ColorResolvable,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
},
],
});
};

View file

@ -1,47 +0,0 @@
// Dependencies
import { ColorResolvable, CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Models
import counterSchema from "../../../../helpers/database/models/counterSchema";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options, guild, user } = interaction;
// Get options
const optionChannel = options?.getChannel("channel");
await counterSchema
?.deleteOne({
guildId: guild?.id,
channelId: optionChannel?.id,
})
?.then(async () => {
// Embed object
const embed = {
title: ":toolbox: Admin - Counters [Remove]" as string,
description: `${optionChannel} is no longer an counting channel.`,
timestamp: new Date(),
color: config?.colors?.success as ColorResolvable,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} removed ${optionChannel?.id} as a counter.`
);
};

View file

@ -1,38 +0,0 @@
// Dependencies
import { CommandInteraction } from "discord.js";
// Modules
import give from "./modules/give";
import take from "./modules/take";
import set from "./modules/set";
import transfer from "./modules/transfer";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options } = interaction;
// Module - Give
if (options?.getSubcommand() === "give") {
// Execute Module - Give
return give(interaction);
}
// Module - Take
else if (options?.getSubcommand() === "take") {
// Execute Module - Take
return take(interaction);
}
// Module - Set
else if (options?.getSubcommand() === "set") {
// Execute Module - Set
return set(interaction);
}
// Module - Transfer
else if (options?.getSubcommand() === "transfer") {
// Execute Module - Transfer
return transfer(interaction);
}
};

View file

@ -1,132 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Helpers
import creditNoun from "../../../../helpers/creditNoun";
// Models
import fetchUser from "../../../../helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { guild, user, options } = interaction;
// User option
const optionUser = options?.getUser("user");
// Amount option
const optionAmount = options?.getInteger("amount");
// If amount option is null
if (optionAmount === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Give]" as string,
description: "We could not read your requested amount." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If amount is zero or below
if (optionAmount <= 0) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Give]" as string,
description: "You can not give zero credits or below." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
if (optionUser === null) return;
if (guild === null) return;
// toUser Information
const toUser = await fetchUser(optionUser, guild);
// If toUser does not exist
if (!toUser) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Give]" as string,
description: `We could not find ${optionUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If toUser.credits does not exist
if (toUser?.credits === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Give]" as string,
description: `We could not find credits for ${optionUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Deposit amount to toUser
toUser.credits += optionAmount;
// Save toUser
await toUser?.save()?.then(async () => {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Give]" as string,
description: `We have given ${optionUser}, ${creditNoun(optionAmount)}.`,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} gave ${
optionUser?.id
} ${creditNoun(optionAmount)}.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
};

View file

@ -1,114 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Helpers
import creditNoun from "../../../../helpers/creditNoun";
// Models
import fetchUser from "../../../../helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options, user, guild } = interaction;
// User Option
const optionUser = options.getUser("user");
// Amount Option
const optionAmount = options.getInteger("amount");
// If amount is null
if (optionAmount === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Set]" as string,
description: "We could not read your requested amount." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
if (optionUser === null) return;
if (guild === null) return;
// toUser Information
const toUser = await fetchUser(optionUser, guild);
// If toUser does not exist
if (!toUser) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Set]" as string,
description: `We could not find ${optionUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If toUser.credits does not exist
if (toUser?.credits === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Set]" as string,
description: `We could not find credits for ${optionUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Set toUser with amount
toUser.credits = optionAmount;
// Save toUser
await toUser?.save()?.then(async () => {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Set]" as string,
description: `We have set ${optionUser} to ${creditNoun(optionAmount)}`,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} set ${
optionUser?.id
} to ${creditNoun(optionAmount)}.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
};

View file

@ -1,134 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Helpers
import creditNoun from "../../../../helpers/creditNoun";
// Models
import fetchUser from "../../../../helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { guild, user, options } = interaction;
// User option
const optionUser = options?.getUser("user");
// Amount option
const optionAmount = options?.getInteger("amount");
// If amount is null
if (optionAmount === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Take]" as string,
description: "We could not read your requested amount." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If amount is zero or below
if (optionAmount <= 0) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Take]" as string,
description: "You can not take zero credits or below." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
if (optionUser === null) return;
if (guild === null) return;
// toUser Information
const toUser = await fetchUser(optionUser, guild);
// If toUser does not exist
if (!toUser) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Take]" as string,
description: `We could not find ${optionUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If toUser.credits does not exist
if (toUser?.credits === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Take]" as string,
description: `We could not find credits for ${optionUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Withdraw amount from toUser
toUser.credits -= optionAmount;
// Save toUser
await toUser?.save()?.then(async () => {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Set]" as string,
description: `We have taken ${creditNoun(
optionAmount
)} from ${optionUser}`,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} set ${
optionUser?.id
} to ${creditNoun(optionAmount)}.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
};

View file

@ -1,171 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Helpers
import creditNoun from "../../../../helpers/creditNoun";
import saveUser from "../../../../helpers/saveUser";
// Models
import fetchUser from "../../../../helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { guild, options, user } = interaction;
// Get options
const optionFromUser = options?.getUser("from");
const optionToUser = options?.getUser("to");
const optionAmount = options?.getInteger("amount");
// If amount is null
if (optionAmount === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Transfer]" as string,
description: "We could not read your requested amount." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
if (guild === null) return;
if (optionFromUser === null) return;
if (optionToUser === null) return;
// Get fromUser object
const fromUser = await fetchUser(optionFromUser, guild);
// Get toUser object
const toUser = await fetchUser(optionToUser, guild);
// If toUser does not exist
if (!fromUser) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Transfer]" as string,
description: `We could not find ${optionFromUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If toUser.credits does not exist
if (!fromUser?.credits) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Transfer]" as string,
description: `We could not find credits for ${optionFromUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If toUser does not exist
if (!toUser) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Transfer]" as string,
description: `We could not find ${optionToUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If toUser.credits does not exist
if (toUser?.credits === null) {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Transfer]" as string,
description: `We could not find credits for ${optionToUser} in our database.`,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Withdraw amount from fromUser
fromUser.credits -= optionAmount;
// Deposit amount to toUser
toUser.credits += optionAmount;
// Save users
await saveUser(fromUser, toUser)?.then(async () => {
// Embed object
const embed = {
title: ":toolbox: Admin - Credits [Transfer]" as string,
description: `You sent ${creditNoun(
optionAmount
)} from ${optionFromUser} to ${optionToUser}.`,
color: config?.colors?.success as ColorResolvable,
fields: [
{
name: `${optionFromUser?.username} Balance`,
value: `${fromUser?.credits}`,
inline: true,
},
{
name: `${optionToUser?.username} Balance`,
value: `${toUser?.credits}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} transferred ${creditNoun(
optionAmount
)} from ${optionFromUser?.id} to ${optionToUser?.id}.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
};

View file

@ -1,177 +0,0 @@
//Dependencies
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction, ColorResolvable, Permissions } from "discord.js";
// Configurations
import config from "../../../config.json";
// Handlers
import logger from "../../handlers/logger";
// Groups
import credits from "./credits";
import counters from "./counters";
// Function
export default {
data: new SlashCommandBuilder()
.setName("admin")
.setDescription("Admin actions.")
.addSubcommandGroup((group) =>
group
.setName("credits")
.setDescription("Manage credits.")
.addSubcommand((command) =>
command
.setName("give")
.setDescription("Give credits to a user")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to pay.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will pay.")
.setRequired(true)
)
)
.addSubcommand((command) =>
command
.setName("set")
.setDescription("Set credits to a user")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to set credits on.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will set.")
.setRequired(true)
)
)
.addSubcommand((command) =>
command
.setName("take")
.setDescription("Take credits from a user")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to take credits from.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will take.")
.setRequired(true)
)
)
.addSubcommand((command) =>
command
.setName("transfer")
.setDescription("Transfer credits from a user to another user.")
.addUserOption((option) =>
option
.setName("from")
.setDescription("The user you want to take credits from.")
.setRequired(true)
)
.addUserOption((option) =>
option
.setName("to")
.setDescription("The user you want to give credits to.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will transfer.")
.setRequired(true)
)
)
)
.addSubcommandGroup((group) =>
group
.setName("counters")
.setDescription("Manage counters.")
.addSubcommand((command) =>
command
.setName("add")
.setDescription("Add a counter")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The counter channel.")
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("word")
.setDescription("The counter word.")
.setRequired(true)
)
.addNumberOption((option) =>
option.setName("start").setDescription("Start at number X.")
)
)
.addSubcommand((command) =>
command
.setName("remove")
.setDescription("Remove a counter")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The counter channel.")
.setRequired(true)
)
)
),
async execute(interaction: CommandInteraction) {
// Destructure
const { memberPermissions, options, user, commandName, guild } =
interaction;
// Check permission
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
// Embed object
const embed = {
title: ":toolbox: Admin" as string,
color: config?.colors?.error as ColorResolvable,
description: "You do not have permission to manage this!" as string,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Group - Credits
if (options?.getSubcommandGroup() === "credits") {
// Execute Group - Credits
return credits(interaction);
}
// Group - Counters
else if (options?.getSubcommandGroup() === "counters") {
// Execute Group - Counters
return counters(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
},
};

View file

@ -1,43 +0,0 @@
// Dependencies
import { CommandInteraction } from "discord.js";
import { SlashCommandBuilder } from "@discordjs/builders";
// Modules
import view from "./modules/view";
// Handlers
import logger from "../../handlers/logger";
// Function
export default {
data: new SlashCommandBuilder()
.setName("counters")
.setDescription("Manage counters.")
.addSubcommand((subcommand) =>
subcommand
.setName("view")
.setDescription("View a counter.")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The counter channel you want to view")
.setRequired(true)
)
),
async execute(interaction: CommandInteraction) {
const { options, guild, user, commandName } = interaction;
// Module - View
if (options?.getSubcommand() === "view") {
// Execute Module - View
return view(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
},
};

View file

@ -1,54 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../config.json";
// Models
import counterSchema from "../../../helpers/database/models/counterSchema";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { options, guild } = interaction;
// Get options
const optionChannel = options?.getChannel("channel");
const counter = await counterSchema?.findOne({
guildId: guild?.id,
channelId: optionChannel?.id,
});
if (!counter) {
// Create embed object
const embed = {
title: ":1234: Counters [View]" as string,
description: `${optionChannel} is not a counting channel.` as string,
timestamp: new Date(),
color: config?.colors?.error as ColorResolvable,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Embed object
const embed = {
title: ":1234: Counters [View]" as string,
color: config.colors.success as ColorResolvable,
description: `${optionChannel} is currently at number ${counter?.counter}.`,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
};

View file

@ -1,90 +0,0 @@
// Dependencies
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
// Handlers
import logger from "../../handlers/logger";
// Modules
import balance from "./modules/balance";
import gift from "./modules/gift";
import top from "./modules/top";
import work from "./modules/work";
// Function
export default {
data: new SlashCommandBuilder()
.setName("credits")
.setDescription("Manage your credits.")
.addSubcommand((subcommand) =>
subcommand
.setName("balance")
.setDescription("Check a user's balance.")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user whose balance you want to check.")
.setRequired(false)
)
)
.addSubcommand((subcommand) =>
subcommand
.setName("gift")
.setDescription("Gift someone credits from your credits.")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to pay.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will pay.")
.setRequired(true)
)
.addStringOption((option) =>
option.setName("reason").setDescription("Your reason.")
)
)
.addSubcommand((subcommand) =>
subcommand.setName("top").setDescription("Check the top balance.")
)
.addSubcommand((subcommand) =>
subcommand.setName("work").setDescription("Work for credits.")
),
async execute(interaction: CommandInteraction) {
const { options, user, guild, commandName } = interaction;
// Module - Balance
if (options?.getSubcommand() === "balance") {
// Execute Module - Balance
return balance(interaction);
}
// Module - Gift
else if (options?.getSubcommand() === "gift") {
// Execute Module - Gift
return gift(interaction);
}
// Module - Top
else if (options?.getSubcommand() === "top") {
// Execute Module - Top
return top(interaction);
}
// Module - Work
else if (options?.getSubcommand() === "work") {
// Execute Module - Work
return work(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
},
};

View file

@ -1,82 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../config.json";
// Helpers
import creditNoun from "../../../helpers/creditNoun";
// Models
import fetchUser from "../../../helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options, user, guild } = interaction;
// User option
const optionUser = options?.getUser("user");
if (guild === null) return;
// Get credit object
const userDB = await fetchUser(optionUser || user, guild);
// If userDB does not exist
if (userDB === null) {
// Embed object
const embed = {
title: ":dollar: Credits [Balance]" as string,
description: `We can not find ${
optionUser || "you"
} in our database.` as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If userDB.credits does not exist
if (userDB.credits === null) {
// Embed object
const embed = {
title: ":dollar: Credits [Balance]" as string,
description: `We can not find credits for ${
optionUser || "you"
} in our database.` as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
} else {
// Embed object
const embed = {
title: ":dollar: Credits [Balance]" as string,
description: `${
optionUser ? `${optionUser} has` : "You have"
} ${creditNoun(userDB.credits)}.` as string,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
};

View file

@ -1,187 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../config.json";
// Handlers
import logger from "../../../handlers/logger";
// Helpers
import saveUser from "../../../helpers/saveUser";
import creditNoun from "../../../helpers/creditNoun";
// Models
import fetchUser from "../../../helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure
const { options, user, guild, client } = interaction;
// User option
const optionUser = options?.getUser("user");
// Amount option
const optionAmount = options?.getInteger("amount");
// Reason option
const optionReason = options?.getString("reason");
if (guild === null) return;
if (optionUser === null) return;
// Get fromUserDB object
const fromUserDB = await fetchUser(user, guild);
// Get toUserDB object
const toUserDB = await fetchUser(optionUser, guild);
if (fromUserDB === null) return;
if (toUserDB === null) return;
// If receiver is same as sender
if (optionUser?.id === user?.id) {
// Create embed object
const embed = {
title: ":dollar: Credits [Gift]" as string,
description: "You can't pay yourself." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If amount is null
if (optionAmount === null) {
// Embed object
const embed = {
title: ":dollar: Credits [Gift]" as string,
description: "We could not read your requested amount." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If amount is zero or below
if (optionAmount <= 0) {
// Embed object
const embed = {
title: ":dollar: Credits [Gift]" as string,
description: "You can't pay zero or below." as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If user has below gifting amount
if (fromUserDB?.credits < optionAmount) {
// Embed object
const embed = {
title: ":dollar: Credits [Gift]" as string,
description:
`You have insufficient credits. Your credits is ${fromUserDB?.credits}` as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// If toUserDB has no credits
if (!toUserDB) {
// Embed object
const embed = {
title: ":dollar: Credits [Gift]" as string,
description:
`That user has no credits, I can not gift credits to ${optionUser}` as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Withdraw amount from fromUserDB
fromUserDB.credits -= optionAmount;
// Deposit amount to toUserDB
toUserDB.credits += optionAmount;
// Save users
await saveUser(fromUserDB, toUserDB)?.then(async () => {
// Interaction embed object
const interactionEmbed = {
title: ":dollar: Credits [Gift]",
description: `You sent ${creditNoun(optionAmount)} to ${optionUser}${
optionReason ? ` with reason: ${optionReason}` : ""
}. Your new credits is ${creditNoun(fromUserDB?.credits)}.`,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// DM embed object
const dmEmbed = {
title: ":dollar: Credits [Gift]" as string,
description: `You received ${creditNoun(optionAmount)} from ${user}${
optionReason ? ` with reason: ${optionReason}` : ""
}. Your new credits is ${creditNoun(toUserDB?.credits)}.` as string,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Get DM user object
const dmUser = client?.users?.cache?.get(interaction?.user?.id);
// Send DM to user
await dmUser?.send({ embeds: [dmEmbed] });
// Send debug message
logger.debug(
`Guild: ${guild?.id} User: ${user?.id} gift sent from: ${user?.id} to: ${optionUser?.id}`
);
// Send interaction reply
return interaction.editReply({
embeds: [interactionEmbed],
});
});
};

View file

@ -1,47 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../config.json";
// Models
import userSchema from "../../../helpers/database/models/userSchema";
// helpers
import creditNoun from "../../../helpers/creditNoun";
// Function
export default async (interaction: CommandInteraction) => {
// Get all users in the guild
const usersDB = await userSchema.find({ guildId: interaction?.guild?.id });
const topTen = usersDB
// Sort them after credits amount (ascending)
.sort((a, b) => (a?.credits > b?.credits ? -1 : 1))
// Return the top 10
.slice(0, 10);
// Create entry object
const entry = (x: any, index: number) =>
`**Top ${index + 1}** - <@${x?.userId}> ${creditNoun(x?.credits)}`;
// Create embed object
const embed = {
title: ":dollar: Credits [Top]" as string,
description: `Below are the top ten.\n${topTen
?.map((x, index) => entry(x, index))
?.join("\n")}` as string,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
};

View file

@ -1,116 +0,0 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
import Chance from "chance";
// Configurations
import config from "../../../../config.json";
// Handlers
import logger from "../../../handlers/logger";
// Models
import timeouts from "../../../helpers/database/models/timeoutSchema";
// Helpers
import creditNoun from "../../../helpers/creditNoun";
import fetchUser from "../../../helpers/fetchUser";
import fetchGuild from "../../../helpers/fetchGuild";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { guild, user } = interaction;
// Chance module
const chance = new Chance();
// Check if user has a timeout
const isTimeout = await timeouts?.findOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
if (guild === null) return;
const guildDB = await fetchGuild(guild);
// If user is not on timeout
if (!isTimeout) {
const creditsEarned = chance.integer({
min: 0,
max: guildDB?.credits?.workRate,
});
const userDB = await fetchUser(user, guild);
if (userDB === null) return;
userDB.credits += creditsEarned;
await userDB?.save()?.then(async () => {
// Send debug message
logger?.debug(`Credits added to user: ${user?.id}`);
// Create embed object
const embed = {
title: ":dollar: Credits [Work]" as string,
description: `You have earned ${creditNoun(creditsEarned)}` as string,
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
return interaction?.editReply({ embeds: [embed] });
});
// Create a timeout for the user
await timeouts?.create({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
setTimeout(async () => {
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has not worked within the last ${
guildDB?.credits?.workTimeout / 1000
} seconds, work can be done`
);
// When timeout is out, remove it from the database
await timeouts?.deleteOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
}, guildDB?.credits?.workTimeout);
} else {
// Create embed object
const embed = {
title: ":dollar: Credits [Work]" as string,
description: `You have worked within the last ${
guildDB?.credits?.workTimeout / 1000
} seconds, you can not work now!` as string,
timestamp: new Date(),
color: config?.colors?.error as ColorResolvable,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has worked within last day, no work can be done`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
};

View file

@ -1,97 +0,0 @@
// Dependencies
import { ColorResolvable, CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../../config.json";
//Handlers
import logger from "../../../../handlers/logger";
// Models
import guildSchema from "../../../../helpers/database/models/guildSchema";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { guild, user, options } = interaction;
// Get options
const status = options?.getBoolean("status");
const rate = options?.getNumber("rate");
const timeout = options?.getNumber("timeout");
const minimumLength = options?.getNumber("minimum-length");
const workRate = options?.getNumber("work-rate");
const workTimeout = options?.getNumber("work-timeout");
// Get guild object
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
// Modify values
guildDB.credits.status = status !== null ? status : guildDB?.credits?.status;
guildDB.credits.rate = rate !== null ? rate : guildDB?.credits?.rate;
guildDB.credits.timeout =
timeout !== null ? timeout : guildDB?.credits?.timeout;
guildDB.credits.workRate =
workRate !== null ? workRate : guildDB?.credits?.workRate;
guildDB.credits.workTimeout =
workTimeout !== null ? workTimeout : guildDB?.credits?.workTimeout;
guildDB.credits.minimumLength =
minimumLength !== null ? minimumLength : guildDB?.credits?.minimumLength;
// Save guild
await guildDB?.save()?.then(async () => {
// Embed object
const embed = {
title: ":tools: Settings - Guild [Credits]" as string,
description: "Following settings is set!" as string,
color: config?.colors?.success as ColorResolvable,
fields: [
{
name: "🤖 Status" as string,
value: `${guildDB?.credits?.status}` as string,
inline: true,
},
{
name: "📈 Rate" as string,
value: `${guildDB?.credits?.rate}` as string,
inline: true,
},
{
name: "📈 Work Rate" as string,
value: `${guildDB?.credits?.workRate}` as string,
inline: true,
},
{
name: "🔨 Minimum Length" as string,
value: `${guildDB?.credits?.minimumLength}` as string,
inline: true,
},
{
name: "⏰ Timeout" as string,
value: `${guildDB?.credits?.timeout}` as string,
inline: true,
},
{
name: "⏰ Work Timeout" as string,
value: `${guildDB?.credits?.workTimeout}` as string,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user.id} has changed credit details.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
};

View file

@ -1,81 +0,0 @@
// Dependencies
import { ColorResolvable, CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Models
import guildSchema from "../../../../helpers/database/models/guildSchema";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { options, guild, user } = interaction;
// Get options
const status = options?.getBoolean("status");
const rate = options?.getNumber("rate");
const timeout = options?.getNumber("timeout");
const minimumLength = options?.getNumber("minimum-length");
// Get guild object
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
// Modify values
guildDB.points.status = status !== null ? status : guildDB?.points?.status;
guildDB.points.rate = rate !== null ? rate : guildDB?.points?.rate;
guildDB.points.timeout =
timeout !== null ? timeout : guildDB?.points?.timeout;
guildDB.points.minimumLength =
minimumLength !== null ? minimumLength : guildDB?.points?.minimumLength;
// Save guild
await guildDB?.save()?.then(async () => {
// Create embed object
const embed = {
title: ":hammer: Settings - Guild [Points]" as string,
description: "Following settings is set!" as string,
color: config.colors.success as ColorResolvable,
fields: [
{
name: "🤖 Status" as string,
value: `${guildDB?.points?.status}` as string,
inline: true,
},
{
name: "📈 Rate" as string,
value: `${guildDB?.points?.rate}` as string,
inline: true,
},
{
name: "🔨 Minimum Length" as string,
value: `${guildDB?.points?.minimumLength}` as string,
inline: true,
},
{
name: "⏰ Timeout" as string,
value: `${guildDB?.points?.timeout}` as string,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has changed credit details.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
};

View file

@ -1,51 +0,0 @@
// Dependencies
import { ColorResolvable, CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../../config.json";
// Handlers
import logger from "../../../../handlers/logger";
// Models
import apiSchema from "../../../../helpers/database/models/apiSchema";
import encryption from "../../../../handlers/encryption";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { options, guild, user } = interaction;
// Get options
const url = options?.getString("url");
const token = encryption.encrypt(options?.getString("token"));
// Update API credentials
await apiSchema
?.findOneAndUpdate(
{ guildId: guild?.id },
{ url, token },
{ new: true, upsert: true }
)
.then(async () => {
// Embed object
const embed = {
title: ":hammer: Settings - Guild [Pterodactyl]" as string,
color: config?.colors?.success as ColorResolvable,
description: "Pterodactyl settings is saved!" as string,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has changed api credentials.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
};

View file

@ -1,62 +0,0 @@
// Dependencies
import { Permissions, ColorResolvable, CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../config.json";
// Handlers
import logger from "../../../handlers/logger";
// Modules
import pterodactyl from "./addons/pterodactyl";
import credits from "./addons/credits";
import points from "./addons/points";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { memberPermissions, options, commandName, user, guild } = interaction;
// Check permission
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
// Create embed object
const embed = {
title: ":tools: Settings - Guild" as string,
color: config?.colors?.error as ColorResolvable,
description: "You do not have permission to manage this!" as string,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Module - Pterodactyl
if (options?.getSubcommand() === "pterodactyl") {
// Execute Module - Pterodactyl
return pterodactyl(interaction);
}
// Module - Credits
else if (options?.getSubcommand() === "credits") {
// Execute Module - Credits
return credits(interaction);
}
// Module - Points
else if (options?.getSubcommand() === "points") {
// Execute Module - Points
return points(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
};

View file

@ -1,144 +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 "../../handlers/logger";
// Function
export default {
data: new SlashCommandBuilder()
.setName("settings")
.setDescription("Manage settings.")
.addSubcommandGroup((group) =>
group
.setName("guild")
.setDescription("Manage guild settings.")
.addSubcommand((command) =>
command
.setName("pterodactyl")
.setDescription("Controlpanel.gg")
.addStringOption((option) =>
option
.setName("url")
.setDescription("The api url")
.setRequired(true)
)
.addStringOption((option) =>
option
.setName("token")
.setDescription("The api token")
.setRequired(true)
)
)
.addSubcommand((command) =>
command
.setName("credits")
.setDescription("Credits")
.addBooleanOption((option) =>
option
.setName("status")
.setDescription("Should credits be enabled?")
)
.addNumberOption((option) =>
option
.setName("rate")
.setDescription("Amount of credits per message.")
)
.addNumberOption((option) =>
option
.setName("minimum-length")
.setDescription("Minimum length of message to earn credits.")
)
.addNumberOption((option) =>
option
.setName("work-rate")
.setDescription("Maximum amount of credits on work.")
)
.addNumberOption((option) =>
option
.setName("work-timeout")
.setDescription(
"Timeout between work schedules (milliseconds)."
)
)
.addNumberOption((option) =>
option
.setName("timeout")
.setDescription(
"Timeout between earning credits (milliseconds)."
)
)
)
.addSubcommand((command) =>
command
.setName("points")
.setDescription("Points")
.addBooleanOption((option) =>
option
.setName("status")
.setDescription("Should credits be enabled?")
)
.addNumberOption((option) =>
option
.setName("rate")
.setDescription("Amount of credits per message.")
)
.addNumberOption((option) =>
option
.setName("minimum-length")
.setDescription("Minimum length of message to earn credits.")
)
.addNumberOption((option) =>
option
.setName("timeout")
.setDescription(
"Timeout between earning credits (milliseconds)."
)
)
)
)
.addSubcommandGroup((group) =>
group
.setName("user")
.setDescription("Manage user settings.")
.addSubcommand((command) =>
command
.setName("appearance")
.setDescription("Manage your appearance")
.addStringOption((option) =>
option
.setName("language")
.setDescription("Configure your language")
.addChoice("English", "en")
.addChoice("Swedish", "sv")
)
)
),
async execute(interaction: CommandInteraction) {
// Destructure
const { options, commandName, user, guild } = interaction;
// Group - Guild
if (options.getSubcommandGroup() === "guild") {
// Execute Group - Guild
await guildGroup(interaction);
}
// Group - User
else if (options.getSubcommandGroup() === "user") {
// Execute Group - User
await userGroup(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
},
};

View file

@ -1,27 +0,0 @@
// Dependencies
import { CommandInteraction } from "discord.js";
// Handlers
import logger from "../../../handlers/logger";
// Modules
import appearance from "./modules/appearance";
// Function
export default async (interaction: CommandInteraction) => {
// Destructure member
const { guild, user, options, commandName } = interaction;
// Module - Appearance
if (options?.getSubcommand() === "appearance") {
// Execute Module - Appearance
await appearance(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
};

View file

@ -1,112 +0,0 @@
// Dependencies
import axios from "axios";
import { CommandInteraction, ColorResolvable } from "discord.js";
// Configurations
import config from "../../../../config.json";
// Handlers
import logger from "../../../handlers/logger";
// Function
export default async (interaction: CommandInteraction) => {
const { options } = interaction;
// Get lookup query
const query = options?.getString("query");
// Make API request
await axios
// Make a get request
?.get(`http://ip-api.com/json/${query}`)
// If successful
?.then(async (res) => {
// If query failed
if (res?.data?.status === "fail") {
// Create embed object
const embed = {
title: ":hammer: Utilities - Lookup" as string,
description: `${res?.data?.message}: ${res?.data?.query}` as string,
color: config?.colors?.error as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
await interaction?.editReply({ embeds: [embed] });
}
// If query is successful
else if (res?.data?.status === "success") {
// Create embed object
const embed = {
title: ":hammer: Utilities - Lookup" as string,
fields: [
{
name: "AS" as string,
value: `${res?.data?.as || "Not available"}` as string,
},
{
name: "Country" as string,
value: `${res?.data?.country || "Not available"}` as string,
},
{
name: "Country Code" as string,
value: `${res?.data?.countryCode || "Not available"}` as string,
},
{
name: "Region" as string,
value: `${res?.data?.region || "Not available"}` as string,
},
{
name: "Region Name" as string,
value: `${res?.data?.regionName || "Not available"}` as string,
},
{
name: "City" as string,
value: `${res?.data?.city || "Not available"}` as string,
},
{
name: "ZIP Code" as string,
value: `${res?.data?.zip || "Not available"}` as string,
},
{
name: "Latitude" as string,
value: `${res?.data?.lat || "Not available"}` as string,
},
{
name: "Longitude" as string,
value: `${res?.data?.lon || "Not available"}` as string,
},
{
name: "Timezone" as string,
value: `${res?.data?.timezone || "Not available"}` as string,
},
{
name: "ISP" as string,
value: `${res?.data?.isp || "Not available"}` as string,
},
{
name: "Organization" as string,
value: `${res?.data?.org || "Not available"}` as string,
},
],
color: config?.colors?.success as ColorResolvable,
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
},
};
// Send interaction reply
await interaction?.editReply({ embeds: [embed] });
}
})
.catch(async (e) => {
logger?.error(e);
});
};

View file

@ -0,0 +1,2 @@
// Controlpanel.gg (Pterodactyl) API token
export const cpggToken = "";

View file

@ -0,0 +1,3 @@
// MongoDB connection string
export const url =
"mongodb+srv://username:password@server/database?retryWrites=true&w=majority";

View file

@ -0,0 +1,5 @@
// Discord API token
export const token = "";
// Discord API id
export const clientId = "";

View file

@ -0,0 +1,17 @@
// Dependencies
import { ColorResolvable } from "discord.js";
// Color for successfully actions
export const successColor: ColorResolvable = "#22bb33";
// Color for waiting actions
export const waitColor: ColorResolvable = "#f0ad4e";
// Color for error actions
export const errorColor: ColorResolvable = "#bb2124";
// Footer text
export const footerText = "https://github.com/ZynerOrg/xyter";
// Footer icon
export const footerIcon = "https://github.com/ZynerOrg.png";

View file

View file

@ -0,0 +1,11 @@
// Development features
export const devMode = false;
// Development guild
export const guildId = "";
// Hoster name
export const hosterName = "someone";
// Hoster Url
export const hosterUrl = "scheme://domain.tld";

View file

@ -0,0 +1,2 @@
// Timeout between repute someone (seconds)
export const timeout = 86400; // One day

15
src/database/index.ts Normal file
View file

@ -0,0 +1,15 @@
import { url } from "@config/database";
import mongoose from "mongoose";
import logger from "@logger";
export default async () => {
await mongoose
.connect(url)
?.then(async () => {
logger.info("Successfully connected to MongoDB!");
})
?.catch(async () => {
logger.error("Error whilst connecting to MongoDB!");
});
};

View file

@ -1,66 +1,85 @@
import mongoose from "mongoose";
import { Schema, model } from "mongoose";
const guildSchema = new mongoose.Schema(
interface IGuild {
guildId: string;
credits: {
status: boolean;
rate: number;
timeout: number;
workRate: number;
minimumLength: number;
workTimeout: number;
};
shop: { roles: { status: boolean; pricePerHour: number } };
points: {
status: boolean;
rate: number;
minimumLength: number;
timeout: number;
};
}
const guildSchema = new Schema<IGuild>(
{
guildId: {
type: mongoose.SchemaTypes.Decimal128,
type: String,
required: true,
unique: true,
index: true,
},
credits: {
status: {
type: mongoose.SchemaTypes.Boolean,
type: Boolean,
default: true,
},
rate: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 1,
},
minimumLength: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 5,
},
timeout: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 5000,
},
workRate: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 15,
},
workTimeout: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 900000,
},
},
shop: {
roles: {
status: {
type: mongoose.SchemaTypes.Boolean,
type: Boolean,
default: true,
},
pricePerHour: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 5,
},
},
},
points: {
status: {
type: mongoose.SchemaTypes.Boolean,
type: Boolean,
default: false,
},
rate: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 1,
},
minimumLength: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 5,
},
timeout: {
type: mongoose.SchemaTypes.Number,
type: Number,
default: 5000,
},
},
@ -68,4 +87,4 @@ const guildSchema = new mongoose.Schema(
{ timestamps: true }
);
export default mongoose.model("guild", guildSchema);
export default model<IGuild>("guild", guildSchema);

View file

@ -0,0 +1,3 @@
import counter from "./counter";
export default { counter };

View file

@ -5,15 +5,12 @@ import { Guild } from "discord.js";
import updatePresence from "../../helpers/updatePresence";
import fetchGuild from "../../helpers/fetchGuild";
// Function
export default {
name: "guildCreate",
async execute(guild: Guild) {
// Destructure
const { client } = guild;
await fetchGuild(guild);
await updatePresence(client);
},
};

View file

@ -5,15 +5,12 @@ import { Guild } from "discord.js";
import updatePresence from "../../helpers/updatePresence";
import dropGuild from "../../helpers/dropGuild";
// Function
export default {
name: "guildDelete",
async execute(guild: Guild) {
// Destructure client
const { client } = guild;
await dropGuild(guild);
await updatePresence(client);
},
};

View file

@ -1,4 +1,7 @@
// Dependencies
import { GuildMember } from "discord.js";
// Helpers
import updatePresence from "../../helpers/updatePresence";
import fetchUser from "../../helpers/fetchUser";
@ -8,7 +11,6 @@ export default {
const { client, user, guild } = member;
await fetchUser(user, guild);
await updatePresence(client);
},
};

View file

@ -1,4 +1,7 @@
// Dependencies
import { GuildMember } from "discord.js";
// Helpers
import updatePresence from "../../helpers/updatePresence";
import dropUser from "../../helpers/dropUser";
@ -8,7 +11,6 @@ export default {
const { client, user, guild } = member;
await dropUser(user, guild);
await updatePresence(client);
},
};

View file

@ -1,57 +1,11 @@
import config from "../../../config.json";
import logger from "../../handlers/logger";
import guilds from "../../helpers/database/models/guildSchema";
// Dependencies
import { CommandInteraction } from "discord.js";
import { Interaction, ColorResolvable } from "discord.js";
import isCommand from "./isCommand";
export default {
name: "interactionCreate",
async execute(interaction: Interaction) {
// Destructure member, client
const { client, guild } = interaction;
// If interaction is command
if (interaction.isCommand()) {
// Get command from collection
const command = client.commands.get(interaction.commandName);
// If command do not exist
if (!command) return;
// Create guild if it does not exist already
await guilds.findOne({ guildId: guild?.id }, { new: true, upsert: true });
try {
// Defer reply
await interaction.deferReply({ ephemeral: true });
// Execute command
await command.execute(interaction);
// Send debug message
logger.debug(`Executing command: ${interaction.commandName}`);
} catch (e) {
// Send debug message
logger.error(e);
// Send interaction reply
await interaction.reply({
embeds: [
{
author: {
name: client?.user?.username,
icon_url: client?.user?.displayAvatarURL(),
url: "https://bot.zyner.org/",
},
title: "Error",
description: "There was an error while executing this command!",
color: config.colors.error as ColorResolvable,
timestamp: new Date(),
},
],
ephemeral: true,
});
}
}
async execute(interaction: CommandInteraction) {
await isCommand(interaction);
},
};

View file

@ -0,0 +1,58 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
import logger from "@logger";
import * as embed from "@config/embed";
import guildSchema from "@schemas/guild";
export default async (interaction: CommandInteraction) => {
if (!interaction.isCommand()) return;
const { client, guild, commandName, user } = interaction;
const currentCommand = client.commands.get(commandName);
if (!currentCommand) return;
// If command do not exist
// Create guild if it does not exist already
await guildSchema.findOne(
{ guildId: guild?.id },
{ new: true, upsert: true }
);
// Defer reply
await interaction.deferReply({ ephemeral: true });
await currentCommand
.execute(interaction)
.then(async () => {
return logger.debug(
`Guild: ${guild?.id} (${guild?.name}) User: ${user?.tag} executed ${commandName}`
);
})
.catch(async (error: any) => {
console.log(error);
logger.error(
`Guild: ${guild?.id} (${guild?.name}) User: ${user?.tag} There was an error executing the command: ${commandName}`
);
logger.error(error);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("Error")
.setDescription(
`There was an error executing the command: **${currentCommand.data.name}**.`
)
.setColor(embed.errorColor)
.setTimestamp(new Date())
.setFooter({ text: embed.footerText, iconURL: embed.footerIcon }),
],
});
});
};

View file

@ -14,7 +14,6 @@ export default {
async execute(message: Message) {
const { author, guild } = message;
// If message author is bot
if (author?.bot) return;
if (guild === null) return;
@ -32,6 +31,6 @@ export default {
await points(guildObj, userObj, message);
// Execute Module - Counters
await counters(guildObj, userObj, message);
await counters(message);
},
};

View file

@ -1,8 +1,8 @@
import counters from "../../../helpers/database/models/counterSchema";
import counters from "../../../database/schemas/counter";
import { Message } from "discord.js";
export default async (guildDB: any, userDB: any, message: Message) => {
export default async (message: Message) => {
const { guild, channel, content } = message;
// Get counter object

View file

@ -1,5 +1,5 @@
import logger from "../../../handlers/logger";
import timeouts from "../../../helpers/database/models/timeoutSchema";
import logger from "../../../logger";
import timeouts from "../../../database/schemas/timeout";
import { Message } from "discord.js";
export default async (guildDB: any, userDB: any, message: Message) => {
const { guild, author, channel, content } = message;

View file

@ -1,5 +1,5 @@
import logger from "../../../handlers/logger";
import timeouts from "../../../helpers/database/models/timeoutSchema";
import logger from "../../../logger";
import timeouts from "../../../database/schemas/timeout";
import { Message } from "discord.js";
export default async (guildDB: any, userDB: any, message: Message) => {

View file

@ -1,27 +1,19 @@
import counters from "../../helpers/database/models/counterSchema";
// Dependencies
import { Message } from "discord.js";
import logger from "../../logger";
// Modules
import counter from "./modules/counter";
export default {
name: "messageUpdate",
async execute(oldMessage: Message, newMessage: Message) {
// If message author is bot
if (newMessage.author.bot) return;
const { author } = newMessage;
// Get counter object
const counter = await counters.findOne({
guildId: newMessage.guild?.id,
channelId: newMessage.channel.id,
});
logger.debug({ oldMessage, newMessage });
// If counter for the message channel
if (counter) {
// If message content is not strictly the same as counter word
if (newMessage.content !== counter.word) {
// Delete the message
await newMessage.delete();
await newMessage.channel.send(
`${newMessage.author} said **${counter.word}**.`
);
}
}
if (author?.bot) return;
await counter(newMessage);
},
};

View file

@ -0,0 +1,28 @@
// Dependencies
import { Message } from "discord.js";
// Models
import counterSchema from "../../../database/schemas/counter";
import logger from "../../../logger";
export default async (message: Message) => {
const { guild, channel, author, content } = message;
const counter = await counterSchema?.findOne({
guildId: guild?.id,
channelId: channel?.id,
});
if (counter === null) return;
const { word } = counter;
if (content === word) return;
await message
?.delete()
?.then(async () => {
await channel?.send(`${author} said **${word}**.`);
})
?.catch(async (error) => {
logger.error(new Error(error));
});
};

View file

@ -1,71 +1,24 @@
import logger from "../../handlers/logger";
import config from "../../../config.json";
import deployCommands from "../../helpers/deployCommands";
import dbGuildFix from "../../helpers/dbGuildFix";
import dbMemberFix from "../../helpers/dbMemberFix";
import userSchema from "../../helpers/database/models/userSchema";
// Dependencies
import { Client } from "discord.js";
import logger from "../../logger";
// Helpers
import deployCommands from "../../handlers/deployCommands";
import updatePresence from "../../helpers/updatePresence";
import devMode from "../../helpers/devMode";
export default {
name: "ready",
once: true,
async execute(client: Client) {
// Send info message
await logger.info(`Ready! Logged in as ${client?.user?.tag}`);
logger.info(`Successfully logged into discord user: ${client?.user?.tag}!`);
await updatePresence(client);
if (config.importToDB) {
const guilds = client.guilds.cache;
await guilds.map(async (guild) => {
await guild?.members.fetch().then(async (members) => {
await members.forEach(async (member) => {
const { user } = member;
dbMemberFix(user, guild);
});
});
await dbGuildFix(guild);
});
}
if (client === null) return;
if (client.application === null) return;
if (!config?.devMode) {
client?.application?.commands
?.set([], config.bot.guildId)
.then(async () => {
logger.info(
`Removed all guild based commands from ${config.bot.guildId}`
);
});
}
if (config.clearUnused) {
await userSchema.find().then(
async (result) =>
await result.map(async (user) => {
if (
user.credits !== 0 ||
user.reputation !== 0 ||
user.points !== 0
) {
logger.info(`Not removing user: ${user}`);
} else {
logger.warn(`Removing user: ${user}`);
console.log({ userId: user.userId, guildId: user.guildId });
await userSchema
.deleteOne({ _id: user._id })
.then(async (result) => {
logger.error(`Removed user: ${user} ${result}`);
});
}
})
);
}
await devMode(client);
await deployCommands();
const guilds = client.guilds.cache;
guilds.map(async (guild) => {
logger.debug({ name: guild.name, members: guild.memberCount });
});
},
};

View file

@ -1,12 +1,23 @@
import fs from "fs"; // fs
import { Collection } from "discord.js"; // discord.js
import { Client } from "../types/common/discord";
import logger from "../logger";
export default async (client: Client) => {
client.commands = new Collection();
const commandFiles = fs.readdirSync("./src/commands");
for (const file of commandFiles) {
const command = require(`../commands/${file}`);
client.commands.set(command.default.data.name, command.default);
fs.readdir("./src/plugins", async (error: any, plugins: any) => {
if (error) {
return logger?.error(new Error(error));
}
await plugins?.map(async (pluginName: any) => {
const plugin = await import(`../plugins/${pluginName}`);
await client?.commands?.set(plugin?.default?.data?.name, plugin?.default);
logger?.debug(
`Successfully loaded plugin: ${plugin?.default?.data?.name} from ${plugin.default?.metadata?.author}`
);
});
});
};

View file

@ -0,0 +1,54 @@
// Dependencies
import { token, clientId } from "@config/discord";
import { devMode, guildId } from "@config/other";
import logger from "../logger";
import fs from "fs";
import { REST } from "@discordjs/rest";
import { Routes } from "discord-api-types/v9";
export default async () => {
fs.readdir("./src/plugins", async (error: any, plugins: any) => {
if (error) {
return logger?.error(new Error(error));
}
const pluginList = [] as any;
await plugins?.map(async (pluginName: any) => {
const plugin = await import(`../plugins/${pluginName}`);
pluginList.push(plugin.default.data.toJSON());
logger?.debug(
`Successfully deployed plugin: ${plugin?.default?.data?.name} from ${plugin.default?.metadata?.author}`
);
});
const rest = new REST({ version: "9" }).setToken(token);
await rest
.put(Routes.applicationCommands(clientId), {
body: pluginList,
})
.then(async () =>
logger.info("Successfully registered application commands.")
)
.catch(async (err: any) => {
logger.error(err);
});
if (devMode) {
await rest
.put(Routes.applicationGuildCommands(clientId, guildId), {
body: pluginList,
})
.then(async () =>
logger.info("Successfully registered guild application commands.")
)
.catch(async (err: any) => {
logger.error(err);
});
}
});
};

View file

@ -1,4 +0,0 @@
import pino from "pino";
import * as config from "../../config.json";
export default pino({ level: config.debug ? "debug" : "info" });

View file

@ -1,65 +0,0 @@
import schedule from "node-schedule";
import users from "../helpers/database/models/userSchema";
import shopRolesSchema from "../helpers/database/models/shopRolesSchema";
import guilds from "../helpers/database/models/guildSchema";
import logger from "./logger";
import { Client } from "discord.js";
export default async (client: Client) => {
schedule.scheduleJob("*/5 * * * *", async () => {
shopRolesSchema.find().then(async (shopRoles: any) => {
shopRoles.map(async (shopRole: any) => {
const payed = new Date(shopRole.lastPayed);
const oneHourAfterPayed = payed.setHours(payed.getHours() + 1);
if (new Date() > new Date(oneHourAfterPayed)) {
logger.debug(
`Role: ${shopRole.roleId} Expires: ${
new Date() < new Date(oneHourAfterPayed)
} Last Payed: ${shopRole.lastPayed}`
);
// Get guild object
const guild = await guilds.findOne({
guildId: shopRole.guildId,
});
const userDB = await users.findOne({
userId: shopRole.userId,
guildId: shopRole.guildId,
});
const { pricePerHour } = guild.shop.roles;
if (userDB === null) return;
if (userDB.credits < pricePerHour) {
const rGuild = client?.guilds?.cache?.get(`${shopRole.guildId}`);
const rMember = await rGuild?.members?.fetch(`${shopRole.userId}`);
shopRolesSchema
.deleteOne({ _id: shopRole._id })
.then(async () =>
logger.debug(`Removed ${shopRole._id} from shopRoles`)
);
return await rMember?.roles
.remove(`${shopRole.roleId}`)
.then(async (test) => console.log("4", test))
.catch(async (test) => console.log("5", test)); // Removes all roles
}
shopRole.lastPayed = new Date();
shopRole.save();
userDB.credits -= pricePerHour;
userDB.save();
await logger.debug(
`${shopRole.roleId} was payed one hour later. BEFORE: ${payed} AFTER: ${oneHourAfterPayed} UPDATED: ${shopRole.updatedAt} CREATED: ${shopRole.createdAt}`
);
}
});
});
await logger.debug("Checking schedules! (Every 5 minutes)");
});
};

View file

@ -1,2 +0,0 @@
export default (amount: number) =>
`${amount <= 1 ? `${amount} credit` : `${amount} credits`}`;

View file

@ -1,9 +0,0 @@
import mongoose from "mongoose";
import * as config from "../../../config.json";
import logger from "../../handlers/logger";
export default async () => {
await mongoose.connect(config.mongodb.url);
logger.info("Connected to the database");
};

View file

@ -1,9 +1,9 @@
// TODO This file will make sure that all guilds always has at least one entry in all collections with "guildId"
import apis from "./database/models/apiSchema";
import guilds from "./database/models/guildSchema";
import apis from "../database/schemas/api";
import guilds from "../database/schemas/guild";
import logger from "../handlers/logger";
import logger from "../logger";
import { Guild } from "discord.js";
export default async (guild: Guild) => {

View file

@ -1,5 +1,5 @@
import users from "./database/models/userSchema";
import logger from "../handlers/logger";
import users from "../database/schemas/user";
import logger from "../logger";
import { Guild, User } from "discord.js";
export default async (user: User, guild: Guild) => {

View file

@ -1,41 +0,0 @@
import config from "../../config.json";
import logger from "../handlers/logger";
import fs from "fs";
import { REST } from "@discordjs/rest";
import { Routes } from "discord-api-types/v9";
export default async () => {
const commands = [];
const commandFiles = fs.readdirSync("./src/commands");
for (const file of commandFiles) {
// eslint-disable-next-line global-require
const command = require(`../commands/${file}`);
commands.push(command.default.data.toJSON());
}
const rest = new REST({ version: "9" }).setToken(config.bot.token);
await rest.put(Routes.applicationCommands(config.bot.clientId), {
body: commands,
});
if (config?.devMode) {
await rest
.put(
Routes.applicationGuildCommands(
config.bot.clientId,
config.bot.guildId
),
{
body: commands,
}
)
.then(async () =>
logger.info("Successfully registered application commands.")
)
.catch(async (err) => {
await logger.error(err);
});
}
};

15
src/helpers/devMode.ts Normal file
View file

@ -0,0 +1,15 @@
// Dependencies
import { Client } from "discord.js";
import logger from "@logger";
// Configuration
import { devMode, guildId } from "@config/other";
export default async (client: Client) => {
if (!devMode) {
client?.application?.commands?.set([], guildId).then(async () => {
logger.verbose(`Removed all guild based commands from ${guildId}`);
});
}
};

View file

@ -1,11 +1,11 @@
import guilds from "../helpers/database/models/guildSchema";
import users from "../helpers/database/models/userSchema";
import apis from "../helpers/database/models/apiSchema";
import counters from "../helpers/database/models/counterSchema";
import shopRoles from "../helpers/database/models/shopRolesSchema";
import timeouts from "../helpers/database/models/timeoutSchema";
import guilds from "../database/schemas/guild";
import users from "../database/schemas/user";
import apis from "../database/schemas/api";
import counters from "../database/schemas/counter";
import shopRoles from "../database/schemas/shopRole";
import timeouts from "../database/schemas/timeout";
import logger from "../handlers/logger";
import logger from "../logger";
import { Guild } from "discord.js";

View file

@ -1,6 +1,6 @@
import users from "../helpers/database/models/userSchema";
import users from "../database/schemas/user";
import logger from "../handlers/logger";
import logger from "../logger";
import { Guild, User } from "discord.js";

View file

@ -2,18 +2,18 @@
import { Guild } from "discord.js";
// Models
import guildSchema from "./database/models/guildSchema";
import guildSchema from "../database/schemas/guild";
// Handlers
import logger from "../handlers/logger";
import logger from "../logger";
// Function
export default async (guild: Guild) => {
const guildObj = await guildSchema?.findOne({ guildId: guild.id });
if (guildObj === null) {
const guildObj = new guildSchema({ guildId: guild.id });
const newGuildObj = new guildSchema({ guildId: guild.id });
await guildObj
await newGuildObj
.save()
.then(async () => {
logger.debug(
@ -24,7 +24,7 @@ export default async (guild: Guild) => {
logger.error(err);
});
return guildObj;
return newGuildObj;
} else {
return guildObj;
}

View file

@ -2,10 +2,10 @@
import { Guild, User } from "discord.js";
// Models
import userSchema from "./database/models/userSchema";
import userSchema from "../database/schemas/user";
// Handlers
import logger from "../handlers/logger";
import logger from "../logger";
// Function
export default async (user: User, guild: Guild) => {
@ -14,12 +14,12 @@ export default async (user: User, guild: Guild) => {
guildId: guild.id,
});
if (userObj === null) {
const userObj = new userSchema({
const newUserObj = new userSchema({
userId: user.id,
guildId: guild.id,
});
await userObj
await newUserObj
.save()
.then(async () => {
logger.debug(
@ -30,7 +30,7 @@ export default async (user: User, guild: Guild) => {
logger.error(err);
});
return userObj;
return newUserObj;
} else {
return userObj;
}

3
src/helpers/index.ts Normal file
View file

@ -0,0 +1,3 @@
import pluralize from "./pluralize";
export default { pluralize };

2
src/helpers/pluralize.ts Normal file
View file

@ -0,0 +1,2 @@
export default (count: number, noun: string, suffix?: string) =>
`${count} ${noun}${count !== 1 ? suffix || "s" : ""}`;

View file

@ -1,5 +1,5 @@
import sleep from "./sleep";
import logger from "../handlers/logger";
import logger from "../logger";
import Chance from "chance";
export default async function saveUser(data: any, data2: any) {

View file

@ -1,16 +1,17 @@
// Dependencies
import "tsconfig-paths/register"; // Allows using tsconfig.json paths during runtime
import { Client, Intents } from "discord.js"; // discord.js
import database from "./helpers/database";
import events from "./handlers/events";
import commands from "./handlers/commands";
import locale from "./handlers/locale";
import schedules from "./handlers/schedules";
import locale from "@locale";
import database from "@database";
import schedules from "@schedules";
import config from "../config.json"; // config.json
import events from "@handlers/events";
import commands from "@handlers/commands";
// Configurations
import { token } from "@config/discord";
(async () => {
// Initialize discord.js client
const client = new Client({
intents: [
Intents?.FLAGS?.GUILDS,
@ -19,10 +20,11 @@ import config from "../config.json"; // config.json
],
});
await database();
await locale();
await events(client);
await commands(client);
await schedules(client);
await client?.login(config?.bot?.token);
})();
locale();
database();
schedules(client);
commands(client);
events(client);
client?.login(token);

26
src/logger/index.ts Normal file
View file

@ -0,0 +1,26 @@
import winston from "winston";
import "winston-daily-rotate-file";
const { combine, timestamp, printf, colorize, align, json } = winston.format;
export default winston.createLogger({
level: process.env.LOG_LEVEL || "silly",
transports: [
new winston.transports.DailyRotateFile({
filename: "logs/combined-%DATE%.log",
datePattern: "YYYY-MM-DD",
maxFiles: "14d",
format: combine(timestamp(), json()),
}),
new winston.transports.Console({
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,20 @@
// Dependencies
import { CommandInteraction } from "discord.js";
import { SlashCommandBuilder } from "@discordjs/builders";
import modules from "@root/plugins/counters/modules";
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("counters")
.setDescription("Manage counters.")
.addSubcommand(modules.view.data),
async execute(interaction: CommandInteraction) {
const { options } = interaction;
if (options?.getSubcommand() === "view") {
return modules.view.execute(interaction);
}
},
};

View file

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

View file

@ -0,0 +1,71 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10";
import counterSchema from "@schemas/counter";
// Configuration
import {
errorColor,
successColor,
footerText,
footerIcon,
} from "@config/embed";
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("view")
.setDescription("View a counter's count.")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The counter channel you want to view.")
.setRequired(true)
.addChannelType(ChannelType.GuildText as number)
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild } = interaction;
const discordChannel = options?.getChannel("channel");
const counter = await counterSchema?.findOne({
guildId: guild?.id,
channelId: discordChannel?.id,
});
if (counter === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:1234:] Counters (View)")
.setDescription(`${discordChannel} is not a counting channel!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({
text: footerText,
iconURL: footerIcon,
}),
],
});
}
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:1234:] Counters (View)")
.setDescription(
`${discordChannel} is currently at number ${counter?.counter}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({
text: footerText,
iconURL: footerIcon,
}),
],
});
},
};

View file

@ -0,0 +1,36 @@
// Dependencies
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction } from "discord.js";
// Modules
import modules from "@root/plugins/credits/modules";
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("credits")
.setDescription("Manage your credits.")
.addSubcommand(modules.balance.data)
.addSubcommand(modules.gift.data)
.addSubcommand(modules.top.data)
.addSubcommand(modules.work.data),
async execute(interaction: CommandInteraction) {
const { options } = interaction;
if (options?.getSubcommand() === "balance") {
return modules.balance.execute(interaction);
}
if (options?.getSubcommand() === "gift") {
return modules.gift.execute(interaction);
}
if (options?.getSubcommand() === "top") {
return modules.top.execute(interaction);
}
if (options?.getSubcommand() === "work") {
return modules.work.execute(interaction);
}
},
};

View file

@ -0,0 +1,100 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Configurations
import {
errorColor,
successColor,
footerText,
footerIcon,
} from "@config/embed";
// Helpers
import pluralize from "@helpers/pluralize";
import fetchUser from "@helpers/fetchUser";
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return (
command
.setName("balance")
.setDescription("Check a user's balance.")
// User
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user whose balance you want to check.")
)
);
},
execute: async (interaction: CommandInteraction) => {
const { options, user, guild } = interaction;
const discordUser = options?.getUser("user");
if (guild === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(`We can not find your guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
const userObj = await fetchUser(discordUser || user, guild);
if (userObj === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(
`We can not find ${discordUser || "you"} in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (userObj.credits === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(
`We can not find credits for ${
discordUser || "you"
} in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Balance)")
.setDescription(
`${discordUser || "You"} have ${pluralize(
userObj.credits,
"credit"
)}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
},
};

View file

@ -0,0 +1,249 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
// Configurations
import {
errorColor,
successColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "../../../../logger";
// Helpers
import saveUser from "../../../../helpers/saveUser";
import pluralize from "../../../../helpers/pluralize";
// Models
import fetchUser from "../../../../helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("gift")
.setDescription("Gift someone credits from your credits.")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to pay.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will pay.")
.setRequired(true)
)
.addStringOption((option) =>
option.setName("reason").setDescription("Your reason.")
);
},
execute: async (interaction: CommandInteraction) => {
const { options, user, guild, client } = interaction;
const optionUser = options?.getUser("user");
const optionAmount = options?.getInteger("amount");
const optionReason = options?.getString("reason");
if (guild === null) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(`We can not find your guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (optionUser === null) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(`We can not find your requested user!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// Get fromUserDB object
const fromUserDB = await fetchUser(user, guild);
// Get toUserDB object
const toUserDB = await fetchUser(optionUser, guild);
if (fromUserDB === null) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`We can not find your requested from user in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (toUserDB === null) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`We can not find your requested to user in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If receiver is same as sender
if (optionUser?.id === user?.id) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(`You can not pay yourself!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If amount is null
if (optionAmount === null) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(`We could not read your requested amount!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If amount is zero or below
if (optionAmount <= 0) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(`You can't gift zero or below!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If user has below gifting amount
if (fromUserDB?.credits < optionAmount) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`You have insufficient credits. Your balance is ${fromUserDB?.credits}!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If toUserDB has no credits
if (toUserDB === null) {
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`We can not find your requested to user in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// Withdraw amount from fromUserDB
fromUserDB.credits -= optionAmount;
// Deposit amount to toUserDB
toUserDB.credits += optionAmount;
// Save users
await saveUser(fromUserDB, toUserDB)?.then(async () => {
// Get DM user object
const dmUser = client?.users?.cache?.get(optionUser?.id);
// Send DM to user
await dmUser
?.send({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`You received ${pluralize(
optionAmount,
"credit"
)} from ${user}${
optionReason ? ` with reason: ${optionReason}` : ""
}. Your new credits is ${pluralize(
toUserDB?.credits,
"credit"
)}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
})
.catch(async () =>
logger.debug(`Can not send DM to user ${optionUser?.id}`)
);
// Send debug message
logger.debug(
`Guild: ${guild?.id} User: ${user?.id} gift sent from: ${user?.id} to: ${optionUser?.id}`
);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Gift)")
.setDescription(
`You sent ${pluralize(optionAmount, "credit")} to ${optionUser}${
optionReason ? ` with reason: ${optionReason}` : ""
}. Your new credits is ${pluralize(
fromUserDB?.credits,
"credit"
)}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
},
};

View file

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

View file

@ -0,0 +1,52 @@
// Dependencies
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { CommandInteraction, MessageEmbed } from "discord.js";
import userSchema from "@schemas/user";
// Configurations
import { successColor, footerText, footerIcon } from "@config/embed";
// Helpers
import pluralize from "@helpers/pluralize";
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command.setName("top").setDescription("Check the top balance.");
},
execute: async (interaction: CommandInteraction) => {
// Get all users in the guild
const usersDB = await userSchema.find({ guildId: interaction?.guild?.id });
const topTen = usersDB
// Sort them after credits amount (ascending)
.sort((a, b) => (a?.credits > b?.credits ? -1 : 1))
// Return the top 10
.slice(0, 10);
// Create entry object
const entry = (x: any, index: number) =>
`**Top ${index + 1}** - <@${x?.userId}> ${pluralize(
x?.credits,
"credit"
)}`;
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Top)")
.setDescription(
`Below are the top ten.
${topTen?.map((x, index) => entry(x, index))?.join("\n")}`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
},
};

View file

@ -0,0 +1,117 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import Chance from "chance";
// Configurations
import { successColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "@logger";
// Models
import timeoutSchema from "@schemas/timeout";
// Helpers
import pluralize from "@helpers/pluralize";
import fetchUser from "@helpers/fetchUser";
import fetchGuild from "@helpers/fetchGuild";
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command.setName("work").setDescription("Work for credits.");
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { guild, user } = interaction;
// Chance module
const chance = new Chance();
// Check if user has a timeout
const isTimeout = await timeoutSchema?.findOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
if (guild === null) return;
const guildDB = await fetchGuild(guild);
// If user is not on timeout
if (!isTimeout) {
const creditsEarned = chance.integer({
min: 0,
max: guildDB?.credits?.workRate,
});
const userDB = await fetchUser(user, guild);
if (userDB === null) return;
userDB.credits += creditsEarned;
await userDB?.save()?.then(async () => {
logger?.debug(`Credits added to user: ${user?.id}`);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Work)")
.setDescription(
`You have earned ${pluralize(creditsEarned, "credit")}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
// Create a timeout for the user
await timeoutSchema?.create({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
setTimeout(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} has not worked within the last ${
guildDB?.credits?.workTimeout / 1000
} seconds, work can be done`
);
// When timeout is out, remove it from the database
await timeoutSchema?.deleteOne({
guildId: guild?.id,
userId: user?.id,
timeoutId: "2022-03-15-19-16",
});
}, guildDB?.credits?.workTimeout);
} else {
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has worked within last day, no work can be done`
);
return interaction.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:dollar:] Credits (Work)")
.setDescription(
`You have worked within the last ${
guildDB?.credits?.workTimeout / 1000
} seconds, you can not work now!`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
},
};

View file

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

View file

@ -0,0 +1,100 @@
// Dependencies
import { MessageEmbed, CommandInteraction } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10";
// Configurations
import {
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "@logger";
// Models
import counterSchema from "../../../../../../database/schemas/counter";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("create")
.setDescription("Add a counter to your guild.")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The channel you want to add a counter to.")
.setRequired(true)
.addChannelType(ChannelType.GuildText as number)
)
.addStringOption((option) =>
option
.setName("word")
.setDescription("The word you want to count.")
.setRequired(true)
)
.addNumberOption((option) =>
option
.setName("start")
.setDescription("The count that the counter will start at.")
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild, user } = interaction;
const discordChannel = options?.getChannel("channel");
const countingWord = options?.getString("word");
const startValue = options?.getNumber("start");
const counter = await counterSchema?.findOne({
guildId: guild?.id,
channelId: discordChannel?.id,
});
if (counter) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Create)")
.setDescription(
`${discordChannel} is already a counting channel, currently it's counting ${counter.word}!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
await counterSchema
?.create({
guildId: guild?.id,
channelId: discordChannel?.id,
word: countingWord,
counter: startValue || 0,
})
.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} added ${discordChannel?.id} as a counter using word "${countingWord}" for counting.`
);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Create)")
.setDescription(
`${discordChannel} is now counting when hearing word ${countingWord} and it starts at number ${
startValue || 0
}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
},
};

View file

@ -0,0 +1,81 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
// Configurations
import {
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "@logger";
// Models
import counterSchema from "../../../../../../database/schemas/counter";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { ChannelType } from "discord-api-types/v10";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("delete")
.setDescription("Delete a counter from your guild.")
.addChannelOption((option) =>
option
.setName("channel")
.setDescription("The channel that you want to delete a counter from.")
.setRequired(true)
.addChannelType(ChannelType.GuildText as number)
);
},
execute: async (interaction: CommandInteraction) => {
const { options, guild, user } = interaction;
const discordChannel = options?.getChannel("channel");
const counter = await counterSchema?.findOne({
guildId: guild?.id,
channelId: discordChannel?.id,
});
if (counter === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Delete)")
.setDescription(`${discordChannel} is not a counting channel!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
await counterSchema
?.deleteOne({
guildId: guild?.id,
channelId: discordChannel?.id,
})
?.then(async () => {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Counters (Delete)")
.setDescription(
`${discordChannel} is no longer an counting channel.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} removed ${discordChannel?.id} as a counter.`
);
},
};

View file

@ -0,0 +1,41 @@
// Dependencies
import { CommandInteraction } from "discord.js";
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
// 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 guild member's credits.")
.addSubcommand(moduleGive.data)
.addSubcommand(moduleSet.data)
.addSubcommand(moduleTake.data)
.addSubcommand(moduleTransfer.data);
},
execute: async (interaction: CommandInteraction) => {
const { options } = interaction;
if (options?.getSubcommand() === "give") {
return moduleGive.execute(interaction);
}
if (options?.getSubcommand() === "set") {
return moduleSet.execute(interaction);
}
if (options?.getSubcommand() === "take") {
return moduleTake.execute(interaction);
}
if (options?.getSubcommand() === "transfer") {
return moduleTransfer.execute(interaction);
}
},
};

View file

@ -0,0 +1,161 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Configurations
import {
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
// Models
import fetchUser from "@helpers/fetchUser";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("give")
.setDescription("Give credits to a user")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to pay.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will pay.")
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure
const { guild, user, options } = interaction;
const discordReceiver = options?.getUser("user");
const creditAmount = options?.getInteger("amount");
// If amount option is null
if (creditAmount === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`We could not read your requested amount!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If amount is zero or below
if (creditAmount <= 0) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`You can not give zero credits or below!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (discordReceiver === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`We could not read receiver user!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (guild === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(`We could not read your guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
const toUser = await fetchUser(discordReceiver, guild);
if (toUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(
`We could not read your receiver user from our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (toUser?.credits === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(
`We could not find credits for ${discordReceiver} in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// Deposit amount to toUser
toUser.credits += creditAmount;
// Save toUser
await toUser?.save()?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} gave ${
discordReceiver?.id
} ${pluralize(creditAmount, "credit")}.`
);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Give)")
.setDescription(
`We have given ${discordReceiver}, ${pluralize(
creditAmount,
"credit"
)}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
},
};

View file

@ -0,0 +1,149 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
// Configurations
import {
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
// Models
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("set")
.setDescription("Set credits to a user")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to set credits on.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will set.")
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
const { options, user, guild } = interaction;
const discordUser = options.getUser("user");
const creditAmount = options.getInteger("amount");
// If amount is null
if (creditAmount === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`We could not read your requested amount!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (discordUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`We could not read your requested user!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (guild === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(`We could not read your guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// toUser Information
const toUser = await fetchUser(discordUser, guild);
// If toUser does not exist
if (toUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(
`We could not read your requested user from our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If toUser.credits does not exist
if (toUser?.credits === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(
`We could not find credits for ${discordUser} in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// Set toUser with amount
toUser.credits = creditAmount;
// Save toUser
await toUser?.save()?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} set ${
discordUser?.id
} to ${pluralize(creditAmount, "credit")}.`
);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Set)")
.setDescription(
`We have set ${discordUser} to ${pluralize(
creditAmount,
"credit"
)}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
},
};

View file

@ -0,0 +1,167 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
// Configurations
import {
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
// Models
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("take")
.setDescription("Take credits from a user")
.addUserOption((option) =>
option
.setName("user")
.setDescription("The user you want to take credits from.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will take.")
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure
const { guild, user, options } = interaction;
// User option
const optionUser = options?.getUser("user");
// Amount option
const optionAmount = options?.getInteger("amount");
// If amount is null
if (optionAmount === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not read your requested amount!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If amount is zero or below
if (optionAmount <= 0) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not take zero credits or below!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (optionUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not read your requested user!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (guild === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(`We could not read your guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// toUser Information
const toUser = await fetchUser(optionUser, guild);
// If toUser does not exist
if (toUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(
`We could not read your requested user from our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If toUser.credits does not exist
if (toUser?.credits === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(
`We could not find credits for ${optionUser} in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// Withdraw amount from toUser
toUser.credits -= optionAmount;
// Save toUser
await toUser?.save()?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} set ${
optionUser?.id
} to ${pluralize(optionAmount, "credit")}.`
);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Take)")
.setDescription(
`We have taken ${pluralize(
optionAmount,
"credit"
)} from ${optionUser}.`
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
},
};

View file

@ -0,0 +1,222 @@
// Dependencies
import { CommandInteraction, MessageEmbed } from "discord.js";
// Configurations
import {
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
// Handlers
import logger from "@logger";
// Helpers
import pluralize from "@helpers/pluralize";
import saveUser from "@helpers/saveUser";
// Models
import fetchUser from "@helpers/fetchUser";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("transfer")
.setDescription("Transfer credits from a user to another user.")
.addUserOption((option) =>
option
.setName("from")
.setDescription("The user you want to take credits from.")
.setRequired(true)
)
.addUserOption((option) =>
option
.setName("to")
.setDescription("The user you want to give credits to.")
.setRequired(true)
)
.addIntegerOption((option) =>
option
.setName("amount")
.setDescription("The amount you will transfer.")
.setRequired(true)
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { guild, options, user } = interaction;
// Get options
const optionFromUser = options?.getUser("from");
const optionToUser = options?.getUser("to");
const optionAmount = options?.getInteger("amount");
// If amount is null
if (optionAmount === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your requested amount!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (guild === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your guild!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (optionFromUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your requested from user!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (optionToUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(`We could not read your requested to user!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// Get fromUser object
const fromUser = await fetchUser(optionFromUser, guild);
// Get toUser object
const toUser = await fetchUser(optionToUser, guild);
// If toUser does not exist
if (fromUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not read your requested from user from our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If toUser.credits does not exist
if (!fromUser?.credits) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not find credits for ${optionFromUser} in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If toUser does not exist
if (toUser === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not read your requested to user from our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// If toUser.credits does not exist
if (toUser?.credits === null) {
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We could not find credits for ${optionToUser} in our database!`
)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
// Withdraw amount from fromUser
fromUser.credits -= optionAmount;
// Deposit amount to toUser
toUser.credits += optionAmount;
// Save users
await saveUser(fromUser, toUser)?.then(async () => {
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} transferred ${pluralize(
optionAmount,
"credit"
)} from ${optionFromUser?.id} to ${optionToUser?.id}.`
);
return interaction?.editReply({
embeds: [
new MessageEmbed()
.setTitle("[:toolbox:] Manage - Credits (Transfer)")
.setDescription(
`We have sent ${pluralize(
optionAmount,
"credit"
)} from ${optionFromUser} to ${optionToUser}.`
)
.addFields(
{
name: `${optionFromUser?.username} Balance`,
value: `${fromUser?.credits}`,
inline: true,
},
{
name: `${optionToUser?.username} Balance`,
value: `${toUser?.credits}`,
inline: true,
}
)
.setTimestamp(new Date())
.setColor(successColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
});
},
};

View file

@ -0,0 +1,47 @@
//Dependencies
import { SlashCommandBuilder } from "@discordjs/builders";
import { CommandInteraction, Permissions, MessageEmbed } from "discord.js";
// Configurations
import { errorColor, footerText, footerIcon } from "@config/embed";
// Groups
import credits from "./groups/credits";
import counters from "./groups/counters";
// Function
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("manage")
.setDescription("Manage your guild.")
.addSubcommandGroup(counters.data)
.addSubcommandGroup(credits.data),
async execute(interaction: CommandInteraction) {
// Destructure
const { memberPermissions, 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 permission to manage this!`)
.setTimestamp(new Date())
.setColor(errorColor)
.setFooter({ text: footerText, iconURL: footerIcon }),
],
});
}
if (options?.getSubcommandGroup() === "credits") {
return credits.execute(interaction);
}
if (options?.getSubcommandGroup() === "counters") {
return counters.execute(interaction);
}
},
};

View file

@ -6,10 +6,11 @@ import { CommandInteraction } from "discord.js";
import view from "./modules/view";
// Handlers
import logger from "../../handlers/logger";
import logger from "../../logger";
// Function
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("profile")
.setDescription("Check a profile.")

View file

@ -1,11 +1,11 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
import { CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../config.json";
import { successColor, footerText, footerIcon } from "@config/embed";
// Models
import fetchUser from "../../../helpers/fetchUser";
import fetchUser from "@helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
@ -28,41 +28,41 @@ export default async (interaction: CommandInteraction) => {
// Embed object
const embed = {
author: {
name: `${discordUser?.username}#${discordUser?.discriminator}` as string,
icon_url: discordUser?.displayAvatarURL() as string,
name: `${discordUser?.username}#${discordUser?.discriminator}`,
icon_url: discordUser?.displayAvatarURL(),
},
color: config?.colors?.success as ColorResolvable,
color: successColor,
fields: [
{
name: `:dollar: Credits` as string,
value: `${userObj?.credits || "Not found"}` as string,
name: `:dollar: Credits`,
value: `${userObj?.credits || "Not found"}`,
inline: true,
},
{
name: `:squeeze_bottle: Level` as string,
value: `${userObj?.level || "Not found"}` as string,
name: `:squeeze_bottle: Level`,
value: `${userObj?.level || "Not found"}`,
inline: true,
},
{
name: `:squeeze_bottle: Points` as string,
value: `${userObj?.points || "Not found"}` as string,
name: `:squeeze_bottle: Points`,
value: `${userObj?.points || "Not found"}`,
inline: true,
},
{
name: `:loudspeaker: Reputation` as string,
value: `${userObj?.reputation || "Not found"}` as string,
name: `:loudspeaker: Reputation`,
value: `${userObj?.reputation || "Not found"}`,
inline: true,
},
{
name: `:rainbow_flag: Language` as string,
value: `${userObj?.language || "Not found"}` as string,
name: `:rainbow_flag: Language`,
value: `${userObj?.language || "Not found"}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
iconURL: footerIcon,
text: footerText,
},
};

View file

@ -6,10 +6,11 @@ import { CommandInteraction } from "discord.js";
import give from "./modules/give";
// Handlers
import logger from "../../handlers/logger";
import logger from "../../logger";
// Function
export default {
metadata: { author: "Zyner" },
data: new SlashCommandBuilder()
.setName("reputation")
.setDescription("Give reputation.")

View file

@ -1,15 +1,22 @@
// Dependencies
import { CommandInteraction, ColorResolvable } from "discord.js";
import { CommandInteraction } from "discord.js";
// Configurations
import config from "../../../../config.json";
import {
successColor,
errorColor,
footerText,
footerIcon,
} from "@config/embed";
import { timeout } from "@config/reputation";
// Handlers
import logger from "../../../handlers/logger";
import logger from "@logger";
// Models
import timeoutSchema from "../../../helpers/database/models/timeoutSchema";
import fetchUser from "../../../helpers/fetchUser";
import timeoutSchema from "@schemas/timeout";
import fetchUser from "@helpers/fetchUser";
// Function
export default async (interaction: CommandInteraction) => {
@ -42,13 +49,13 @@ export default async (interaction: CommandInteraction) => {
if (optionTarget?.id === user?.id) {
// Embed object
const embed = {
title: ":loudspeaker: Reputation [Give]" as string,
description: "You can not repute yourself." as string,
title: ":loudspeaker: Reputation [Give]",
description: "You can not repute yourself.",
timestamp: new Date(),
color: config?.colors?.error as ColorResolvable,
color: errorColor,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
iconURL: footerIcon,
text: footerText,
},
};
@ -70,14 +77,13 @@ export default async (interaction: CommandInteraction) => {
await userObj?.save()?.then(async () => {
// Embed object
const embed = {
title: ":loudspeaker: Reputation [Give]" as string,
description:
`You have given ${optionTarget} a ${optionType} reputation!` as string,
title: ":loudspeaker: Reputation [Give]",
description: `You have given ${optionTarget} a ${optionType} reputation!`,
timestamp: new Date(),
color: config?.colors?.success as ColorResolvable,
color: successColor,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
iconURL: footerIcon,
text: footerText,
},
};
@ -99,9 +105,7 @@ export default async (interaction: CommandInteraction) => {
setTimeout(async () => {
// send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has not repute within last ${
config?.reputation?.timeout / 1000
} seconds, reputation can be given`
`Guild: ${guild?.id} User: ${user?.id} has not repute within last ${timeout} seconds, reputation can be given`
);
// When timeout is out, remove it from the database
@ -110,27 +114,23 @@ export default async (interaction: CommandInteraction) => {
userId: user?.id,
timeoutId: "2022-04-10-16-42",
});
}, config?.reputation?.timeout);
}, timeout);
} else {
// Create embed object
const embed = {
title: ":loudspeaker: Reputation [Give]" as string,
description: `You have given reputation within the last ${
config?.reputation?.timeout / 1000
} seconds, you can not repute now!` as string,
title: ":loudspeaker: Reputation [Give]",
description: `You have given reputation within the last ${timeout} seconds, you can not repute now!`,
timestamp: new Date(),
color: config.colors.error as ColorResolvable,
color: errorColor,
footer: {
iconURL: config?.footer?.icon as string,
text: config?.footer?.text as string,
iconURL: footerIcon,
text: footerText,
},
};
// Log debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has repute within last ${
config?.reputation?.timeout / 1000
} seconds, no reputation can be given`
`Guild: ${guild?.id} User: ${user?.id} has repute within last ${timeout} seconds, no reputation can be given`
);
// Return interaction reply

View file

@ -0,0 +1,74 @@
// 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 { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
// Function
export default {
data: (group: SlashCommandSubcommandGroupBuilder) => {
return group
.setName("guild")
.setDescription("Manage guild settings.")
.addSubcommand(pterodactyl.data)
.addSubcommand(credits.data)
.addSubcommand(points.data);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { memberPermissions, options, commandName, user, guild } =
interaction;
// Check permission
if (!memberPermissions?.has(Permissions?.FLAGS?.MANAGE_GUILD)) {
// Create embed object
const embed = {
title: ":tools: Settings - Guild",
color: errorColor,
description: "You do not have permission to manage this!",
timestamp: new Date(),
footer: {
iconURL: footerIcon as string,
text: footerText as string,
},
};
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
}
// Module - Pterodactyl
if (options?.getSubcommand() === "pterodactyl") {
// Execute Module - Pterodactyl
return pterodactyl.execute(interaction);
}
// Module - Credits
else if (options?.getSubcommand() === "credits") {
// Execute Module - Credits
return credits.execute(interaction);
}
// Module - Points
else if (options?.getSubcommand() === "points") {
// Execute Module - Points
return points.execute(interaction);
}
// Send debug message
return logger?.debug(
`Guild: ${guild?.id} User: ${
user?.id
} executed /${commandName} ${options?.getSubcommandGroup()} ${options?.getSubcommand()}`
);
},
};

View file

@ -0,0 +1,134 @@
// Dependencies
import { CommandInteraction } from "discord.js";
// Configurations
import { successColor, footerText, footerIcon } from "@config/embed";
//Handlers
import logger from "@logger";
// Models
import guildSchema from "@schemas/guild";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("credits")
.setDescription("Credits")
.addBooleanOption((option) =>
option.setName("status").setDescription("Should credits be enabled?")
)
.addNumberOption((option) =>
option.setName("rate").setDescription("Amount of credits per message.")
)
.addNumberOption((option) =>
option
.setName("minimum-length")
.setDescription("Minimum length of message to earn credits.")
)
.addNumberOption((option) =>
option
.setName("work-rate")
.setDescription("Maximum amount of credits on work.")
)
.addNumberOption((option) =>
option
.setName("work-timeout")
.setDescription("Timeout between work schedules (milliseconds).")
)
.addNumberOption((option) =>
option
.setName("timeout")
.setDescription("Timeout between earning credits (milliseconds).")
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { guild, user, options } = interaction;
// Get options
const status = options?.getBoolean("status");
const rate = options?.getNumber("rate");
const timeout = options?.getNumber("timeout");
const minimumLength = options?.getNumber("minimum-length");
const workRate = options?.getNumber("work-rate");
const workTimeout = options?.getNumber("work-timeout");
// Get guild object
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
if (guildDB === null) return;
// Modify values
guildDB.credits.status =
status !== null ? status : guildDB?.credits?.status;
guildDB.credits.rate = rate !== null ? rate : guildDB?.credits?.rate;
guildDB.credits.timeout =
timeout !== null ? timeout : guildDB?.credits?.timeout;
guildDB.credits.workRate =
workRate !== null ? workRate : guildDB?.credits?.workRate;
guildDB.credits.workTimeout =
workTimeout !== null ? workTimeout : guildDB?.credits?.workTimeout;
guildDB.credits.minimumLength =
minimumLength !== null ? minimumLength : guildDB?.credits?.minimumLength;
// Save guild
await guildDB?.save()?.then(async () => {
// Embed object
const embed = {
title: ":tools: Settings - Guild [Credits]",
description: "Following settings is set!",
color: successColor,
fields: [
{
name: "🤖 Status",
value: `${guildDB?.credits?.status}`,
inline: true,
},
{
name: "📈 Rate",
value: `${guildDB?.credits?.rate}`,
inline: true,
},
{
name: "📈 Work Rate",
value: `${guildDB?.credits?.workRate}`,
inline: true,
},
{
name: "🔨 Minimum Length",
value: `${guildDB?.credits?.minimumLength}`,
inline: true,
},
{
name: "⏰ Timeout",
value: `${guildDB?.credits?.timeout}`,
inline: true,
},
{
name: "⏰ Work Timeout",
value: `${guildDB?.credits?.workTimeout}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user.id} has changed credit details.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
},
};

View file

@ -0,0 +1,107 @@
// Dependencies
import { CommandInteraction } from "discord.js";
// Configurations
import { successColor, footerText, footerIcon } from "@config/embed";
// Handlers
import logger from "../../../../logger";
// Models
import guildSchema from "../../../../database/schemas/guild";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
// Function
export default {
data: (command: SlashCommandSubcommandBuilder) => {
return command
.setName("points")
.setDescription("Points")
.addBooleanOption((option) =>
option.setName("status").setDescription("Should credits be enabled?")
)
.addNumberOption((option) =>
option.setName("rate").setDescription("Amount of credits per message.")
)
.addNumberOption((option) =>
option
.setName("minimum-length")
.setDescription("Minimum length of message to earn credits.")
)
.addNumberOption((option) =>
option
.setName("timeout")
.setDescription("Timeout between earning credits (milliseconds).")
);
},
execute: async (interaction: CommandInteraction) => {
// Destructure member
const { options, guild, user } = interaction;
// Get options
const status = options?.getBoolean("status");
const rate = options?.getNumber("rate");
const timeout = options?.getNumber("timeout");
const minimumLength = options?.getNumber("minimum-length");
// Get guild object
const guildDB = await guildSchema?.findOne({
guildId: guild?.id,
});
if (guildDB === null) return;
// Modify values
guildDB.points.status = status !== null ? status : guildDB?.points?.status;
guildDB.points.rate = rate !== null ? rate : guildDB?.points?.rate;
guildDB.points.timeout =
timeout !== null ? timeout : guildDB?.points?.timeout;
guildDB.points.minimumLength =
minimumLength !== null ? minimumLength : guildDB?.points?.minimumLength;
// Save guild
await guildDB?.save()?.then(async () => {
// Create embed object
const embed = {
title: ":hammer: Settings - Guild [Points]",
description: "Following settings is set!",
color: successColor,
fields: [
{
name: "🤖 Status",
value: `${guildDB?.points?.status}`,
inline: true,
},
{
name: "📈 Rate",
value: `${guildDB?.points?.rate}`,
inline: true,
},
{
name: "🔨 Minimum Length",
value: `${guildDB?.points?.minimumLength}`,
inline: true,
},
{
name: "⏰ Timeout",
value: `${guildDB?.points?.timeout}`,
inline: true,
},
],
timestamp: new Date(),
footer: {
iconURL: footerIcon,
text: footerText,
},
};
// Send debug message
logger?.debug(
`Guild: ${guild?.id} User: ${user?.id} has changed credit details.`
);
// Return interaction reply
return interaction?.editReply({ embeds: [embed] });
});
},
};

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