mirror of
https://github.com/JonnyBro/JaBa.git
synced 2024-12-29 23:03:02 +05:00
Compare commits
8 commits
11c1c5640e
...
a3c7d1fef6
Author | SHA1 | Date | |
---|---|---|---|
|
a3c7d1fef6 | ||
|
f3d85c3ec2 | ||
|
f20c7a5550 | ||
|
0ea85ec3ac | ||
|
136d52a268 | ||
|
12054c35c5 | ||
|
fa3f71dd43 | ||
|
b570759c09 |
13 changed files with 102 additions and 123 deletions
|
@ -57,7 +57,7 @@ If you want to contribute, feel free to fork this repo and making a pull request
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
* [ ] Refactor [tictactoe](./helpers/tictactoe.js).
|
* [ ] Refactor [tictactoe](./helpers/tictactoe.js).
|
||||||
* [ ] Rewrite dashboard.
|
* [ ] Finish and release *dashboard-core* submodule.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,20 @@ export default class IDatabaseAdapter {
|
||||||
async disconnect() {
|
async disconnect() {
|
||||||
throw new Error("Method `disconnect` not implemented.");
|
throw new Error("Method `disconnect` not implemented.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async find() {
|
||||||
|
throw new Error("Method \"find\" must be implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOne() {
|
||||||
|
throw new Error("Method \"findOne\" must be implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateOne() {
|
||||||
|
throw new Error("Method \"updateOne\" must be implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteOne() {
|
||||||
|
throw new Error("Method \"deleteOne\" must be implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,4 +29,20 @@ export default class MongooseAdapter extends IDatabaseAdapter {
|
||||||
await mongoose.disconnect();
|
await mongoose.disconnect();
|
||||||
logger.warn("Database disconnected.");
|
logger.warn("Database disconnected.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async find(model, query = {}, options = {}) {
|
||||||
|
return model.find(query, null, options).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOne(model, query = {}, options = {}) {
|
||||||
|
return model.findOne(query, null, options).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateOne(model, filter, update, options = {}) {
|
||||||
|
return model.updateOne(filter, update, options).exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteOne(model, filter) {
|
||||||
|
return model.deleteOne(filter).exec();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
const { SlashCommandBuilder, PermissionsBitField, InteractionContextType, ApplicationIntegrationType } = require("discord.js"),
|
|
||||||
{ QueryType } = require("discord-player");
|
|
||||||
const BaseCommand = require("../../base/BaseCommand"),
|
|
||||||
fs = require("fs");
|
|
||||||
|
|
||||||
class Clips extends BaseCommand {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../base/Client")} client
|
|
||||||
*/
|
|
||||||
constructor(client) {
|
|
||||||
super({
|
|
||||||
command: new SlashCommandBuilder()
|
|
||||||
.setName("clips")
|
|
||||||
.setDescription(client.translate("music/clips:DESCRIPTION"))
|
|
||||||
.setDescriptionLocalizations({
|
|
||||||
uk: client.translate("music/clips:DESCRIPTION", null, "uk-UA"),
|
|
||||||
ru: client.translate("music/clips:DESCRIPTION", null, "ru-RU"),
|
|
||||||
})
|
|
||||||
.setIntegrationTypes([ApplicationIntegrationType.GuildInstall])
|
|
||||||
.setContexts([InteractionContextType.Guild])
|
|
||||||
.addStringOption(option =>
|
|
||||||
option
|
|
||||||
.setName("query")
|
|
||||||
.setDescription(client.translate("music/clips:QUERY"))
|
|
||||||
.setDescriptionLocalizations({
|
|
||||||
uk: client.translate("music/clips:QUERY", null, "uk-UA"),
|
|
||||||
ru: client.translate("music/clips:QUERY", null, "ru-RU"),
|
|
||||||
})
|
|
||||||
.setRequired(true)
|
|
||||||
.setAutocomplete(true),
|
|
||||||
),
|
|
||||||
dirname: __dirname,
|
|
||||||
ownerOnly: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../../base/Client")} client
|
|
||||||
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
|
||||||
*/
|
|
||||||
async execute(client, interaction) {
|
|
||||||
await interaction.deferReply();
|
|
||||||
|
|
||||||
const query = interaction.options.getString("query"),
|
|
||||||
voice = interaction.member.voice.channel;
|
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { edit: true });
|
|
||||||
|
|
||||||
const perms = voice.permissionsFor(client.user);
|
|
||||||
if (!perms.has(PermissionsBitField.Flags.Connect) || !perms.has(PermissionsBitField.Flags.Speak)) return interaction.error("music/play:VOICE_CHANNEL_CONNECT", null, { edit: true });
|
|
||||||
|
|
||||||
client.player.play(interaction.member.voice.channel, query, {
|
|
||||||
nodeOptions: {
|
|
||||||
metadata: interaction,
|
|
||||||
},
|
|
||||||
searchEngine: QueryType.FILE,
|
|
||||||
selfDeaf: true,
|
|
||||||
leaveOnEnd: false,
|
|
||||||
leaveOnStop: true,
|
|
||||||
skipOnNoStream: true,
|
|
||||||
bufferingTimeout: 1000,
|
|
||||||
});
|
|
||||||
|
|
||||||
interaction.editReply({
|
|
||||||
content: interaction.translate("music/play:ADDED_QUEUE", {
|
|
||||||
songName: query.substring(8, query.length - 4),
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../../base/Client")} client
|
|
||||||
* @param {import("discord.js").AutocompleteInteraction} interaction
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
async autocompleteRun(client, interaction) {
|
|
||||||
const query = interaction.options.getString("query"),
|
|
||||||
files = fs.readdirSync("./clips"),
|
|
||||||
results = files.filter(f => f.includes(query));
|
|
||||||
|
|
||||||
return await interaction.respond(
|
|
||||||
results.slice(0, 25).map(file => ({
|
|
||||||
name: file.substring(0, file.length - 4),
|
|
||||||
value: `./clips/${file}`,
|
|
||||||
})),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Clips;
|
|
|
@ -1,4 +1,26 @@
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
|
import { GatewayIntentBits } from "discord.js";
|
||||||
|
import { AsyncLocalStorage } from "node:async_hooks";
|
||||||
|
|
||||||
export const PROJECT_ROOT = path.join(import.meta.dirname, "..");
|
export const PROJECT_ROOT = path.join(import.meta.dirname, "..");
|
||||||
export const CONFIG_PATH = path.join(PROJECT_ROOT, "..", "config.json");
|
export const CONFIG_PATH = path.join(PROJECT_ROOT, "..", "config.json");
|
||||||
|
export const CLIENT_INTENTS = [
|
||||||
|
GatewayIntentBits.Guilds,
|
||||||
|
GatewayIntentBits.GuildMembers,
|
||||||
|
GatewayIntentBits.GuildModeration,
|
||||||
|
GatewayIntentBits.GuildEmojisAndStickers,
|
||||||
|
GatewayIntentBits.GuildIntegrations,
|
||||||
|
GatewayIntentBits.GuildInvites,
|
||||||
|
GatewayIntentBits.GuildVoiceStates,
|
||||||
|
GatewayIntentBits.GuildPresences,
|
||||||
|
GatewayIntentBits.GuildMessages,
|
||||||
|
GatewayIntentBits.GuildMessageReactions,
|
||||||
|
GatewayIntentBits.GuildMessageTyping,
|
||||||
|
GatewayIntentBits.MessageContent,
|
||||||
|
GatewayIntentBits.DirectMessageTyping,
|
||||||
|
GatewayIntentBits.DirectMessages,
|
||||||
|
GatewayIntentBits.DirectMessageReactions,
|
||||||
|
];
|
||||||
|
export const CLIENT_ALLOWED_MENTIONS = { parse: ["everyone", "roles", "users"] };
|
||||||
|
|
||||||
|
export const SUPER_CONTEXT = new AsyncLocalStorage();
|
||||||
|
|
|
@ -38,7 +38,6 @@ class Ready extends BaseEvent {
|
||||||
`I'm in ${servers} ${client.functions.getNoun(servers, client.translate("misc:NOUNS:SERVER:1"), client.translate("misc:NOUNS:SERVER:2"), client.translate("misc:NOUNS:SERVER:5"))}!`,
|
`I'm in ${servers} ${client.functions.getNoun(servers, client.translate("misc:NOUNS:SERVER:1"), client.translate("misc:NOUNS:SERVER:2"), client.translate("misc:NOUNS:SERVER:5"))}!`,
|
||||||
`Cached ${users} ${client.functions.getNoun(users, client.translate("misc:NOUNS:USERS:1"), client.translate("misc:NOUNS:USERS:2"), client.translate("misc:NOUNS:USERS:5"))}.`,
|
`Cached ${users} ${client.functions.getNoun(users, client.translate("misc:NOUNS:USERS:1"), client.translate("misc:NOUNS:USERS:2"), client.translate("misc:NOUNS:USERS:5"))}.`,
|
||||||
"Use /help for commands list!",
|
"Use /help for commands list!",
|
||||||
"Did you know that I have a brother called JaBa IT? Yeah! Ask Jonny about him.",
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { resolve } from "node:path";
|
import { resolve } from "node:path";
|
||||||
import logger from "../../helpers/logger.js";
|
import logger from "../../helpers/logger.js";
|
||||||
import { client } from "../../index.js";
|
import useClient from "../../utils/use-client.js";
|
||||||
import { getFilePaths } from "../../utils/index.js";
|
import { getFilePaths } from "../../utils/index.js";
|
||||||
import { toFileURL } from "../../utils/resolve-file.js";
|
import { toFileURL } from "../../utils/resolve-file.js";
|
||||||
import registerCommands from "./functions/registerCommands.js";
|
import registerCommands from "./functions/registerCommands.js";
|
||||||
|
@ -8,6 +8,7 @@ import registerCommands from "./functions/registerCommands.js";
|
||||||
export const commands = [];
|
export const commands = [];
|
||||||
|
|
||||||
export const init = async () => {
|
export const init = async () => {
|
||||||
|
const client = useClient();
|
||||||
await buildCommands();
|
await buildCommands();
|
||||||
|
|
||||||
await registerCommands({
|
await registerCommands({
|
||||||
|
@ -17,6 +18,7 @@ export const init = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildCommands = async () => {
|
const buildCommands = async () => {
|
||||||
|
const client = useClient();
|
||||||
const cmdPath = resolve(client.configService.get("paths.commands"));
|
const cmdPath = resolve(client.configService.get("paths.commands"));
|
||||||
const commandFilePaths = (await getFilePaths(cmdPath, true)).filter(path => path.endsWith(".js"));
|
const commandFilePaths = (await getFilePaths(cmdPath, true)).filter(path => path.endsWith(".js"));
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import { resolve } from "node:path";
|
import { resolve } from "node:path";
|
||||||
import logger from "../../helpers/logger.js";
|
import logger from "../../helpers/logger.js";
|
||||||
import { client } from "../../index.js";
|
import useClient from "../../utils/use-client.js";
|
||||||
import { getFilePaths } from "../../utils/index.js";
|
import { getFilePaths } from "../../utils/index.js";
|
||||||
import { toFileURL } from "../../utils/resolve-file.js";
|
import { toFileURL } from "../../utils/resolve-file.js";
|
||||||
|
import { useMainPlayer } from "discord-player";
|
||||||
|
|
||||||
export const events = [];
|
export const events = [];
|
||||||
|
|
||||||
|
@ -12,6 +13,7 @@ export const init = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildEvents = async () => {
|
const buildEvents = async () => {
|
||||||
|
const client = useClient();
|
||||||
try {
|
try {
|
||||||
const eventPath = resolve(client.configService.get("paths.events"));
|
const eventPath = resolve(client.configService.get("paths.events"));
|
||||||
const eventFilePaths = (await getFilePaths(eventPath, true)).filter(path => path.endsWith(".js"));
|
const eventFilePaths = (await getFilePaths(eventPath, true)).filter(path => path.endsWith(".js"));
|
||||||
|
@ -37,7 +39,10 @@ const buildEvents = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const registerEvents = async () => {
|
const registerEvents = async () => {
|
||||||
|
const client = useClient();
|
||||||
|
const player = useMainPlayer();
|
||||||
for (const { data, run } of events) {
|
for (const { data, run } of events) {
|
||||||
|
if (data.player) player.events.on(data.name, run);
|
||||||
if (data.once) client.once(data.name, run);
|
if (data.once) client.once(data.name, run);
|
||||||
else client.on(data.name, run);
|
else client.on(data.name, run);
|
||||||
}
|
}
|
||||||
|
|
30
src/index.js
30
src/index.js
|
@ -1,26 +1,10 @@
|
||||||
import { GatewayIntentBits } from "discord.js";
|
|
||||||
import { ExtendedClient } from "./structures/client.js";
|
import { ExtendedClient } from "./structures/client.js";
|
||||||
import logger from "./helpers/logger.js";
|
import logger from "./helpers/logger.js";
|
||||||
|
import { CLIENT_INTENTS, CLIENT_ALLOWED_MENTIONS } from "./constants/index.js";
|
||||||
|
|
||||||
export const client = new ExtendedClient({
|
const client = new ExtendedClient({
|
||||||
intents: [
|
intents: CLIENT_INTENTS,
|
||||||
GatewayIntentBits.Guilds,
|
allowedMentions: CLIENT_ALLOWED_MENTIONS,
|
||||||
GatewayIntentBits.GuildMembers,
|
|
||||||
GatewayIntentBits.GuildModeration,
|
|
||||||
GatewayIntentBits.GuildEmojisAndStickers,
|
|
||||||
GatewayIntentBits.GuildIntegrations,
|
|
||||||
GatewayIntentBits.GuildInvites,
|
|
||||||
GatewayIntentBits.GuildVoiceStates,
|
|
||||||
GatewayIntentBits.GuildPresences,
|
|
||||||
GatewayIntentBits.GuildMessages,
|
|
||||||
GatewayIntentBits.GuildMessageReactions,
|
|
||||||
GatewayIntentBits.GuildMessageTyping,
|
|
||||||
GatewayIntentBits.MessageContent,
|
|
||||||
GatewayIntentBits.DirectMessageTyping,
|
|
||||||
GatewayIntentBits.DirectMessages,
|
|
||||||
GatewayIntentBits.DirectMessageReactions,
|
|
||||||
],
|
|
||||||
allowedMentions: { parse: ["everyone", "roles", "users"] },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
client.init();
|
client.init();
|
||||||
|
@ -28,7 +12,7 @@ client.init();
|
||||||
client
|
client
|
||||||
.on("disconnect", () => logger.warn("Bot disconnected."))
|
.on("disconnect", () => logger.warn("Bot disconnected."))
|
||||||
.on("reconnecting", () => logger.warn("Bot reconnecting..."))
|
.on("reconnecting", () => logger.warn("Bot reconnecting..."))
|
||||||
.on("warn", console.log)
|
.on("warn", logger.log)
|
||||||
.on("error", console.log);
|
.on("error", logger.log);
|
||||||
|
|
||||||
process.on("unhandledRejection", console.log).on("uncaughtException", console.log);
|
process.on("unhandledRejection", logger.log).on("uncaughtException", logger.log);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { model, Schema } from "mongoose";
|
import { model, Schema } from "mongoose";
|
||||||
import { client } from "../index.js";
|
import useClient from "../utils/use-client.js";
|
||||||
|
|
||||||
|
const client = useClient();
|
||||||
|
|
||||||
export default model(
|
export default model(
|
||||||
"Guild",
|
"Guild",
|
||||||
|
|
|
@ -1,21 +1,29 @@
|
||||||
import { Client } from "discord.js";
|
import { Client } from "discord.js";
|
||||||
|
import { Player } from "discord-player";
|
||||||
import MongooseAdapter from "../adapters/database/MongooseAdapter.js";
|
import MongooseAdapter from "../adapters/database/MongooseAdapter.js";
|
||||||
import { init as initCommands } from "../handlers/command-handler/index.js";
|
import { init as initCommands } from "../handlers/command-handler/index.js";
|
||||||
import { init as initEvents } from "../handlers/event-handler/index.js";
|
import { init as initEvents } from "../handlers/event-handler/index.js";
|
||||||
import logger from "../helpers/logger.js";
|
import logger from "../helpers/logger.js";
|
||||||
import ConfigService from "../services/config/index.js";
|
import ConfigService from "../services/config/index.js";
|
||||||
import InternationalizationService from "../services/languages/index.js";
|
import InternationalizationService from "../services/languages/index.js";
|
||||||
|
import { SUPER_CONTEXT } from "../constants/index.js";
|
||||||
|
|
||||||
export class ExtendedClient extends Client {
|
export class ExtendedClient extends Client {
|
||||||
/**
|
/**
|
||||||
* @param {import("discord.js").ClientOptions} options
|
* @param {import("discord.js").ClientOptions} options
|
||||||
*/
|
*/
|
||||||
constructor(options) {
|
constructor(options) {
|
||||||
|
if (SUPER_CONTEXT.getStore()) {
|
||||||
|
return SUPER_CONTEXT.getStore();
|
||||||
|
}
|
||||||
super(options);
|
super(options);
|
||||||
|
|
||||||
this.configService = new ConfigService();
|
this.configService = new ConfigService();
|
||||||
this.adapter = new MongooseAdapter(this.configService.get("mongoDB"));
|
this.adapter = new MongooseAdapter(this.configService.get("mongoDB"));
|
||||||
this.i18n = new InternationalizationService(this);
|
this.i18n = new InternationalizationService(this);
|
||||||
|
new Player(this);
|
||||||
|
|
||||||
|
SUPER_CONTEXT.enterWith(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
import { EmbedBuilder } from "discord.js";
|
import { EmbedBuilder } from "discord.js";
|
||||||
import { client } from "../index.js";
|
import useClient from "../utils/use-client.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import("discord.js").EmbedData} data - embed data
|
* @param {import("discord.js").EmbedData} data - embed data
|
||||||
* @returns The generated EmbedBuilder instance.
|
* @returns The generated EmbedBuilder instance.
|
||||||
*/
|
*/
|
||||||
export const createEmbed = data =>
|
export const createEmbed = data => {
|
||||||
|
const client = useClient();
|
||||||
new EmbedBuilder({
|
new EmbedBuilder({
|
||||||
footer: typeof data.footer === "object" ? data.footer : data.footer ? { text: data.footer } : client.configService.get("embed.footer"),
|
footer: typeof data.footer === "object" ? data.footer : data.footer ? { text: data.footer } : client.configService.get("embed.footer"),
|
||||||
color: data.color ?? client.configService.get("embed.color"),
|
color: data.color ?? client.configService.get("embed.color"),
|
||||||
...data,
|
...data,
|
||||||
});
|
});
|
||||||
|
};
|
||||||
|
|
16
src/utils/use-client.js
Normal file
16
src/utils/use-client.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { SUPER_CONTEXT } from "../constants/index.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the instance of the client.
|
||||||
|
*
|
||||||
|
* @throws {Error} Client is not initialized. Please initialize it first.
|
||||||
|
*
|
||||||
|
* @returns {import("../structures/client.js").ExtendedClient} The client instance.
|
||||||
|
*/
|
||||||
|
export default function useClient() {
|
||||||
|
const store = SUPER_CONTEXT.getStore();
|
||||||
|
if (!store) {
|
||||||
|
throw new Error("Client is not initialized. Please initialize it first.");
|
||||||
|
}
|
||||||
|
return store;
|
||||||
|
}
|
Loading…
Reference in a new issue