refactor: transfer some functionality from old ready to new one

sync old commands with main for reference
This commit is contained in:
Jonny_Bro (Nikita) 2025-02-08 16:24:12 +05:00
parent 526f16c74f
commit 9212f21acb
28 changed files with 166 additions and 153 deletions

5
.gitignore vendored
View file

@ -2,15 +2,12 @@
.DS_Store
Thumbs.db
# Bot Configuration
# Configuration
/config.json
# DB
/giveaways.json
# Clips
/clips/*
# Node
node_modules
dist

View file

@ -17,12 +17,12 @@
"owner": {
"id": "123456789098765432"
},
"apiKeys": {},
"paths": {
"commands": "./src/commands",
"events": "./src/events",
"locales": "./src/services/languages/locales",
"tasks": "./src/helpers/tasks"
},
"defaultLang": "en-US"
"defaultLang": "en-US",
"apiKeys": {}
}

View file

@ -0,0 +1,67 @@
import { replyError, replySuccess } from "@/helpers/extenders.js";
import { CommandData, SlashCommandProps } from "@/types.js";
import useClient from "@/utils/use-client.js";
import { ApplicationCommandOptionType, ApplicationIntegrationType, InteractionContextType } from "discord.js";
const client = useClient();
export const data: CommandData = {
name: "addemoji",
description: client.translate("administration/addemoji:DESCRIPTION"),
// eslint-disable-next-line camelcase
description_localizations: {
uk: client.translate("administration/addemoji:DESCRIPTION", { lng: "uk-UA" }),
ru: client.translate("administration/addemoji:DESCRIPTION", { lng: "ru-RU" }),
},
// eslint-disable-next-line camelcase
integration_types: [ApplicationIntegrationType.GuildInstall],
contexts: [InteractionContextType.Guild],
options: [
{
name: "link",
description: client.translate("common:LINK"),
type: ApplicationCommandOptionType.String,
required: true,
// eslint-disable-next-line camelcase
description_localizations: {
uk: client.translate("common:LINK", { lng: "uk-UA" }),
ru: client.translate("common:LINK", { lng: "ru-RU" }),
},
},
{
name: "name",
description: client.translate("common:NAME"),
type: ApplicationCommandOptionType.String,
required: true,
// eslint-disable-next-line camelcase
description_localizations: {
uk: client.translate("common:NAME", { lng: "uk-UA" }),
ru: client.translate("common:NAME", { lng: "ru-RU" }),
},
},
],
};
export const run = async ({ interaction }: SlashCommandProps) => {
await interaction.deferReply({ ephemeral: true });
const link = interaction.options.getString("link") || "",
name = interaction.options.getString("name") || "";
interaction.guild?.emojis
.create({
name: name,
attachment: link,
})
.then(emoji =>
replySuccess(interaction, "administration/stealemoji:SUCCESS", {
emoji: emoji.toString(),
}, { edit: true }),
)
.catch(e => {
replyError(interaction, "administration/stealemoji:ERROR", {
name,
e,
}, { edit: true });
});
};

View file

@ -103,8 +103,7 @@ class Config extends BaseCommand {
? interaction.translate("administration/config:WELCOME_CONTENT", {
channel: `<#${guildData.plugins.welcome.channel}>`,
withImage: guildData.plugins.welcome.withImage ? interaction.translate("common:YES") : interaction.translate("common:NO"),
})
: interaction.translate("common:DISABLED"),
}) : interaction.translate("common:DISABLED"),
inline: true,
},
{
@ -113,8 +112,7 @@ class Config extends BaseCommand {
? interaction.translate("administration/config:GOODBYE_CONTENT", {
channel: `<#${guildData.plugins.goodbye.channel}>`,
withImage: guildData.plugins.goodbye.withImage ? interaction.translate("common:YES") : interaction.translate("common:NO"),
})
: interaction.translate("common:DISABLED"),
}) : interaction.translate("common:DISABLED"),
inline: true,
},
{
@ -127,22 +125,19 @@ class Config extends BaseCommand {
(guildData.plugins.warnsSanctions.kick
? interaction.translate("administration/config:KICK_CONTENT", {
count: guildData.plugins.warnsSanctions.kick,
})
: interaction.translate("administration/config:KICK_NOT_DEFINED")) +
}) : interaction.translate("administration/config:KICK_NOT_DEFINED")) +
"\n" +
(guildData.plugins.warnsSanctions.ban
? interaction.translate("administration/config:BAN_CONTENT", {
count: guildData.plugins.warnsSanctions.ban,
})
: interaction.translate("administration/config:BAN_NOT_DEFINED")),
}) : interaction.translate("administration/config:BAN_NOT_DEFINED")),
},
{
name: interaction.translate("administration/config:AUTOMOD_TITLE"),
value: guildData.plugins.automod.enabled
? interaction.translate("administration/config:AUTOMOD_CONTENT", {
channels: guildData.plugins.automod.ignored.map(ch => ` ${ch}`),
})
: interaction.translate("common:DISABLED"),
}) : interaction.translate("common:DISABLED"),
},
{
name: interaction.translate("administration/config:MONITORING_CHANNELS"),
@ -216,14 +211,13 @@ async function changeSetting(interaction, setting, state, channel) {
content: `${interaction.translate(`administration/config:${settingSplitted.length === 2 ? settingSplitted[1].toUpperCase() : setting.toUpperCase()}`)}: **${interaction.translate("common:ENABLED")}** (${channel.toString()})`,
ephemeral: true,
});
} else {
} else
return interaction.reply({
content: `${interaction.translate(`administration/config:${settingSplitted.length === 2 ? settingSplitted[1].toUpperCase() : setting.toUpperCase()}`)}: ${
data.plugins[setting] ? `**${interaction.translate("common:ENABLED")}** (<#${data.plugins[setting]}>)` : `**${interaction.translate("common:DISABLED")}**`
}`,
ephemeral: true,
});
}
}
} else {
if (!state) {
@ -247,14 +241,13 @@ async function changeSetting(interaction, setting, state, channel) {
content: `${interaction.translate(`administration/config:${setting.toUpperCase()}`)}: **${interaction.translate("common:ENABLED")}** (${channel.toString()})`,
ephemeral: true,
});
} else {
} else
return interaction.reply({
content: `${interaction.translate(`administration/config:${setting.toUpperCase()}`)}: ${
data.plugins[setting] ? `**${interaction.translate("common:ENABLED")}** (<#${data.plugins[setting]}>)` : `**${interaction.translate("common:DISABLED")}**`
}`,
ephemeral: true,
});
}
}
}
}

View file

@ -63,7 +63,7 @@ class Shorturl extends BaseCommand {
}).then(res => res.json());
interaction.editReply({
content: `<${res.shortLink}>`,
content: `<https://s.jonnybro.ru/${res.link.slug}>`,
});
}
}

View file

@ -1,6 +1,7 @@
const { SlashCommandBuilder, InteractionContextType, ApplicationIntegrationType } = require("discord.js");
const BaseCommand = require("../../base/BaseCommand"),
fetch = require("node-fetch");
fetch = require("node-fetch"),
moment = require("moment");
class Checkjar extends BaseCommand {
/**
@ -55,7 +56,7 @@ class Checkjar extends BaseCommand {
jarTransactions.length = 10;
jarTransactions.forEach(t => {
const time = new Intl.DateTimeFormat("ru-RU").format(t.time);
const time = moment.unix(t.time);
embed.data.fields.push([
{

View file

@ -270,7 +270,7 @@ async function updateEmbed(interaction, queue) {
{ name: "\u200B", value: "\u200B", inline: true },
{
name: interaction.translate("common:VIEWS"),
value: track.raw.live ? "Live" : new Intl.NumberFormat(interaction.client.defaultLanguage.locale, { notation: "standard" }).format(track.raw.views),
value: track.raw.live ? "Live" : new Intl.NumberFormat(interaction.client.defaultLanguage.moment, { notation: "standard" }).format(track.raw.views),
inline: true,
},
{

View file

@ -104,7 +104,7 @@ class CloseTicket extends BaseCommand {
const member = interaction.guild.members.cache.find(u => u.user.id === interaction.channel.topic);
await interaction.channel.permissionOverwrites.edit(member, { ViewChannel: false, SendMessages: null });
await interaction.channel.setName(`${interaction.channel.name}-closed`);
await interaction.channel.setName(`closed-${interaction.channel.name}`);
}
});

View file

@ -40,7 +40,7 @@ class CreateTicketEmbed extends BaseCommand {
description: interaction.translate("tickets/createticketembed:TICKET_DESC"),
});
const supportButton = new ButtonBuilder().setCustomId("support_ticket").setLabel(interaction.translate("tickets/createticketembed:TICKET_SUPPORT")).setStyle(ButtonStyle.Primary);
const supportButton = new ButtonBuilder().setCustomId("ticket_create").setLabel(interaction.translate("tickets/createticketembed:TICKET_SUPPORT")).setStyle(ButtonStyle.Primary);
const row = new ActionRowBuilder().addComponents(supportButton);
await interaction.channel.send({ embeds: [embed], components: [row] });

View file

@ -1,8 +1,11 @@
import logger from "../helpers/logger.js";
import { resolve } from "node:path";
import loadCronTasks from "@/utils/loadCronTasks.js";
import { getUsername } from "@/helpers/extenders.js";
import { getNoun } from "@/helpers/functions.js";
import logger from "@/helpers/logger.js";
import { CronManager } from "@/services/cron/index.js";
import { ExtendedClient } from "@/structures/client.js";
import loadCronTasks from "@/utils/loadCronTasks.js";
import { ActivityType } from "discord.js";
import { resolve } from "node:path";
export const data = {
name: "ready",
@ -10,7 +13,10 @@ export const data = {
};
export async function run(client: ExtendedClient) {
logger.ready(client.user.tag + " is online!");
let guildsCount = client.guilds.cache.size;
const status = ["Use /help for commands list!", `I'm in ${guildsCount} ${getNoun(guildsCount, [client.translate("misc:NOUNS:SERVER:1"), client.translate("misc:NOUNS:SERVER:2"), client.translate("misc:NOUNS:SERVER:5")])}!`];
logger.ready(`${getUsername(client.user)} is online! Serving ${guildsCount}`);
// Fetching all app emojis, because we need to use them
await client.application.emojis.fetch();
@ -18,7 +24,20 @@ export async function run(client: ExtendedClient) {
const taskPath = resolve(client.configService.get("paths.tasks"));
const cronTasks = await loadCronTasks(taskPath);
const cronManager = new CronManager(cronTasks);
await cronManager.init();
// Update guilds count
let i = 0;
setInterval(async () => {
guildsCount = (await client.guilds.fetch()).size;
client.user.setActivity({
type: ActivityType.Custom,
name: "custom",
state: status[i],
});
i = (i + 1) % status.length; // Wrap around to the start when reaching the end
}, 30 * 1000); // Every 30 seconds
}

View file

@ -1,5 +1,5 @@
import { InteractionType } from "discord.js";
import BaseEvent from "../base/BaseEvent";
const { InteractionType } = require("discord.js");
const BaseEvent = require("../base/BaseEvent");
class CommandHandler extends BaseEvent {
constructor() {
@ -33,10 +33,12 @@ class CommandHandler extends BaseEvent {
if (interaction.type !== InteractionType.ApplicationCommand || !interaction.isCommand()) return;
// IAT Guild Command Check
if (command?.dirname.includes("IAT") && interaction.guildId !== "1039187019957555252") return interaction.reply({ content: "IAT only", ephemeral: true });
if (command?.dirname.includes("IAT") && interaction.guildId !== "1039187019957555252")
return interaction.reply({ content: "IAT only", ephemeral: true });
// Owner-only command check
if (command.ownerOnly && interaction.user.id !== client.config.owner.id) return interaction.error("misc:OWNER_ONLY", null, { ephemeral: true });
if (command.ownerOnly && interaction.user.id !== client.config.owner.id)
return interaction.error("misc:OWNER_ONLY", null, { ephemeral: true });
// First command achievement check
const { firstCommand } = interaction.data.user.achievements;
@ -66,4 +68,4 @@ class CommandHandler extends BaseEvent {
}
}
export default CommandHandler;
module.exports = CommandHandler;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class guildBanAdd extends BaseEvent {
constructor() {
@ -26,10 +26,8 @@ class guildBanAdd extends BaseEvent {
await ban.user.send({
embeds: [embed],
});
} catch {
/**/
}
} catch (e) { /**/ }
}
}
export default guildBanAdd;
module.exports = guildBanAdd;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class GuildCreate extends BaseEvent {
constructor() {
@ -62,13 +62,12 @@ class GuildCreate extends BaseEvent {
const logChannel = client.channels.cache.get(client.config.support.logs);
if (logChannel) {
if (logChannel)
await logChannel.send({
embeds: [embed],
});
}
}
}
}
export default GuildCreate;
module.exports = GuildCreate;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class GuildDelete extends BaseEvent {
constructor() {
@ -25,13 +25,13 @@ class GuildDelete extends BaseEvent {
const logChannel = client.channels.cache.get(client.config.support.logs);
if (logChannel) {
if (logChannel)
await logChannel.send({
embeds: [embed],
});
} else client.logger.warn(`Log channel not found for guild deletion: ${guild.name}`);
else client.logger.warn(`Log channel not found for guild deletion: ${guild.name}`);
}
}
}
export default GuildDelete;
module.exports = GuildDelete;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class GuildMemberAdd extends BaseEvent {
constructor() {
@ -46,4 +46,4 @@ class GuildMemberAdd extends BaseEvent {
}
}
export default GuildMemberAdd;
module.exports = GuildMemberAdd;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class GuildMemberRemove extends BaseEvent {
constructor() {
@ -37,4 +37,4 @@ class GuildMemberRemove extends BaseEvent {
}
}
export default GuildMemberRemove;
module.exports = GuildMemberRemove;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class GuildMemberUpdate extends BaseEvent {
constructor() {
@ -44,4 +44,4 @@ class GuildMemberUpdate extends BaseEvent {
}
}
export default GuildMemberUpdate;
module.exports = GuildMemberUpdate;

View file

@ -1,5 +1,5 @@
import { PermissionsBitField, ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
import BaseEvent from "../base/BaseEvent";
const { PermissionsBitField, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require("discord.js");
const BaseEvent = require("../base/BaseEvent");
const xpCooldown = {};
@ -69,7 +69,8 @@ class MessageCreate extends BaseEvent {
if (msg.content) embed.addFields([{ name: message.translate("misc:QUOTE_CONTENT"), value: msg.content }]);
if (msg.attachments.size > 0) {
if (msg.attachments.find(a => a.contentType.includes("image/"))) embed.setImage(msg.attachments.find(a => a.contentType.includes("image/")).url);
if (msg.attachments.find(a => a.contentType.includes("image/")))
embed.setImage(msg.attachments.find(a => a.contentType.includes("image/")).url);
embed.addFields([
{
@ -159,4 +160,4 @@ class MessageCreate extends BaseEvent {
}
}
export default MessageCreate;
module.exports = MessageCreate;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class messageDelete extends BaseEvent {
constructor() {
@ -40,4 +40,4 @@ class messageDelete extends BaseEvent {
}
}
export default messageDelete;
module.exports = messageDelete;

View file

@ -1,4 +1,4 @@
import BaseEvent from "../../base/BaseEvent";
const BaseEvent = require("../../base/BaseEvent");
class messageUpdate extends BaseEvent {
constructor() {
@ -42,4 +42,4 @@ class messageUpdate extends BaseEvent {
}
}
export default messageUpdate;
module.exports = messageUpdate;

View file

@ -1,63 +0,0 @@
import { ActivityType } from "discord.js";
import BaseEvent from "../base/BaseEvent";
class Ready extends BaseEvent {
constructor() {
super({
name: "ready",
once: false,
});
}
/**
*
* @param {import("../base/Client")} client
*/
async execute(client) {
const commands = [...new Map(client.commands.map(v => [v.constructor.name, v])).values()];
let servers = client.guilds.cache.size;
let users = 0;
client.guilds.cache.forEach(g => {
users += g.memberCount;
});
const birthdays = require("../helpers/birthdays");
birthdays.init(client);
const checkReminds = require("../helpers/checkReminds");
checkReminds.init(client);
client.logger.ready(`Loaded a total of ${commands.length} command(s).`);
client.logger.ready(`${client.user.getUsername()}, ready to serve ${users} members in ${servers} servers.`);
console.timeEnd("botReady");
const version = require("../package.json").version;
const status = [
`${commands.length} ${client.functions.getNoun(commands.length, client.translate("misc:NOUNS:COMMANDS:1"), client.translate("misc:NOUNS:COMMANDS:2"), client.translate("misc:NOUNS:COMMANDS:5"))} available!`,
`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"))}.`,
"Use /help for commands list!",
];
let i = 0;
setInterval(async () => {
servers = (await client.guilds.fetch()).size;
users = 0;
client.guilds.cache.forEach(g => {
users += g.memberCount;
});
client.user.setActivity({
type: ActivityType.Custom,
name: "custom",
state: `${status[i]} | v${version}`,
});
i = (i + 1) % status.length; // Wrap around to the start when reaching the end
}, 30 * 1000); // Every 30 seconds
}
}
export default Ready;

View file

@ -1,5 +1,5 @@
import { ButtonBuilder, ActionRowBuilder, ButtonStyle, ChannelType, PermissionsBitField } from "discord.js";
import BaseEvent from "../base/BaseEvent";
const { ButtonBuilder, ActionRowBuilder, ButtonStyle, ChannelType, PermissionsBitField } = require("discord.js");
const BaseEvent = require("../base/BaseEvent");
class CommandHandler extends BaseEvent {
constructor() {
@ -60,13 +60,9 @@ class CommandHandler extends BaseEvent {
});
await logChannel.send({ embeds: [logEmbed] });
await interaction.success(
"tickets/createticketembed:TICKET_CREATED",
{
channel: channel.toString(),
},
{ ephemeral: true },
);
await interaction.success("tickets/createticketembed:TICKET_CREATED", {
channel: channel.toString(),
}, { ephemeral: true });
await channel.send(`<@${interaction.user.id}>`);
@ -79,8 +75,14 @@ class CommandHandler extends BaseEvent {
description: interaction.translate("tickets/createticketembed:TICKET_CREATED_DESC"),
});
const closeButton = new ButtonBuilder().setCustomId("close_ticket").setLabel(interaction.translate("tickets/closeticket:CLOSE_TICKET")).setStyle(ButtonStyle.Danger);
const transcriptButton = new ButtonBuilder().setCustomId("transcript_ticket").setLabel(interaction.translate("tickets/closeticket:TRANSCRIPT_TICKET")).setStyle(ButtonStyle.Secondary);
const closeButton = new ButtonBuilder()
.setCustomId("ticket_close")
.setLabel(interaction.translate("tickets/closeticket:CLOSE_TICKET"))
.setStyle(ButtonStyle.Danger);
const transcriptButton = new ButtonBuilder()
.setCustomId("ticket_transcript")
.setLabel(interaction.translate("tickets/closeticket:TRANSCRIPT_TICKET"))
.setStyle(ButtonStyle.Secondary);
const row = new ActionRowBuilder().addComponents(closeButton, transcriptButton);
guildData.plugins.tickets.count++;
@ -133,18 +135,14 @@ class CommandHandler extends BaseEvent {
});
transcript += "---- TICKET CLOSED ----\n";
if (transcriptionLogs !== null) {
interaction.guild.channels.cache
.get(transcriptionLogs)
.send({ content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: `<#${interaction.channelId}>` }), files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
}
if (transcriptionLogs !== null) interaction.guild.channels.cache.get(transcriptionLogs).send({ content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: `<#${interaction.channelId}>` }), files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }] });
try {
await interaction.user.send({
content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: interaction.channel.name }),
files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }],
});
} catch {
} catch (e) {
interaction.followUp({ content: interaction.translate("misc:CANT_DM"), ephemeral: true });
}
}
@ -162,7 +160,7 @@ class CommandHandler extends BaseEvent {
const member = interaction.guild.members.cache.find(u => u.user.id === interaction.channel.topic);
await interaction.channel.permissionOverwrites.edit(member, { ViewChannel: false, SendMessages: null });
await interaction.channel.setName(`${interaction.channel.name}-closed`);
await interaction.channel.setName(`closed-${interaction.channel.name}`);
}
});
} else if (button.customId === "ticket_transcript") {
@ -183,7 +181,7 @@ class CommandHandler extends BaseEvent {
content: interaction.translate("tickets/closeticket:TRANSCRIPT", { channel: `<#${interaction.channelId}>` }),
files: [{ attachment: Buffer.from(transcript), name: `${interaction.channel.name}.txt` }],
});
} catch {
} catch (error) {
interaction.followUp({ content: interaction.translate("misc:CANT_DM"), ephemeral: true });
}
} else return;
@ -191,4 +189,4 @@ class CommandHandler extends BaseEvent {
}
}
export default CommandHandler;
module.exports = CommandHandler;

View file

@ -42,7 +42,7 @@ const registerGlobalCommands = async (client: ExtendedClient, commands: CommandF
}),
);
logger.log(`Registered ${commands.length} global commands`);
logger.log(`Registered ${commands.length} global command(s)`);
};
const registerDevCommands = async (client: ExtendedClient, commands: CommandFileObject[], guildsIds: string[]) => {
@ -84,5 +84,5 @@ const registerDevCommands = async (client: ExtendedClient, commands: CommandFile
}),
);
logger.log(`Registered dev commands in ${devGuilds.length} server(s)`);
logger.log(`Registered ${commands.length} dev command(s) in ${devGuilds.length} server(s)`);
};

View file

@ -37,12 +37,12 @@ export class CommandHandler {
const { data, run, options } = await import(toFileURL(cmdFilePath));
if (!data || !data.name) {
logger.warn(`Command ${cmdFilePath} does not have a data object or name`);
logger.warn(`Command ${cmdFilePath} does not have a 'data' object or name`);
continue;
}
if (typeof run !== "function") {
logger.warn(`Command ${cmdFilePath} does not have a run function or it is not a function`);
logger.warn(`Command ${cmdFilePath} does not have a 'run' function or it is not a function`);
continue;
}

View file

@ -3,5 +3,5 @@
"USAGE": "[emoji]",
"EXAMPLES": "stealemoji emoji::coolstorybob:",
"SUCCESS": "{{emoji}} has been added",
"ERROR": "An error occurred while adding {{emoji}}.\n```{{e}}```"
"ERROR": "An error occurred while adding {{name}}.\n```{{e}}```"
}

View file

@ -3,5 +3,5 @@
"USAGE": "[emoji]",
"EXAMPLES": "stealemoji emoji::coolstorybob:",
"SUCCESS": "{{emoji}} добавлен",
"ERROR": "Произошла ошибка при добавлении {{emoji}}.\n```{{e}}```"
"ERROR": "Произошла ошибка при добавлении {{name}}.\n```{{e}}```"
}

View file

@ -3,5 +3,5 @@
"USAGE": "[emoji]",
"EXAMPLES": "stealemoji emoji::coolstorybob:",
"SUCCESS": "{{emoji}} додано",
"ERROR": "Відбулася помилка при додаванні {{emoji}}.\n```{{e}}```"
"ERROR": "Відбулася помилка при додаванні {{name}}.\n```{{e}}```"
}

View file

@ -15,6 +15,7 @@ export class ExtendedClient extends Client<true> {
adapter = new MongooseAdapter(this.configService.get("mongoDB"));
cacheReminds = new Map<string, cacheRemindsData>();
i18n = new InternationalizationService(this);
translate!: (
_key: string,
_options?: