2022-08-04 19:26:17 +05:00
|
|
|
const { Client, Collection, SlashCommandBuilder, ContextMenuCommandBuilder } = require("discord.js"),
|
2023-03-24 00:09:26 +05:00
|
|
|
{ Player } = require("discord-player"),
|
2022-01-04 02:18:28 +05:00
|
|
|
{ GiveawaysManager } = require("discord-giveaways"),
|
2022-07-23 17:14:42 +05:00
|
|
|
{ REST } = require("@discordjs/rest"),
|
2023-04-21 22:47:21 +05:00
|
|
|
{ Routes } = require("discord-api-types/v10");
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2022-07-31 17:08:00 +05:00
|
|
|
const BaseEvent = require("./BaseEvent.js"),
|
2022-07-23 17:14:42 +05:00
|
|
|
BaseCommand = require("./BaseCommand.js"),
|
2022-01-04 02:18:28 +05:00
|
|
|
path = require("path"),
|
2022-07-23 17:14:42 +05:00
|
|
|
fs = require("fs").promises,
|
2023-04-20 11:47:47 +05:00
|
|
|
mongoose = require("mongoose");
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2023-11-05 16:03:23 +05:00
|
|
|
class JaBaClient extends Client {
|
2022-01-04 02:18:28 +05:00
|
|
|
constructor(options) {
|
|
|
|
super(options);
|
2022-08-04 19:26:17 +05:00
|
|
|
this.config = require("../config");
|
|
|
|
this.customEmojis = require("../emojis");
|
|
|
|
this.languages = require("../languages/language-meta");
|
|
|
|
this.commands = new Collection();
|
|
|
|
this.logger = require("../helpers/logger");
|
|
|
|
this.wait = require("node:timers/promises").setTimeout;
|
|
|
|
this.functions = require("../helpers/functions");
|
|
|
|
this.guildsData = require("../base/Guild");
|
|
|
|
this.usersData = require("../base/User");
|
|
|
|
this.membersData = require("../base/Member");
|
2023-06-26 17:25:17 +05:00
|
|
|
this.dashboard = require("../dashboard/dashboard");
|
2022-08-04 19:26:17 +05:00
|
|
|
this.states = {};
|
2022-01-04 02:18:28 +05:00
|
|
|
this.knownGuilds = [];
|
|
|
|
|
|
|
|
this.databaseCache = {};
|
|
|
|
this.databaseCache.users = new Collection();
|
|
|
|
this.databaseCache.guilds = new Collection();
|
|
|
|
this.databaseCache.members = new Collection();
|
2022-08-29 21:31:36 +05:00
|
|
|
this.databaseCache.usersReminds = new Collection();
|
2022-06-10 15:32:43 +05:00
|
|
|
|
2023-10-31 20:35:12 +05:00
|
|
|
this.player = new Player(this);
|
|
|
|
|
|
|
|
this.player.extractors.loadDefault();
|
2022-08-04 22:06:26 +05:00
|
|
|
|
2023-03-24 00:09:26 +05:00
|
|
|
this.player.events.on("playerStart", async (queue, track) => {
|
2023-11-04 16:56:10 +05:00
|
|
|
const m = (await queue.metadata.channel.send({
|
|
|
|
content: this.translate("music/play:NOW_PLAYING", { songName: track.title }, queue.metadata.channel.guild.data.language),
|
|
|
|
})).id;
|
|
|
|
|
2022-12-15 21:02:38 +05:00
|
|
|
if (track.durationMS > 1)
|
2022-09-10 23:38:11 +05:00
|
|
|
setTimeout(() => {
|
2023-11-04 16:56:10 +05:00
|
|
|
const message = queue.metadata.channel.messages.cache.get(m);
|
|
|
|
|
2023-11-25 18:41:36 +05:00
|
|
|
if (message && message.deletable) message.delete();
|
2022-09-10 23:38:11 +05:00
|
|
|
}, track.durationMS);
|
2022-12-15 21:02:38 +05:00
|
|
|
else
|
2022-09-10 23:38:11 +05:00
|
|
|
setTimeout(() => {
|
2023-11-04 16:56:10 +05:00
|
|
|
const message = queue.metadata.channel.messages.cache.get(m);
|
|
|
|
|
2023-11-25 18:41:36 +05:00
|
|
|
if (message && message.deletable) message.delete();
|
2023-07-05 00:58:06 +05:00
|
|
|
}, 5 * 60 * 1000); // m * s * ms
|
2022-09-10 23:38:11 +05:00
|
|
|
});
|
2023-03-24 00:09:26 +05:00
|
|
|
this.player.events.on("emptyQueue", queue => queue.metadata.channel.send(this.translate("music/play:QUEUE_ENDED", null, queue.metadata.channel.guild.data.language)));
|
|
|
|
this.player.events.on("emptyChannel", queue => queue.metadata.channel.send(this.translate("music/play:STOP_EMPTY", null, queue.metadata.channel.guild.data.language)));
|
|
|
|
this.player.events.on("playerError", (queue, e) => {
|
2022-09-10 23:38:11 +05:00
|
|
|
queue.metadata.channel.send({ content: this.translate("music/play:ERR_OCCURRED", { error: e.message }, queue.metadata.channel.guild.data.language) });
|
2023-10-31 20:35:12 +05:00
|
|
|
console.log(e);
|
2022-09-10 23:38:11 +05:00
|
|
|
});
|
2023-03-24 00:09:26 +05:00
|
|
|
this.player.events.on("error", (queue, e) => {
|
2022-09-10 23:38:11 +05:00
|
|
|
queue.metadata.channel.send({ content: this.translate("music/play:ERR_OCCURRED", { error: e.message }, queue.metadata.channel.guild.data.language) });
|
2023-10-31 20:35:12 +05:00
|
|
|
console.log(e);
|
2022-09-10 23:38:11 +05:00
|
|
|
});
|
2022-01-04 02:18:28 +05:00
|
|
|
|
|
|
|
this.giveawaysManager = new GiveawaysManager(this, {
|
|
|
|
storage: "./giveaways.json",
|
|
|
|
default: {
|
|
|
|
botsCanWin: false,
|
|
|
|
embedColor: this.config.embed.color,
|
2022-01-05 02:11:13 +05:00
|
|
|
embedColorEnd: "#FF0000",
|
2022-12-15 21:02:38 +05:00
|
|
|
reaction: "🎉",
|
|
|
|
},
|
2022-01-04 02:18:28 +05:00
|
|
|
});
|
2022-01-13 00:26:23 +05:00
|
|
|
}
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2022-09-26 19:54:35 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Login into account and connect to DB
|
2022-09-26 19:54:35 +05:00
|
|
|
*/
|
2022-08-01 20:06:09 +05:00
|
|
|
async init() {
|
|
|
|
this.login(this.config.token);
|
|
|
|
|
2023-07-05 00:58:06 +05:00
|
|
|
mongoose
|
2023-10-19 22:48:38 +05:00
|
|
|
.connect(this.config.mongoDB)
|
2023-07-05 00:58:06 +05:00
|
|
|
.then(() => {
|
|
|
|
this.logger.log("Connected to the Mongodb database.", "log");
|
|
|
|
})
|
|
|
|
.catch(err => {
|
2023-10-19 22:48:38 +05:00
|
|
|
this.logger.log(`Unable to connect to the Mongodb database.\nError: ${err}`, "error");
|
2023-07-05 00:58:06 +05:00
|
|
|
});
|
2022-08-01 20:06:09 +05:00
|
|
|
|
2023-04-25 13:53:14 +05:00
|
|
|
await this.player.extractors.loadDefault();
|
|
|
|
|
2023-06-26 17:25:17 +05:00
|
|
|
// const autoUpdateDocs = require("../helpers/autoUpdateDocs");
|
|
|
|
// autoUpdateDocs.update(this);
|
2022-08-01 20:06:09 +05:00
|
|
|
}
|
|
|
|
|
2022-07-23 17:14:42 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Loads commands from directory
|
2022-10-03 20:21:42 +05:00
|
|
|
* @param {String} dir Directory where's all commands located
|
2022-07-25 22:09:02 +05:00
|
|
|
* @returns
|
|
|
|
*/
|
2022-07-26 19:46:32 +05:00
|
|
|
async loadCommands(dir) {
|
2022-12-17 13:49:03 +05:00
|
|
|
const rest = new REST().setToken(this.config.token),
|
|
|
|
filePath = path.join(__dirname, dir),
|
2023-07-05 00:58:06 +05:00
|
|
|
folders = (await fs.readdir(filePath)).map(file => path.join(filePath, file)).filter(async path => (await fs.lstat(path)).isDirectory());
|
2022-12-15 21:02:38 +05:00
|
|
|
|
2022-07-23 17:14:42 +05:00
|
|
|
const commands = [];
|
2022-07-29 23:31:08 +05:00
|
|
|
for (let index = 0; index < folders.length; index++) {
|
|
|
|
const folder = folders[index];
|
2023-05-31 20:11:38 +05:00
|
|
|
|
|
|
|
if (folder.endsWith("!DISABLED")) continue;
|
|
|
|
|
2022-07-29 23:31:08 +05:00
|
|
|
const files = await fs.readdir(folder);
|
|
|
|
|
|
|
|
for (let index = 0; index < files.length; index++) {
|
|
|
|
const file = files[index];
|
|
|
|
|
|
|
|
if (file.endsWith(".js")) {
|
|
|
|
const Command = require(path.join(folder, file));
|
|
|
|
if (Command.prototype instanceof BaseCommand) {
|
|
|
|
const command = new Command(this);
|
|
|
|
this.commands.set(command.command.name, command);
|
|
|
|
const aliases = [];
|
2022-12-15 21:02:38 +05:00
|
|
|
if (command.aliases && Array.isArray(command.aliases) && command.aliases.length > 0)
|
2023-02-01 00:23:01 +05:00
|
|
|
command.aliases.forEach(alias => {
|
2023-07-05 00:58:06 +05:00
|
|
|
const command_alias = command.command instanceof SlashCommandBuilder || command.command instanceof ContextMenuCommandBuilder ? { ...command.command.toJSON() } : { ...command.command };
|
2022-07-29 23:31:08 +05:00
|
|
|
command_alias.name = alias;
|
|
|
|
aliases.push(command_alias);
|
|
|
|
this.commands.set(alias, command);
|
|
|
|
});
|
2022-07-23 17:14:42 +05:00
|
|
|
|
2023-07-05 00:58:06 +05:00
|
|
|
commands.push(command.command instanceof SlashCommandBuilder || command.command instanceof ContextMenuCommandBuilder ? command.command.toJSON() : command.command, ...aliases);
|
2022-07-23 17:14:42 +05:00
|
|
|
|
2022-07-29 23:31:08 +05:00
|
|
|
if (command.onLoad || typeof command.onLoad === "function") await command.onLoad(this);
|
|
|
|
this.logger.log(`Successfully loaded "${file}" command file. (Command: ${command.command.name})`);
|
|
|
|
}
|
2022-07-23 17:14:42 +05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-04 02:18:28 +05:00
|
|
|
try {
|
2022-12-15 21:02:38 +05:00
|
|
|
if (this.config.production)
|
2023-07-05 00:58:06 +05:00
|
|
|
await rest.put(Routes.applicationCommands(this.config.userId), {
|
|
|
|
body: commands,
|
|
|
|
});
|
2022-12-15 21:02:38 +05:00
|
|
|
else
|
2023-07-05 00:58:06 +05:00
|
|
|
await rest.put(Routes.applicationGuildCommands(this.config.userId, this.config.support.id), {
|
|
|
|
body: commands,
|
|
|
|
});
|
2022-07-26 19:46:32 +05:00
|
|
|
|
2022-07-23 17:14:42 +05:00
|
|
|
this.logger.log("Successfully registered application commands.");
|
|
|
|
} catch (err) {
|
|
|
|
this.logger.log("Cannot load commands: " + err.message, "error");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-26 19:46:32 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Loads single command in directory
|
2022-09-26 19:54:35 +05:00
|
|
|
* @param {String} dir Directory where command is
|
|
|
|
* @param {String} file Filename of the command
|
2022-07-26 19:46:32 +05:00
|
|
|
*/
|
|
|
|
async loadCommand(dir, file) {
|
|
|
|
const Command = require(path.join(dir, `${file}.js`));
|
|
|
|
if (Command.prototype instanceof BaseCommand) {
|
|
|
|
const command = new Command(this);
|
|
|
|
this.commands.set(command.command.name, command);
|
|
|
|
const aliases = [];
|
2022-12-15 21:02:38 +05:00
|
|
|
if (command.aliases && Array.isArray(command.aliases) && command.aliases.length > 0)
|
2023-02-01 00:23:01 +05:00
|
|
|
command.aliases.forEach(alias => {
|
2022-07-26 19:46:32 +05:00
|
|
|
const command_alias = command.command instanceof SlashCommandBuilder ? { ...command.command.toJSON() } : { ...command.command };
|
|
|
|
command_alias.name = alias;
|
|
|
|
aliases.push(command_alias);
|
|
|
|
this.commands.set(alias, command);
|
|
|
|
});
|
|
|
|
|
|
|
|
if (command.onLoad || typeof command.onLoad === "function") await command.onLoad(this);
|
|
|
|
this.logger.log(`Successfully loaded "${file}" command file. (Command: ${command.command.name})`);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Unloads command from cache
|
2022-09-26 19:54:35 +05:00
|
|
|
* @param {String} dir Directory of the command
|
|
|
|
* @param {String} name Name of the command
|
2022-07-26 19:46:32 +05:00
|
|
|
*/
|
|
|
|
async unloadCommand(dir, name) {
|
|
|
|
delete require.cache[require.resolve(`${dir}${path.sep}${name}.js`)];
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-23 17:14:42 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Loads events from directory
|
2022-10-03 20:21:42 +05:00
|
|
|
* @param {String} dir Directory where's all events located
|
2022-07-25 22:09:02 +05:00
|
|
|
* @returns
|
|
|
|
*/
|
2022-07-23 17:14:42 +05:00
|
|
|
async loadEvents(dir) {
|
|
|
|
const filePath = path.join(__dirname, dir);
|
|
|
|
const files = await fs.readdir(filePath);
|
|
|
|
for (let index = 0; index < files.length; index++) {
|
|
|
|
const file = files[index];
|
|
|
|
const stat = await fs.lstat(path.join(filePath, file));
|
2022-07-25 22:09:02 +05:00
|
|
|
if (stat.isDirectory()) this.loadEvents(path.join(dir, file));
|
2022-07-23 17:14:42 +05:00
|
|
|
if (file.endsWith(".js")) {
|
|
|
|
const Event = require(path.join(filePath, file));
|
|
|
|
if (Event.prototype instanceof BaseEvent) {
|
|
|
|
const event = new Event();
|
|
|
|
if (!event.name || !event.name.length) return console.error(`Cannot load "${file}" event file: Event name is not set!`);
|
|
|
|
if (event.once) this.once(event.name, event.execute.bind(event, this));
|
|
|
|
else this.on(event.name, event.execute.bind(event, this));
|
|
|
|
this.logger.log(`Successfully loaded "${file}" event file. (Event: ${event.name})`);
|
|
|
|
}
|
|
|
|
}
|
2022-01-13 00:26:23 +05:00
|
|
|
}
|
|
|
|
}
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2022-09-26 19:54:35 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* @returns {String} Bot's default language
|
2022-09-26 19:54:35 +05:00
|
|
|
*/
|
2022-07-25 22:09:02 +05:00
|
|
|
get defaultLanguage() {
|
|
|
|
return this.languages.find(language => language.default).name;
|
|
|
|
}
|
2022-07-23 17:14:42 +05:00
|
|
|
|
2022-07-25 22:09:02 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Translates from a key to language
|
2022-09-26 19:54:35 +05:00
|
|
|
* @param {String} key Key
|
|
|
|
* @param {Array} args Arguments for translation
|
|
|
|
* @param {String} locale Language
|
2022-07-25 22:09:02 +05:00
|
|
|
*/
|
2022-08-28 16:45:05 +05:00
|
|
|
translate(key, args, locale = this.defaultLanguage) {
|
2023-11-04 16:56:10 +05:00
|
|
|
const lang = this.translations.get(locale);
|
2022-07-23 17:14:42 +05:00
|
|
|
|
2023-11-04 16:56:10 +05:00
|
|
|
return lang(key, args);
|
2022-07-25 22:09:02 +05:00
|
|
|
}
|
2022-07-23 17:14:42 +05:00
|
|
|
|
2022-09-26 19:54:35 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Finds or creates user in DB
|
2023-10-30 21:13:12 +05:00
|
|
|
* @param {String} userID User ID
|
|
|
|
* @returns {import("./User")} Mongoose model
|
2022-09-26 19:54:35 +05:00
|
|
|
*/
|
2023-10-30 21:13:12 +05:00
|
|
|
async findOrCreateUser(userID) {
|
2023-07-03 19:30:47 +05:00
|
|
|
if (this.databaseCache.users.get(userID)) return this.databaseCache.users.get(userID);
|
2022-01-04 02:18:28 +05:00
|
|
|
else {
|
2023-07-03 19:30:47 +05:00
|
|
|
let userData = await this.usersData.findOne({ id: userID });
|
|
|
|
|
2022-01-04 02:18:28 +05:00
|
|
|
if (userData) {
|
2023-07-03 19:30:47 +05:00
|
|
|
this.databaseCache.users.set(userID, userData);
|
2022-01-04 02:18:28 +05:00
|
|
|
|
|
|
|
return userData;
|
|
|
|
} else {
|
2023-07-03 19:30:47 +05:00
|
|
|
userData = new this.usersData({ id: userID });
|
2023-10-30 21:45:10 +05:00
|
|
|
|
2022-01-04 02:18:28 +05:00
|
|
|
await userData.save();
|
2023-07-03 19:30:47 +05:00
|
|
|
|
2022-01-04 02:18:28 +05:00
|
|
|
this.databaseCache.users.set(userID, userData);
|
|
|
|
|
2023-07-03 19:30:47 +05:00
|
|
|
return userData;
|
2022-01-13 00:26:23 +05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2022-09-26 19:54:35 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Finds or creates member in DB
|
2023-10-30 21:13:12 +05:00
|
|
|
* @param {Array} { id: Member ID, Guild ID }
|
|
|
|
* @returns {import("./Member")} Mongoose model
|
2022-09-26 19:54:35 +05:00
|
|
|
*/
|
2023-07-03 19:30:47 +05:00
|
|
|
async findOrCreateMember({ id: memberID, guildId }) {
|
|
|
|
let memberData = await this.membersData.findOne({ guildID: guildId, id: memberID });
|
|
|
|
|
|
|
|
if (memberData) {
|
|
|
|
this.databaseCache.members.set(`${memberID}${guildId}`, memberData);
|
|
|
|
|
|
|
|
return memberData;
|
|
|
|
} else {
|
|
|
|
memberData = new this.membersData({ id: memberID, guildID: guildId });
|
2023-10-30 21:45:10 +05:00
|
|
|
|
2023-07-03 19:30:47 +05:00
|
|
|
await memberData.save();
|
|
|
|
|
2023-10-15 15:05:10 +05:00
|
|
|
const guildData = await this.findOrCreateGuild(guildId);
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2023-07-03 19:30:47 +05:00
|
|
|
if (guildData) {
|
|
|
|
guildData.members.push(memberData._id);
|
|
|
|
|
|
|
|
await guildData.save();
|
2022-01-13 00:26:23 +05:00
|
|
|
}
|
2023-07-03 19:30:47 +05:00
|
|
|
|
|
|
|
this.databaseCache.members.set(`${memberID}${guildId}`, memberData);
|
|
|
|
|
|
|
|
return memberData;
|
2022-01-13 00:26:23 +05:00
|
|
|
}
|
|
|
|
}
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2022-09-26 19:54:35 +05:00
|
|
|
/**
|
2023-07-19 21:43:56 +05:00
|
|
|
* Finds or creates guild in DB
|
2023-10-30 21:13:12 +05:00
|
|
|
* @param {String} guildId Guild ID
|
|
|
|
* @returns {import("./Guild")} Mongoose model
|
2022-09-26 19:54:35 +05:00
|
|
|
*/
|
2023-10-15 15:05:10 +05:00
|
|
|
async findOrCreateGuild(guildId) {
|
2023-07-03 19:30:47 +05:00
|
|
|
let guildData = await this.guildsData.findOne({ id: guildId }).populate("members");
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2023-07-03 19:30:47 +05:00
|
|
|
if (guildData) {
|
|
|
|
this.databaseCache.guilds.set(guildId, guildData);
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2023-07-03 19:30:47 +05:00
|
|
|
return guildData;
|
|
|
|
} else {
|
|
|
|
guildData = new this.guildsData({ id: guildId });
|
2023-10-30 21:45:10 +05:00
|
|
|
|
2023-07-03 19:30:47 +05:00
|
|
|
await guildData.save();
|
|
|
|
|
|
|
|
this.databaseCache.guilds.set(guildId, guildData);
|
|
|
|
|
|
|
|
return guildData;
|
2022-01-13 00:26:23 +05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-01-04 02:18:28 +05:00
|
|
|
|
2023-11-05 16:03:23 +05:00
|
|
|
module.exports = JaBaClient;
|