commit
d26402115f
40 changed files with 937 additions and 231 deletions
|
@ -13,6 +13,7 @@ inställningar
|
|||
inte
|
||||
Krediter
|
||||
multistream
|
||||
nastyox
|
||||
Nivå
|
||||
omdöme
|
||||
Omdöme
|
||||
|
@ -20,11 +21,15 @@ Otillgänglig
|
|||
pino
|
||||
Poäng
|
||||
Profil
|
||||
rando
|
||||
satta
|
||||
senaste
|
||||
Sifell
|
||||
själv
|
||||
Språk
|
||||
Språkkod
|
||||
upsert
|
||||
uuidv
|
||||
Vermium
|
||||
xyter
|
||||
Zyner
|
||||
|
|
2
.eslintignore
Normal file
2
.eslintignore
Normal file
|
@ -0,0 +1,2 @@
|
|||
node_modules
|
||||
dist
|
15
.eslintrc
Normal file
15
.eslintrc
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint", "no-loops", "prettier"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"no-console": 1,
|
||||
"no-loops/no-loops": 2
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@typescript-eslint", "prettier"],
|
||||
"plugins": ["@typescript-eslint", "no-loops", "prettier"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
|
@ -9,10 +9,7 @@
|
|||
"prettier"
|
||||
],
|
||||
"rules": {
|
||||
"@typescript-eslint/ban-ts-comment": 0,
|
||||
"@typescript-eslint/no-var-requires": 0,
|
||||
"@typescript-eslint/no-explicit-any": 0,
|
||||
"no-async-promise-executor": 0,
|
||||
"prettier/prettier": "error"
|
||||
"no-console": 1,
|
||||
"no-loops/no-loops": 2
|
||||
}
|
||||
}
|
||||
|
|
1
.husky/.gitignore
vendored
Normal file
1
.husky/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
_
|
4
.husky/pre-commit
Normal file
4
.husky/pre-commit
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx lint-staged
|
|
@ -1,34 +0,0 @@
|
|||
{
|
||||
"bot": {
|
||||
"token": "required",
|
||||
"clientId": "required",
|
||||
"guildId": "required"
|
||||
},
|
||||
"colors": {
|
||||
"success": "0x22bb33",
|
||||
"error": "0xbb2124",
|
||||
"wait": "0xf0ad4e"
|
||||
},
|
||||
"mongodb": {
|
||||
"url": "mongodb+srv://username:password@server/database?retryWrites=true&w=majority"
|
||||
},
|
||||
"footer": {
|
||||
"icon": "https://avatars.githubusercontent.com/u/83163073",
|
||||
"text": "https://github.com/ZynerOrg/xyter"
|
||||
},
|
||||
"disable": {
|
||||
"redeem": false
|
||||
},
|
||||
"hoster": {
|
||||
"name": "someone",
|
||||
"url": "scheme://domain.tld"
|
||||
},
|
||||
"debug": false,
|
||||
"reputation": {
|
||||
"timeout": 86400000
|
||||
},
|
||||
"secretKey": "SET A LONG RANDOM PASSWORD HERE, ITS FOR USE OF ENCRYPTION WITH LENGTH OF 32",
|
||||
"importToDB": false,
|
||||
"clearUnused": false,
|
||||
"devMode": false
|
||||
}
|
30
package.json
30
package.json
|
@ -4,14 +4,17 @@
|
|||
"description": "Earn credits while chatting! And more",
|
||||
"main": "src/index.ts",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"start": "nodemon | pino-pretty -i pid,hostname -t yyyy-mm-dd HH:MM:s"
|
||||
"test": "jest",
|
||||
"start": "nodemon | pino-pretty -i pid,hostname -t yyyy-mm-dd HH:MM:s",
|
||||
"prettier-format": "prettier \"src/**/*.ts\" --write",
|
||||
"lint": "eslint ./src --ext .ts",
|
||||
"prepare": "husky install"
|
||||
},
|
||||
"keywords": [
|
||||
"zyner",
|
||||
"Zyner",
|
||||
"xyter",
|
||||
"controlpanel",
|
||||
"controlpanel.gg",
|
||||
"vermium"
|
||||
"controlpanel.gg"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -26,25 +29,15 @@
|
|||
"dependencies": {
|
||||
"@discordjs/builders": "^0.12.0",
|
||||
"@discordjs/rest": "^0.3.0",
|
||||
"@nastyox/rando.js": "^2.0.5",
|
||||
"axios": "^0.26.0",
|
||||
"better-sqlite3": "^7.5.0",
|
||||
"chance": "^1.1.8",
|
||||
"common": "^0.2.5",
|
||||
"crypto": "^1.0.1",
|
||||
"dbd-dark-dashboard": "^1.6.45",
|
||||
"discord-api-types": "^0.31.0",
|
||||
"discord-dashboard": "^2.3.14",
|
||||
"discord-easy-dashboard": "^1.2.1",
|
||||
"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",
|
||||
|
@ -61,7 +54,14 @@
|
|||
"eslint-config-airbnb-base": "15.0.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-plugin-import": "2.26.0",
|
||||
"eslint-plugin-no-loops": "^0.3.0",
|
||||
"eslint-plugin-prettier": "^4.0.0",
|
||||
"husky": "^7.0.0",
|
||||
"jest": "^27.5.1",
|
||||
"lint-staged": "^12.3.7",
|
||||
"prettier": "^2.6.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.ts": "eslint --cache --fix"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
// Controlpanel.gg (Pterodactyl) API token
|
||||
export const cpggToken = "";
|
|
@ -1,5 +1,14 @@
|
|||
import { Intents } from "discord.js"; // discord.js
|
||||
|
||||
// Discord API token
|
||||
export const token = "";
|
||||
|
||||
// Discord API id
|
||||
export const clientId = "";
|
||||
|
||||
// Discord API intents
|
||||
export const intents = [
|
||||
Intents.FLAGS.GUILDS,
|
||||
Intents.FLAGS.GUILD_MESSAGES,
|
||||
Intents.FLAGS.GUILD_MEMBERS,
|
||||
];
|
||||
|
|
|
@ -8,13 +8,13 @@ import logger from "@logger";
|
|||
import { url } from "@config/database";
|
||||
|
||||
export default async () => {
|
||||
mongoose.connect(url).then(async (connection: any) => {
|
||||
mongoose.connect(url).then(async (connection) => {
|
||||
logger?.info(`Connected to database: ${connection.connection.name}`);
|
||||
});
|
||||
mongoose.connection.on("error", (error: any) => {
|
||||
mongoose.connection.on("error", (error) => {
|
||||
logger?.error(error);
|
||||
});
|
||||
mongoose.connection.on("warn", (warning: any) => {
|
||||
mongoose.connection.on("warn", (warning) => {
|
||||
logger?.warn(warning);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -17,6 +17,14 @@ interface IGuild {
|
|||
minimumLength: number;
|
||||
timeout: number;
|
||||
};
|
||||
welcome: {
|
||||
status: boolean;
|
||||
joinChannel: string;
|
||||
leaveChannel: string;
|
||||
joinChannelMessage: string;
|
||||
leaveChannelMessage: string;
|
||||
};
|
||||
audits: { status: boolean; channelId: string };
|
||||
}
|
||||
|
||||
const guildSchema = new Schema<IGuild>(
|
||||
|
@ -83,6 +91,20 @@ const guildSchema = new Schema<IGuild>(
|
|||
default: 5000,
|
||||
},
|
||||
},
|
||||
welcome: {
|
||||
status: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
joinChannel: { type: String },
|
||||
leaveChannel: { type: String },
|
||||
joinChannelMessage: { type: String },
|
||||
leaveChannelMessage: { type: String },
|
||||
},
|
||||
audits: {
|
||||
status: { type: Boolean, default: false },
|
||||
channelId: { type: String },
|
||||
},
|
||||
},
|
||||
{ timestamps: true }
|
||||
);
|
||||
|
|
43
src/events/guildMemberAdd/audits.ts
Normal file
43
src/events/guildMemberAdd/audits.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
import logger from "@logger";
|
||||
import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
import { footerText, footerIcon, successColor } from "@config/embed";
|
||||
|
||||
export default {
|
||||
execute: async (member: GuildMember) => {
|
||||
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
|
||||
|
||||
const { client } = member;
|
||||
|
||||
if (guildData === null) return;
|
||||
|
||||
if (guildData.audits.status !== true) return;
|
||||
if (!guildData.audits.channelId) return;
|
||||
|
||||
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
|
||||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: "Member Joined",
|
||||
iconURL: member.user.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(`${member.user} ${member.user.tag}`)
|
||||
.addFields([
|
||||
{ name: "Account Age", value: `${member.user.createdAt}` },
|
||||
])
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -5,6 +5,8 @@ import { GuildMember } from "discord.js";
|
|||
import updatePresence from "@helpers/updatePresence";
|
||||
import fetchUser from "@helpers/fetchUser";
|
||||
import logger from "@logger";
|
||||
import joinMessage from "../guildMemberAdd/joinMessage";
|
||||
import audits from "../guildMemberAdd/audits";
|
||||
|
||||
export default {
|
||||
name: "guildMemberAdd",
|
||||
|
@ -15,6 +17,8 @@ export default {
|
|||
`New member: ${user.tag} (${user.id}) added to guild: ${guild.name} (${guild.id})`
|
||||
);
|
||||
|
||||
await audits.execute(member);
|
||||
await joinMessage.execute(member);
|
||||
await fetchUser(user, guild);
|
||||
await updatePresence(client);
|
||||
},
|
||||
|
|
45
src/events/guildMemberAdd/joinMessage.ts
Normal file
45
src/events/guildMemberAdd/joinMessage.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import logger from "@logger";
|
||||
import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
import { footerText, footerIcon, successColor } from "@config/embed";
|
||||
|
||||
export default {
|
||||
execute: async (member: GuildMember) => {
|
||||
logger.info(member);
|
||||
|
||||
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
|
||||
|
||||
const { client } = member;
|
||||
|
||||
if (guildData === null) return;
|
||||
|
||||
if (guildData.welcome.status !== true) return;
|
||||
if (!guildData.welcome.joinChannel) return;
|
||||
|
||||
const channel = client.channels.cache.get(
|
||||
`${guildData.welcome.joinChannel}`
|
||||
);
|
||||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setTitle(`${member.user.username} has joined the server!`)
|
||||
.setThumbnail(member.user.displayAvatarURL())
|
||||
.setDescription(
|
||||
guildData.welcome.joinChannelMessage ||
|
||||
"Configure a join message in the `/settings guild welcome`."
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
40
src/events/guildMemberRemove/audits.ts
Normal file
40
src/events/guildMemberRemove/audits.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import logger from "@logger";
|
||||
import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
import { footerText, footerIcon, errorColor } from "@config/embed";
|
||||
|
||||
export default {
|
||||
execute: async (member: GuildMember) => {
|
||||
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
|
||||
|
||||
const { client } = member;
|
||||
|
||||
if (guildData === null) return;
|
||||
|
||||
if (guildData.audits.status !== true) return;
|
||||
if (!guildData.audits.channelId) return;
|
||||
|
||||
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
|
||||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(errorColor)
|
||||
.setAuthor({
|
||||
name: "Member Left",
|
||||
iconURL: member.user.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(`${member.user} ${member.user.tag}`)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -5,6 +5,8 @@ import { GuildMember } from "discord.js";
|
|||
import updatePresence from "@helpers/updatePresence";
|
||||
import dropUser from "@helpers/dropUser";
|
||||
import logger from "@logger";
|
||||
import leaveMessage from "./leaveMessage";
|
||||
import audits from "./audits";
|
||||
|
||||
export default {
|
||||
name: "guildMemberRemove",
|
||||
|
@ -15,6 +17,8 @@ export default {
|
|||
`Removed member: ${user.tag} (${user.id}) from guild: ${guild.name} (${guild.id})`
|
||||
);
|
||||
|
||||
await audits.execute(member);
|
||||
await leaveMessage.execute(member);
|
||||
await dropUser(user, guild);
|
||||
await updatePresence(client);
|
||||
},
|
||||
|
|
45
src/events/guildMemberRemove/leaveMessage.ts
Normal file
45
src/events/guildMemberRemove/leaveMessage.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import logger from "@logger";
|
||||
import { GuildMember, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
import { footerText, footerIcon, errorColor } from "@config/embed";
|
||||
|
||||
export default {
|
||||
execute: async (member: GuildMember) => {
|
||||
logger.info(member);
|
||||
|
||||
const guildData = await guildSchema.findOne({ guildId: member.guild.id });
|
||||
|
||||
const { client } = member;
|
||||
|
||||
if (guildData === null) return;
|
||||
|
||||
if (guildData.welcome.status !== true) return;
|
||||
if (!guildData.welcome.leaveChannel) return;
|
||||
|
||||
const channel = client.channels.cache.get(
|
||||
`${guildData.welcome.leaveChannel}`
|
||||
);
|
||||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(errorColor)
|
||||
.setTitle(`${member.user.username} has left the server!`)
|
||||
.setThumbnail(member.user.displayAvatarURL())
|
||||
.setDescription(
|
||||
guildData.welcome.leaveChannelMessage ||
|
||||
"Configure a leave message in the `/settings guild welcome`."
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
48
src/events/interactionCreate/audits.ts
Normal file
48
src/events/interactionCreate/audits.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
import logger from "@logger";
|
||||
import { Interaction, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
import { footerText, footerIcon, successColor } from "@config/embed";
|
||||
|
||||
export default {
|
||||
execute: async (interaction: Interaction) => {
|
||||
if (interaction === null) return;
|
||||
|
||||
if (interaction.guild === null) return;
|
||||
|
||||
const guildData = await guildSchema.findOne({
|
||||
guildId: interaction.guild.id,
|
||||
});
|
||||
|
||||
const { client } = interaction;
|
||||
|
||||
if (guildData === null) return;
|
||||
|
||||
if (guildData.audits.status !== true) return;
|
||||
if (!guildData.audits.channelId) return;
|
||||
|
||||
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
|
||||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setDescription(
|
||||
`
|
||||
**Interaction created by** ${interaction.user.username} **in** ${interaction.channel}
|
||||
`
|
||||
)
|
||||
.setThumbnail(interaction.user.displayAvatarURL())
|
||||
.addFields([{ name: "Event", value: "interactionCreate" }])
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -4,6 +4,7 @@ import { CommandInteraction } from "discord.js";
|
|||
// Dependencies
|
||||
import isCommand from "@root/events/interactionCreate/components/isCommand";
|
||||
import logger from "@logger";
|
||||
import audits from "./audits";
|
||||
|
||||
export default {
|
||||
name: "interactionCreate",
|
||||
|
@ -14,6 +15,7 @@ export default {
|
|||
`New interaction: ${id} in guild: ${guild?.name} (${guild?.id})`
|
||||
);
|
||||
|
||||
await audits.execute(interaction);
|
||||
await isCommand(interaction);
|
||||
},
|
||||
};
|
||||
|
|
51
src/events/messageDelete/audits.ts
Normal file
51
src/events/messageDelete/audits.ts
Normal file
|
@ -0,0 +1,51 @@
|
|||
import logger from "@logger";
|
||||
import { Message, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
import { footerText, footerIcon, successColor } from "@config/embed";
|
||||
|
||||
export default {
|
||||
execute: async (message: Message) => {
|
||||
if (message === null) return;
|
||||
|
||||
if (message.guild === null) return;
|
||||
|
||||
const guildData = await guildSchema.findOne({
|
||||
guildId: message.guild.id,
|
||||
});
|
||||
|
||||
const { client } = message;
|
||||
|
||||
if (guildData === null) return;
|
||||
|
||||
if (guildData.audits.status !== true) return;
|
||||
if (!guildData.audits.channelId) return;
|
||||
|
||||
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
|
||||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: message.author.username,
|
||||
iconURL: message.author.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(
|
||||
`
|
||||
**Message sent by** ${message.author} **deleted in** ${message.channel}
|
||||
${message.content}
|
||||
`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
9
src/events/messageDelete/index.ts
Normal file
9
src/events/messageDelete/index.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { Message } from "discord.js";
|
||||
import audits from "@events/messageDelete/audits";
|
||||
|
||||
export default {
|
||||
name: "messageDelete",
|
||||
async execute(message: Message) {
|
||||
await audits.execute(message);
|
||||
},
|
||||
};
|
53
src/events/messageUpdate/audits.ts
Normal file
53
src/events/messageUpdate/audits.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
/* eslint-disable no-loops/no-loops */
|
||||
import logger from "@logger";
|
||||
import { Message, MessageEmbed, TextChannel } from "discord.js";
|
||||
|
||||
import guildSchema from "@schemas/guild";
|
||||
|
||||
import { footerText, footerIcon, successColor } from "@config/embed";
|
||||
|
||||
export default {
|
||||
execute: async (oldMessage: Message, newMessage: Message) => {
|
||||
if (oldMessage === null) return;
|
||||
if (newMessage === null) return;
|
||||
|
||||
if (oldMessage.guild === null) return;
|
||||
if (newMessage.guild === null) return;
|
||||
|
||||
const guildData = await guildSchema.findOne({
|
||||
guildId: oldMessage.guild.id,
|
||||
});
|
||||
|
||||
const { client } = oldMessage;
|
||||
|
||||
if (guildData === null) return;
|
||||
|
||||
if (guildData.audits.status !== true) return;
|
||||
if (!guildData.audits.channelId) return;
|
||||
|
||||
const channel = client.channels.cache.get(`${guildData.audits.channelId}`);
|
||||
|
||||
if (channel === null) return;
|
||||
|
||||
(channel as TextChannel).send({
|
||||
embeds: [
|
||||
new MessageEmbed()
|
||||
.setColor(successColor)
|
||||
.setAuthor({
|
||||
name: newMessage.author.username,
|
||||
iconURL: newMessage.author.displayAvatarURL(),
|
||||
})
|
||||
.setDescription(
|
||||
`
|
||||
**Message edited in** ${newMessage.channel} [jump to message](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.id})
|
||||
`
|
||||
)
|
||||
.setTimestamp()
|
||||
.setFooter({
|
||||
text: footerText,
|
||||
iconURL: footerIcon,
|
||||
}),
|
||||
],
|
||||
});
|
||||
},
|
||||
};
|
|
@ -5,11 +5,15 @@ import logger from "@logger";
|
|||
// Modules
|
||||
import counter from "./modules/counter";
|
||||
|
||||
import audits from "./audits";
|
||||
|
||||
export default {
|
||||
name: "messageUpdate",
|
||||
async execute(_oldMessage: Message, newMessage: Message) {
|
||||
async execute(oldMessage: Message, newMessage: Message) {
|
||||
const { author, guild } = newMessage;
|
||||
|
||||
await audits.execute(oldMessage, newMessage);
|
||||
|
||||
logger?.verbose(
|
||||
`Message update event fired by ${author.tag} (${author.id}) in guild: ${guild?.name} (${guild?.id})`
|
||||
);
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
// Dependencies
|
||||
import { Client } from "discord.js";
|
||||
import logger from "../../logger";
|
||||
import logger from "@logger";
|
||||
|
||||
// Helpers
|
||||
import deployCommands from "../../handlers/deployCommands";
|
||||
import updatePresence from "../../helpers/updatePresence";
|
||||
import devMode from "../../helpers/devMode";
|
||||
import updatePresence from "@helpers/updatePresence";
|
||||
import deployCommands from "@handlers/deployCommands";
|
||||
import devMode from "@handlers/devMode";
|
||||
|
||||
export default {
|
||||
name: "ready",
|
||||
once: true,
|
||||
async execute(client: Client) {
|
||||
logger?.info(`${client.user?.tag} (${client.user?.id}) is ready`);
|
||||
logger.info(`${client.user?.tag} (${client.user?.id}) is ready`);
|
||||
|
||||
await updatePresence(client);
|
||||
await devMode(client);
|
||||
await deployCommands();
|
||||
await deployCommands(client);
|
||||
|
||||
client?.guilds?.cache?.forEach((guild) => {
|
||||
logger?.info(
|
||||
`${client.user?.tag} (${client.user?.id}) is in guild: ${guild.name} (${guild.id})`
|
||||
client.guilds?.cache.forEach((guild) => {
|
||||
logger.verbose(
|
||||
`${client.user?.tag} (${client.user?.id}) is in guild: ${guild.name} (${guild.id}) with member count of ${guild.memberCount}`
|
||||
);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import fs from "fs"; // fs
|
||||
import { Collection } from "discord.js"; // discord.js
|
||||
import { Client } from "../types/common/discord";
|
||||
import logger from "../logger";
|
||||
import { Client } from "@root/types/common/discord";
|
||||
import logger from "@logger";
|
||||
|
||||
export default async (client: Client) => {
|
||||
client.commands = new Collection();
|
||||
|
||||
fs.readdir("./src/plugins", async (error: any, plugins: any) => {
|
||||
fs.readdir("./src/plugins", async (error, plugins) => {
|
||||
if (error) {
|
||||
return logger?.error(`Error reading plugins: ${error}`);
|
||||
return logger.error(`Error reading plugins: ${error}`);
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
plugins?.map(async (pluginName: any) => {
|
||||
plugins.map(async (pluginName) => {
|
||||
const plugin = await import(`../plugins/${pluginName}`);
|
||||
|
||||
await client?.commands?.set(
|
||||
|
@ -20,8 +20,14 @@ export default async (client: Client) => {
|
|||
plugin?.default
|
||||
);
|
||||
|
||||
logger?.verbose(`Loaded plugin: ${pluginName}`);
|
||||
logger.verbose(`Loaded plugin: ${pluginName}`);
|
||||
})
|
||||
);
|
||||
)
|
||||
.then(async () => {
|
||||
logger.debug("Successfully loaded plugins.");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
logger.error(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,52 +3,51 @@ import { token, clientId } from "@config/discord";
|
|||
import { devMode, guildId } from "@config/other";
|
||||
|
||||
import logger from "../logger";
|
||||
import fs from "fs";
|
||||
import { Client } from "@root/types/common/discord";
|
||||
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));
|
||||
}
|
||||
export default async (client: Client) => {
|
||||
const pluginList = [] as string[];
|
||||
|
||||
const pluginList = [] as any;
|
||||
await Promise.all(
|
||||
client.commands.map(async (pluginData: any) => {
|
||||
pluginList.push(pluginData.data.toJSON());
|
||||
logger.verbose(
|
||||
`${pluginData.data.name} successfully pushed to plugin list.`
|
||||
);
|
||||
})
|
||||
)
|
||||
.then(async () => {
|
||||
logger.debug("Successfully pushed all plugins to plugin list.");
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger.error(error);
|
||||
});
|
||||
|
||||
await Promise.all(
|
||||
plugins?.map(async (pluginName: any) => {
|
||||
const plugin = await import(`../plugins/${pluginName}`);
|
||||
const rest = new REST({ version: "9" }).setToken(token);
|
||||
|
||||
pluginList.push(plugin.default.data.toJSON());
|
||||
|
||||
logger?.verbose(`Loaded plugin: ${pluginName} for deployment`);
|
||||
})
|
||||
);
|
||||
|
||||
const rest = new REST({ version: "9" }).setToken(token);
|
||||
await rest
|
||||
.put(Routes.applicationCommands(clientId), {
|
||||
body: pluginList,
|
||||
})
|
||||
.then(async () => {
|
||||
logger.debug(`Successfully deployed plugins to Discord`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger.error(error);
|
||||
});
|
||||
|
||||
if (devMode) {
|
||||
await rest
|
||||
.put(Routes.applicationCommands(clientId), {
|
||||
.put(Routes.applicationGuildCommands(clientId, guildId), {
|
||||
body: pluginList,
|
||||
})
|
||||
.then(async () => {
|
||||
logger?.info(`Successfully deployed plugins to Discord`);
|
||||
})
|
||||
.catch(async (err: any) => {
|
||||
logger.error(err);
|
||||
.then(async () =>
|
||||
logger.debug(`Successfully deployed guild plugins to Discord`)
|
||||
)
|
||||
.catch(async (error) => {
|
||||
logger.error(error);
|
||||
});
|
||||
|
||||
if (devMode) {
|
||||
await rest
|
||||
.put(Routes.applicationGuildCommands(clientId, guildId), {
|
||||
body: pluginList,
|
||||
})
|
||||
.then(async () =>
|
||||
logger?.info(`Successfully deployed guild plugins to Discord`)
|
||||
)
|
||||
.catch(async (err: any) => {
|
||||
logger.error(err);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
|
@ -9,11 +9,11 @@ import { devMode, guildId } from "@config/other";
|
|||
export default async (client: Client) => {
|
||||
if (!devMode) {
|
||||
return client?.application?.commands?.set([], guildId).then(async () => {
|
||||
return logger?.verbose(
|
||||
return logger.debug(
|
||||
`Development commands disabled for guild: ${guildId}`
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return logger?.verbose(`Development commands enabled for guild: ${guildId}`);
|
||||
return logger.debug(`Development commands enabled for guild: ${guildId}`);
|
||||
};
|
|
@ -3,20 +3,33 @@ import { Client } from "discord.js"; // discord.js
|
|||
import logger from "@logger";
|
||||
|
||||
export default async (client: Client) => {
|
||||
const eventFiles = fs.readdirSync("./src/events");
|
||||
|
||||
for (const file of eventFiles) {
|
||||
const event = require(`../events/${file}`);
|
||||
if (event.once) {
|
||||
client.once(event.default.name, (...args) =>
|
||||
event.default.execute(...args)
|
||||
);
|
||||
logger?.verbose(`Loaded event: ${event.default.name}`);
|
||||
} else {
|
||||
client.on(event.default.name, (...args) =>
|
||||
event.default.execute(...args)
|
||||
);
|
||||
logger?.verbose(`Loaded event: ${event.default.name}`);
|
||||
fs.readdir("./src/events", async (error, events) => {
|
||||
if (error) {
|
||||
return logger.error(`Error reading plugins: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
events.map(async (eventName) => {
|
||||
const event = await import(`../events/${eventName}`);
|
||||
|
||||
logger.verbose(`Loaded event: ${eventName}`);
|
||||
|
||||
if (event.once) {
|
||||
return client.once(event.default.name, async (...args) =>
|
||||
event.default.execute(...args)
|
||||
);
|
||||
}
|
||||
|
||||
return client.on(event.default.name, async (...args) =>
|
||||
event.default.execute(...args)
|
||||
);
|
||||
})
|
||||
)
|
||||
.then(async () => {
|
||||
logger.debug("Successfully loaded events.");
|
||||
})
|
||||
.catch(async (err) => {
|
||||
logger.error(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ import { Guild, User } from "discord.js";
|
|||
|
||||
export default async (user: User, guild: Guild) => {
|
||||
await userSchema
|
||||
.deleteOne({ userId: user?.id, guildId: guild?.id })
|
||||
.deleteOne({ userId: user.id, guildId: guild.id })
|
||||
.then(async () => {
|
||||
logger?.verbose(`Deleted user: ${user?.id} from guild: ${guild?.id}`);
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import sleep from "./sleep";
|
||||
import logger from "../logger";
|
||||
import sleep from "@helpers/sleep";
|
||||
import logger from "@logger";
|
||||
import Chance from "chance";
|
||||
|
||||
export default async function saveUser(data: any, data2: any) {
|
||||
|
|
34
src/index.ts
34
src/index.ts
|
@ -1,30 +1,28 @@
|
|||
// Dependencies
|
||||
import "tsconfig-paths/register"; // Allows using tsconfig.json paths during runtime
|
||||
import { Client, Intents } from "discord.js"; // discord.js
|
||||
|
||||
import { token, intents } from "@config/discord";
|
||||
|
||||
import { Client } from "discord.js"; // discord.js
|
||||
|
||||
import locale from "@locale";
|
||||
import database from "@database";
|
||||
import schedules from "@schedules";
|
||||
|
||||
import events from "@handlers/events";
|
||||
import commands from "@handlers/commands";
|
||||
|
||||
// Configurations
|
||||
import { token } from "@config/discord";
|
||||
async function main() {
|
||||
const client = new Client({
|
||||
intents,
|
||||
});
|
||||
|
||||
const client = new Client({
|
||||
intents: [
|
||||
Intents?.FLAGS?.GUILDS,
|
||||
Intents?.FLAGS?.GUILD_MESSAGES,
|
||||
Intents?.FLAGS?.GUILD_MEMBERS,
|
||||
],
|
||||
});
|
||||
await locale();
|
||||
await database();
|
||||
await schedules(client);
|
||||
|
||||
locale();
|
||||
database();
|
||||
schedules(client);
|
||||
await commands(client);
|
||||
await events(client);
|
||||
|
||||
commands(client);
|
||||
events(client);
|
||||
await client.login(token);
|
||||
}
|
||||
|
||||
client?.login(token);
|
||||
main();
|
||||
|
|
|
@ -135,9 +135,9 @@ export default async () => {
|
|||
},
|
||||
})
|
||||
.then(async () => {
|
||||
logger?.verbose(`i18next initialized`);
|
||||
logger.debug(`i18next initialized`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(`i18next failed to initialize: ${error}`);
|
||||
logger.error(`i18next failed to initialize: ${error}`);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,10 +3,10 @@ import { SlashCommandBuilder } from "@discordjs/builders";
|
|||
import { CommandInteraction } from "discord.js";
|
||||
|
||||
// Modules
|
||||
import give from "./modules/give";
|
||||
import give from "@plugins/reputation/modules/give";
|
||||
|
||||
// Handlers
|
||||
import logger from "../../logger";
|
||||
import logger from "@logger";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
|
|
|
@ -11,6 +11,8 @@ import logger from "@logger";
|
|||
import pterodactyl from "./modules/pterodactyl";
|
||||
import credits from "./modules/credits";
|
||||
import points from "./modules/points";
|
||||
import welcome from "./modules/welcome";
|
||||
import audits from "./modules/audits";
|
||||
import { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
|
||||
|
||||
// Function
|
||||
|
@ -21,7 +23,9 @@ export default {
|
|||
.setDescription("Guild settings.")
|
||||
.addSubcommand(pterodactyl.data)
|
||||
.addSubcommand(credits.data)
|
||||
.addSubcommand(points.data);
|
||||
.addSubcommand(points.data)
|
||||
.addSubcommand(welcome.data)
|
||||
.addSubcommand(audits.data);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Destructure member
|
||||
|
@ -51,16 +55,32 @@ export default {
|
|||
logger?.verbose(`Executing pterodactyl subcommand`);
|
||||
|
||||
return pterodactyl.execute(interaction);
|
||||
} else if (options?.getSubcommand() === "credits") {
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "credits") {
|
||||
logger?.verbose(`Executing credits subcommand`);
|
||||
|
||||
return credits.execute(interaction);
|
||||
} else if (options?.getSubcommand() === "points") {
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "points") {
|
||||
logger?.verbose(`Executing points subcommand`);
|
||||
|
||||
return points.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "welcome") {
|
||||
logger?.verbose(`Executing welcome subcommand`);
|
||||
|
||||
return welcome.execute(interaction);
|
||||
}
|
||||
|
||||
if (options?.getSubcommand() === "audits") {
|
||||
logger?.verbose(`Executing audit subcommand`);
|
||||
|
||||
return audits.execute(interaction);
|
||||
}
|
||||
|
||||
logger?.verbose(`No subcommand found`);
|
||||
},
|
||||
};
|
||||
|
|
85
src/plugins/settings/guild/modules/audits.ts
Normal file
85
src/plugins/settings/guild/modules/audits.ts
Normal file
|
@ -0,0 +1,85 @@
|
|||
// 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";
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("audits")
|
||||
.setDescription("Audits")
|
||||
.addBooleanOption((option) =>
|
||||
option.setName("status").setDescription("Should audits be enabled?")
|
||||
)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("Channel for audit messages.")
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Destructure member
|
||||
const { options, guild } = interaction;
|
||||
|
||||
// Get options
|
||||
const status = options?.getBoolean("status");
|
||||
const channel = options?.getChannel("channel");
|
||||
|
||||
// Get guild object
|
||||
const guildDB = await guildSchema?.findOne({
|
||||
guildId: guild?.id,
|
||||
});
|
||||
|
||||
if (guildDB === null) {
|
||||
return logger?.verbose(`Guild not found in database.`);
|
||||
}
|
||||
|
||||
// Modify values
|
||||
guildDB.audits.status = status !== null ? status : guildDB?.audits?.status;
|
||||
guildDB.audits.channelId =
|
||||
channel !== null ? channel.id : guildDB?.audits?.channelId;
|
||||
|
||||
// Save guild
|
||||
await guildDB?.save()?.then(async () => {
|
||||
logger?.verbose(`Guild audits updated.`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
{
|
||||
title: ":hammer: Settings - Guild [Audits]",
|
||||
description: `Audits settings updated.`,
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: "🤖 Status",
|
||||
value: `${guildDB?.audits?.status}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🌊 Channel",
|
||||
value: `${guildDB?.audits?.channelId}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
131
src/plugins/settings/guild/modules/welcome.ts
Normal file
131
src/plugins/settings/guild/modules/welcome.ts
Normal file
|
@ -0,0 +1,131 @@
|
|||
// 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";
|
||||
import { ChannelType } from "discord-api-types/v10";
|
||||
|
||||
// Function
|
||||
export default {
|
||||
data: (command: SlashCommandSubcommandBuilder) => {
|
||||
return command
|
||||
.setName("welcome")
|
||||
.setDescription("Welcome")
|
||||
.addBooleanOption((option) =>
|
||||
option.setName("status").setDescription("Should welcome be enabled?")
|
||||
)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("join-channel")
|
||||
.setDescription("Channel for join messages.")
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
)
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("leave-channel")
|
||||
.setDescription("Channel for leave messages.")
|
||||
.addChannelType(ChannelType.GuildText as number)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("leave-message")
|
||||
.setDescription("Message for leave messages.")
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("join-message")
|
||||
.setDescription("Message for join messages.")
|
||||
);
|
||||
},
|
||||
execute: async (interaction: CommandInteraction) => {
|
||||
// Destructure member
|
||||
const { options, guild } = interaction;
|
||||
|
||||
// Get options
|
||||
const status = options?.getBoolean("status");
|
||||
const joinChannel = options?.getChannel("join-channel");
|
||||
const leaveChannel = options?.getChannel("leave-channel");
|
||||
const joinChannelMessage = options?.getString("join-message");
|
||||
const leaveChannelMessage = options?.getString("leave-message");
|
||||
|
||||
// Get guild object
|
||||
const guildDB = await guildSchema?.findOne({
|
||||
guildId: guild?.id,
|
||||
});
|
||||
|
||||
if (guildDB === null) {
|
||||
return logger?.verbose(`Guild not found in database.`);
|
||||
}
|
||||
|
||||
// Modify values
|
||||
guildDB.welcome.status =
|
||||
status !== null ? status : guildDB?.welcome?.status;
|
||||
guildDB.welcome.joinChannel =
|
||||
joinChannel !== null ? joinChannel.id : guildDB?.welcome?.joinChannel;
|
||||
guildDB.welcome.leaveChannel =
|
||||
leaveChannel !== null ? leaveChannel.id : guildDB?.welcome?.leaveChannel;
|
||||
|
||||
guildDB.welcome.joinChannelMessage =
|
||||
joinChannelMessage !== null
|
||||
? joinChannelMessage
|
||||
: guildDB?.welcome?.joinChannelMessage;
|
||||
guildDB.welcome.leaveChannelMessage =
|
||||
leaveChannelMessage !== null
|
||||
? leaveChannelMessage
|
||||
: guildDB?.welcome?.leaveChannelMessage;
|
||||
|
||||
// Save guild
|
||||
await guildDB?.save()?.then(async () => {
|
||||
logger?.verbose(`Guild welcome updated.`);
|
||||
|
||||
return interaction?.editReply({
|
||||
embeds: [
|
||||
{
|
||||
title: ":hammer: Settings - Guild [Welcome]",
|
||||
description: `Welcome settings updated.`,
|
||||
color: successColor,
|
||||
fields: [
|
||||
{
|
||||
name: "🤖 Status",
|
||||
value: `${guildDB?.welcome?.status}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🌊 Join Channel",
|
||||
value: `${guildDB?.welcome?.joinChannel}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "🌊 Leave Channel",
|
||||
value: `${guildDB?.welcome?.leaveChannel}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📄 Join Channel Message",
|
||||
value: `${guildDB?.welcome?.joinChannelMessage}`,
|
||||
inline: true,
|
||||
},
|
||||
{
|
||||
name: "📄 Leave Channel Message",
|
||||
value: `${guildDB?.welcome?.leaveChannelMessage}`,
|
||||
inline: true,
|
||||
},
|
||||
],
|
||||
timestamp: new Date(),
|
||||
footer: {
|
||||
iconURL: footerIcon,
|
||||
text: footerText,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
},
|
||||
};
|
|
@ -11,7 +11,14 @@ export default async (client: Client) => {
|
|||
const expression = "*/5 * * * *";
|
||||
|
||||
schedule.scheduleJob(expression, async () => {
|
||||
logger?.verbose("Running shop roles job.");
|
||||
await shopRoles(client);
|
||||
logger.info("Running jobs.");
|
||||
|
||||
await shopRoles(client)
|
||||
.then(() => {
|
||||
logger.info("Shop roles job finished.");
|
||||
})
|
||||
.catch((err) => {
|
||||
logger.error(`Shop roles job failed: ${err}`);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
|
|
@ -9,51 +9,131 @@ import shopRoleSchema from "@schemas/shopRole";
|
|||
import guildSchema from "@schemas/guild";
|
||||
|
||||
export default async (client: Client) => {
|
||||
await shopRoleSchema?.find()?.then(async (shopRoles: any) => {
|
||||
shopRoles?.map(async (shopRole: any) => {
|
||||
const payed = new Date(shopRole?.lastPayed);
|
||||
const roles = await shopRoleSchema.find();
|
||||
|
||||
const oneHourAfterPayed = payed?.setHours(payed?.getHours() + 1);
|
||||
await Promise.all(
|
||||
roles.map(async (role) => {
|
||||
const { guildId, userId, roleId } = role;
|
||||
|
||||
if (new Date() > new Date(oneHourAfterPayed)) {
|
||||
logger?.verbose(`Shop role ${shopRole?.roleId} is expired.`);
|
||||
const lastPayment = new Date(role.lastPayed);
|
||||
|
||||
// Get guild object
|
||||
const guild = await guildSchema?.findOne({
|
||||
guildId: shopRole?.guildId,
|
||||
});
|
||||
const nextPayment = new Date(
|
||||
lastPayment.setHours(lastPayment.getHours() + 1)
|
||||
);
|
||||
|
||||
if (guild === null) return;
|
||||
const userDB = await userSchema?.findOne({
|
||||
userId: shopRole?.userId,
|
||||
guildId: shopRole?.guildId,
|
||||
});
|
||||
const { pricePerHour } = guild.shop.roles;
|
||||
if (new Date() < nextPayment) {
|
||||
logger.silly(`Shop role ${roleId} is not due for payment.`);
|
||||
}
|
||||
|
||||
if (userDB === null) return;
|
||||
const guildData = await guildSchema.findOne({ guildId });
|
||||
|
||||
if (userDB?.credits < pricePerHour) {
|
||||
const rGuild = client?.guilds?.cache?.get(`${shopRole?.guildId}`);
|
||||
const rMember = await rGuild?.members?.fetch(`${shopRole?.userId}`);
|
||||
if (!guildData) {
|
||||
logger.error(`Guild ${guildId} not found.`);
|
||||
return;
|
||||
}
|
||||
|
||||
shopRoleSchema
|
||||
?.deleteOne({ _id: shopRole?._id })
|
||||
?.then(async () =>
|
||||
logger?.verbose(`Shop role ${shopRole?.roleId} was deleted.`)
|
||||
)
|
||||
.catch(async (error) => {
|
||||
return logger?.error(error);
|
||||
});
|
||||
if (!userId) {
|
||||
logger.error(`User ID not found for shop role ${roleId}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
return rMember?.roles?.remove(`${shopRole?.roleId}`);
|
||||
const userData = await userSchema.findOne({ guildId, userId });
|
||||
|
||||
if (!userData) {
|
||||
logger.error(`User ${userId} not found for shop role ${roleId}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const rGuild = client?.guilds?.cache?.get(guildId);
|
||||
|
||||
const rMember = await rGuild?.members?.fetch(userId);
|
||||
|
||||
if (!rMember) {
|
||||
logger.error(`Member ${userId} not found for shop role ${roleId}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const rRole = rMember.roles.cache.get(roleId);
|
||||
|
||||
if (!rRole) {
|
||||
logger.error(`Role ${roleId} not found for shop role ${roleId}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!rMember) {
|
||||
logger.error(`Member ${userId} not found for shop role ${roleId}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (new Date() > nextPayment) {
|
||||
logger.verbose(
|
||||
`Shop role ${roleId} is due for payment. Withdrawing credits from user ${userId}.`
|
||||
);
|
||||
|
||||
const { pricePerHour } = guildData.shop.roles;
|
||||
|
||||
if (userData.credits < pricePerHour) {
|
||||
logger.error(
|
||||
`User ${userId} does not have enough credits to pay for shop role ${roleId}.`
|
||||
);
|
||||
|
||||
if (!rMember) {
|
||||
logger.error(`Member ${userId} not found for shop role ${roleId}.`);
|
||||
await shopRoleSchema
|
||||
.deleteOne({
|
||||
userId,
|
||||
roleId,
|
||||
guildId,
|
||||
})
|
||||
.then(async () => {
|
||||
logger.verbose(
|
||||
`Shop role document ${roleId} has been deleted from user ${userId}.`
|
||||
);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger.error(
|
||||
`Error deleting shop role document ${roleId} from user ${userId}.`,
|
||||
error
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
rMember.roles.remove(roleId);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
shopRole.lastPayed = new Date();
|
||||
shopRole?.save()?.then(async () => {
|
||||
userDB.credits -= pricePerHour;
|
||||
userDB?.save();
|
||||
});
|
||||
userData.credits -= pricePerHour;
|
||||
|
||||
await userData
|
||||
.save()
|
||||
.then(async () => {
|
||||
role.lastPayed = new Date();
|
||||
|
||||
await role
|
||||
.save()
|
||||
.then(async () => {
|
||||
logger.verbose(`Shop role ${roleId} has been paid for.`);
|
||||
})
|
||||
.catch(async (err) => {
|
||||
logger.error(
|
||||
`Error saving shop role ${roleId} last payed date.`,
|
||||
err
|
||||
);
|
||||
});
|
||||
|
||||
logger.verbose(
|
||||
`Shop role ${roleId} has been paid for. Keeping role ${roleId} for user ${userId}.`
|
||||
);
|
||||
})
|
||||
.catch(async (err) => {
|
||||
logger.error(
|
||||
`Error saving user ${userId} credits for shop role ${roleId}.`,
|
||||
err
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2019",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"module": "commonjs",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"outDir": "./build",
|
||||
"baseUrl": "./src",
|
||||
"typeRoots": ["/types/common", "./node_modules/@types"],
|
||||
"paths": {
|
||||
"@interface/*": ["Interfaces/*"],
|
||||
"@root/*": ["*"],
|
||||
"@config/*": ["config/*"],
|
||||
"@events/*": ["events/*"],
|
||||
"@logger": ["logger"],
|
||||
"@database": ["database"],
|
||||
"@schedules": ["schedules"],
|
||||
"@handlers/*": ["handlers/*"],
|
||||
"@helpers/*": ["helpers/*"],
|
||||
"@locale": ["locale"],
|
||||
"@schemas/*": ["database/schemas/*"]
|
||||
}
|
||||
},
|
||||
"include": ["./src"],
|
||||
"exclude": ["./node_modules", "./test"]
|
||||
}
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2022",
|
||||
"module": "CommonJS",
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"strict": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"moduleResolution": "node",
|
||||
"isolatedModules": true,
|
||||
"outDir": "./build",
|
||||
"baseUrl": "./src",
|
||||
"typeRoots": ["/types/common", "./node_modules/@types"],
|
||||
"paths": {
|
||||
"@interface/*": ["Interfaces/*"],
|
||||
"@root/*": ["*"],
|
||||
"@config/*": ["config/*"],
|
||||
"@events/*": ["events/*"],
|
||||
"@logger": ["logger"],
|
||||
"@database": ["database"],
|
||||
"@schedules": ["schedules"],
|
||||
"@handlers/*": ["handlers/*"],
|
||||
"@helpers/*": ["helpers/*"],
|
||||
"@locale": ["locale"],
|
||||
"@plugins/*": ["plugins/*"],
|
||||
"@schemas/*": ["database/schemas/*"]
|
||||
}
|
||||
},
|
||||
"include": ["./src"],
|
||||
"exclude": ["./node_modules", "./test"]
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue