diff --git a/TO REWRITE/Administration/addemoji.js b/TO REWRITE/Administration/addemoji.js new file mode 100644 index 00000000..e16706a7 --- /dev/null +++ b/TO REWRITE/Administration/addemoji.js @@ -0,0 +1,38 @@ +const Command = require("../../base/Command"); + +class Addemoji extends Command { + constructor(client) { + super(client, { + name: "addemoji", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["adde"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + const url = args[0]; + if (!url) return message.error("administration/addemoji:MISSING_URL"); + + const name = args[1] ? args[1].replace(/[^a-z0-9]/gi, "") : null; + if (!name) return message.error("administration/addemoji:MISSING_NAME"); + if (name.length < 2 || name.length > 32) return message.error("administration/addemoji:INVALID_NAME"); + + message.guild.emojis + .create(url, name) + .then(emoji => message.success("administration/addemoji:SUCCESS", { + emoji: emoji.name + })) + .catch(() => message.error("administration/addemoji:ERROR", { + emoji: name + })); + } +} + +module.exports = Addemoji; \ No newline at end of file diff --git a/TO REWRITE/Administration/automod.js b/TO REWRITE/Administration/automod.js new file mode 100644 index 00000000..c19365bd --- /dev/null +++ b/TO REWRITE/Administration/automod.js @@ -0,0 +1,55 @@ +const Command = require("../../base/Command"); + +class Automod extends Command { + constructor(client) { + super(client, { + name: "automod", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["autom"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const status = args[0]; + if (!status || (status !== "on" && status !== "off")) return message.error("administration/automod:MISSING_STATUS"); + + if (status === "on") { + data.guild.plugins.automod = { + enabled: true, + ignored: [] + }; + data.guild.markModified("plugins.automod"); + data.guild.save(); + message.success("administration/automod:ENABLED", { + prefix: data.guild.prefix + }); + } else if (status === "off") { + if (message.mentions.channels.filter((ch) => ch.type === "GUILD_TEXT" && ch.guild.id === message.guild.id).first()) { + const channel = message.mentions.channels.first(); + data.guild.plugins.automod.ignored.push(channel); + data.guild.markModified("plugins.automod"); + data.guild.save(); + message.success("administration/automod:DISABLED_CHANNEL", { + channel: channel.toString() + }); + } else { + data.guild.plugins.automod = { + enabled: false, + ignored: [] + }; + data.guild.markModified("plugins.automod"); + data.guild.save(); + message.success("administration/automod:DISABLED"); + } + } + } +} + +module.exports = Automod; \ No newline at end of file diff --git a/TO REWRITE/Administration/autorole.js b/TO REWRITE/Administration/autorole.js new file mode 100644 index 00000000..234d4d42 --- /dev/null +++ b/TO REWRITE/Administration/autorole.js @@ -0,0 +1,60 @@ +const Command = require("../../base/Command"), + Resolvers = require("../../helpers/resolvers"); + +class Autorole extends Command { + constructor(client) { + super(client, { + name: "autorole", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["autor"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const status = args[0]; + if (status !== "on" && status !== "off") return message.error("administration/autorole:MISSING_STATUS"); + + if (status === "on") { + const role = await Resolvers.resolveRole({ + message, + search: args.slice(1).join(" ") + }); + if (!role) return message.error("administration/autorole:MISSING_ROLE"); + + data.guild.plugins.autorole = { + enabled: true, + role: role.id + }; + data.guild.markModified("plugins.autorole"); + await data.guild.save(); + + message.success("administration/autorole:SUCCESS_ENABLED", { + roleName: role.name + }); + } else if (status === "off") { + if (!data.guild.plugins.autorole.enabled) return message.success("administration/autorole:ALREADY_DISABLED", { + prefix: data.guild.prefix + }); + + data.guild.plugins.autorole = { + enabled: false, + role: null + }; + data.guild.markModified("plugins.autorole"); + await data.guild.save(); + + message.success("administration/autorole:SUCCESS_DISABLED", { + prefix: data.guild.prefix + }); + } + } +} + +module.exports = Autorole; \ No newline at end of file diff --git a/TO REWRITE/Administration/backup.js b/TO REWRITE/Administration/backup.js new file mode 100644 index 00000000..27e034e2 --- /dev/null +++ b/TO REWRITE/Administration/backup.js @@ -0,0 +1,145 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + backup = require("discord-backup"); + +backup.setStorageFolder(__dirname + "/../../backups"); + +class Backup extends Command { + constructor(client) { + super(client, { + name: "backup", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["ba"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "ADMINISTRATOR"], + nsfw: false, + ownerOnly: false, + cooldown: 20000 + }); + } + + async run(message, args, data) { + const status = args[0]; + if (!status) return message.error("administration/backup:MISSING_STATUS"); + + if (status === "create") { + const m = await message.sendT("misc:PLEASE_WAIT", null, { + prefixEmoji: "loading" + }); + backup.create(message.guild).then((backup) => { + m.delete(); + + message.success("administration/backup:SUCCESS_PUBLIC"); + message.author.send(message.translate("administration/backup:SUCCESS_PRIVATE", { + backupID: backup.id + })).catch(() => { + backup.remove(backup.id); + message.error("misc:CANNOT_DM"); + }); + }).catch((err) => { + console.error(err); + return message.error("misc:ERR_OCCURRED"); + }); + } else if (status === "load") { + const backupID = args[1]; + if (!backupID) return message.error("administration/backup:MISSING_BACKUP_ID"); + + backup.fetch(backupID).then(async () => { + message.sendT("administration/backup:CONFIRMATION"); + + const filter = m => m.author.id === message.author.id; + const collector = message.channel.createMessageCollector({ + filter, + time: 20000 + }); + + collector.on("collect", async msg => { + if (msg.content.toLowerCase() === message.translate("common:YES").toLowerCase()) { + message.author.send(message.translate("administration/backup:START_LOADING")); + + backup.load(backupID, message.guild).then(() => { + backup.remove(backupID); + message.author.send(message.translate("administration/backup:LOAD_SUCCESS")); + collector.stop(); + }).catch((err) => { + console.error(err); + return message.error("misc:ERR_OCCURRED"); + }); + } + }); + + collector.on("end", (_, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + }); + }).catch((err) => { + console.error(err); + return message.error("administration/backup:NO_BACKUP_FOUND", { + backupID + }); + }); + } else if (status === "info") { + const backupID = args[1]; + if (!backupID) return message.error("administration/backup:MISSING_BACKUP_ID"); + + backup.fetch(backupID).then(async (backupInfo) => { + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("administration/backup:TITLE_INFO") + }) + .addField(message.translate("administration/backup:TITLE_ID"), backupInfo.id, true) + .addField(message.translate("administration/backup:TITLE_SERVER_ID"), backupInfo.data.guildID.toString(), true) + .addField(message.translate("administration/backup:TITLE_SIZE"), `${backupInfo.size} kb`, true) + .addField(message.translate("administration/backup:TITLE_CREATED_AT"), this.client.printDate(new Date(backupInfo.data.createdTimestamp)), true) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + message.reply({ + embeds: [embed] + }); + }).catch((err) => { + console.error(err); + return message.error("administration/backup:NO_BACKUP_FOUND", { + backupID + }); + }); + } else if (status === "remove") { + const backupID = args[1]; + if (!backupID) return message.error("administration/backup:MISSING_BACKUP_ID"); + + backup.fetch(backupID).then(async () => { + message.sendT("administration/backup:REMOVE_CONFIRMATION"); + + const filter = m => m.author.id === message.author.id; + const collector = message.channel.createMessageCollector({ + filter, + time: 20000 + }); + + collector.on("collect", async msg => { + if (msg.content.toLowerCase() === message.translate("common:YES").toLowerCase()) { + backup.remove(backupID).then(async () => { + message.success("administration/backup:SUCCESS_REMOVED"); + }); + collector.stop(); + } + }); + + collector.on("end", (_, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + }); + }).catch((err) => { + console.error(err); + return message.error("administration/backup:NO_BACKUP_FOUND", { + backupID + }); + }); + } else { + return message.error("administration/backup:MISSING_STATUS"); + } + } +} + +module.exports = Backup; \ No newline at end of file diff --git a/TO REWRITE/Administration/configuration.js b/TO REWRITE/Administration/configuration.js new file mode 100644 index 00000000..e6d75ef2 --- /dev/null +++ b/TO REWRITE/Administration/configuration.js @@ -0,0 +1,98 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Configuration extends Command { + constructor(client) { + super(client, { + name: "configuration", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["conf", "config"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const guildData = data.guild; + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.guild.name, + iconURL: message.guild.iconURL({ + dynamic: true + }) + }) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + // Guild prefix + embed.addField(message.translate("administration/configuration:PREFIX_TITLE"), guildData.prefix); + + // Ignored channels + embed.addField(message.translate("administration/configuration:IGNORED_CHANNELS_TITLE"), guildData.ignoredChannels.length > 0 ? guildData.ignoredChannels.map((ch) => `<#${ch}>`).join(", ") : message.translate("administration/configuration:NO_IGNORED_CHANNELS")); + + // Autorole plugin + embed.addField(message.translate("administration/configuration:AUTOROLE_TITLE"), guildData.plugins.autorole.enabled ? message.translate("administration/configuration:AUTOROLE_CONTENT", { + roleName: `<@&${guildData.plugins.autorole.role}>` + }) : message.translate("administration/configuration:AUTOROLE_DISABLED")); + + // Welcome plugin + embed.addField(message.translate("administration/configuration:WELCOME_TITLE"), guildData.plugins.welcome.enabled ? message.translate("administration/configuration:WELCOME_CONTENT", { + channel: `<#${guildData.plugins.welcome.channel}>`, + withImage: guildData.plugins.welcome.withImage ? message.translate("common:YES") : message.translate("common:NO") + }) : message.translate("administration/configuration:WELCOME_DISABLED")); + + // Goodbye plugin + embed.addField(message.translate("administration/configuration:GOODBYE_TITLE"), guildData.plugins.goodbye.enabled ? message.translate("administration/configuration:GOODBYE_CONTENT", { + channel: `<#${guildData.plugins.goodbye.channel}>`, + withImage: guildData.plugins.goodbye.withImage ? message.translate("common:YES") : message.translate("common:NO") + }) : message.translate("administration/configuration:GOODBYE_DISABLED")); + + // Special channels + embed.addField(message.translate("administration/configuration:SPECIAL_CHANNELS"), + message.translate("administration/configuration:SUGGESTIONS", { + channel: guildData.plugins.suggestions ? `<#${guildData.plugins.suggestions}>` : message.translate("common:NOT_DEFINED") + }) + "\n" + + message.translate("administration/configuration:REPORTS", { + channel: guildData.plugins.reports ? `<#${guildData.plugins.reports}>` : message.translate("common:NOT_DEFINED") + }) + "\n" + + message.translate("administration/configuration:MODLOGS", { + channel: guildData.plugins.modlogs ? `<#${guildData.plugins.modlogs}>` : message.translate("common:NOT_DEFINED") + }) + "\n" + + message.translate("administration/configuration:BIRTHDAYS", { + channel: guildData.plugins.birthdays ? `<#${guildData.plugins.birthdays}>` : message.translate("common:NOT_DEFINED") + }) + ); + + // Auto sanctions + embed.addField(message.translate("administration/configuration:AUTO_SANCTIONS"), (guildData.plugins.warnsSanctions.kick ? message.translate("administration/configuration:KICK_CONTENT", { + count: guildData.plugins.warnsSanctions.kick + }) : message.translate("administration/configuration:KICK_NOT_DEFINED")) + "\n" + (guildData.plugins.warnsSanctions.ban ? message.translate("administration/configuration:BAN_CONTENT", { + count: guildData.plugins.warnsSanctions.ban + }) : message.translate("administration/configuration:BAN_NOT_DEFINED"))); + + // Automod plugin + embed.addField(message.translate("administration/configuration:AUTOMOD_TITLE"), guildData.plugins.automod.enabled ? message.translate("administration/configuration:AUTOMOD_CONTENT", { + channels: guildData.plugins.automod.ignored.map((ch) => `<#${ch}>`) + }) : message.translate("administration/configuration:AUTOMOD_DISABLED")); + + // Auto-delete mod commands + embed.addField(message.translate("administration/configuration:AUTODELETEMOD"), guildData.autoDeleteModCommands ? message.translate("administration/configuration:AUTODELETEMOD_ENABLED") : message.translate("administration/configuration:AUTODELETEMOD_DISABLED")); + + // Dashboard link + embed.addField(message.translate("administration/configuration:DASHBOARD_TITLE"), `[${message.translate("administration/configuration:DASHBOARD_CONTENT")}](${data.config.dashboard.baseURL})`); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Configuration; \ No newline at end of file diff --git a/TO REWRITE/Administration/deletemod.js b/TO REWRITE/Administration/deletemod.js new file mode 100644 index 00000000..ce4c9500 --- /dev/null +++ b/TO REWRITE/Administration/deletemod.js @@ -0,0 +1,35 @@ +const Command = require("../../base/Command"); + +class Deletemod extends Command { + constructor(client) { + super(client, { + name: "deletemod", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["delm"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const status = args[0]; + if (!status || status !== "on" && status !== "off") return message.error("administration/deletemod:MISSING_STATUS"); + + if (status === "on") { + data.guild.autoDeleteModCommands = true; + data.guild.save(); + message.success("administration/deletemod:ENABLED"); + } else { + data.guild.autoDeleteModCommands = false; + data.guild.save(); + message.success("administration/deletemod:DISABLED"); + } + } +} + +module.exports = Deletemod; \ No newline at end of file diff --git a/TO REWRITE/Administration/goodbye.js b/TO REWRITE/Administration/goodbye.js new file mode 100644 index 00000000..8a2c1573 --- /dev/null +++ b/TO REWRITE/Administration/goodbye.js @@ -0,0 +1,108 @@ +const Command = require("../../base/Command"), + Resolvers = require("../../helpers/resolvers"); + +class Goodbye extends Command { + constructor(client) { + super(client, { + name: "goodbye", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["gb"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + if (args[0] === "test" && data.guild.plugins.goodbye.enabled) { + this.client.emit("guildMemberRemove", message.member); + return message.success("administration/goodbye:TEST_SUCCESS"); + } + + if ((!args[0] || !["edit", "off"].includes(args[0])) && data.guild.plugins.goodbye.enabled) return message.error("administration/goodbye:MISSING_STATUS"); + + if (args[0] === "off") { + data.guild.plugins.goodbye = { + enabled: false, + message: null, + channelID: null, + withImage: null + }; + data.guild.markModified("plugins.goodbye"); + data.guild.save(); + return message.error("administration/goodbye:DISABLED", { + prefix: data.guild.prefix + }); + } else { + const goodbye = { + enabled: true, + channel: null, + message: null, + withImage: null, + }; + + message.sendT("administration/goodbye:FORM_1", { + author: message.author.toString() + }); + + const filter = m => m.author.id === message.author.id; + const collector = message.channel.createMessageCollector({ + filter, + time: 120000 // 2 minutes + }); + + collector.on("collect", async msg => { + // If the message is filled, it means the user sent yes or no for the image + if (goodbye.message) { + if (msg.content.toLowerCase() === message.translate("common:YES").toLowerCase()) goodbye.withImage = true; + else if (msg.content.toLowerCase() === message.translate("common:NO").toLowerCase()) goodbye.withImage = false; + else return message.error("misc:INVALID_YES_NO"); + + data.guild.plugins.goodbye = goodbye; + data.guild.markModified("plugins.goodbye"); + await data.guild.save(); + message.sendT("administration/goodbye:FORM_SUCCESS", { + prefix: data.guild.prefix, + channel: `<#${goodbye.channel}>` + }); + return collector.stop(); + } + + // If the channel is filled and the message is not, it means the user sent the message + if (goodbye.channel && !goodbye.message) { + if (msg.content.length < 1800) { + goodbye.message = msg.content; + return message.sendT("administration/goodbye:FORM_3"); + } + return message.error("administration/goodbye:MAX_CHARACT"); + } + + // If the channel is not filled, it means the user sent it + if (!goodbye.channel) { + const channel = await Resolvers.resolveChannel({ + message: msg, + channelType: "GUILD_TEXT" + }); + if (!channel) return message.error("misc:INVALID_CHANNEL"); + + goodbye.channel = channel.id; + return message.sendT("administration/goodbye:FORM_2", { + channel: channel.toString(), + author: msg.author.tag, + memberCount: msg.guild.memberCount + }); + } + }); + + collector.on("end", (_, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + }); + } + } +} + +module.exports = Goodbye; \ No newline at end of file diff --git a/TO REWRITE/Administration/set.js b/TO REWRITE/Administration/set.js new file mode 100644 index 00000000..013784b5 --- /dev/null +++ b/TO REWRITE/Administration/set.js @@ -0,0 +1,57 @@ +const Command = require("../../base/Command"); + +class Set extends Command { + constructor(client) { + super(client, { + name: "set", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: [], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args) { + const status = args[0]; + if (!status || !["level", "xp", "credits", "bank"].includes(status)) return message.error("administration/set:NO_STATUS"); + + const member = await this.client.resolveMember(args[1], message.guild); + if (!member) return message.error("administration/set:INVALID_MEMBER"); + if (member.user.bot) return message.error("administration/set:BOT_USER"); + + const number = args[2]; + if (!number || isNaN(number) || parseInt(number, 10) < 0) return message.error("administration/set:INVALID_AMOUNT"); + const amount = Math.ceil(parseInt(number, 10)); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + + if (status === "level") { + memberData.level = parseInt(amount, 10); + memberData.save(); + } else if (status === "xp") { + memberData.exp = parseInt(amount, 10); + memberData.save(); + } else if (status === "credits") { + memberData.money = parseInt(amount, 10); + memberData.save(); + } else if (status === "bank") { + memberData.bankSold = parseInt(amount, 10); + memberData.save(); + } + + message.success("administration/set:SUCCESS_" + status.toUpperCase(), { + username: member.user.tag, + amount + }); + } +} + +module.exports = Set; \ No newline at end of file diff --git a/TO REWRITE/Administration/setbirthdays.js b/TO REWRITE/Administration/setbirthdays.js new file mode 100644 index 00000000..660d9091 --- /dev/null +++ b/TO REWRITE/Administration/setbirthdays.js @@ -0,0 +1,45 @@ +const Command = require("../../base/Command"), + Resolvers = require("../../helpers/resolvers"); + +class Setbirthdays extends Command { + constructor(client) { + super(client, { + name: "setbirthdays", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["setb"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const areBirthdaysEnabled = Boolean(data.guild.plugins.birthdays); + const sentChannel = await Resolvers.resolveChannel({ + message, + search: args.join(" "), + channelType: "GUILD_TEXT" + }); + + if (!sentChannel && areBirthdaysEnabled) { + data.guild.plugins.birthdays = null; + data.guild.markModified("plugins.birthdays"); + await data.guild.save(); + return message.success("administration/setbirthdays:DISABLED"); + } else { + const channel = sentChannel || message.channel; + data.guild.plugins.birthdays = channel.id; + data.guild.markModified("plugins.birthdays"); + await data.guild.save(); + return message.success("administration/setbirthdays:ENABLED", { + channel: channel.toString() + }); + } + } +} + +module.exports = Setbirthdays; \ No newline at end of file diff --git a/TO REWRITE/Administration/setlang.js b/TO REWRITE/Administration/setlang.js new file mode 100644 index 00000000..9c092c77 --- /dev/null +++ b/TO REWRITE/Administration/setlang.js @@ -0,0 +1,33 @@ +const Command = require("../../base/Command"); + +class Setlang extends Command { + constructor(client) { + super(client, { + name: "setlang", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["setl"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const language = this.client.languages.find((l) => l.name === args[0] || l.aliases.includes(args[0])); + + if (!args[0] || !language) return message.error("administration/setlang:MISSING_LANG", { list: this.client.languages.map((l) => `\`${l.name} (${l.aliases.slice(0, 2).join(", ")})\``).join(", ") }); + + data.guild.language = language.name; + await data.guild.save(); + + return message.sendT("administration/setlang:SUCCESS", { + lang: language.nativeName + }); + } +} + +module.exports = Setlang; \ No newline at end of file diff --git a/TO REWRITE/Administration/setmodlogs.js b/TO REWRITE/Administration/setmodlogs.js new file mode 100644 index 00000000..6a5cc145 --- /dev/null +++ b/TO REWRITE/Administration/setmodlogs.js @@ -0,0 +1,45 @@ +const Command = require("../../base/Command"), + Resolvers = require("../../helpers/resolvers"); + +class Setmodlogs extends Command { + constructor(client) { + super(client, { + name: "setmodlogs", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["setm"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const areModLogsEnabled = Boolean(data.guild.plugins.modlogs); + const sentChannel = await Resolvers.resolveChannel({ + message, + search: args.join(" "), + channelType: "GUILD_TEXT" + }); + + if (!sentChannel && areModLogsEnabled) { + data.guild.plugins.modlogs = null; + data.guild.markModified("plugins.modlogs"); + await data.guild.save(); + return message.success("administration/setmodlogs:DISABLED"); + } else { + const channel = sentChannel || message.channel; + data.guild.plugins.modlogs = channel.id; + data.guild.markModified("plugins.modlogs"); + await data.guild.save(); + return message.success("administration/setmodlogs:ENABLED", { + channel: channel.toString() + }); + } + } +} + +module.exports = Setmodlogs; \ No newline at end of file diff --git a/TO REWRITE/Administration/setprefix.js b/TO REWRITE/Administration/setprefix.js new file mode 100644 index 00000000..a680f126 --- /dev/null +++ b/TO REWRITE/Administration/setprefix.js @@ -0,0 +1,33 @@ +const Command = require("../../base/Command"); + +class Setprefix extends Command { + constructor(client) { + super(client, { + name: "setprefix", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["setp"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const prefix = args[0]; + if (!prefix) return message.error("administration/setprefix:MISSING_PREFIX"); + if (prefix.length > 5) return message.error("administration/setprefix:TOO_LONG"); + + data.guild.prefix = prefix; + data.guild.save(); + + return message.success("administration/setprefix:SUCCESS", { + prefix + }); + } +} + +module.exports = Setprefix; \ No newline at end of file diff --git a/TO REWRITE/Administration/setreports.js b/TO REWRITE/Administration/setreports.js new file mode 100644 index 00000000..7e73f550 --- /dev/null +++ b/TO REWRITE/Administration/setreports.js @@ -0,0 +1,45 @@ +const Command = require("../../base/Command"), + Resolvers = require("../../helpers/resolvers"); + +class Setreports extends Command { + constructor(client) { + super(client, { + name: "setreports", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["setr"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const areReportsEnabled = Boolean(data.guild.plugins.reports); + const sentChannel = await Resolvers.resolveChannel({ + message, + search: args.join(" "), + channelType: "GUILD_TEXT" + }); + + if (!sentChannel && areReportsEnabled) { + data.guild.plugins.reports = null; + data.guild.markModified("plugins.reports"); + await data.guild.save(); + return message.success("administration/setreports:DISABLED"); + } else { + const channel = sentChannel || message.channel; + data.guild.plugins.reports = channel.id; + data.guild.markModified("plugins.reports"); + await data.guild.save(); + return message.success("administration/setreports:ENABLED", { + channel: channel.toString() + }); + } + } +} + +module.exports = Setreports; \ No newline at end of file diff --git a/TO REWRITE/Administration/setsuggests.js b/TO REWRITE/Administration/setsuggests.js new file mode 100644 index 00000000..5bdf3664 --- /dev/null +++ b/TO REWRITE/Administration/setsuggests.js @@ -0,0 +1,45 @@ +const Command = require("../../base/Command"), + Resolvers = require("../../helpers/resolvers"); + +class Setsuggests extends Command { + constructor(client) { + super(client, { + name: "setsuggests", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["setsu"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const areSuggestsEnabled = Boolean(data.guild.plugins.suggestions); + const sentChannel = await Resolvers.resolveChannel({ + message, + search: args.join(" "), + channelType: "GUILD_TEXT" + }); + + if (!sentChannel && areSuggestsEnabled) { + data.guild.plugins.suggestions = null; + data.guild.markModified("plugins.suggestions"); + await data.guild.save(); + return message.success("administration/setsuggests:DISABLED"); + } else { + const channel = sentChannel || message.channel; + data.guild.plugins.suggestions = channel.id; + data.guild.markModified("plugins.suggestions"); + await data.guild.save(); + return message.success("administration/setsuggests:ENABLED", { + channel: channel.toString() + }); + } + } +} + +module.exports = Setsuggests; \ No newline at end of file diff --git a/TO REWRITE/Administration/stealemoji.js b/TO REWRITE/Administration/stealemoji.js new file mode 100644 index 00000000..7c7d3709 --- /dev/null +++ b/TO REWRITE/Administration/stealemoji.js @@ -0,0 +1,39 @@ +const Command = require("../../base/Command"), + { Util } = require("discord.js"); + +class Stealemoji extends Command { + constructor(client) { + super(client, { + name: "stealemoji", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["steale"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + if (!args.length) return message.error("administration/stealemoji:MISSING_EMOJI"); + + for (const rawEmoji of args) { + const parsedEmoji = Util.parseEmoji(rawEmoji); + const extension = parsedEmoji.animated ? "gif" : "png"; + + message.guild.emojis + .create(`https://cdn.discordapp.com/emojis/${parsedEmoji.id}.${extension}`, parsedEmoji.name) + .then(emoji => message.success("administration/stealemoji:SUCCESS", { + emoji: emoji.name + })) + .catch(() => message.error("administration/stealemoji:ERROR", { + emoji: parsedEmoji.name + })); + } + } +} + +module.exports = Stealemoji; \ No newline at end of file diff --git a/TO REWRITE/Administration/welcome.js b/TO REWRITE/Administration/welcome.js new file mode 100644 index 00000000..2e2bd7ad --- /dev/null +++ b/TO REWRITE/Administration/welcome.js @@ -0,0 +1,111 @@ +const Command = require("../../base/Command"), + Resolvers = require("../../helpers/resolvers"); + +class Welcome extends Command { + constructor(client) { + super(client, { + name: "welcome", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["welc"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + if (args[0] === "test" && data.guild.plugins.welcome.enabled) { + this.client.emit("guildMemberAdd", message.member); + return message.success("administration/welcome:TEST_SUCCESS"); + } + + if ((!args[0] || !["edit", "off"].includes(args[0])) && data.guild.plugins.welcome.enabled) return message.error("administration/welcome:MISSING_STATUS"); + + if (args[0] === "off") { + data.guild.plugins.welcome = { + enabled: false, + message: null, + channelID: null, + withImage: null + }; + data.guild.markModified("plugins.welcome"); + data.guild.save(); + return message.error("administration/welcome:DISABLED", { + prefix: data.guild.prefix + }); + } else { + const welcome = { + enabled: true, + channel: null, + message: null, + withImage: null, + }; + + message.sendT("administration/welcome:FORM_1", { + author: message.author.toString() + }); + + const filter = m => m.author.id === message.author.id; + const collector = message.channel.createMessageCollector({ + filter, + time: 120000 // 2 minutes + }); + + collector.on("collect", async msg => { + // If the message is filled, it means the user sent yes or no for the image + if (welcome.message) { + if (msg.content.toLowerCase() === message.translate("common:YES").toLowerCase()) { + welcome.withImage = true; + } else if (msg.content.toLowerCase() === message.translate("common:NO").toLowerCase()) { + welcome.withImage = false; + } else { + return message.error("misc:INVALID_YES_NO"); + } + data.guild.plugins.welcome = welcome; + data.guild.markModified("plugins.welcome"); + await data.guild.save(); + message.sendT("administration/welcome:FORM_SUCCESS", { + prefix: data.guild.prefix, + channel: `<#${welcome.channel}>` + }); + return collector.stop(); + } + + // If the channel is filled and the message is not, it means the user sent the message + if (welcome.channel && !welcome.message) { + if (msg.content.length < 1800) { + welcome.message = msg.content; + return message.sendT("administration/welcome:FORM_3"); + } + return message.error("administration/goodbye:MAX_CHARACT"); + } + + // If the channel is not filled, it means the user sent it + if (!welcome.channel) { + const channel = await Resolvers.resolveChannel({ + message: msg, + channelType: "GUILD_TEXT" + }); + if (!channel) return message.error("misc:INVALID_CHANNEL"); + + welcome.channel = channel.id; + return message.sendT("administration/welcome:FORM_2", { + guildName: message.guild.name, + author: msg.author.tag, + memberCount: msg.guild.memberCount + }); + } + }); + + collector.on("end", (_, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + }); + } + } +} + +module.exports = Welcome; \ No newline at end of file diff --git a/TO REWRITE/Economy/achievements.js b/TO REWRITE/Economy/achievements.js new file mode 100644 index 00000000..ea8c6180 --- /dev/null +++ b/TO REWRITE/Economy/achievements.js @@ -0,0 +1,80 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Achievements extends Command { + constructor(client) { + super(client, { + name: "achievements", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["ac"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + let member = message.guild ? message.member : message.author; + if (args[0]) member = await this.client.resolveMember(args[0], message.guild); + if (message.guild && member.user.bot) return message.error("economy/profile:BOT_USER"); + + const userData = (member.id === message.author.id ? data.userData : await this.client.findOrCreateUser({ + id: member.id + })); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("economy/achievements:TITLE") + }) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + embed.addField(message.translate("economy/achievements:SEND_CMD"), message.translate("economy/achievements:PROGRESS", { + now: userData.achievements.firstCommand.progress.now, + total: userData.achievements.firstCommand.progress.total, + percent: Math.round(100 * (userData.achievements.firstCommand.progress.now / userData.achievements.firstCommand.progress.total)) + })); + embed.addField(message.translate("economy/achievements:CLAIM_SALARY"), message.translate("economy/achievements:PROGRESS", { + now: userData.achievements.work.progress.now, + total: userData.achievements.work.progress.total, + percent: Math.round(100 * (userData.achievements.work.progress.now / userData.achievements.work.progress.total)) + })); + embed.addField(message.translate("economy/achievements:MARRY"), message.translate("economy/achievements:PROGRESS", { + now: userData.achievements.married.progress.now, + total: userData.achievements.married.progress.total, + percent: Math.round(100 * (userData.achievements.married.progress.now / userData.achievements.married.progress.total)) + })); + embed.addField(message.translate("economy/achievements:SLOTS"), message.translate("economy/achievements:PROGRESS", { + now: userData.achievements.slots.progress.now, + total: userData.achievements.slots.progress.total, + percent: Math.round(100 * (userData.achievements.slots.progress.now / userData.achievements.slots.progress.total)) + })); + embed.addField(message.translate("economy/achievements:TIP"), message.translate("economy/achievements:PROGRESS", { + now: userData.achievements.tip.progress.now, + total: userData.achievements.tip.progress.total, + percent: Math.round(100 * (userData.achievements.tip.progress.now / userData.achievements.tip.progress.total)) + })); + embed.addField(message.translate("economy/achievements:REP"), message.translate("economy/achievements:PROGRESS", { + now: userData.achievements.rep.progress.now, + total: userData.achievements.rep.progress.total, + percent: Math.round(100 * (userData.achievements.rep.progress.now / userData.achievements.rep.progress.total)) + })); + embed.addField(message.translate("economy/achievements:INVITE"), message.translate("economy/achievements:PROGRESS", { + now: userData.achievements.invite.progress.now, + total: userData.achievements.invite.progress.total, + percent: Math.round(100 * (userData.achievements.invite.progress.now / userData.achievements.invite.progress.total)) + })); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Achievements; \ No newline at end of file diff --git a/TO REWRITE/Economy/birthdate.js b/TO REWRITE/Economy/birthdate.js new file mode 100644 index 00000000..30e12059 --- /dev/null +++ b/TO REWRITE/Economy/birthdate.js @@ -0,0 +1,50 @@ +const Command = require("../../base/Command"); + +class Birthdate extends Command { + constructor(client) { + super(client, { + name: "birthdate", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["bd"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const date = args[0]; + if (!date) return message.error("economy/birthdate:MISSING_DATE"); + + const tArgs = date.split("/"); + const [day, month, year] = tArgs; + if (!day || !month || !year) return message.error("economy/birthdate:INVALID_DATE"); + + const match = date.match(/\d+/g); + if (!match) return message.error("economy/birthdate:INVALID_DATE"); + + const tday = +match[0], + tmonth = +match[1] - 1; + let tyear = +match[2]; + + if (tyear < 100) tyear += tyear < 50 ? 2000 : 1900; + + const d = new Date(tyear, tmonth, tday); + if (!(tday == d.getDate() && tmonth == d.getMonth() && tyear == d.getFullYear())) return message.error("economy/birthdate:INVALID_DATE"); + if (d.getTime() > Date.now()) return message.error("economy/birthdate:DATE_TOO_HIGH"); + if (d.getTime() < (Date.now() - 2.523e+12)) return message.error("economy/birthdate:DATE_TOO_LOW"); + + data.userData.birthdate = d; + data.userData.save(); + + message.success("economy/birthdate:SUCCESS", { + date: this.client.printDate(d) + }); + } +} + +module.exports = Birthdate; \ No newline at end of file diff --git a/TO REWRITE/Economy/deposit.js b/TO REWRITE/Economy/deposit.js new file mode 100644 index 00000000..3cdd2547 --- /dev/null +++ b/TO REWRITE/Economy/deposit.js @@ -0,0 +1,52 @@ +const Command = require("../../base/Command"); + +class Deposit extends Command { + constructor(client) { + super(client, { + name: "deposit", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["bank", "dep"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + let amount = args[0]; + + if (!(parseInt(data.memberData.money, 10) > 0)) return message.error("economy/deposit:NO_CREDIT"); + + if (args[0] === "all") { + amount = parseInt(data.memberData.money, 10); + } else { + if (isNaN(amount) || parseInt(amount, 10) < 1) return message.error("economy/deposit:MISSING_AMOUNT"); + amount = parseInt(amount, 10); + } + + if (data.memberData.money < amount) return message.error("economy/deposit:NOT_ENOUGH_CREDIT", { money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` }); + + const info = { + user: message.translate("economy/transactions:BANK"), + amount: amount, + date: Date.now(), + type: "send" + }; + + data.memberData.transactions.push(info); + + data.memberData.money = data.memberData.money - amount; + data.memberData.bankSold = data.memberData.bankSold + amount; + data.memberData.save(); + + message.success("economy/deposit:SUCCESS", { + money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` + }); + } +} + +module.exports = Deposit; \ No newline at end of file diff --git a/TO REWRITE/Economy/divorce.js b/TO REWRITE/Economy/divorce.js new file mode 100644 index 00000000..84aabcf4 --- /dev/null +++ b/TO REWRITE/Economy/divorce.js @@ -0,0 +1,45 @@ +const Command = require("../../base/Command"); + +class Divorce extends Command { + constructor(client) { + super(client, { + name: "divorce", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["di"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + if (!data.userData.lover) return message.error("economy/divorce:NOT_MARRIED"); + + const user = this.client.users.cache.get(data.userData.lover) || await this.client.users.fetch(data.userData.lover); + + data.userData.lover = null; + data.userData.save(); + + const oldLover = await this.client.findOrCreateUser({ + id: user.id + }); + oldLover.lover = null; + oldLover.save(); + + message.success("economy/divorce:DIVORCED", { + username: user.username + }); + + user.send({ + content: message.translate("economy/divorce:DIVORCED_U", { + username: message.author.username + }) + }); + } +} + +module.exports = Divorce; \ No newline at end of file diff --git a/TO REWRITE/Economy/horserace.js b/TO REWRITE/Economy/horserace.js new file mode 100644 index 00000000..650db328 --- /dev/null +++ b/TO REWRITE/Economy/horserace.js @@ -0,0 +1,184 @@ +const Command = require("../../base/Command"); + +const games = {}; + +class Horserace extends Command { + constructor(client) { + super(client, { + name: "horserace", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["hr"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + if (!args[0]) return message.error("economy/horserace:MISSING_STATUS"); + const author = message.author; + + if (args[0] === "create") { + let thisGame = games[message.channel.id]; + + if (thisGame) return message.error("economy/horserace:GAME_RUNNING"); + else { + games[message.channel.id] = { + horseSpeeds: [], + bets: [] + }; + + thisGame = games[message.channel.id]; + + const f = []; + for (let i = 0; i < 5; i++) { + const speed = this.client.functions.randomNum(1, 5); + const profit = { + 1: 3.5, + 2: 3, + 3: 2.5, + 4: 2, + 5: 1.5, + }; + // const profit = Math.floor((((8.9 / 9) * (6 - speed)) + 1.1) * 10) / 10; + thisGame.horseSpeeds.push(speed); + f.push({ + name: message.translate("economy/horserace:HORSE_NAME", { + number: i + 1 + }), + value: message.translate("economy/horserace:HORSE_VALUE", { + speed, + profit: profit[speed] + }) + }); + } + message.reply({ + embeds: [{ + color: data.config.embed.color, + title: message.translate("economy/horserace:EMBED_T"), + fields: f + }] + }); + } + } else if (args[0] === "bet") { + const thisGame = games[message.channel.id]; + const horse = parseInt(args[1]); + const amount = parseInt(args[2]); + + if (horse > 5) return message.error("economy/horserace:HORSE_NUM"); + if (!thisGame) return message.error("economy/horserace:NO_GAME_RUNNING"); + + if (!amount || isNaN(amount) || parseInt(amount, 10) <= 0) return message.error("economy/pay:INVALID_AMOUNT"); + if (amount > data.memberData.money) return message.error("economy/pay:ENOUGH_MONEY", { + amount: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDITS:1"), message.translate("misc:NOUNS:CREDITS:2"), message.translate("misc:NOUNS:CREDITS:5"))}` + }); + + thisGame.bets[author.id] = { + amount, + horse + }; + + message.sendT("economy/horserace:BET", { + user: author, + amount: `**${Math.floor(amount)}** ${message.getNoun(Math.floor(amount), message.translate("misc:NOUNS:CREDITS:1"), message.translate("misc:NOUNS:CREDITS:2"), message.translate("misc:NOUNS:CREDITS:5"))}`, + horse + }); + + } else if (args[0] === "go") { + const thisGame = games[message.channel.id]; + const horsePositions = [0, 0, 0, 0, 0]; + + if (!thisGame) return message.error("economy/horserace:NO_GAME_RUNNING"); + + // eslint-disable-next-line no-constant-condition + while (true) { + for (let i = 0; i < 5; i++) { + if (thisGame.horseSpeeds[i] >= Math.floor(Math.random() * 15)) { + horsePositions[i] += 1; + if (horsePositions[i] === 3) { + const winnings = []; + + const profit = { + 1: 3.5, + 2: 3, + 3: 2.5, + 4: 2, + 5: 1.5, + }; + + // const profit = Math.floor((((8.9 / 9) * (6 - thisGame.horseSpeeds[i])) + 1.1) * 10) / 10; + + for (let j = 0; j < Object.keys(thisGame.bets).length; j++) { + if (Object.values(thisGame.bets)[j].horse === i + 1) { + winnings.push([Object.keys(thisGame.bets)[j], Object.values(thisGame.bets)[j].amount * profit[thisGame.horseSpeeds[i]]]); + } + } + + if (winnings.length === 0) { + for (let j = 0; j < Object.keys(thisGame.bets).length; j++) { + if (Object.values(thisGame.bets)[j].horse !== i + 1) { + const memberData = await this.client.findOrCreateMember({ + id: Object.keys(thisGame.bets)[j], + guildID: message.guild.id + }); + + const info = { + user: message.translate("economy/transactions:HORSERACE"), + amount: Object.values(thisGame.bets)[j].amount, + date: Date.now(), + type: "send" + }; + + memberData.transactions.push(info); + memberData.money -= Object.values(thisGame.bets)[j].amount; + } + } + + message.sendT("economy/horserace:NO_WINNERS", { + horse: i + 1 + }); + } else { + let winners = ""; + for (let j = 0; j < winnings.length; j++) { + winners += `\n<@${winnings[j][0]}> выиграл **${Math.floor(winnings[j][1])}** ${message.getNoun(Math.floor(winnings[j][1]), message.translate("misc:NOUNS:CREDITS:1"), message.translate("misc:NOUNS:CREDITS:2"), message.translate("misc:NOUNS:CREDITS:5"))}!`; + + const memberData = await this.client.findOrCreateMember({ + id: winnings[j][0], + guildID: message.guild.id + }); + + const toAdd = Math.floor(winnings[j][1]) - Object.values(thisGame.bets)[j].amount; + + const info = { + user: message.translate("economy/transactions:HORSERACE"), + amount: toAdd, + date: Date.now(), + type: "got" + }; + + memberData.transactions.push(info); + memberData.money += toAdd; + memberData.save(); + } + + message.sendT("economy/horserace:WINNERS", { + horse: i + 1, + winners + }); + } + + delete games[message.channel.id]; + return; + } + } + } + } + } + } +} + +module.exports = Horserace; \ No newline at end of file diff --git a/TO REWRITE/Economy/leaderboard.js b/TO REWRITE/Economy/leaderboard.js new file mode 100644 index 00000000..627184bd --- /dev/null +++ b/TO REWRITE/Economy/leaderboard.js @@ -0,0 +1,174 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Leaderboard extends Command { + constructor(client) { + super(client, { + name: "leaderboard", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["lb"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const isOnMobile = (message.member.presence.clientStatus ? JSON.stringify(Object.keys(message.member.presence.clientStatus)) === JSON.stringify(["mobile"]) : false); + + const type = args[0]; + if (!type || !["credits", "level", "rep"].includes(type)) return message.error("economy/leaderboard:MISSING_TYPE"); + + if (type === "credits") { + const members = await this.client.membersData.find({ + guildID: message.guild.id + }).lean(), + membersLeaderboard = members.map((m) => { + return { + id: m.id, + money: m.money + m.bankSold + }; + }).sort((a, b) => b.money - a.money); + if (membersLeaderboard.length > 20) membersLeaderboard.length = 20; + + let userNames = ""; + let money = ""; + for (let i = 0; i < membersLeaderboard.length; i++) { + const data = membersLeaderboard[i]; + const user = (await this.client.users.fetch(data.id)).tag; + + userNames += `**${i + 1}**. ${user}\n`; + money += `${data.money}\n`; + } + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("economy/leaderboard:TABLE", { + name: message.guild.name + }), + iconURL: message.guild.iconURL({ + dynamic: true + }) + }) + .setColor(data.config.embed.color) + .addFields({ + name: message.translate("economy/leaderboard:TOP"), + value: userNames, + inline: true + }, { + name: message.translate("common:CREDITS"), + value: money, + inline: true + }); + + message.reply({ + embeds: [embed] + }); + } else if (type === "level") { + const members = await this.client.membersData.find({ + guildID: message.guild.id + }).lean(), + membersLeaderboard = members.map((m) => { + return { + id: m.id, + level: m.level, + xp: m.exp + }; + }).sort((a, b) => b.level - a.level); + if (membersLeaderboard.length > 20) membersLeaderboard.length = 20; + + let userNames = ""; + let level = ""; + let xp = ""; + for (let i = 0; i < membersLeaderboard.length; i++) { + const data = membersLeaderboard[i]; + const user = (await this.client.users.fetch(data.id)).tag; + + userNames += `**${i + 1}**. ${user}\n`; + level += `${data.level}\n`; + xp += `${data.xp} / ${5 * (data.level * data.level) + 80 * data.level + 100}\n`; + } + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("economy/leaderboard:TABLE", { + name: message.guild.name + }), + iconURL: message.guild.iconURL({ + dynamic: true + }) + }) + .setColor(data.config.embed.color) + .addFields({ + name: message.translate("economy/leaderboard:TOP"), + value: userNames, + inline: true + }, { + name: message.translate("common:LEVEL"), + value: level, + inline: true + }, { + name: message.translate("common:XP"), + value: xp, + inline: true + }); + + message.reply({ + embeds: [embed] + }); + } else if (type === "rep") { + const users = await this.client.usersData.find({ + rep: { $gt: 0 } + }).lean(), + usersLeaderboard = users.map((u) => { + return { + id: u.id, + rep: u.rep + }; + }).sort((a, b) => b.rep - a.rep); + if (usersLeaderboard.length > 20) usersLeaderboard.length = 20; + + let userNames = ""; + let rep = ""; + for (let i = 0; i < usersLeaderboard.length; i++) { + const data = usersLeaderboard[i]; + const user = (await this.client.users.fetch(data.id)).tag; + + userNames += `**${i + 1}**. ${user}\n`; + rep += `${data.rep}\n`; + } + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("economy/leaderboard:TABLE", { + name: message.guild.name + }), + iconURL: message.guild.iconURL({ + dynamic: true + }) + }) + .setColor(data.config.embed.color) + .addFields({ + name: message.translate("economy/leaderboard:TOP"), + value: userNames, + inline: true + }, { + name: message.translate("common:REP"), + value: rep, + inline: true + }); + + message.reply({ + embeds: [embed] + }); + } + + if (isOnMobile) message.sendT("economy/leaderboard:MOBILE"); + } +} + +module.exports = Leaderboard; \ No newline at end of file diff --git a/TO REWRITE/Economy/marry.js b/TO REWRITE/Economy/marry.js new file mode 100644 index 00000000..2ad02c54 --- /dev/null +++ b/TO REWRITE/Economy/marry.js @@ -0,0 +1,134 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +const pendings = {}; + +class Marry extends Command { + constructor(client) { + super(client, { + name: "marry", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + if (data.userData.lover) return message.error("economy/marry:ALREADY_MARRIED", { prefix: data.guild.prefix }); + + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("economy/marry:INVALID_MEMBER"); + + const userData = await this.client.findOrCreateUser({ + id: member.id + }); + + if (userData.lover) return message.error("economy/marry:ALREADY_MARRIED_USER", { username: member.user.tag }); + if (member.user.bot) return message.error("economy/marry:BOT_USER"); + if (member.id === message.author.id) return message.error("economy/marry:YOURSELF"); + + for (const requester in pendings) { + const receiver = pendings[requester]; + // If the member already sent a request to someone + if (requester === message.author.id) { + const user = this.client.users.cache.get(receiver) || await this.client.users.fetch(receiver); + return message.error("economy/marry:REQUEST_AUTHOR_TO_AMEMBER", { + username: user.tag + }); + } else if (receiver === message.author.id) { // If there is a pending request for this member + const user = this.client.users.cache.get(requester) || await this.client.users.fetch(requester); + return message.error("economy/marry:REQUEST_AMEMBER_TO_AUTHOR", { + username: user.tag + }); + } else if (requester === member.id) { // If the asked member has sent pending request + const user = this.client.users.cache.get(receiver) || await this.client.users.fetch(receiver); + return message.error("economy/marry:REQUEST_AMEMBER_TO_MEMBER", { + firstUsername: member.user.tag, + secondUsername: user.tag + }); + } else if (receiver === member.id) { // If there is a pending request for the asked member + const user = this.client.users.cache.get(requester) || await this.client.users.fetch(requester); + return message.error("economy/marry:REQUEST_MEMBER_TO_AMEMBER", { + firstUsername: member.user.tag, + secondUsername: user.tag + }); + } + } + + // Update pending requests + pendings[message.author.id] = member.id; + + message.sendT("economy/marry:REQUEST", { + from: message.author.toString(), + to: member.user.toString() + }); + + const filter = m => m.author.id === member.id; + const collector = new Discord.MessageCollector(message.channel, { + filter, + time: 120000 + }); + + collector.on("collect", (msg) => { + if (msg.content.toLowerCase() === message.translate("common:YES").toLowerCase()) { + return collector.stop(true); + } else if (msg.content.toLowerCase() === message.translate("common:NO").toLowerCase()) { + return collector.stop(false); + } else { + return message.error("misc:INVALID_YES_NO"); + } + }); + + collector.on("end", async (_collected, reason) => { + // Delete pending request + delete pendings[message.author.id]; + if (reason === "time") return message.error("economy/marry:TIMEOUT", { username: member.user.toString() }); + if (reason) { + data.userData.lover = member.id; + await data.userData.save(); + userData.lover = message.author.id; + await userData.save(); + const messageOptions = { + content: `${member.toString()} :heart: ${message.author.toString()}`, + files: [{ + name: "achievement_unlocked3.png", + attachment: "./assets/img/achievements/achievement_unlocked3.png" + }] + }; + let sent = false; + if (!userData.achievements.married.achieved) { + message.channel.send(messageOptions); + sent = true; + userData.achievements.married.achieved = true; + userData.achievements.married.progress.now = 1; + userData.markModified("achievements.married"); + userData.save(); + } + if (!data.userData.achievements.married.achieved) { + if (!sent) message.channel.send(messageOptions); + data.userData.achievements.married.achieved = true; + data.userData.achievements.married.progress.now = 1; + data.userData.markModified("achievements.married"); + data.userData.save(); + } + return message.success("economy/marry:SUCCESS", { + creator: message.author.toString(), + partner: member.user.toString() + }); + } else { + return message.success("economy/marry:DENIED", { + creator: message.author.toString(), + partner: member.user.toString() + }); + } + }); + } +} + +module.exports = Marry; \ No newline at end of file diff --git a/TO REWRITE/Economy/money.js b/TO REWRITE/Economy/money.js new file mode 100644 index 00000000..d173f229 --- /dev/null +++ b/TO REWRITE/Economy/money.js @@ -0,0 +1,75 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +const asyncForEach = async (collection, callback) => { + const allPromises = collection.map(async key => { + await callback(key); + }); + + return await Promise.all(allPromises); +}; + +class Money extends Command { + constructor(client) { + super(client, { + name: "money", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["balance", "mon"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + let member = await this.client.resolveMember(args[0], message.guild); + if (!member) member = message.member; + const user = member.user; + + if (user.bot) return message.error("misc:BOT_USER"); + + const memberData = (message.author === user) ? data.memberData : await this.client.findOrCreateMember({ + id: user.id, + guildID: message.guild.id + }); + + const commonsGuilds = this.client.guilds.cache.filter((g) => g.members.cache.get(user.id)); + let globalMoney = 0; + await asyncForEach(commonsGuilds, async (guild) => { + const data = await this.client.findOrCreateMember({ + id: user.id, + guildID: guild.id + }); + globalMoney += data.money; + globalMoney += data.bankSold; + }); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("economy/money:TITLE", { + username: member.user.username + }), + iconURL: member.user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .addField(message.translate("economy/profile:CASH"), `**${memberData.money}** ${message.getNoun(memberData.money, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, true) + .addField(message.translate("economy/profile:BANK"), `**${memberData.bankSold}** ${message.getNoun(memberData.bankSold, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, true) + .addField(message.translate("economy/profile:GLOBAL"), `**${globalMoney}** ${message.getNoun(globalMoney, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, true) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Money; \ No newline at end of file diff --git a/TO REWRITE/Economy/number.js b/TO REWRITE/Economy/number.js new file mode 100644 index 00000000..333b35af --- /dev/null +++ b/TO REWRITE/Economy/number.js @@ -0,0 +1,97 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +const currentGames = {}; + +class Number extends Command { + constructor(client) { + super(client, { + name: "number", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["num"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + if (currentGames[message.guild.id]) return message.error("economy/number:GAME_RUNNING"); + + const participants = [], + number = this.client.functions.randomNum(1000, 6000); + + await message.sendT("economy/number:GAME_START"); + + // Store the date wich the game has started + const gameCreatedAt = Date.now(); + + const filter = m => !m.author.bot; + const collector = new Discord.MessageCollector(message.channel, { + filter, + time: 480000 // 8 minutes + }); + currentGames[message.guild.id] = true; + + collector.on("collect", async msg => { + if (!participants.includes(msg.author.id)) participants.push(msg.author.id); + if (msg.content === "STOP") return collector.stop("force"); + if (isNaN(msg.content)) return; + + const parsedNumber = parseInt(msg.content, 10); + + if (parsedNumber === number) { + const time = this.client.convertTime(message.guild, Date.now() - gameCreatedAt); + message.sendT("economy/number:GAME_STATS", { + winner: msg.author.toString(), + number, + time, + participantCount: participants.length, + participants: participants.map(p => `<@${p}>`).join(", ") + }); + + if (participants.length > 1 && data.guild.disabledCategories && !data.guild.disabledCategories.includes("Economy")) { + const won = 100 * (participants.length * 0.5); + + message.sendT("economy/number:WON", { + winner: msg.author.username, + credits: `**${won}** ${message.getNoun(won, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` + }); + + const memberData = await this.client.findOrCreateMember({ + id: msg.author.id, + guildID: message.guild.id + }); + + const info = { + user: message.translate("economy/transactions:NUMBERS"), + amount: won, + date: Date.now(), + type: "got" + }; + + data.memberData.transactions.push(info); + + memberData.money += won; + memberData.save(); + } + + collector.stop(); + } + if (parseInt(msg.content) < number) message.error("economy/number:BIG", { user: msg.author.toString(), number: parsedNumber }); + if (parseInt(msg.content) > number) message.error("economy/number:SMALL", { user: msg.author.toString(), number: parsedNumber }); + }); + + collector.on("end", (_collected, reason) => { + delete currentGames[message.guild.id]; + if (reason === "time") return message.error("economy/number:DEFEAT", { number }); + else if (reason === "force") return message.error("misc:FORCE_STOP", { user: message.author.toString() }); + }); + } +} + +module.exports = Number; \ No newline at end of file diff --git a/TO REWRITE/Economy/pay.js b/TO REWRITE/Economy/pay.js new file mode 100644 index 00000000..0afd9c9c --- /dev/null +++ b/TO REWRITE/Economy/pay.js @@ -0,0 +1,59 @@ +const Command = require("../../base/Command"); + +class Pay extends Command { + constructor(client) { + super(client, { + name: "pay", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("economy/pay:INVALID_MEMBER"); + if (member.user.bot) return message.error("economy/pay:BOT_USER"); + if (member.id === message.author.id) return message.error("economy/pay:YOURSELF"); + + const sentAmount = args[1]; + if (!sentAmount || isNaN(sentAmount) || parseInt(sentAmount, 10) <= 0) return message.error("economy/pay:INVALID_AMOUNT"); + + const amount = Math.ceil(parseInt(sentAmount, 10)); + if (amount > data.memberData.money) return message.error("economy/pay:ENOUGH_MONEY", { + amount: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDITS:1"), message.translate("misc:NOUNS:CREDITS:2"), message.translate("misc:NOUNS:CREDITS:5"))}` + }); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + + const info = { + user: member.user.tag, + amount: parseInt(amount, 10), + date: Date.now(), + type: "send" + }; + + data.memberData.transactions.push(info); + data.memberData.money = data.memberData.money - parseInt(amount, 10); + data.memberData.save(); + + memberData.money = memberData.money + parseInt(amount, 10); + memberData.save(); + + message.success("economy/pay:SUCCESS", { + amount: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + username: member.user.tag + }); + } +} + +module.exports = Pay; \ No newline at end of file diff --git a/TO REWRITE/Economy/profile.js b/TO REWRITE/Economy/profile.js new file mode 100644 index 00000000..45e564b1 --- /dev/null +++ b/TO REWRITE/Economy/profile.js @@ -0,0 +1,98 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +const asyncForEach = async (collection, callback) => { + const allPromises = collection.map(async key => { + await callback(key); + }); + + return await Promise.all(allPromises); +}; + +class Profile extends Command { + constructor(client) { + super(client, { + name: "profile", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["prof"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const arg = args[0] || message.author; + let member = await this.client.resolveMember(arg, message.guild); + if (!member) member = message.member; + if (member.user.bot) return message.error("economy/profile:BOT_USER"); + + const memberData = (member.id === message.author.id ? data.memberData : await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + })); + const userData = (member.id === message.author.id ? data.userData : await this.client.findOrCreateUser({ + id: member.id + })); + if (userData.lover && !this.client.users.cache.get(userData.lover)) await this.client.users.fetch(userData.lover, true); + + const commonsGuilds = this.client.guilds.cache.filter((g) => g.members.cache.get(member.id)); + let globalMoney = 0; + await asyncForEach(commonsGuilds, async (guild) => { + const data = await this.client.findOrCreateMember({ + id: member.id, + guildID: guild.id + }); + globalMoney += data.money; + globalMoney += data.bankSold; + }); + + const profileEmbed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("economy/profile:TITLE", { + username: member.user.tag + }), + iconURL: member.user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .setImage("attachment://achievements.png") + .addField(this.client.customEmojis.link + " " + message.translate("economy/profile:LINK"), `[${message.translate("economy/profile:LINK_TEXT")}](${this.client.config.dashboard.baseURL}/user/${member.user.id}/${message.guild.id})`) + .addField(message.translate("economy/profile:BIO"), userData.bio ? userData.bio : message.translate("economy/profile:NO_BIO")) + .addField(message.translate("economy/profile:CASH"), `**${memberData.money}** ${message.getNoun(memberData.money, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, true) + .addField(message.translate("economy/profile:BANK"), `**${memberData.bankSold}** ${message.getNoun(memberData.bankSold, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, true) + .addField(message.translate("economy/profile:GLOBAL"), `**${globalMoney}** ${message.getNoun(globalMoney, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, true) + .addField(message.translate("economy/profile:REPUTATION"), `**${userData.rep}** ${message.getNoun(userData.rep, message.translate("misc:NOUNS:POINTS:1"), message.translate("misc:NOUNS:POINTS:2"), message.translate("misc:NOUNS:POINTS:5"))}`, true) + .addField(message.translate("economy/profile:LEVEL"), `**${memberData.level}**`, true) + .addField(message.translate("economy/profile:EXP"), `**${memberData.exp}/${5 * (memberData.level * memberData.level) + 80 * memberData.level + 100}** xp`, true) + .addField(message.translate("economy/profile:REGISTERED"), this.client.printDate(new Date(memberData.registeredAt)), true) + .addField(message.translate("economy/profile:BIRTHDATE"), (!userData.birthdate ? message.translate("economy/profile:NO_BIRTHDATE") : this.client.printDate(new Date(userData.birthdate))), true) + .addField(message.translate("economy/profile:LOVER"), (!userData.lover ? message.translate("economy/profile:NO_LOVER") : this.client.users.cache.get(userData.lover).tag), true) + .addField(message.translate("economy/profile:ACHIEVEMENTS"), message.translate("economy/profile:ACHIEVEMENTS_CONTENT", { + prefix: data.guild.prefix + })) + .setColor(data.config.embed.color) // Sets the color of the embed + .setFooter({ + text: data.config.embed.footer + }) // Sets the footer of the embed + .setTimestamp(); + + const buffer = await userData.getAchievements(); + + message.reply({ + embeds: [profileEmbed], + files: [{ + name: "achievements.png", + attachment: buffer + }] + }); + } +} + +module.exports = Profile; \ No newline at end of file diff --git a/TO REWRITE/Economy/rep.js b/TO REWRITE/Economy/rep.js new file mode 100644 index 00000000..dc4ba37f --- /dev/null +++ b/TO REWRITE/Economy/rep.js @@ -0,0 +1,71 @@ +const Command = require("../../base/Command"); + +class Rep extends Command { + constructor(client) { + super(client, { + name: "rep", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["reputation"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + // if the member is already in the cooldown db + const isInCooldown = (data.userData.cooldowns || { + rep: 0 + }).rep; + if (isInCooldown) { + /*if the timestamp recorded in the database indicating + when the member will be able to execute the order again + is greater than the current date, display an error message */ + if (isInCooldown > Date.now()) return message.error("economy/rep:COOLDOWN", { + time: this.client.convertTime(isInCooldown, "to", true) + }); + } + + const user = await this.client.resolveUser(args[0]); + if (!user) return message.error("economy/rep:INVALID_USER"); + if (user.bot) return message.error("economy/rep:BOT_USER"); + if (user.id === message.author.id) return message.error("economy/rep:YOURSELF"); + + // Records in the database the time when the member will be able to execute the command again (in 12 hours) + const toWait = Date.now() + 21600000; + data.userData.cooldowns = {}; + data.userData.cooldowns.rep = toWait; + data.userData.markModified("cooldowns"); + data.userData.save(); + + const userData = await this.client.findOrCreateUser({ + id: user.id + }); + userData.rep++; + if (!userData.achievements.rep.achieved) { + userData.achievements.rep.progress.now = (userData.rep > userData.achievements.rep.progress.total ? userData.achievements.rep.progress.total : userData.rep); + if (userData.achievements.rep.progress.now >= userData.achievements.rep.progress.total) { + userData.achievements.rep.achieved = true; + message.channel.send({ + content: `${user}`, + files: [{ + name: "achievement_unlocked6.png", + attachment: "./assets/img/achievements/achievement_unlocked6.png" + }] + }); + } + userData.markModified("achievements.rep"); + } + await userData.save(); + + message.success("economy/rep:SUCCESS", { + username: user.username + }); + } +} + +module.exports = Rep; \ No newline at end of file diff --git a/TO REWRITE/Economy/rob.js b/TO REWRITE/Economy/rob.js new file mode 100644 index 00000000..ea682ba1 --- /dev/null +++ b/TO REWRITE/Economy/rob.js @@ -0,0 +1,78 @@ +const Command = require("../../base/Command"); + +class Rob extends Command { + constructor(client) { + super(client, { + name: "rob", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["steal"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("economy/rob:MISSING_MEMBER"); + if (member.id === message.author.id) return message.error("economy/rob:YOURSELF"); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + const isInCooldown = memberData.cooldowns.rob || 0; + if (isInCooldown) { + if (isInCooldown > Date.now()) return message.error("economy/rob:COOLDOWN", { user: member.user }); + } + + let amountToRob = args[1]; + if (!amountToRob || isNaN(amountToRob) || parseInt(amountToRob, 10) <= 0) return message.error("economy/rob:MISSING_AMOUNT", { user: member.user }); + + amountToRob = Math.floor(parseInt(amountToRob, 10)); + + if (amountToRob > memberData.money) return message.error("economy/rob:NOT_ENOUGH_MEMBER", { user: member.user }); + + const potentiallyLose = Math.floor(amountToRob * 1.5); + if (potentiallyLose > data.memberData.money) return message.error("economy/rob:NOT_ENOUGH_AUTHOR", { + moneyMin: `${potentiallyLose} ${message.getNoun(potentiallyLose, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + moneyCurrent: `${data.memberData.money} ${message.getNoun(data.memberData.money, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` + }); + + const itsAWon = Math.floor(this.client.functions.randomNum(0, 100) < 25); + + if (itsAWon) { + const toWait = Date.now() + 6 * (60 * 60000); // 6 hours + memberData.cooldowns.rob = toWait; + memberData.markModified("cooldowns"); + await memberData.save(); + const randomNum = this.client.functions.randomNum(1, 2); + message.sendT("economy/rob:ROB_WON_" + randomNum, { + money: `${amountToRob} ${message.getNoun(amountToRob, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + user: member.user + }); + data.memberData.money += amountToRob; + memberData.money -= amountToRob, 10; + memberData.save(); + data.memberData.save(); + } else { + const won = Math.floor(0.9 * amountToRob); + const randomNum = this.client.functions.randomNum(1, 2); + message.sendT("economy/rob:ROB_LOSE_" + randomNum, { + fine: `${potentiallyLose} ${message.getNoun(potentiallyLose, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + offset: `${won} ${message.getNoun(won, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + user: member.user + }); + data.memberData.money -= potentiallyLose; + memberData.money += won; + memberData.save(); + data.memberData.save(); + } + } +} + +module.exports = Rob; \ No newline at end of file diff --git a/TO REWRITE/Economy/setbio.js b/TO REWRITE/Economy/setbio.js new file mode 100644 index 00000000..d3e8998e --- /dev/null +++ b/TO REWRITE/Economy/setbio.js @@ -0,0 +1,30 @@ +const Command = require("../../base/Command"); + +class Setbio extends Command { + constructor(client) { + super(client, { + name: "setbio", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["biography", "setdesc", "sb"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const newBio = args.join(" "); + if (!newBio) return message.error("economy/setbio:MISSING"); + if (newBio.length > 100) return message.error("economy/setbio:MAX_CHARACT"); + + data.userData.bio = newBio; + message.success("economy/setbio:SUCCESS"); + await data.userData.save(); + } +} + +module.exports = Setbio; \ No newline at end of file diff --git a/TO REWRITE/Economy/slots.js b/TO REWRITE/Economy/slots.js new file mode 100644 index 00000000..31fe1e4c --- /dev/null +++ b/TO REWRITE/Economy/slots.js @@ -0,0 +1,208 @@ +const Command = require("../../base/Command"); + +class Slots extends Command { + constructor(client) { + super(client, { + name: "slots", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["casino", "slot"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const fruits = ["🍎", "🍐", "🍌", "🍇", "🍉", "🍒", "🍓"]; + + let i1 = 0, j1 = 0, k1 = 0, + i2 = 1, j2 = 1, k2 = 1, + i3 = 2, j3 = 2, k3 = 2; + + // Gets three random fruits array + const colonnes = [ + this.client.functions.shuffle(fruits), + this.client.functions.shuffle(fruits), + this.client.functions.shuffle(fruits) + ]; + + // Gets the amount provided + let amount = args[0]; + if (!amount || isNaN(amount) || amount < 1) amount = 50; + if (amount > data.memberData.money) return message.error("economy/slots:NOT_ENOUGH", { money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` }); + + amount = Math.round(amount); + + function getCredits(number, isJackpot) { + if (!isJackpot) number = number * 1.5; + else if (isJackpot) number = number * 5; + + return Math.round(number); + } + + const tmsg = await message.sendT("misc:PLEASE_WAIT", null, { + prefixEmoji: "loading" + }); + editMsg(); + + const interval = setInterval(editMsg, 1000); + + setTimeout(() => { + clearInterval(interval); + end(tmsg); + }, 4000); + + async function end() { + let msg = "[ :slot_machine: | **СЛОТЫ** ]\n------------------\n"; + + i1 = (i1 < fruits.length - 1) ? i1 + 1 : 0; + i2 = (i2 < fruits.length - 1) ? i2 + 1 : 0; + i3 = (i3 < fruits.length - 1) ? i3 + 1 : 0; + j1 = (j1 < fruits.length - 1) ? j1 + 1 : 0; + j2 = (j2 < fruits.length - 1) ? j2 + 1 : 0; + j3 = (j3 < fruits.length - 1) ? j3 + 1 : 0; + k1 = (k1 < fruits.length - 1) ? k1 + 1 : 0; + k2 = (k2 < fruits.length - 1) ? k2 + 1 : 0; + k3 = (k3 < fruits.length - 1) ? k3 + 1 : 0; + + msg += colonnes[0][i1] + " : " + colonnes[1][j1] + " : " + colonnes[2][k1] + "\n"; + msg += colonnes[0][i2] + " : " + colonnes[1][j2] + " : " + colonnes[2][k2] + " **<**\n"; + msg += colonnes[0][i3] + " : " + colonnes[1][j3] + " : " + colonnes[2][k3] + "\n------------------\n"; + + if ((colonnes[0][i2] == colonnes[1][j2]) && (colonnes[1][j2] == colonnes[2][k2])) { + msg += "| : : : **" + (message.translate("common:VICTORY").toUpperCase()) + "** : : : |"; + tmsg.edit(msg); + const credits = getCredits(amount, true); + message.channel.send({ + content: "**!! ДЖЕКПОТ !!**\n" + message.translate("economy/slots:VICTORY", { + money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + won: `**${credits}** ${message.getNoun(credits, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + username: message.author.username + }) + }); + + const toAdd = credits - amount; + + const info = { + user: message.translate("economy/slots:DESCRIPTION"), + amount: toAdd, + date: Date.now(), + type: "got" + }; + + data.memberData.transactions.push(info); + + data.memberData.money = data.memberData.money + toAdd; + if (!data.userData.achievements.slots.achieved) { + data.userData.achievements.slots.progress.now += 1; + if (data.userData.achievements.slots.progress.now === data.userData.achievements.slots.progress.total) { + data.userData.achievements.slots.achieved = true; + message.reply({ + files: [{ + name: "achievement_unlocked4.png", + attachment: "./assets/img/achievements/achievement_unlocked4.png" + }] + }); + } + data.userData.markModified("achievements.slots"); + await data.userData.save(); + } + await data.memberData.save(); + return; + } + + if (colonnes[0][i2] == colonnes[1][j2] || colonnes[1][j2] == colonnes[2][k2] || colonnes[0][i2] == colonnes[2][k2]) { + msg += "| : : : **" + (message.translate("common:VICTORY").toUpperCase()) + "** : : : |"; + tmsg.edit(msg); + const credits = getCredits(amount, false); + message.channel.send({ + content: message.translate("economy/slots:VICTORY", { + money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + won: `**${credits}** ${message.getNoun(credits, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + username: message.author.username + }) + }); + const toAdd = credits - amount; + + const info = { + user: message.translate("economy/slots:DESCRIPTION"), + amount: toAdd, + date: Date.now(), + type: "got" + }; + + data.memberData.transactions.push(info); + + data.memberData.money = data.memberData.money + toAdd; + if (!data.userData.achievements.slots.achieved) { + data.userData.achievements.slots.progress.now += 1; + if (data.userData.achievements.slots.progress.now === data.userData.achievements.slots.progress.total) { + data.userData.achievements.slots.achieved = true; + message.reply({ + files: [{ + name: "achievement_unlocked4.png", + attachment: "./assets/img/achievements/achievement_unlocked4.png" + }] + }); + } + data.userData.markModified("achievements.slots"); + await data.userData.save(); + } + await data.memberData.save(); + return; + } + + msg += "| : : : **" + (message.translate("common:DEFEAT").toUpperCase()) + "** : : : |"; + message.channel.send({ + content: message.translate("economy/slots:DEFEAT", { + money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}`, + username: message.author.username + }) + }); + + const info = { + user: message.translate("economy/slots:DESCRIPTION"), + amount: amount, + date: Date.now(), + type: "send" + }; + + data.memberData.transactions.push(info); + + data.memberData.money = data.memberData.money - amount; + if (!data.userData.achievements.slots.achieved) { + data.userData.achievements.slots.progress.now = 0; + data.userData.markModified("achievements.slots"); + await data.userData.save(); + } + await data.memberData.save(); + return; + } + + function editMsg() { + let msg = "[ :slot_machine: | **СЛОТЫ** ]\n------------------\n"; + + i1 = (i1 < fruits.length - 1) ? i1 + 1 : 0; + i2 = (i2 < fruits.length - 1) ? i2 + 1 : 0; + i3 = (i3 < fruits.length - 1) ? i3 + 1 : 0; + j1 = (j1 < fruits.length - 1) ? j1 + 1 : 0; + j2 = (j2 < fruits.length - 1) ? j2 + 1 : 0; + j3 = (j3 < fruits.length - 1) ? j3 + 1 : 0; + k1 = (k1 < fruits.length - 1) ? k1 + 1 : 0; + k2 = (k2 < fruits.length - 1) ? k2 + 1 : 0; + k3 = (k3 < fruits.length - 1) ? k3 + 1 : 0; + + msg += colonnes[0][i1] + " : " + colonnes[1][j1] + " : " + colonnes[2][k1] + "\n"; + msg += colonnes[0][i2] + " : " + colonnes[1][j2] + " : " + colonnes[2][k2] + " **<**\n"; + msg += colonnes[0][i3] + " : " + colonnes[1][j3] + " : " + colonnes[2][k3] + "\n"; + + tmsg.edit(msg); + } + } +} + +module.exports = Slots; \ No newline at end of file diff --git a/TO REWRITE/Economy/tictactoe.js b/TO REWRITE/Economy/tictactoe.js new file mode 100644 index 00000000..e011cdd9 --- /dev/null +++ b/TO REWRITE/Economy/tictactoe.js @@ -0,0 +1,46 @@ +const Command = require("../../base/Command"), + tictactoe = require("../../helpers/tictactoe"); + +class TicTacToe extends Command { + constructor(client) { + super(client, { + name: "tictactoe", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["ttt"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + tictactoe(message, { + resultBtn: true, + embedColor: data.config.embed.color, + embedFoot: data.config.embed.footer + }).then(async winner => { + const memberData = await this.client.findOrCreateMember({ + id: winner.id, + guildID: message.guild.id + }); + + const info = { + user: message.translate("economy/transactions:TTT"), + amount: 100, + date: Date.now(), + type: "got" + }; + + memberData.transactions.push(info); + + memberData.money += 100; + memberData.save(); + }); + } +} + +module.exports = TicTacToe; \ No newline at end of file diff --git a/TO REWRITE/Economy/transactions.js b/TO REWRITE/Economy/transactions.js new file mode 100644 index 00000000..426f79ec --- /dev/null +++ b/TO REWRITE/Economy/transactions.js @@ -0,0 +1,56 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Transactions extends Command { + constructor(client) { + super(client, { + name: "transactions", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["tr"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("economy/transactions:EMBED_TRANSACTIONS"), + iconURL: message.author.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + const transactions = data.memberData.transactions, + sortedTransactions = [ [], [] ]; + + transactions.slice(-20).forEach((t) => { + const array = t.type === "got" ? sortedTransactions[0] : sortedTransactions[1]; + array.push(`${message.translate("economy/transactions:T_USER_" + t.type.toUpperCase())}: ${t.user}\n${message.translate("economy/transactions:T_AMOUNT")}: ${t.amount}\n${message.translate("economy/transactions:T_DATE")}: ${this.client.printDate(t.date, "Do MMMM YYYY, HH:mm")}\n`); + }); + + if (transactions.length < 1) { + embed.setDescription(message.translate("economy/transactions:NO_TRANSACTIONS")); + } else { + if (sortedTransactions[0].length > 0) embed.addField(message.translate("economy/transactions:T_GOT"), sortedTransactions[0].join("\n"), true); + if (sortedTransactions[1].length > 0) embed.addField(message.translate("economy/transactions:T_SEND"), sortedTransactions[1].join("\n"), true); + } + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Transactions; \ No newline at end of file diff --git a/TO REWRITE/Economy/withdraw.js b/TO REWRITE/Economy/withdraw.js new file mode 100644 index 00000000..f19dc6ad --- /dev/null +++ b/TO REWRITE/Economy/withdraw.js @@ -0,0 +1,52 @@ +const Command = require("../../base/Command"); + +class Withdraw extends Command { + constructor(client) { + super(client, { + name: "withdraw", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["wd"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + let amount = args[0]; + + if (!(parseInt(data.memberData.bankSold, 10) > 0)) return message.error("economy/withdraw:NO_CREDIT"); + + if (args[0] === "all") { + amount = parseInt(data.memberData.bankSold, 10); + } else { + if (isNaN(amount) || parseInt(amount, 10) < 1) return message.error("economy/withdraw:MISSING_AMOUNT"); + amount = parseInt(amount, 10); + } + + if (data.memberData.bankSold < amount) return message.error("economy/withdraw:NOT_ENOUGH", { money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` }); + + const info = { + user: message.translate("economy/transactions:BANK"), + amount: amount, + date: Date.now(), + type: "got" + }; + + data.memberData.transactions.push(info); + + data.memberData.money = data.memberData.money + amount; + data.memberData.bankSold = data.memberData.bankSold - amount; + data.memberData.save(); + + message.success("economy/withdraw:SUCCESS", { + money: `**${amount}** ${message.getNoun(amount, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` + }); + } +} + +module.exports = Withdraw; \ No newline at end of file diff --git a/TO REWRITE/Economy/work.js b/TO REWRITE/Economy/work.js new file mode 100644 index 00000000..a1ed8570 --- /dev/null +++ b/TO REWRITE/Economy/work.js @@ -0,0 +1,114 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Work extends Command { + constructor(client) { + super(client, { + name: "work", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["salary", "daily"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + // if the member is already in the cooldown db + const isInCooldown = data.memberData.cooldowns.work; + if (isInCooldown) { + /*if the timestamp recorded in the database indicating + when the member will be able to execute the order again + is greater than the current date, display an error message */ + if (isInCooldown > Date.now()) return message.error("economy/work:COOLDOWN", { + time: this.client.convertTime(isInCooldown, "to", true) + }); + } + + if (Date.now() > data.memberData.cooldowns.work + (24 * 3600000)) data.memberData.workStreak = 0; + + // Records in the database the time when the member will be able to execute the command again (in 12 hours) + const toWait = Date.now() + 43200000; + data.memberData.cooldowns.work = toWait; + data.memberData.markModified("cooldowns"); + + data.memberData.workStreak = (data.memberData.workStreak || 0) + 1; + await data.memberData.save(); + + const embed = new Discord.MessageEmbed() + .setFooter({ + text: message.translate("economy/work:AWARD"), + iconURL: message.author.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .setColor(data.config.embed.color); + + const award = [ + this.client.customEmojis.letters.a, + this.client.customEmojis.letters.w, + this.client.customEmojis.letters.a, + this.client.customEmojis.letters.r, + this.client.customEmojis.letters.d + ]; + let won = 200; + + if (data.memberData.workStreak >= 5) { + won += 200; + embed.addField(message.translate("economy/work:SALARY"), message.translate("economy/work:SALARY_CONTENT", { + won: `${won} ${message.getNoun(won, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` + })) + .addField(message.translate("economy/work:STREAK"), message.translate("economy/work:STREAK_CONTENT")); + data.memberData.workStreak = 0; + } else { + for (let i = 0; i < award.length; i++) { + if (data.memberData.workStreak > i) { + const letter = Discord.Util.parseEmoji(award[i]).name.split("_")[1]; + award[i] = `:regional_indicator_${letter.toLowerCase()}:`; + } + } + embed.addField(message.translate("economy/work:SALARY"), message.translate("economy/work:SALARY_CONTENT", { + won: `**${won}** ${message.getNoun(won, message.translate("misc:NOUNS:CREDIT:1"), message.translate("misc:NOUNS:CREDIT:2"), message.translate("misc:NOUNS:CREDIT:5"))}` + })) + .addField(message.translate("economy/work:STREAK"), award.join("")); + } + + const info = { + user: message.translate("economy/work:SALARY"), + amount: won, + date: Date.now(), + type: "got" + }; + + data.memberData.transactions.push(info); + data.memberData.money = data.memberData.money + won; + data.memberData.save(); + + const messageOptions = { + embeds: [embed] + }; + if (!data.userData.achievements.work.achieved) { + data.userData.achievements.work.progress.now += 1; + if (data.userData.achievements.work.progress.now === data.userData.achievements.work.progress.total) { + messageOptions.files = [{ + name: "unlocked.png", + attachment: "./assets/img/achievements/achievement_unlocked1.png" + }]; + data.userData.achievements.work.achieved = true; + } + data.userData.markModified("achievements.work"); + data.userData.save(); + } + + // Send the embed in the current channel + message.reply(messageOptions); + } +} + +module.exports = Work; \ No newline at end of file diff --git a/commands/Examples/mention.js b/TO REWRITE/Examples/mention.js similarity index 100% rename from commands/Examples/mention.js rename to TO REWRITE/Examples/mention.js diff --git a/commands/Examples/ping.js b/TO REWRITE/Examples/ping.js similarity index 100% rename from commands/Examples/ping.js rename to TO REWRITE/Examples/ping.js diff --git a/commands/Examples/repeat.js b/TO REWRITE/Examples/repeat.js similarity index 100% rename from commands/Examples/repeat.js rename to TO REWRITE/Examples/repeat.js diff --git a/TO REWRITE/Fun/8ball.js b/TO REWRITE/Fun/8ball.js new file mode 100644 index 00000000..e0ab1bc7 --- /dev/null +++ b/TO REWRITE/Fun/8ball.js @@ -0,0 +1,31 @@ +const Command = require("../../base/Command"); + +class Eightball extends Command { + constructor(client) { + super(client, { + name: "8ball", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["8b"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args) { + if (!args[0] || !message.content.endsWith("?")) return message.error("fun/8ball:ERR_QUESTION"); + + const answerN = this.client.functions.randomNum(1, 20); + const answer = message.translate(`fun/8ball:RESPONSE_${answerN}`); + + message.reply({ + content: answer + }); + } +} + +module.exports = Eightball; \ No newline at end of file diff --git a/TO REWRITE/Fun/ascii.js b/TO REWRITE/Fun/ascii.js new file mode 100644 index 00000000..ae70522b --- /dev/null +++ b/TO REWRITE/Fun/ascii.js @@ -0,0 +1,34 @@ +const Command = require("../../base/Command"), + figlet = require("figlet"), + util = require("util"), + figletAsync = util.promisify(figlet); + +class Ascii extends Command { + constructor(client) { + super(client, { + name: "ascii", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args) { + const text = args.join(" "); + if (!text || text.length > 20) return message.error("fun/ascii:TEXT_MISSING"); + + const rendered = await figletAsync(text); + + message.reply({ + content: "```" + rendered + "```" + }); + } +} + +module.exports = Ascii; \ No newline at end of file diff --git a/TO REWRITE/Fun/flip.js b/TO REWRITE/Fun/flip.js new file mode 100644 index 00000000..09944fe1 --- /dev/null +++ b/TO REWRITE/Fun/flip.js @@ -0,0 +1,25 @@ +const Command = require("../../base/Command"); + +class Flip extends Command { + constructor(client) { + super(client, { + name: "flip", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["dice", "coin"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message) { + const isHeads = Math.random() > 0.5; + isHeads ? message.sendT("fun/flip:HEADS") : message.sendT("fun/flip:TAILS"); + } +} + +module.exports = Flip; \ No newline at end of file diff --git a/TO REWRITE/Fun/lmg.js b/TO REWRITE/Fun/lmg.js new file mode 100644 index 00000000..0742216b --- /dev/null +++ b/TO REWRITE/Fun/lmg.js @@ -0,0 +1,30 @@ +const Command = require("../../base/Command"); + +class Lmg extends Command { + constructor(client) { + super(client, { + name: "lmg", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["lmgtfy"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + const question = args.join(" "); + if (!question) return message.error("fun/lmg:MISSING"); + const encodedQuestion = question.replace(/[' '_]/g, "+"); + await message.reply({ + content: `` + }); + message.delete().catch(() => {}); + } +} + +module.exports = Lmg; \ No newline at end of file diff --git a/TO REWRITE/Fun/lovecalc.js b/TO REWRITE/Fun/lovecalc.js new file mode 100644 index 00000000..102f4a9d --- /dev/null +++ b/TO REWRITE/Fun/lovecalc.js @@ -0,0 +1,59 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + md5 = require("md5"); + +class Lovecalc extends Command { + constructor(client) { + super(client, { + name: "lovecalc", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["lc"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const firstMember = message.mentions.members.filter(m => m.id !== message.author.id).first(); + if (!firstMember) return message.error("fun/lovecalc:MISSING"); + const secondMember = message.mentions.members + .filter(m => m.id !== firstMember.id) + .filter(m => m.id !== message.author.id) + .first() || message.member; + if (!secondMember) return message.error("fun/lovecalc:MISSING"); + + const members = [firstMember, secondMember].sort((a, b) => parseInt(a.id, 10) - parseInt(b.id, 10)); + const hash = md5(`${members[0].id}${members[1].user.username}${members[0].user.username}${members[1].id}`); + + const string = hash + .split("") + .filter(e => !isNaN(e)) + .join(""); + const percent = parseInt(string.substr(0, 2), 10); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: `❤️ ${message.translate("fun/lovecalc:DESCRIPTION")}` + }) + .setDescription(message.translate("fun/lovecalc:CONTENT", { + percent, + firstUsername: firstMember.user.username, + secondUsername: secondMember.user.username + })) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Lovecalc; \ No newline at end of file diff --git a/TO REWRITE/Fun/memes.js b/TO REWRITE/Fun/memes.js new file mode 100644 index 00000000..5026f94c --- /dev/null +++ b/TO REWRITE/Fun/memes.js @@ -0,0 +1,78 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + fetch = require("node-fetch"); + +class Memes extends Command { + constructor(client) { + super(client, { + name: "memes", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["mem"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "ATTACH_FILES"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const tag = args[0]; + const subs = ["memes", "dankmemes", "me_irl", "wholesomememes"]; + + if (tag === "list") { + const embed = new Discord.MessageEmbed() + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setTitle(message.translate("fun/memes:EMBED_TITLE")) + .setDescription(subs.join("\n")) + .setTimestamp(); + + message.reply({ + embeds: [embed] + }); + } else if (!tag) { + const m = await message.sendT("fun/memes:SEARCHING_RANDOM"); + + const res = await fetch("https://meme-api.herokuapp.com/gimme/").then(response => response.json()); + const embed = new Discord.MessageEmbed() + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setTitle(`${res.title}\n${message.translate("fun/memes:SUBREDDIT")}: ${res.subreddit}\n${message.translate("common:AUTHOR")}: ${res.author}\n${message.translate("fun/memes:UPS")}: ${res.ups}`) + .setImage(res.url) + .setTimestamp(); + + m.edit({ + content: null, + embeds: [embed] + }); + } else if (subs.includes(tag)) { + const m = await message.sendT("fun/memes:SEARCHING", { + tag + }); + + const res = await fetch(`https://meme-api.herokuapp.com/gimme/${tag}`).then(response => response.json()); + const embed = new Discord.MessageEmbed() + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setTitle(`${res.title}\n${message.translate("fun/memes:SUBREDDIT")}: ${res.subreddit}\n${message.translate("common:AUTHOR")}: ${res.author}\n${message.translate("fun/memes:UPS")}: ${res.ups}`) + .setImage(res.url) + .setTimestamp(); + + m.edit({ + content: null, + embeds: [embed] + }); + } else return message.error("fun/memes:NOT_FOUND"); + } +} + +module.exports = Memes; \ No newline at end of file diff --git a/TO REWRITE/General/activity.js b/TO REWRITE/General/activity.js new file mode 100644 index 00000000..aa8d852f --- /dev/null +++ b/TO REWRITE/General/activity.js @@ -0,0 +1,263 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Activity extends Command { + constructor(client) { + super(client, { + name: "activity", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["act"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const voice = message.member.voice.channel; + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + + const perms = voice.permissionsFor(this.client.user); + if (!perms.has(Discord.Permissions.FLAGS.CONNECT) || !perms.has(Discord.Permissions.FLAGS.SPEAK)) return message.error("music/play:VOICE_CHANNEL_CONNECT"); + + const activities = [ + "betrayal", + `checkers (${message.translate("general/activity:NO_BOOST")})`, + `chess (${message.translate("general/activity:NO_BOOST")})`, + "sketchheads", + `ocho (${message.translate("general/activity:NO_BOOST")})`, + "fishing", + "lettertile", + `poker (${message.translate("general/activity:NO_BOOST")})`, + `spellcast (${message.translate("general/activity:NO_BOOST")})`, + "wordsnack", + "puttparty", + "youtube" + ]; + const activity = args[0]; + + switch (activity) { + case "betrayal": + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "betrayal").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Betrayal.io") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Betrayal.io", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "checkers": + if (message.guild.premiumTier === "NONE") return message.error("general/activity:NO_BOOST"); + + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "checkers").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Checkers In The Park") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Checkers In The Park", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "chess": + if (message.guild.premiumTier === "NONE") return message.error("general/activity:NO_BOOST"); + + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "chess").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Chess In The Park") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Chess In The Park", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "sketchheads": + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "sketchheads").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Sketch Heads") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Sketch Heads", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "ocho": + if (message.guild.premiumTier === "NONE") return message.error("general/activity:NO_BOOST"); + + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "ocho").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Ocho") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Ocho", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "fishing": + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "fishing").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Fishington.io") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Fishington.io", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "lettertile": + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "lettertile").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Letter Tile") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Letter Tile", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "poker": + if (message.guild.premiumTier === "NONE") return message.error("general/activity:NO_BOOST"); + + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "poker").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Poker Night") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Poker Night", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "spellcast": + if (message.guild.premiumTier === "NONE") return message.error("general/activity:NO_BOOST"); + + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "spellcast").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Spell Cast") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Spell Cast", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "wordsnack": + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "wordsnack").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Words Snack") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Words Snack", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "puttparty": + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "puttparty").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Puttparty") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Puttparty", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + case "youtube": + this.client.discordTogether.createTogetherCode(message.member.voice.channelId, "youtube").then(async invite => { + const embed = new Discord.MessageEmbed() + .setTitle("Youtube Together") + .setColor(data.config.embed.color) + .setDescription(`**[${message.translate("misc:CLICK_HERE", { activity: "Youtube Together", channel: voice.name })}](${invite.code})**`) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + }); + break; + + default: { + const embed = new Discord.MessageEmbed() + .setTitle(message.translate("general/activity:TITLE")) + .setDescription(activities.join("\n")) + .setColor(data.config.embed.color) + .setFooter({ + text: message.translate("general/activity:FOOTER") + }) + .setTimestamp(); + message.reply({ + embeds: [embed] + }); + } + } + } +} + +module.exports = Activity; \ No newline at end of file diff --git a/TO REWRITE/General/avatar.js b/TO REWRITE/General/avatar.js new file mode 100644 index 00000000..f875f72a --- /dev/null +++ b/TO REWRITE/General/avatar.js @@ -0,0 +1,37 @@ +const Command = require("../../base/Command"); + +class Avatar extends Command { + constructor(client) { + super(client, { + name: "avatar", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "ATTACH_FILES"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args) { + let user = await this.client.resolveUser(args[0]); + if (!user) user = message.author; + const avatarURL = user.displayAvatarURL({ + dynamic: true, + size: 512 + }); + + if (args[0] === "link") return message.reply({ content: `<${avatarURL}>` }); + + message.reply({ + files: [{ + attachment: avatarURL + }] + }); + } +} + +module.exports = Avatar; \ No newline at end of file diff --git a/TO REWRITE/General/emoji.js b/TO REWRITE/General/emoji.js new file mode 100644 index 00000000..bfbfd5bf --- /dev/null +++ b/TO REWRITE/General/emoji.js @@ -0,0 +1,46 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class EmojiInfo extends Command { + constructor(client) { + super(client, { + name: "emoji", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["emi"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const rawEmoji = args[0]; + if (!rawEmoji) return message.error("administration/stealemoji:MISSING_EMOJI"); + + const parsedEmoji = Discord.Util.parseEmoji(rawEmoji); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("general/emoji:TITLE", { + emoji: parsedEmoji.name + }) + }) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .addField(message.translate("general/emoji:NAME"), parsedEmoji.name) + .addField(message.translate("general/emoji:ANIMATED"), parsedEmoji.animated ? message.translate("common:YES") : message.translate("common:NO")) + .addField(message.translate("general/emoji:ID"), parsedEmoji.id ? parsedEmoji.id.toString() : message.translate("general/emoji:STANDART")); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = EmojiInfo; \ No newline at end of file diff --git a/TO REWRITE/General/help.js b/TO REWRITE/General/help.js new file mode 100644 index 00000000..882c3d08 --- /dev/null +++ b/TO REWRITE/General/help.js @@ -0,0 +1,117 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Help extends Command { + constructor(client) { + super(client, { + name: "help", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["h", "commands"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + if (args[0]) { + const isCustom = (message.guild && data.guild.customCommands ? data.guild.customCommands.find((c) => c.name === args[0]) : false); + + const cmd = this.client.commands.get(args[0]) || this.client.commands.get(this.client.aliases.get(args[0])); + if (!cmd && isCustom) { + return message.error("general/help:CUSTOM", { + cmd: args[0] + }); + } else if (!cmd) { + return message.error("general/help:NOT_FOUND", { + search: args[0] + }); + } + + const description = message.translate(`${cmd.help.category.toLowerCase()}/${cmd.help.name}:DESCRIPTION`); + const usage = message.translate(`${cmd.help.category.toLowerCase()}/${cmd.help.name}:USAGE`, { + prefix: message.guild ? data.guild.prefix : "" + }); + const examples = message.translate(`${cmd.help.category.toLowerCase()}/${cmd.help.name}:EXAMPLES`, { + prefix: message.guild ? data.guild.prefix : "" + }); + + const groupEmbed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("general/help:CMD_TITLE", { + cmd: cmd.help.name + }) + }) + .addField(message.translate("general/help:FIELD_DESCRIPTION"), description) + .addField(message.translate("general/help:FIELD_USAGE"), usage) + .addField(message.translate("general/help:FIELD_EXAMPLES"), examples) + .addField(message.translate("general/help:FIELD_ALIASES"), cmd.help.aliases.length > 0 ? cmd.help.aliases.map(a => "`" + a + "`").join("\n") : message.translate("general/help:NO_ALIAS")) + .addField(message.translate("general/help:FIELD_PERMISSIONS"), cmd.conf.memberPermissions.length > 0 ? cmd.conf.memberPermissions.map((p) => `\`${p}\``).join("\n") : message.translate("general/help:NO_REQUIRED_PERMISSION")) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + return message.reply({ + embeds: [groupEmbed] + }); + } + + const categories = []; + const commands = this.client.commands; + + commands.forEach((command) => { + if (!categories.includes(command.help.category)) { + if (command.help.category === "Owner" && message.author.id !== data.config.owner.id) return; + categories.push(command.help.category); + } + }); + + const emojis = this.client.customEmojis; + + const embed = new Discord.MessageEmbed() + .setDescription(message.translate("general/help:INFO", { + prefix: message.guild ? data.guild.prefix : "" + })) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + categories.sort().forEach((cat) => { + const tCommands = commands.filter((cmd) => cmd.help.category === cat); + embed.addField(`${emojis.categories[cat.toLowerCase()]} ${cat} - (${tCommands.size})`, `${tCommands.map((cmd) => `\`${cmd.help.name}\``).join(", ")}`); + }); + + if (message.guild) { + if (data.guild.customCommands.length > 0) embed.addField(`${emojis.categories.custom} ${message.guild.name} | ${message.translate("general/help:CUSTOM_COMMANDS")} - (${data.guild.customCommands.length})`, data.guild.customCommands.map((cmd) => `\`${cmd.name}\``).join(", ")); + } + + embed.addField("\u200B", message.translate("misc:STATS_FOOTER", { + dashboardLink: this.client.config.dashboard.baseURL, + docsLink: `${this.client.config.dashboard.baseURL}/docs/`, + inviteLink: this.client.generateInvite({ scopes: ["bot", "applications.commands"], permissions: [Discord.Permissions.FLAGS.ADMINISTRATOR] }), + donateLink: "https://qiwi.com/n/JONNYBRO/", + owner: data.config.owner.id + })); + embed.setAuthor({ + name: message.translate("general/help:TITLE", { + name: this.client.user.username + }), + iconURL: this.client.user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }); + + return message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Help; \ No newline at end of file diff --git a/TO REWRITE/General/invite.js b/TO REWRITE/General/invite.js new file mode 100644 index 00000000..e7e08a95 --- /dev/null +++ b/TO REWRITE/General/invite.js @@ -0,0 +1,55 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Invite extends Command { + constructor(client) { + super(client, { + name: "invite", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["i"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const inviteLink = this.client.generateInvite({ + scopes: ["bot", "applications.commands"], + permissions: [Discord.Permissions.FLAGS.ADMINISTRATOR] + }); + const donateLink = "https://qiwi.com/n/JONNYBRO/"; + + if (args[0] && args[0] === "copy") return message.reply({ + content: inviteLink + }); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("general/invite:LINKS") + }) + .setDescription(message.translate("general/invite:TIP", { + prefix: data.guild.prefix || "" + })) + .addField(message.translate("general/invite:ADD"), message.translate("general/invite:CLICK", { + link: inviteLink + })) + .addField(message.translate("general/invite:SUPPORT"), message.translate("general/invite:CLICK", { + link: donateLink + }) + `\n*для других способов пишите в ЛС <@${data.config.owner.id}> (указывайте ваш Discord тэг чтобы я мог выдать вам ачивку)*`) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Invite; \ No newline at end of file diff --git a/TO REWRITE/General/invites.js b/TO REWRITE/General/invites.js new file mode 100644 index 00000000..64621010 --- /dev/null +++ b/TO REWRITE/General/invites.js @@ -0,0 +1,72 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Invites extends Command { + constructor(client) { + super(client, { + name: "invites", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["invs"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "MANAGE_GUILD"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + let member = await this.client.resolveMember(args[0], message.guild); + if (!member) member = message.member; + + const invites = await message.guild.invites.fetch().catch(() => {}); + if (!invites) return message.error("misc:ERR_OCCURRED"); + + const memberInvites = invites.filter((i) => i.inviter && i.inviter.id === member.user.id); + + if (memberInvites.size <= 0) { + if (member === message.member) { + return message.error("general/invites:NOBODY_AUTHOR"); + } else { + return message.error("general/invites:NOBODY_MEMBER", { + member: member.user.tag + }); + } + } + + const content = memberInvites.map((i) => { + return message.translate("general/invites:CODE", { + uses: i.uses, + code: i.code, + channel: i.channel.toString() + }); + }).join("\n"); + let index = 0; + memberInvites.forEach((invite) => index += invite.uses); + + const embed = new Discord.MessageEmbed() + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setAuthor({ + name: message.translate("general/invites:TRACKER") + }) + .setDescription(message.translate("general/invites:TITLE", { + member: member.user.tag, + guild: message.guild.name + })) + .addField(message.translate("general/invites:FIELD_INVITED"), message.translate("general/invites:FIELD_MEMBERS", { + total: index + })) + .addField(message.translate("general/invites:FIELD_CODES"), content); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Invites; \ No newline at end of file diff --git a/TO REWRITE/General/minecraft.js b/TO REWRITE/General/minecraft.js new file mode 100644 index 00000000..22679cf7 --- /dev/null +++ b/TO REWRITE/General/minecraft.js @@ -0,0 +1,85 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + gamedig = require("gamedig"); + +class Minecraft extends Command { + constructor(client) { + super(client, { + name: "minecraft", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["mc"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const ip = args[0]; + if (!ip) return message.error("general/minecraft:MISSING_IP"); + + const favicon = `https://eu.mc-api.net/v3/server/favicon/${ip}`; + let options = { + type: "minecraft", + host: ip + }; + + if (ip.split(":").length > 1) { + const ipp = ip.split(":"); + options = { + type: "minecraft", + host: ipp[0], + port: ipp[1] + }; + } + + const m = await message.sendT("misc:PLEASE_WAIT", null, { + prefixEmoji: "loading" + }); + + let json = null; + + await gamedig.query(options).then((res) => { + json = res; + }).catch((err) => { + console.error(err); + }); + + if (!json) { + options.type = "minecraftpe"; + await gamedig.query(options).then((res) => { + json = res; + }).catch((err) => { + console.error(err); + }); + } + + if (!json) return m.error("general/minecraft:FAILED", null, { edit: true }); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: json.name + }) + .addField(message.translate("general/minecraft:FIELD_STATUS"), message.translate("general/minecraft:ONLINE")) + .addField(message.translate("general/minecraft:FIELD_CONNECTED"), `**${(json.raw.players ? json.raw.players.online : json.players.length)}** ${message.getNoun((json.raw.players ? json.raw.players.online : json.players.length), message.translate("misc:NOUNS:PLAYERS:1"), message.translate("misc:NOUNS:PLAYERS:2"), message.translate("misc:NOUNS:PLAYERS:5"))} / **${(json.raw.players ? json.raw.players.max : json.maxplayers)}** ${message.getNoun((json.raw.players ? json.raw.players.max : json.maxplayers), message.translate("misc:NOUNS:PLAYERS:1"), message.translate("misc:NOUNS:PLAYERS:2"), message.translate("misc:NOUNS:PLAYERS:5"))}`) + .addField(message.translate("general/minecraft:FIELD_IP"), json.connect, true) + .addField(message.translate("general/minecraft:FIELD_VERSION"), json.raw.vanilla.raw.version.name, true) + .addField(message.translate("general/minecraft:FIELD_PING"), json.raw.vanilla.ping.toString()) + .setColor(data.config.embed.color) + .setThumbnail(favicon) + .setFooter({ + text: data.config.embed.footer + }); + + m.edit({ + content: null, + embeds: [embed] + }); + } +} + +module.exports = Minecraft; \ No newline at end of file diff --git a/TO REWRITE/General/permissions.js b/TO REWRITE/General/permissions.js new file mode 100644 index 00000000..de3c1ef0 --- /dev/null +++ b/TO REWRITE/General/permissions.js @@ -0,0 +1,50 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +const permissions = Object.keys(Discord.Permissions.FLAGS); + +class Permissions extends Command { + constructor(client) { + super(client, { + name: "permissions", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["perms"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message) { + const member = message.mentions.members.first() || message.member; + const mPermissions = message.channel.permissionsFor(member); + const total = { + denied: 0, + allowed: 0 + }; + + let text = `**${message.translate("general/permissions:TITLE", { user: member.user.username, channel: message.channel.name })}**\n`; + permissions.forEach((perm) => { + if (perm === "REQUEST_TO_SPEAK") return; + + if (!mPermissions.has(perm)) { + text += `${message.translate(`misc:PERMISSIONS:${perm}`)} ❌\n`; + total.denied++; + } else { + text += `${message.translate(`misc:PERMISSIONS:${perm}`)} ✅\n`; + total.allowed++; + } + }); + text += `\n${total.allowed} ✅ | ${total.denied} ❌`; + + message.reply({ + content: text + }); + } +} + +module.exports = Permissions; \ No newline at end of file diff --git a/TO REWRITE/General/quote.js b/TO REWRITE/General/quote.js new file mode 100644 index 00000000..f464a03f --- /dev/null +++ b/TO REWRITE/General/quote.js @@ -0,0 +1,88 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Quote extends Command { + constructor(client) { + super(client, { + name: "quote", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["qu"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + function embed(m) { + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: m.author.tag, + iconURL: m.author.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .setDescription(m.content) + .setColor(m.member ? m.member.roles.highest ? m.member.roles.highest.color : data.config.embed.color : data.config.embed.color) + .setFooter({ + text: m.guild.name + " | #" + m.channel.name + }) + .setTimestamp(m.createdTimestamp); + if (m.attachments.size > 0) embed.setImage(m.attachments.first().url); + return embed; + } + + const msgID = args[0]; + if (isNaN(msgID)) { + message.error("general/quote:MISSING_ID").then(() => { + if (message.deletable) message.delete(); + }); + return; + } + + let channel = args[1]; + if (args[1]) { + channel = this.client.channels.cache.get(args[1]); + if (!channel) { + message.error("general/quote:NO_MESSAGE_ID").then(() => { + if (message.deletable) message.delete(); + }); + return; + } + } + + if (!channel) { + message.channel.messages.fetch(msgID).catch(() => { + message.error("general/quote:NO_MESSAGE_ID").then(() => { + if (message.deletable) message.delete(); + }); + return; + }).then((msg) => { + if (message.deletable) message.delete(); + message.reply({ + embeds: [embed(msg)] + }); + }); + } else { + channel.messages.fetch(msgID).then((msg) => { + if (message.deletable) message.delete(); + message.reply({ + embeds: [embed(msg)] + }); + }).catch(() => { + message.error("general/quote:NO_MESSAGE_ID").then(() => { + if (message.deletable) message.delete(); + }); + return; + }); + } + } +} + +module.exports = Quote; \ No newline at end of file diff --git a/TO REWRITE/General/remindme.js b/TO REWRITE/General/remindme.js new file mode 100644 index 00000000..eb5861b6 --- /dev/null +++ b/TO REWRITE/General/remindme.js @@ -0,0 +1,45 @@ +const Command = require("../../base/Command"), + ms = require("ms"); + +class Remindme extends Command { + constructor(client) { + super(client, { + name: "remindme", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["reminder", "remind", "rem"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const time = args[0]; + if (!time || isNaN(ms(time))) return message.error("misc:INVALID_TIME"); + + const msg = args.slice(1).join(" "); + if (!msg) return message.error("general/remindme:MISSING_MESSAGE"); + + const rData = { + message: msg, + createdAt: Date.now(), + sendAt: Date.now() + ms(time) + }; + + if (!data.userData.reminds) data.userData.reminds = []; + + + data.userData.reminds.push(rData); + data.userData.markModified("reminds"); + data.userData.save(); + this.client.databaseCache.usersReminds.set(message.author.id, data.userData); + + message.success("general/remindme:SAVED"); + } +} + +module.exports = Remindme; \ No newline at end of file diff --git a/TO REWRITE/General/report.js b/TO REWRITE/General/report.js new file mode 100644 index 00000000..b63c239e --- /dev/null +++ b/TO REWRITE/General/report.js @@ -0,0 +1,69 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Report extends Command { + constructor(client) { + super(client, { + name: "report", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["repo"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + if (message.author.id === "285109105717280768") return message.reply({ content: "Пошёл нахуй фахон" }); + + const repChannel = message.guild.channels.cache.get(data.guild.plugins.reports); + if (!repChannel) return message.error("general/report:MISSING_CHANNEL"); + + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("general/report:MISSING_USER"); + if (member.id === message.author.id) return message.error("general/report:INVALID_USER"); + + const rep = args.slice(1).join(" "); + if (!rep) return message.error("general/report:MISSING_REASON"); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("general/report:TITLE", { + user: member.user.tag + }), + iconURL: message.author.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .addField(message.translate("common:AUTHOR"), message.author.tag, true) + .addField(message.translate("common:DATE"), this.client.printDate(new Date(Date.now())), true) + .addField(message.translate("common:REASON"), rep, true) + .addField(message.translate("common:USER"), `\`${member.user.tag}\` (${member.user.toString()})`, true) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + const success = Discord.Util.parseEmoji(this.client.customEmojis.success).id; + const error = Discord.Util.parseEmoji(this.client.customEmojis.error).id; + + repChannel.send({ + embeds: [embed] + }).then(async (m) => { + await m.react(success); + await m.react(error); + }); + + message.success("general/report:SUCCESS", { + channel: repChannel.toString() + }); + } +} + +module.exports = Report; \ No newline at end of file diff --git a/TO REWRITE/General/serverinfo.js b/TO REWRITE/General/serverinfo.js new file mode 100644 index 00000000..4124ee3e --- /dev/null +++ b/TO REWRITE/General/serverinfo.js @@ -0,0 +1,71 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Serverinfo extends Command { + constructor(client) { + super(client, { + name: "serverinfo", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["si"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + let guild = message.guild; + + if (args[0]) { + let found = this.client.guilds.cache.get(args[0]); + if (!found) { + found = this.client.guilds.cache.find(g => g.name.includes(args.join(" ")) || g.id === args[0]); + if (found) guild = found; + } + } + + await guild.members.fetch(); + const owner = await guild.fetchOwner(); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: guild.name, + iconURL: guild.iconURL({ + dynamic: true + }) + }) + .setThumbnail(guild.iconURL({ + dynamic: true + })) + .addField(this.client.customEmojis.link + " " + message.translate("general/serverinfo:LINK"), `[${message.translate("general/serverinfo:LINK_TEXT")}](${this.client.config.dashboard.baseURL}/stats/${guild.id})`) + .addField(this.client.customEmojis.title + message.translate("common:NAME"), guild.name, true) + .addField(this.client.customEmojis.calendar + message.translate("common:CREATION"), this.client.printDate(guild.createdAt), true) + .addField(this.client.customEmojis.users + message.translate("common:MEMBERS"), + `${guild.members.cache.filter(m => !m.user.bot).size} ${message.getNoun(guild.members.cache.filter(m => !m.user.bot).size, message.translate("misc:NOUNS:MEMBERS:1"), message.translate("misc:NOUNS:MEMBERS:2"), message.translate("misc:NOUNS:MEMBERS:5"))}` + + "\n" + `${guild.members.cache.filter(m => m.user.bot).size} ${message.getNoun(guild.members.cache.filter(m => m.user.bot).size, message.translate("misc:NOUNS:BOTS:1"), message.translate("misc:NOUNS:BOTS:2"), message.translate("misc:NOUNS:BOTS:5"))}`, true + ) + .addField(this.client.customEmojis.afk + message.translate("general/serverinfo:AFK_CHANNEL"), guild.afkChannel ? guild.afkChannel.toString() : message.translate("general/serverinfo:NO_AFK_CHANNEL"), true) + .addField(this.client.customEmojis.id + message.translate("common:ID"), guild.id, true) + .addField(this.client.customEmojis.crown + message.translate("common:OWNER"), owner.toString(), true) + .addField(this.client.customEmojis.boost + message.translate("general/serverinfo:BOOSTS"), guild.premiumSubscriptionCount.toString() || "0", true) + .addField(this.client.customEmojis.channels + message.translate("common:CHANNELS"), + `${guild.channels.cache.filter(c => c.type === "GUILD_TEXT").size} ${message.getNoun(guild.channels.cache.filter(c => c.type === "GUILD_TEXT").size, message.translate("misc:NOUNS:TEXT:1"), message.translate("misc:NOUNS:TEXT:2"), message.translate("misc:NOUNS:TEXT:5"))}` + + "\n" + `${guild.channels.cache.filter(c => c.type === "GUILD_VOICE").size} ${message.getNoun(guild.channels.cache.filter(c => c.type === "GUILD_VOICE").size, message.translate("misc:NOUNS:VOICE:1"), message.translate("misc:NOUNS:VOICE:2"), message.translate("misc:NOUNS:VOICE:5"))}` + + "\n" + `${guild.channels.cache.filter(c => c.type === "GUILD_CATEGORY").size} ${message.getNoun(guild.channels.cache.filter(c => c.type === "GUILD_CATEGORY").size, message.translate("misc:NOUNS:CATEGORY:1"), message.translate("misc:NOUNS:CATEGORY:2"), message.translate("misc:NOUNS:CATEGORY:5"))}`, true + ) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Serverinfo; \ No newline at end of file diff --git a/TO REWRITE/General/setafk.js b/TO REWRITE/General/setafk.js new file mode 100644 index 00000000..2d54f2b4 --- /dev/null +++ b/TO REWRITE/General/setafk.js @@ -0,0 +1,49 @@ +const Command = require("../../base/Command"); + +class Setafk extends Command { + constructor(client) { + super(client, { + name: "setafk", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["afk"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const reason = args.join(" "); + if (!reason || reason.length > 250) return message.error("general/setafk:MISSING_REASON"); + + if (reason === "delete") { + if (data.userData.afk) { + data.userData.afk = null; + data.userData.save(); + + return message.sendT("general/setafk:DELETED", { + username: message.author.username + }); + } + } else { + data.userData.afk = reason; + data.userData.save(); + + const m = await message.success("general/setafk:SUCCESS", { + reason, + prefix: message.guild ? data.guild.prefix : "" + }); + + setTimeout(() => { + if (m.deletable) m.delete(); + if (message.deletable) message.delete(); + }, 10 * 1000); + } + } +} + +module.exports = Setafk; \ No newline at end of file diff --git a/TO REWRITE/General/shorturl.js b/TO REWRITE/General/shorturl.js new file mode 100644 index 00000000..d353f77a --- /dev/null +++ b/TO REWRITE/General/shorturl.js @@ -0,0 +1,42 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + fetch = require("node-fetch"); + +class ShortURL extends Command { + constructor(client) { + super(client, { + name: "shorturl", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["minimize"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const url = args[0]; + if (!url) return message.error("general/shorturl:MISSING_URL"); + + const res = await fetch(`https://is.gd/create.php?format=simple&url=${encodeURI(url)}`); + const body = await res.text(); + + if (body === "Error: Please enter a valid URL to shorten") return message.error("general/shorturl:MISSING_URL"); + + const embed = new Discord.MessageEmbed() + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setDescription(body); + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = ShortURL; \ No newline at end of file diff --git a/TO REWRITE/General/staff.js b/TO REWRITE/General/staff.js new file mode 100644 index 00000000..e05204ae --- /dev/null +++ b/TO REWRITE/General/staff.js @@ -0,0 +1,42 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Staff extends Command { + constructor(client) { + super(client, { + name: "staff", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["staf"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + await message.guild.members.fetch(); + const administrators = message.guild.members.cache.filter((m) => m.permissions.has(Discord.Permissions.FLAGS.ADMINISTRATOR) && !m.user.bot); + const moderators = message.guild.members.cache.filter((m) => !administrators.has(m.id) && m.permissions.has(Discord.Permissions.FLAGS.MANAGE_MESSAGES) && !m.user.bot); + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("general/staff:TITLE", { + guild: message.guild.name + }) + }) + .addField(message.translate("general/staff:ADMINS"), (administrators.size > 0 ? administrators.map((a) => `${a.presence ? this.client.customEmojis.status[a.presence.status] : this.client.customEmojis.status.offline} | <@${a.user.id}>`).join("\n") : message.translate("general/staff:NO_ADMINS"))) + .addField(message.translate("general/staff:MODS"), (moderators.size > 0 ? moderators.map((m) => `${m.presence ? this.client.customEmojis.status[m.presence.status] : this.client.customEmojis.status.offline} | <@${m.user.id}>`).join("\n") : message.translate("general/staff:NO_MODS"))) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Staff; \ No newline at end of file diff --git a/TO REWRITE/General/stats.js b/TO REWRITE/General/stats.js new file mode 100644 index 00000000..4164aa37 --- /dev/null +++ b/TO REWRITE/General/stats.js @@ -0,0 +1,63 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Stats extends Command { + constructor(client) { + super(client, { + name: "stats", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["stat"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const hiddenGuild = await this.client.guilds.fetch("568120814776614924"); + const users = this.client.users.cache.size - hiddenGuild.memberCount; + const servers = this.client.guilds.cache.size - 1; + + const statsEmbed = new Discord.MessageEmbed() + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setAuthor({ + name: message.translate("common:STATS") + }) + .setDescription(message.translate("general/stats:MADE")) + .addField(this.client.customEmojis.stats + " " + message.translate("general/stats:COUNTS_TITLE"), message.translate("general/stats:COUNTS_CONTENT", { + servers: servers, + users: users + }), true) + .addField(this.client.customEmojis.version + " " + message.translate("general/stats:VERSIONS_TITLE"), `\`Discord.js : v${Discord.version}\`\n\`Nodejs : v${process.versions.node}\``, true) + .addField(this.client.customEmojis.ram + " " + message.translate("general/stats:RAM_TITLE"), `\`${(process.memoryUsage().heapUsed / 1024 / 1024).toFixed(2)}MB\``, true) + .addField(this.client.customEmojis.status.online + " " + message.translate("general/stats:ONLINE_TITLE"), message.translate("general/stats:ONLINE_CONTENT", { + time: this.client.convertTime(Date.now() + this.client.uptime, "from", true) + })) + .addField(this.client.customEmojis.voice + " " + message.translate("general/stats:MUSIC_TITLE"), message.translate("general/stats:MUSIC_CONTENT", { + count: `${this.client.player.voices.collection.size} ${message.getNoun(this.client.player.voices.collection.size, message.translate("misc:NOUNS:SERVERS:1"), message.translate("misc:NOUNS:SERVERS:2"), message.translate("misc:NOUNS:SERVERS:5"))}` + })) + .addField(message.translate("general/stats:CREDITS_TITLE"), message.translate("general/stats:CREDITS_CONTENT", { + donators: ["**`Добрый Спецназ#8801`** - Тестер, генератор идей"].join("\n"), + translators: ["**`Jonny_Bro#4226`** - :flag_ru:", "**`[ДАННЫЕ УДАЛЕНЫ]#4507`** - :flag_ua:"].join("\n") + })) + .addField(this.client.customEmojis.link + " " + message.translate("general/stats:LINKS_TITLE"), message.translate("misc:STATS_FOOTER", { + dashboardLink: this.client.config.dashboard.baseURL, + docsLink: `${this.client.config.dashboard.baseURL}/docs/`, + inviteLink: this.client.generateInvite({ scopes: ["bot", "applications.commands"], permissions: [Discord.Permissions.FLAGS.ADMINISTRATOR] }), + donateLink: "https://qiwi.com/n/JONNYBRO/", + owner: data.config.owner.id + })); + message.reply({ + embeds: [statsEmbed] + }); + } +} + +module.exports = Stats; \ No newline at end of file diff --git a/TO REWRITE/General/suggest.js b/TO REWRITE/General/suggest.js new file mode 100644 index 00000000..e4fd01f6 --- /dev/null +++ b/TO REWRITE/General/suggest.js @@ -0,0 +1,64 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Suggest extends Command { + constructor(client) { + super(client, { + name: "suggest", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["sugg"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + if (message.author.id === "285109105717280768") return message.reply({ content: "Пошёл нахуй фахон" }); + + const suggChannel = message.guild.channels.cache.get(data.guild.plugins.suggestions); + if (!suggChannel) return message.error("general/suggest:MISSING_CHANNEL"); + + const sugg = args.join(" "); + if (!sugg) return message.error("general/suggest:MISSING_CONTENT"); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("general/suggest:TITLE", { + user: message.author.username + }), + iconURL: message.author.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .addField(message.translate("common:AUTHOR"), `\`${message.author.username}#${message.author.discriminator}\``, true) + .addField(message.translate("common:DATE"), this.client.printDate(new Date(Date.now())), true) + .addField(message.translate("common:CONTENT"), sugg) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + const success = Discord.Util.parseEmoji(this.client.customEmojis.cool).id; + const error = Discord.Util.parseEmoji(this.client.customEmojis.notcool).id; + + suggChannel.send({ + embeds: [embed] + }).then(async (m) => { + await m.react(success); + await m.react(error); + }); + + message.success("general/suggest:SUCCESS", { + channel: suggChannel.toString() + }); + } +} + +module.exports = Suggest; \ No newline at end of file diff --git a/TO REWRITE/General/translate.js b/TO REWRITE/General/translate.js new file mode 100644 index 00000000..b5bb2219 --- /dev/null +++ b/TO REWRITE/General/translate.js @@ -0,0 +1,72 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + translate = require("@k3rn31p4nic/google-translate-api"); + +const langs = ["afrikaans", "albanian", "amharic", "arabic", "armenian", "azerbaijani", "bangla", "basque", "belarusian", "bengali", "bosnian", "bulgarian", "burmese", "catalan", "cebuano", "chichewa", "corsican", "croatian", "czech", "danish", "dutch", "english", "esperanto", "estonian", "filipino", "finnish", "french", "frisian", "galician", "georgian", "german", "greek", "gujarati", "haitian creole", "hausa", "hawaiian", "hebrew", "hindi", "hmong", "hungarian", "icelandic", "igbo", "indonesian", "irish", "italian", "japanese", "javanese", "kannada", "kazakh", "khmer", "korean", "kurdish (kurmanji)", "kyrgyz", "lao", "latin", "latvian", "lithuanian", "luxembourgish", "macedonian", "malagasy", "malay", "malayalam", "maltese", "maori", "marathi", "mongolian", "myanmar (burmese)", "nepali", "norwegian", "nyanja", "pashto", "persian", "polish", "portugese", "punjabi", "romanian", "russian", "samoan", "scottish gaelic", "serbian", "sesotho", "shona", "sindhi", "sinhala", "slovak", "slovenian", "somali", "spanish", "sundanese", "swahili", "swedish", "tajik", "tamil", "telugu", "thai", "turkish", "ukrainian", "urdu", "uzbek", "vietnamese", "welsh", "xhosa", "yiddish", "yoruba", "zulu"]; + +class Translate extends Command { + constructor(client) { + super(client, { + name: "translate", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["tran"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args, data) { + if (args[0] === "langs-list") { + const langsList = "```css\n" + (langs.map((lang, i) => `${i + 1} - ${lang}`).join("\n")) + "```"; + message.author.send(langsList).then(() => { + message.success("general/translate:LIST_SENT"); + }).catch(() => { + message.error("misc:CANNOT_DM"); + }); + return; + } + + const pWait = await message.sendT("misc:PLEASE_WAIT", null, { + prefixEmoji: "loading" + }); + + if (!args[0]) return pWait.error("general/translate:MISSING_LANGUAGE", { prefix: data.guild.prefix }, { edit: true }); + if (!args[1]) return pWait.error("general/translate:MISSING_CONTENT", null, { edit: true }); + + // Gets different args + const language = args[0].toLowerCase(); + const toTranslate = args.slice(1).join(" "); + + if (!langs.includes(language)) return pWait.error("general/translate:INVALID_LANGUAGE", { prefix: data.guild.prefix, search: language }, { edit: true }); + + const translated = await translate(toTranslate, { to: language }); + + const resEmbed = new Discord.MessageEmbed() + .setAuthor({ + name: "Переводчик", + iconURL: this.client.user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .addField(translated.from.language.iso, "```" + toTranslate + "```") + .addField(language, "```" + translated.text + "```") + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + return pWait.edit({ + content: null, + embeds: [resEmbed] + }); + } +} + +module.exports = Translate; \ No newline at end of file diff --git a/TO REWRITE/General/userinfo.js b/TO REWRITE/General/userinfo.js new file mode 100644 index 00000000..32d57873 --- /dev/null +++ b/TO REWRITE/General/userinfo.js @@ -0,0 +1,94 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Userinfo extends Command { + constructor(client) { + super(client, { + name: "userinfo", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["ui"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + let displayPresence = true; + + const isID = !isNaN(args[0]); + + let user; + if (!args[0]) user = message.author; + if (message.mentions.users.first()) user = message.mentions.users.first(); + + if (isID && !user) { + user = this.client.users.cache.get(args[0]); + if (!user) { + user = await this.client.users.fetch(args[0], true).catch(() => {}); + displayPresence = false; + } + } + + if (!user) return message.error("general/userinfo:INVALID_USER"); + + let member = null; + if (message.guild) member = await message.guild.members.fetch(user).catch(() => {}); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: `${user.tag} (${user.id})`, + iconURL: user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .setThumbnail(user.displayAvatarURL({ + dynamic: true + })) + .addField(":man: " + message.translate("common:USERNAME"), user.username, true) + .addField(this.client.customEmojis.discriminator + " " + message.translate("common:DISCRIMINATOR"), user.discriminator, true) + .addField(this.client.customEmojis.bot + " " + message.translate("common:ROBOT"), (user.bot ? message.translate("common:YES") : message.translate("common:NO")), true) + .addField(this.client.customEmojis.calendar + " " + message.translate("common:CREATION"), this.client.printDate(user.createdAt), true) + .addField(this.client.customEmojis.avatar + " " + message.translate("common:AVATAR"), user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + })) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + if (displayPresence) { + if (member.presence.activities[0].name === "Custom Status") { + embed.addField(this.client.customEmojis.games + " " + message.translate("common:GAME"), (member.presence.activities[0] ? `Пользовательский статус\n${member.presence.activities[0].state || message.translate("common:NOT_DEFINED")}` : message.translate("general/userinfo:NO_GAME")), true); + embed.addField(this.client.customEmojis.status[member.presence.status] + " " + message.translate("common:STATUS"), message.translate("common:STATUS_" + (member.presence.status.toUpperCase())), true); + } else { + embed.addField(this.client.customEmojis.games + " " + message.translate("common:GAME"), (member.presence.activities[0] ? `${member.presence.activities[0].name}\n${member.presence.activities[0].details}\n${member.presence.activities[0].state}` : message.translate("general/userinfo:NO_GAME")), true); + embed.addField(this.client.customEmojis.status[member.presence.status] + " " + message.translate("common:STATUS"), message.translate("common:STATUS_" + (member.presence.status.toUpperCase())), true); + } + } + + if (member) { + // embed.addField(this.client.customEmojis.up + " " + message.translate("general/userinfo:ROLE"), (member.roles.highest ? member.roles.highest : message.translate("general/userinfo:NO_ROLE")), true) + embed.addField(this.client.customEmojis.calendar2 + " " + message.translate("common:JOIN"), this.client.printDate(member.joinedAt), true); + embed.addField(this.client.customEmojis.color + " " + message.translate("common:COLOR"), member.displayHexColor, true); + embed.addField(this.client.customEmojis.pencil + " " + message.translate("common:NICKNAME"), (member.nickname ? member.nickname : message.translate("general/userinfo:NO_NICKNAME")), true); + embed.addField(this.client.customEmojis.roles + " " + message.translate("common:ROLES"), (member.roles.size > 10 ? member.roles.cache.map((r) => r).slice(0, 9).join(", ") + " " + message.translate("general/userinfo:MORE_ROLES", { + count: member.roles.cache.size - 10 + }) : (member.roles.cache.size < 1) ? message.translate("general/userinfo:NO_ROLE") : member.roles.cache.map((r) => r).join(", "))); + } + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Userinfo; \ No newline at end of file diff --git a/TO REWRITE/General/whois.js b/TO REWRITE/General/whois.js new file mode 100644 index 00000000..93c741c4 --- /dev/null +++ b/TO REWRITE/General/whois.js @@ -0,0 +1,73 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + fetch = require("node-fetch"); + +class Whois extends Command { + constructor(client) { + super(client, { + name: "whois", + dirname: __dirname, + enabled: true, + guildOnly: false, + aliases: ["ip"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + if (!args[0]) return message.error("general/whois:NO_IP"); + + const whois = await fetch(`http://ip-api.com/json/${args[0]}?fields=status,message,continent,continentCode,country,countryCode,region,regionName,city,zip,timezone,currency,isp,org,as,mobile,proxy,hosting,query`).then(response => response.json()); + + if (whois.status === "fail") { + const embed = new Discord.MessageEmbed() + .setDescription(whois.message) + .setTitle(message.translate("general/whois:ERROR", { + ip: args[0] + })) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setTimestamp(); + return message.reply({ + embeds: [embed] + }); + } + + const embed = new Discord.MessageEmbed() + .setTitle(message.translate("general/whois:INFO_ABOUT", { + ip: args[0] + })) + .setFooter({ + text: data.config.embed.footer + }) + .setColor(data.config.embed.color) + .addFields( + { name: "IP", value: whois.query, inline: true }, + { name: message.translate("general/whois:COUNTRY"), value: `${whois.country || "Неизвестно"} (${whois.countryCode || "Неизвестно"})`, inline: true }, + { name: message.translate("general/whois:REGION"), value: `${whois.regionName || "Неизвестно"} (${whois.region || "Неизвестно"})`, inline: true }, + { name: message.translate("general/whois:CITY"), value: `${whois.city || "Неизвестно"}`, inline: true }, + { name: message.translate("general/whois:ZIP"), value: `${whois.zip || "Неизвестно"}`, inline: true }, + { name: message.translate("general/whois:TIMEZONE"), value: `${whois.timezone || "Неизвестно"}`, inline: true }, + { name: message.translate("general/whois:CONTINENT"), value: `${whois.continent || "Неизвестно"} (${whois.continentCode || "Неизвестно"})`, inline: true }, + { name: message.translate("general/whois:CURRENCY"), value: `${whois.currency || "Неизвестно"}`, inline: true }, + { name: message.translate("general/whois:ISP"), value: `${whois.isp || "Неизвестно"}`, inline: true } + ) + .setTimestamp(); + + if (whois.proxy == true) embed.addFields({ name: message.translate("general/whois:INFO"), value: message.translate("general/whois:PROXY") }); + else if (whois.mobile == true) embed.addFields({ name: message.translate("general/whois:INFO"), value: message.translate("general/whois:MOBILE") }); + else if (whois.hosting == true) embed.addFields({ name: message.translate("general/whois:INFO"), value: message.translate("general/whois:HOSTING") }); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Whois; \ No newline at end of file diff --git a/TO REWRITE/Moderation/announcement.js b/TO REWRITE/Moderation/announcement.js new file mode 100644 index 00000000..e6a604bc --- /dev/null +++ b/TO REWRITE/Moderation/announcement.js @@ -0,0 +1,99 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Announcement extends Command { + constructor(client) { + super(client, { + name: "announcement", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["ann"], + memberPermissions: ["MENTION_EVERYONE"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const text = args.join(" "); + if (!text) return message.error("moderation/announcement:MISSING_TEXT"); + if (text.length > 1030) return message.error("moderation/announcement:TOO_LONG"); + + let mention = null; + const msg = await message.sendT("moderation/announcement:MENTION_PROMPT"); + + const filter = m => m.author.id === message.author.id; + const collector = new Discord.MessageCollector(message.channel, { + filter, + time: 240000 + }); + + collector.on("collect", async (tmsg) => { + if (tmsg.content.toLowerCase() === message.translate("common:NO").toLowerCase()) { + tmsg.delete(); + msg.delete(); + collector.stop(true); + + if (message.deletable) message.delete(); + } + + if (tmsg.content.toLowerCase() === message.translate("common:YES").toLowerCase()) { + tmsg.delete(); + msg.delete(); + const tmsg1 = await message.channel.send(message.translate("moderation/announcement:MENTION_TYPE_PROMPT")); + + const filter = m => m.author.id === message.author.id; + const c = new Discord.MessageCollector(message.channel, { + filter, + time: 60000 + }); + c.on("collect", (m) => { + if (m.content.toLowerCase() === "here") { + mention = "@here"; + tmsg1.delete(); + m.delete(); + collector.stop(true); + c.stop(true); + } else if (m.content.toLowerCase() === "everyone") { + mention = "@everyone"; + tmsg1.delete(); + m.delete(); + collector.stop(true); + c.stop(true); + } + }); + + c.on("end", (collected, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + }); + + if (message.deletable) message.delete(); + } + }); + + collector.on("end", (collected, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("moderation/announcement:TITLE") + }) + .setColor(data.config.embed.color) + .setFooter({ + text: message.author.tag + }) + .setTimestamp() + .setDescription(text); + + message.channel.send({ + content: mention, + embeds: [embed] + }); + }); + } +} + +module.exports = Announcement; \ No newline at end of file diff --git a/TO REWRITE/Moderation/ban.js b/TO REWRITE/Moderation/ban.js new file mode 100644 index 00000000..16090e9c --- /dev/null +++ b/TO REWRITE/Moderation/ban.js @@ -0,0 +1,112 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Ban extends Command { + constructor(client) { + super(client, { + name: "ban", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["b"], + memberPermissions: ["BAN_MEMBERS"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "BAN_MEMBERS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const user = await this.client.resolveUser(args[0]); + if (!user) return message.error("moderation/ban:MISSING_MEMBER"); + + const memberData = message.guild.members.cache.get(user.id) ? await this.client.findOrCreateMember({ + id: user.id, + guildID: message.guild.id + }) : null; + + if (user.id === message.author.id) return message.error("moderation/ban:YOURSELF"); + + // If the user is already banned + const banned = await message.guild.bans.fetch(); + if (banned.some((m) => m.user.id === user.id)) return message.error("moderation/ban:ALREADY_BANNED", { + username: user.tag + }); + + // Gets the ban reason + let reason = args.slice(1).join(" "); + if (!reason) reason = message.translate("misc:NO_REASON_PROVIDED"); + + const member = await message.guild.members.fetch(user.id).catch(() => {}); + if (member) { + const memberPosition = member.roles.highest.position; + const moderationPosition = message.member.roles.highest.position; + if (message.member.ownerId !== message.author.id && !(moderationPosition > memberPosition)) return message.error("moderation/ban:SUPERIOR"); + if (!member.bannable) return message.error("moderation/ban:MISSING_PERM"); + } + + await user.send(message.translate("moderation/ban:BANNED_DM", { + username: user.tag, + server: message.guild.name, + moderator: message.author.tag, + reason + })).catch(() => {}); + + // Ban the user + message.guild.members.ban(user, { + reason + }).then(() => { + // Send a success message in the current channel + message.reply({ + content: message.translate("moderation/ban:BANNED", { + username: user.tag, + server: message.guild.name, + moderator: message.author.tag, + reason + }) + }); + + const caseInfo = { + channel: message.channel.id, + moderator: message.author.id, + date: Date.now(), + type: "ban", + case: data.guild.casesCount, + reason + }; + + if (memberData) { + memberData.sanctions.push(caseInfo); + memberData.save(); + } + + data.guild.casesCount++; + data.guild.save(); + + if (data.guild.plugins.modlogs) { + const channel = message.guild.channels.cache.get(data.guild.plugins.modlogs); + if (!channel) return; + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("moderation/ban:CASE", { + count: data.guild.casesCount + }) + }) + .addField(message.translate("common:USER"), `\`${user.tag}\` (${user.toString()})`, true) + .addField(message.translate("common:MODERATOR"), `\`${message.author.tag}\` (${message.author.toString()})`, true) + .addField(message.translate("common:REASON"), reason, true) + .setColor("#e02316"); + channel.send({ + embeds: [embed] + }); + } + + }).catch((err) => { + console.log(err); + return message.error("moderation/ban:MISSING_PERM"); + }); + } +} + +module.exports = Ban; \ No newline at end of file diff --git a/TO REWRITE/Moderation/clear.js b/TO REWRITE/Moderation/clear.js new file mode 100644 index 00000000..e4b1c27d --- /dev/null +++ b/TO REWRITE/Moderation/clear.js @@ -0,0 +1,80 @@ +const Command = require("../../base/Command"); + +class Clear extends Command { + constructor(client) { + super(client, { + name: "clear", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["cl", "purge"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "MANAGE_MESSAGES"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + if (args[0] === "all") { + message.channel.send(message.translate("moderation/clear:ALL_CONFIRM")); + + const filter = m => m.author.id === message.author.id && m.content === "confirm"; + const collector = message.channel.createMessageCollector({ + filter, + time: 120000 // 2 minutes + }); + + collector.on("collect", async message => { + const position = message.channel.position; + const newChannel = await message.channel.clone(); + await message.channel.delete(); + newChannel.setPosition(position); + return newChannel.send({ + content: message.translate("moderation/clear:CHANNEL_CLEARED") + }); + }); + + collector.on("end", (_, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + }); + } else { + const amount = args[0]; + if (!amount || isNaN(amount) || parseInt(amount) < 1) return message.error("moderation/clear:MISSING_AMOUNT"); + + await message.delete(); + + const user = message.mentions.users.first(); + + let messages = await message.channel.messages.fetch({ + limit: amount + }); + if (user) messages = messages.filter((m) => m.author.id === user.id); + if (messages.length > amount) messages.length = parseInt(amount, 10); + + messages = messages.filter((m) => !m.pinned); + + message.channel.bulkDelete(messages, true); + + let toDelete = null; + + if (user) { + toDelete = await message.channel.send(message.translate("moderation/clear:CLEARED_MEMBER", { + amount: `${amount} ${message.getNoun(amount, message.translate("misc:NOUNS:MESSAGES:1"), message.translate("misc:NOUNS:MESSAGES:2"), message.translate("misc:NOUNS:MESSAGES:5"))}`, + username: user.tag + })); + } else { + toDelete = await message.channel.send(message.translate("moderation/clear:CLEARED", { + amount: `${amount} ${message.getNoun(amount, message.translate("misc:NOUNS:MESSAGES:1"), message.translate("misc:NOUNS:MESSAGES:2"), message.translate("misc:NOUNS:MESSAGES:5"))}` + })); + } + + setTimeout(function () { + toDelete.delete(); + }, 2000); + } + } +} + +module.exports = Clear; \ No newline at end of file diff --git a/TO REWRITE/Moderation/clearwarns.js b/TO REWRITE/Moderation/clearwarns.js new file mode 100644 index 00000000..5303012f --- /dev/null +++ b/TO REWRITE/Moderation/clearwarns.js @@ -0,0 +1,35 @@ +const Command = require("../../base/Command"); + +class Clearwarns extends Command { + constructor(client) { + super(client, { + name: "clearwarns", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["clearw", "clw"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("moderation/clearwarns:MISSING_MEMBER"); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + memberData.sanctions = []; + memberData.save(); + message.success("moderation/clearwarns:SUCCESS", { + username: member.user.tag + }); + } +} + +module.exports = Clearwarns; \ No newline at end of file diff --git a/TO REWRITE/Moderation/giveaway.js b/TO REWRITE/Moderation/giveaway.js new file mode 100644 index 00000000..e90878f7 --- /dev/null +++ b/TO REWRITE/Moderation/giveaway.js @@ -0,0 +1,127 @@ +const Command = require("../../base/Command"), + ms = require("ms"); + +class Giveaway extends Command { + constructor(client) { + super(client, { + name: "giveaway", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["gaway"], + memberPermissions: ["MENTION_EVERYONE"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + const status = args[0]; + if (!status) return message.error("moderation/giveaway:MISSING_STATUS"); + + if (status === "create") { + const currentGiveaways = this.client.giveawaysManager.giveaways.filter((g) => g.guildId === message.guild.id && !g.ended).length; + if (currentGiveaways > 3) return message.error("moderation/giveaway:MAX_COUNT"); + + const time = args[1]; + if (!time) return message.error("moderation/giveaway:INVALID_CREATE", { prefix: data.guild.prefix }); + if (isNaN(ms(time))) return message.error("misc:INVALID_TIME"); + if (ms(time) > ms("15d")) return message.error("moderation/giveaway:MAX_DURATION"); + + const winnersCount = args[2]; + if (!winnersCount) return message.error("moderation/giveaway:INVALID_CREATE", { prefix: data.guild.prefix }); + if (isNaN(winnersCount) || winnersCount > 10 || winnersCount < 1) return message.error("misc:INVALID_NUMBER_RANGE", { min: 1, max: 10 }); + + const drop = (args[3] === "true"); + let prize = args.slice(3).join(" "); + + if (drop) prize = args.slice(4).join(" "); + else prize = args.slice(3).join(" "); + + if (!prize) return message.error("moderation/giveaway:INVALID_CREATE", { prefix: data.guild.prefix }); + + this.client.giveawaysManager.start(message.channel, { + duration: ms(time), + winnerCount: parseInt(winnersCount, 10), + prize: prize, + hostedBy: message.author, + isDrop: drop, + messages: { + giveaway: message.translate("moderation/giveaway:TITLE"), + giveawayEnded: message.translate("moderation/giveaway:ENDED"), + timeRemaining: message.translate("moderation/giveaway:TIME_REMAINING"), + inviteToParticipate: message.translate("moderation/giveaway:INVITE_PARTICIPATE"), + winMessage: message.translate("moderation/giveaway:WIN_MESSAGE"), + drawing: message.translate("moderation/giveaway:DRAWING"), + dropMessage: message.translate("moderation/giveaway:DROP"), + embedFooter: message.translate("moderation/giveaway:FOOTER"), + noWinner: message.translate("moderation/giveaway:NO_WINNER"), + winners: message.translate("moderation/giveaway:WINNERS"), + endedAt: message.translate("moderation/giveaway:END_AT"), + hostedBy: message.translate("moderation/giveaway:HOSTEDBY"), + units: { + seconds: message.translate("time:SECONDS", { + amount: "" + }).trim(), + minutes: message.translate("time:MINUTES", { + amount: "" + }).trim(), + hours: message.translate("time:HOURS", { + amount: "" + }).trim(), + days: message.translate("time:DAYS", { + amount: "" + }).trim() + } + } + }).then(() => { + message.success("moderation/giveaway:GIVEAWAY_CREATED"); + }); + } else if (status === "reroll") { + const messageID = args[1]; + if (!messageID) return message.error("moderation/giveaway:MISSING_ID"); + + this.client.giveawaysManager.reroll(messageID, { + messages: { + congrat: message.translate("moderation/giveaway:REROLL_CONGRAT"), + error: message.translate("moderation/giveaway:REROLL_ERROR") + } + }).then(() => { + return message.success("moderation/giveaway:GIVEAWAY_REROLLED"); + }).catch(() => { + return message.error("moderation/giveaway:NOT_FOUND_ENDED", { + messageID + }); + }); + } else if (status === "delete") { + const messageID = args[1]; + if (!messageID) return message.error("moderation/giveaway:MISSING_ID"); + + this.client.giveawaysManager.delete(messageID).then(() => { + return message.success("moderation/giveaway:GIVEAWAY_DELETED"); + }).catch(() => { + return message.error("moderation/giveaway:NOT_FOUND", { + messageID + }); + }); + } else if (status === "end") { + const messageID = args[1]; + if (!messageID) return message.error("moderation/giveaway:MISSING_ID"); + + try { + this.client.giveawaysManager.end(messageID); + return message.success("moderation/giveaway:GIVEAWAY_ENDED"); + } catch (e) { + return message.error("moderation/giveaway:NOT_FOUND", { + messageID + }); + } + } else { + return message.error("moderation/giveaway:MISSING_STATUS"); + } + } +} + +module.exports = Giveaway; \ No newline at end of file diff --git a/TO REWRITE/Moderation/kick.js b/TO REWRITE/Moderation/kick.js new file mode 100644 index 00000000..c2fbee21 --- /dev/null +++ b/TO REWRITE/Moderation/kick.js @@ -0,0 +1,100 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Kick extends Command { + constructor(client) { + super(client, { + name: "kick", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["k"], + memberPermissions: ["KICK_MEMBERS"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "KICK_MEMBERS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("moderation/kick:MISSING_MEMBER"); + + if (member.id === message.author.id) return message.error("moderation/kick:YOURSELF"); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + + // Gets the kcik reason + let reason = args.slice(1).join(" "); + if (!reason) reason = message.translate("misc:NO_REASON_PROVIDED"); + + const memberPosition = member.roles.highest.position; + const moderationPosition = message.member.roles.highest.position; + if (message.member.ownerId !== message.author.id && !(moderationPosition > memberPosition)) return message.error("moderation/ban:SUPERIOR"); + if (!member.kickable) return message.error("moderation/kick:MISSING_PERM"); + + await member.send({ + content: message.translate("moderation/kick:KICKED_DM", { + username: member.user.tag, + server: message.guild.name, + moderator: message.author.tag, + reason + }) + }); + + // Kick the user + member.kick(reason).then(() => { + // Send a success message in the current channel + message.reply({ + content: message.translate("moderation/kick:KICKED", { + username: member.user.tag, + server: message.guild.name, + moderator: message.author.tag, + reason + }) + }); + + data.guild.casesCount++; + data.guild.save(); + + const caseInfo = { + channel: message.channel.id, + moderator: message.author.id, + date: Date.now(), + type: "kick", + case: data.guild.casesCount, + reason, + }; + + memberData.sanctions.push(caseInfo); + memberData.save(); + + if (data.guild.plugins.modlogs) { + const channel = message.guild.channels.cache.get(data.guild.plugins.modlogs); + if (!channel) return; + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("moderation/kick:CASE", { + count: data.guild.casesCount + }) + }) + .addField(message.translate("common:USER"), `\`${member.user.tag}\` (${member.user.toString()})`, true) + .addField(message.translate("common:MODERATOR"), `\`${message.author.tag}\` (${message.author.toString()})`, true) + .addField(message.translate("common:REASON"), reason, true) + .setColor("#e88709"); + channel.send({ + embeds: [embed] + }); + } + + }).catch(() => { + return message.error("moderation/kick:MISSING_PERM"); + }); + } +} + +module.exports = Kick; \ No newline at end of file diff --git a/TO REWRITE/Moderation/mute.js b/TO REWRITE/Moderation/mute.js new file mode 100644 index 00000000..4d07030b --- /dev/null +++ b/TO REWRITE/Moderation/mute.js @@ -0,0 +1,113 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + ms = require("ms"); + +class Mute extends Command { + constructor(client) { + super(client, { + name: "mute", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["m"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "MANAGE_CHANNELS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("moderation/mute:MISSING_MEMBER"); + if (member.id === message.author.id) return message.error("moderation/mute:YOURSELF"); + + const memberPosition = member.roles.highest.position; + const moderationPosition = message.member.roles.highest.position; + if (message.member.ownerId !== message.author.id && !(moderationPosition > memberPosition)) return message.error("moderation/ban:SUPERIOR"); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + + const time = args[1]; + if (!time || isNaN(ms(time))) return message.error("misc:INVALID_TIME"); + let reason = args.slice(2).join(" "); + if (!reason) reason = message.translate("misc:NO_REASON_PROVIDED"); + + message.guild.channels.cache.forEach((channel) => { + channel.permissionOverwrites.edit(member.id, { + SEND_MESSAGES: false, + ADD_REACTIONS: false, + CONNECT: false + }).catch(() => {}); + }); + + member.send({ + content: message.translate("moderation/mute:MUTED_DM", { + username: member.user.username, + server: message.guild.name, + moderator: message.author.tag, + time, + reason + }) + }); + + message.success("moderation/mute:MUTED", { + username: member.user.tag, + server: message.guild.name, + moderator: message.author.tag, + time, + reason + }); + + data.guild.casesCount++; + + const caseInfo = { + channel: message.channel.id, + moderator: message.author.id, + date: Date.now(), + type: "mute", + case: data.guild.casesCount, + reason, + time + }; + + memberData.mute.muted = true; + memberData.mute.endDate = Date.now() + ms(time); + memberData.mute.case = data.guild.casesCount; + memberData.sanctions.push(caseInfo); + + memberData.markModified("sanctions"); + memberData.markModified("mute"); + + await memberData.save(); + await data.guild.save(); + + this.client.databaseCache.mutedUsers.set(`${member.id}${message.guild.id}`, memberData); + + if (data.guild.plugins.modlogs) { + const channel = message.guild.channels.cache.get(data.guild.plugins.modlogs); + if (!channel) return; + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("moderation/mute:CASE", { + count: data.guild.casesCount + }) + }) + .addField(message.translate("common:USER"), `\`${member.user.tag}\` (${member.user.toString()})`, true) + .addField(message.translate("common:MODERATOR"), `\`${message.author.tag}\` (${message.author.toString()})`, true) + .addField(message.translate("common:REASON"), reason, true) + .addField(message.translate("common:DURATION"), time, true) + .addField(message.translate("common:EXPIRY"), this.client.printDate(new Date(Date.now() + ms(time))), true) + .setColor("#f44271"); + channel.send({ + embeds: [embed] + }); + } + } +} + +module.exports = Mute; \ No newline at end of file diff --git a/TO REWRITE/Moderation/poll.js b/TO REWRITE/Moderation/poll.js new file mode 100644 index 00000000..070c607e --- /dev/null +++ b/TO REWRITE/Moderation/poll.js @@ -0,0 +1,109 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Poll extends Command { + constructor(client) { + super(client, { + name: "poll", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["po"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const question = args.join(" "); + if (!question) return message.error("moderation/poll:MISSING_QUESTION"); + + let mention = null; + const msg = await message.sendT("moderation/announcement:MENTION_PROMPT"); + + const filter = m => m.author.id === message.author.id; + const collector = new Discord.MessageCollector(message.channel, { + filter, + time: 240000 + }); + + collector.on("collect", async (tmsg) => { + if (tmsg.content.toLowerCase() === message.translate("common:NO").toLowerCase()) { + tmsg.delete(); + msg.delete(); + collector.stop(true); + + message.delete(); + } + + if (tmsg.content.toLowerCase() === message.translate("common:YES").toLowerCase()) { + tmsg.delete(); + msg.delete(); + const tmsg1 = await message.channel.send(message.translate("moderation/announcement:MENTION_TYPE_PROMPT")); + + const filter = m => m.author.id === message.author.id; + const c = new Discord.MessageCollector(message.channel, { + filter, + time: 60000 + }); + + c.on("collect", (m) => { + if (m.content.toLowerCase() === "here") { + mention = "@here"; + tmsg1.delete(); + m.delete(); + collector.stop(true); + c.stop(true); + } else if (m.content.toLowerCase() === "everyone") { + mention = "@everyone"; + tmsg1.delete(); + m.delete(); + collector.stop(true); + c.stop(true); + } + }); + + c.on("end", (collected, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + }); + + message.delete(); + } + }); + + collector.on("end", (collected, reason) => { + if (reason === "time") return message.error("misc:TIMES_UP"); + + const success = this.client.customEmojis.success.split(":")[1]; + const error = this.client.customEmojis.error.split(":")[1]; + + const emojis = [ + this.client.emojis.cache.find(e => e.name === success), + this.client.emojis.cache.find(e => e.name === error) + ]; + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("moderation/poll:TITLE") + }) + .setColor(data.config.embed.color) + .addField(question, message.translate("moderation/poll:REACT", { + success: emojis[0].toString(), + error: emojis[1].toString() + })); + + message.channel.send({ + content: mention, + embeds: [embed] + }).then(async (m) => { + await m.react(emojis[0]); + await m.react(emojis[1]); + }); + }); + } +} + +module.exports = Poll; \ No newline at end of file diff --git a/TO REWRITE/Moderation/sanctions.js b/TO REWRITE/Moderation/sanctions.js new file mode 100644 index 00000000..794267f3 --- /dev/null +++ b/TO REWRITE/Moderation/sanctions.js @@ -0,0 +1,61 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Warns extends Command { + constructor(client) { + super(client, { + name: "warns", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["ws"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const user = await this.client.resolveUser(args[0]); + if (!user) return message.error("moderation/warns:MISSING_MEMBER"); + + const memberData = await this.client.findOrCreateMember({ + id: user.id, + guildID: message.guild.id + }); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: user.tag, + iconURL: user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + if (memberData.sanctions.length < 1) { + embed.setDescription(message.translate("moderation/warns:NO_SANCTION", { + username: user.tag + })); + return message.reply({ + embeds: [embed] + }); + } else { + memberData.sanctions.forEach((s) => { + embed.addField(s.type + " | #" + s.case, `${message.translate("common:MODERATOR")}: <@${s.moderator}>\n${message.translate("common:REASON")}: ${s.reason}`, true); + }); + } + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Warns; \ No newline at end of file diff --git a/TO REWRITE/Moderation/setwarns.js b/TO REWRITE/Moderation/setwarns.js new file mode 100644 index 00000000..8aebfdee --- /dev/null +++ b/TO REWRITE/Moderation/setwarns.js @@ -0,0 +1,68 @@ +const Command = require("../../base/Command"); + +class Setwarns extends Command { + constructor(client) { + super(client, { + name: "setwarns", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["setw"], + memberPermissions: ["MANAGE_GUILD"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "BAN_MEMBERS", "KICK_MEMBERS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const sanction = args[0]; + if (!sanction || (sanction !== "kick" && sanction !== "ban")) return message.error("moderation/setwarns:MISSING_TYPE"); + + const number = args[1]; + + if (number === "reset") { + if (sanction === "kick") { + data.guild.plugins.warnsSanctions.kick = false; + data.guild.markModified("plugins.warnsSanctions"); + data.guild.save(); + return message.success("moderation/setwarns:SUCCESS_KICK_RESET", { + prefix: data.guild.prefix, + count: `${number} ${message.getNoun(number, message.translate("misc:NOUNS:WARNS:1"), message.translate("misc:NOUNS:WARNS:2"), message.translate("misc:NOUNS:WARNS:5"))}` + }); + } else if (sanction === "ban") { + data.guild.plugins.warnsSanctions.ban = false; + data.guild.markModified("plugins.warnsSanctions"); + data.guild.save(); + return message.success("moderation/setwarns:SUCCESS_BAN_RESET", { + prefix: data.guild.prefix, + count: `${number} ${message.getNoun(number, message.translate("misc:NOUNS:WARNS:1"), message.translate("misc:NOUNS:WARNS:2"), message.translate("misc:NOUNS:WARNS:5"))}` + }); + } + } + + if (!number || isNaN(number)) return message.error("misc:INVALID_NUMBER"); + if (number < 1 || number > 10) return message.error("misc:INVALID_NUMBER_RANGE", 1, 10); + + if (sanction === "kick") { + data.guild.plugins.warnsSanctions.kick = number; + data.guild.markModified("plugins.warnsSanctions"); + data.guild.save(); + return message.success("moderation/setwarns:SUCCESS_KICK", { + prefix: data.guild.prefix, + count: `${number} ${message.getNoun(number, message.translate("misc:NOUNS:WARNS:1"), message.translate("misc:NOUNS:WARNS:2"), message.translate("misc:NOUNS:WARNS:5"))}` + }); + } else if (sanction === "ban") { + data.guild.plugins.warnsSanctions.ban = number; + data.guild.markModified("plugins.warnsSanctions"); + data.guild.save(); + return message.success("moderation/setwarns:SUCCESS_BAN", { + prefix: data.guild.prefix, + count: `${number} ${message.getNoun(number, message.translate("misc:NOUNS:WARNS:1"), message.translate("misc:NOUNS:WARNS:2"), message.translate("misc:NOUNS:WARNS:5"))}` + }); + } + } +} + +module.exports = Setwarns; \ No newline at end of file diff --git a/TO REWRITE/Moderation/unban.js b/TO REWRITE/Moderation/unban.js new file mode 100644 index 00000000..ea0468be --- /dev/null +++ b/TO REWRITE/Moderation/unban.js @@ -0,0 +1,60 @@ +const Command = require("../../base/Command"); + +class Unban extends Command { + constructor(client) { + super(client, { + name: "unban", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["ub"], + memberPermissions: ["BAN_MEMBERS"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "BAN_MEMBERS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + let user = null; + + if (!args[0]) return message.error("moderation/unban:MISSING_ID"); + + // Check if the arg is an ID or a username + const isId = !isNaN(args[0]); + + if (isId) { + // Try to find a user with that ID + await this.client.users.fetch(args[0]).then((u) => { + // if a user was found + user = u; + }).catch(() => {}); + } else if (!isId) { + const arr = args[0].split("#"); + if (arr.length < 2) { + return message.error("misc:NO_USER_FOUND_ID", { + id: args[0] + }); + } + user = this.client.users.filter((u) => u.username === arr[0]).find((u) => u.discriminator === arr[1]); + } + + if (!user) return message.error("misc:NO_USER_FOUND_ID", { id: args[0] }); + + // check if the user is banned + const banned = await message.guild.bans.fetch(); + if (!banned.some((e) => e.user.id === user.id)) return message.success("moderation/unban:NOT_BANNED", { username: user.tag }); + + // Unban user + message.guild.members.unban(user).catch(() => {}); + + // Send a success message in the current channel + message.success("moderation/unban:UNBANNED", { + username: user.tag, + server: message.guild.name + }); + } +} + +module.exports = Unban; \ No newline at end of file diff --git a/TO REWRITE/Moderation/unmute.js b/TO REWRITE/Moderation/unmute.js new file mode 100644 index 00000000..6a8fb313 --- /dev/null +++ b/TO REWRITE/Moderation/unmute.js @@ -0,0 +1,47 @@ +const Command = require("../../base/Command"); + +class Unmute extends Command { + constructor(client) { + super(client, { + name: "unmute", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["um"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS", "MANAGE_CHANNELS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.success("moderation/unmute:MISSING_MEMBER"); + + const memberPosition = member.roles.highest.position; + const moderationPosition = message.member.roles.highest.position; + if (message.member.ownerId !== message.author.id && !(moderationPosition > memberPosition)) return message.error("moderation/ban:SUPERIOR"); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + + if (memberData.mute.muted) { + memberData.mute.endDate = Date.now(); + memberData.markModified("mute"); + memberData.save(); + message.success("moderation/unmute:SUCCESS", { + username: member.user.tag + }); + } else { + message.error("moderation/unmute:NOT_MUTED", { + username: member.user.tag + }); + } + } +} + +module.exports = Unmute; \ No newline at end of file diff --git a/TO REWRITE/Moderation/warn.js b/TO REWRITE/Moderation/warn.js new file mode 100644 index 00000000..698978fc --- /dev/null +++ b/TO REWRITE/Moderation/warn.js @@ -0,0 +1,144 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Warn extends Command { + constructor(client) { + super(client, { + name: "warn", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["w"], + memberPermissions: ["MANAGE_MESSAGES"], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const member = await this.client.resolveMember(args[0], message.guild); + if (!member) return message.error("moderation/warn:MISSING_MEMBER"); + if (member.user.bot) return message.error("misc:BOT_USER"); + + const memberData = await this.client.findOrCreateMember({ + id: member.id, + guildID: message.guild.id + }); + + if (member.id === message.author.id) return message.error("moderation/warn:YOURSELF"); + + const memberPosition = member.roles.highest.position; + const moderationPosition = message.member.roles.highest.position; + if (message.member.ownerId !== message.author.id && !(moderationPosition > memberPosition)) return message.error("moderation/ban:SUPERIOR"); + + const reason = args.slice(1).join(" "); + if (!reason) return message.error("moderation/warn:MISSING_REASON"); + + // Gets current member sanctions + const sanctions = memberData.sanctions.filter((s) => s.type === "warn").length; + const banCount = data.guild.plugins.warnsSanctions.ban; + const kickCount = data.guild.plugins.warnsSanctions.kick; + + data.guild.casesCount++; + data.guild.save(); + + const caseInfo = { + channel: message.channel.id, + moderator: message.author.id, + date: Date.now(), + type: "warn", + case: data.guild.casesCount, + reason + }; + + const embed = new Discord.MessageEmbed() + .addField(message.translate("common:USER"), `\`${member.user.tag}\` (${member.user.toString()})`) + .addField(message.translate("common:MODERATOR"), `\`${message.author.tag}\` (${message.author.toString()})`) + .addField(message.translate("common:REASON"), reason, true); + + if (banCount) { + if (sanctions >= banCount) { + member.send({ + content: message.translate("moderation/ban:BANNED_DM", { + username: member.user, + moderator: message.author.tag, + server: message.guild.name, + reason + }) + }); + caseInfo.type = "ban"; + embed.setAuthor({ + name: message.translate("moderation/ban:CASE", { + count: data.guild.casesCount + }) + }) + .setColor("#e02316"); + message.guild.members.ban(member).catch(() => {}); + message.success("moderation/setwarns:AUTO_BAN", { + username: member.user.tag, + count: banCount + }); + } + } + + if (kickCount) { + if (sanctions >= kickCount) { + member.send({ + content: message.translate("moderation/kick:KICKED_DM", { + username: member.user, + moderator: message.author.tag, + server: message.guild.name, + reason + }) + }); + caseInfo.type = "kick"; + embed.setAuthor({ + name: message.translate("moderation/kick:CASE", { + count: data.guild.casesCount + }) + }) + .setColor("#e88709"); + member.kick().catch(() => {}); + message.success("moderation/setwarns:AUTO_KICK", { + username: member.user.tag, + count: kickCount + }); + } + } + + member.send({ + content: message.translate("moderation/warn:WARNED_DM", { + username: member.user.tag, + server: message.guild.name, + moderator: message.author.tag, + reason + }) + }); + caseInfo.type = "warn"; + embed.setAuthor({ + name: message.translate("moderation/warn:CASE", { + caseNumber: data.guild.casesCount + }) + }) + .setColor("#8c14e2"); + message.success("moderation/warn:WARNED", { + username: member.user.tag, + reason + }); + + memberData.sanctions.push(caseInfo); + memberData.save(); + + if (data.guild.plugins.modlogs) { + const channel = message.guild.channels.cache.get(data.guild.plugins.modlogs); + if (!channel) return; + channel.send({ + embeds: [embed] + }); + } + } +} + +module.exports = Warn; \ No newline at end of file diff --git a/TO REWRITE/Music/autoplay.js b/TO REWRITE/Music/autoplay.js new file mode 100644 index 00000000..2372c601 --- /dev/null +++ b/TO REWRITE/Music/autoplay.js @@ -0,0 +1,32 @@ +const Command = require("../../base/Command"); + +class AutoPlay extends Command { + constructor(client) { + super(client, { + name: "autoplay", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["autop"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + + const autoplay = queue.toggleAutoplay(); + + message.success(`music/autoplay:SUCCESS_${autoplay ? "ENABLED" : "DISABLED"}`); + } +} + +module.exports = AutoPlay; \ No newline at end of file diff --git a/TO REWRITE/Music/back.js b/TO REWRITE/Music/back.js new file mode 100644 index 00000000..e5fac879 --- /dev/null +++ b/TO REWRITE/Music/back.js @@ -0,0 +1,50 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Back extends Command { + constructor(client) { + super(client, { + name: "back", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["previous"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args, data) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + if (!queue.previousSongs[0]) return message.error("music/back:NO_PREV_SONG"); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("music/back:DESCRIPTION") + }) + .setThumbnail(queue.tracks[0].thumbnail) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }); + + const m = await message.reply({ + embeds: [embed] + }); + + this.client.player.previous(message); + embed.setDescription(message.translate("music/back:SUCCESS")); + m.edit({ + embeds: [embed] + }); + } +} + +module.exports = Back; \ No newline at end of file diff --git a/TO REWRITE/Music/clip.js b/TO REWRITE/Music/clip.js new file mode 100644 index 00000000..de287a0e --- /dev/null +++ b/TO REWRITE/Music/clip.js @@ -0,0 +1,58 @@ +const Command = require("../../base/Command"), + fs = require("fs"), + { joinVoiceChannel, createAudioResource, createAudioPlayer, getVoiceConnection, AudioPlayerStatus } = require("@discordjs/voice"); + +class Clip extends Command { + constructor(client) { + super(client, { + name: "clip", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + const clip = args[0]; + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (getVoiceConnection(message.guild.id)) return message.error("music/clip:ACTIVE_CLIP"); + if (queue) return message.error("music/clip:ACTIVE_QUEUE"); + if (!clip) return message.error("music/clip:NO_ARG"); + if (!fs.existsSync(`./clips/${clip}.mp3`)) return message.error("music/clip:NO_FILE", { file: clip }); + + try { + const connection = joinVoiceChannel({ + channelId: voice.id, + guildId: message.guild.id, + adapterCreator: message.guild.voiceAdapterCreator + }); + + const resource = createAudioResource(fs.createReadStream(`./clips/${clip}.mp3`)); + const player = createAudioPlayer() + .on("error", err => { + connection.destroy(); + console.error(err.message); + }); + + player.play(resource); + connection.subscribe(player); + + player.on(AudioPlayerStatus.Idle, () => { + connection.destroy(); + }); + } catch (error) { + console.error(error); + } + } +} + +module.exports = Clip; \ No newline at end of file diff --git a/TO REWRITE/Music/clips.js b/TO REWRITE/Music/clips.js new file mode 100644 index 00000000..e687a05a --- /dev/null +++ b/TO REWRITE/Music/clips.js @@ -0,0 +1,46 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + fs = require("fs"); + +class Clips extends Command { + constructor(client) { + super(client, { + name: "clips", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 2000 + }); + } + + async run(message, args, data) { + fs.readdir("./clips", function (err, files) { + if (err) return console.log("Unable to read directory: " + err); + + const clips = []; + + files.forEach(function (file) { + clips.push(file.substring(0, file.length - 4)); + }); + + const embed = new Discord.MessageEmbed() + .setTitle(message.translate("music/clips:EMBED_TITLE")) + .setDescription(clips.join("\n")) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setTimestamp(); + message.reply({ + embeds: [embed] + }); + }); + } +} + +module.exports = Clips; \ No newline at end of file diff --git a/TO REWRITE/Music/jump.js b/TO REWRITE/Music/jump.js new file mode 100644 index 00000000..0006e4fa --- /dev/null +++ b/TO REWRITE/Music/jump.js @@ -0,0 +1,53 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Jump extends Command { + constructor(client) { + super(client, { + name: "jump", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["j"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args, data) { + const queue = this.client.player.getQueue(message); + const voice = message.member.voice.channel; + const number = parseInt(args[0]); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + if (number < 0) return message.error("music/jump:NO_PREV_SONG", { prefix: data.guild.prefix }); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("music/jump:SUCCESS") + }) + .setThumbnail(queue.songs[number].thumbnail) + .setFooter({ + text: data.config.embed.footer + }) + .setColor(data.config.embed.color); + + const m = await message.reply({ + embeds: [embed] + }); + + this.client.player.jump(message, number); + embed.setDescription(message.translate("music/play:NOW_PLAYING", { + songName: queue.songs[number].name + })); + m.edit({ + embeds: [embed] + }); + } +} + +module.exports = Jump; \ No newline at end of file diff --git a/TO REWRITE/Music/loop.js b/TO REWRITE/Music/loop.js new file mode 100644 index 00000000..05a19d7a --- /dev/null +++ b/TO REWRITE/Music/loop.js @@ -0,0 +1,40 @@ +const Command = require("../../base/Command"); + +class Loop extends Command { + constructor(client) { + super(client, { + name: "loop", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["repeat", "l"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES"], + nsfw: false, + ownerOnly: false, + cooldown: 1000 + }); + } + + async run(message, args) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + + const type = args[0]; + let mode = null; + if (type === "queue" || type === "all") { + mode = this.client.player.setRepeatMode(message, 2); + } else if (type === "song" || type === "single") { + mode = this.client.player.setRepeatMode(message, 1); + } else { + mode = this.client.player.setRepeatMode(message, 0); + } + + message.success(`music/loop:${mode ? mode === 2 ? "QUEUE" : "SONG" : "DISABLED"}`); + } +} + +module.exports = Loop; \ No newline at end of file diff --git a/TO REWRITE/Music/np.js b/TO REWRITE/Music/np.js new file mode 100644 index 00000000..08a5d85a --- /dev/null +++ b/TO REWRITE/Music/np.js @@ -0,0 +1,63 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Np extends Command { + constructor(client) { + super(client, { + name: "np", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["nowplaying"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args, data) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + + const track = queue.songs[0]; + + const status = queue => + `${message.translate("music/np:FILTERS")}: \`${ + queue.filters.join(", ") || message.translate("music/np:DISABLED") + }\` | ${message.translate("music/np:REPEAT")}: \`${ + queue.repeatMode + ? queue.repeatMode === 2 ? message.translate("music/np:QUEUE") : message.translate("music/np:SONG") + : message.translate("music/np:DISABLED") + }\` | ${message.translate("music/np:AUTOPLAY")}: \`${ + queue.autoplay + ? message.translate("music/np:ENABLED") + : message.translate("music/np:DISABLED") + }\``; + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("music/queue:TITLE") + }) + .setThumbnail(track.thumbnail) + .addField(message.translate("music/np:T_TITLE"), `[${track.name}](${track.url})`) + .addField(message.translate("music/np:T_CHANNEL"), track.uploader.name ? track.uploader.name : "Отсутствует") + .addField(message.translate("music/np:T_DURATION"), `${queue.formattedCurrentTime} / ${track.duration > 1 ? track.formattedDuration : message.translate("music/play:LIVE")}`) + .addField(message.translate("music/np:T_CONF"), status(queue)) + .setColor(data.config.embed.color) + .setFooter({ + text: data.config.embed.footer + }) + .setTimestamp(); + + message.reply({ + embeds: [embed] + }); + } +} + +module.exports = Np; \ No newline at end of file diff --git a/TO REWRITE/Music/pause.js b/TO REWRITE/Music/pause.js new file mode 100644 index 00000000..efa90801 --- /dev/null +++ b/TO REWRITE/Music/pause.js @@ -0,0 +1,32 @@ +const Command = require("../../base/Command"); + +class Pause extends Command { + constructor(client) { + super(client, { + name: "pause", + dirname: __dirname, + enabled: false, + guildOnly: true, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music:play:NOT_PLAYING"); + + await this.client.player.pause(message); + + message.sendT("music/pause:SUCCESS"); + } +} + +module.exports = Pause; \ No newline at end of file diff --git a/TO REWRITE/Music/play.js b/TO REWRITE/Music/play.js new file mode 100644 index 00000000..8ae57349 --- /dev/null +++ b/TO REWRITE/Music/play.js @@ -0,0 +1,45 @@ +const Command = require("../../base/Command"), + { Permissions } = require("discord.js"); + +class Play extends Command { + constructor(client) { + super(client, { + name: "play", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["p"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args) { + const voice = message.member.voice.channel; + const name = args.join(" "); + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!name) return message.error("music/play:MISSING_SONG_NAME"); + + // Check my permissions + const perms = voice.permissionsFor(this.client.user); + if (!perms.has(Permissions.FLAGS.CONNECT) || !perms.has(Permissions.FLAGS.SPEAK)) return message.error("music/play:VOICE_CHANNEL_CONNECT"); + + try { + this.client.player.play(message.member.voice.channel, args.join(" "), { + member: message.member, + textChannel: message.channel, + message + }); + } catch (e) { + message.error("music/play:ERR_OCCURRED", { + error: e + }); + console.error(e); + } + } +} + +module.exports = Play; \ No newline at end of file diff --git a/TO REWRITE/Music/queue.js b/TO REWRITE/Music/queue.js new file mode 100644 index 00000000..972f0768 --- /dev/null +++ b/TO REWRITE/Music/queue.js @@ -0,0 +1,66 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"), + Pagination = require("discord-paginationembed"); + +class Queue extends Command { + constructor(client) { + super(client, { + name: "queue", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["q"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args, data) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + + if (queue.songs.length === 1) { + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("music/queue:TITLE"), + iconURL: message.guild.iconURL({ + dynamic: true + }) + }) + .addField(message.translate("music/np:CURRENTLY_PLAYING"), `[${queue.songs[0].name}](${queue.songs[0].url})\n*${message.translate("music/queue:ADDED")} ${queue.songs[0].member}*\n`) + .setColor(data.config.embed.color); + return message.reply({ + embeds: [embed] + }); + } + + const FieldsEmbed = new Pagination.FieldsEmbed(); + + FieldsEmbed.embed + .setColor(data.config.embed.color) + .setAuthor({ + name: message.translate("music/queue:TITLE"), + iconURL: message.guild.iconURL({ + dynamic: true + }) + }) + .addField(message.translate("music/np:CURRENTLY_PLAYING"), `[${queue.songs[0].name}](${queue.songs[0].url})\n*${message.translate("music/queue:ADDED")} ${queue.songs[0].member}*\n`); + FieldsEmbed + .setArray(queue.songs[1] ? queue.songs.slice(1, queue.songs.length) : []) + .setAuthorizedUsers([message.author.id]) + .setChannel(message.channel) + .setElementsPerPage(5) + .setDeleteOnTimeout(true) + .setPageIndicator(true) + .formatField(message.translate("music/queue:TITLE"), (track) => `**${queue.songs.indexOf(track)}**. [${track.name}](${track.url})\n*${message.translate("music/queue:ADDED")} ${track.member}*\n`) + .build(); + } +} + +module.exports = Queue; \ No newline at end of file diff --git a/TO REWRITE/Music/resume.js b/TO REWRITE/Music/resume.js new file mode 100644 index 00000000..b056d6eb --- /dev/null +++ b/TO REWRITE/Music/resume.js @@ -0,0 +1,32 @@ +const Command = require("../../base/Command"); + +class Resume extends Command { + constructor(client) { + super(client, { + name: "resume", + dirname: __dirname, + enabled: false, + guildOnly: true, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music:play:NOT_PLAYING"); + + await this.client.player.resume(message); + + message.sendT("music/resume:SUCCESS"); + } +} + +module.exports = Resume; \ No newline at end of file diff --git a/TO REWRITE/Music/seek.js b/TO REWRITE/Music/seek.js new file mode 100644 index 00000000..5501b67f --- /dev/null +++ b/TO REWRITE/Music/seek.js @@ -0,0 +1,35 @@ +const Command = require("../../base/Command"); +const ms = require("ms"); + +class Seek extends Command { + constructor(client) { + super(client, { + name: "seek", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: [], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + const time = ms(args[0]) / 1000; + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + if (isNaN(time)) return message.error("music/seek:INVALID_TIME"); + + await this.client.player.seek(message, time); + + message.sendT("music/seek:SUCCESS"); + } +} + +module.exports = Seek; \ No newline at end of file diff --git a/TO REWRITE/Music/skip.js b/TO REWRITE/Music/skip.js new file mode 100644 index 00000000..ff403bc5 --- /dev/null +++ b/TO REWRITE/Music/skip.js @@ -0,0 +1,52 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Skip extends Command { + constructor(client) { + super(client, { + name: "skip", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["s"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args, data) { + const voice = message.member.voice.channel; + const queue = this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + if (!queue.songs[1]) return message.error("music/skip:NO_NEXT_SONG"); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("music/skip:SUCCESS") + }) + .setThumbnail(queue.songs[1].thumbnail) + .setFooter({ + text: data.config.embed.footer + }) + .setColor(data.config.embed.color); + + const m = await message.reply({ + embeds: [embed] + }); + + this.client.player.skip(message); + embed.setDescription(message.translate("music/play:NOW_PLAYING", { + songName: queue.songs[1].name + })); + m.edit({ + embeds: [embed] + }); + } +} + +module.exports = Skip; \ No newline at end of file diff --git a/TO REWRITE/Music/stop.js b/TO REWRITE/Music/stop.js new file mode 100644 index 00000000..6607bf89 --- /dev/null +++ b/TO REWRITE/Music/stop.js @@ -0,0 +1,48 @@ +const Command = require("../../base/Command"), + Discord = require("discord.js"); + +class Stop extends Command { + constructor(client) { + super(client, { + name: "stop", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: ["leave", "st"], + memberPermissions: [], + botPermissions: ["SEND_MESSAGES", "EMBED_LINKS"], + nsfw: false, + ownerOnly: false, + cooldown: 3000 + }); + } + + async run(message, args, data) { + const voice = message.member.voice.channel; + const queue = await this.client.player.getQueue(message); + + if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); + if (!queue) return message.error("music/play:NOT_PLAYING"); + + const embed = new Discord.MessageEmbed() + .setAuthor({ + name: message.translate("music/stop:DESCRIPTION") + }) + .setFooter({ + text: data.config.embed.footer + }) + .setColor(data.config.embed.color); + + const m = await message.reply({ + embeds: [embed] + }); + + this.client.player.stop(message); + embed.setDescription(message.translate("music/stop:SUCCESS")); + m.edit({ + embeds: [embed] + }); + } +} + +module.exports = Stop; \ No newline at end of file diff --git a/base/JaBa.js b/base/JaBa.js index 7de8e4ed..fb025bba 100644 --- a/base/JaBa.js +++ b/base/JaBa.js @@ -122,37 +122,39 @@ class JaBa extends Client { * @param {String} dir * @returns */ + async loadCommands(dir) { const filePath = path.join(__dirname, dir); - const files = await fs.readdir(filePath); + var folders = await fs.readdir(filePath); folders = folders.map(file => path.join(filePath, file)).filter(async (path) => { path = await fs.lstat(path); path.isDirectory(); }); const rest = new REST({ version: "9" }).setToken(this.config.token); const commands = []; - const guild_commands = []; - for (let index = 0; index < files.length; index++) { - const file = files[index]; - const stat = await fs.lstat(path.join(filePath, file)); - if (stat.isDirectory()) this.loadCommands(path.join(dir, file)); + for (let index = 0; index < folders.length; index++) { + const folder = folders[index]; + const files = await fs.readdir(folder); - if (file.endsWith(".js")) { - const Command = require(path.join(filePath, file)); - if (Command.prototype instanceof BaseCommand) { - const command = new Command(this); - this.commands.set(command.command.name, command); - const aliases = []; - if (command.aliases && Array.isArray(command.aliases) && command.aliases.length > 0) { - command.aliases.forEach((alias) => { - 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); - }); + 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 = []; + if (command.aliases && Array.isArray(command.aliases) && command.aliases.length > 0) { + command.aliases.forEach((alias) => { + 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); + }); + } + + commands.push(command.command instanceof SlashCommandBuilder ? command.command.toJSON() : command.command, ...aliases); + + if (command.onLoad || typeof command.onLoad === "function") await command.onLoad(this); + this.logger.log(`Successfully loaded "${file}" command file. (Command: ${command.command.name})`); } - - if (!this.config.production) guild_commands.push(command.command instanceof SlashCommandBuilder ? command.command.toJSON() : command.command, ...aliases); - else commands.push(command.command instanceof SlashCommandBuilder ? command.command.toJSON() : command.command, ...aliases); - - if (command.onLoad || typeof command.onLoad === "function") await command.onLoad(this); - this.logger.log(`Successfully loaded "${file}" command file. (Command: ${command.command.name})`); } } } @@ -161,7 +163,7 @@ class JaBa extends Client { if (!this.config.production) { await rest.put( Routes.applicationGuildCommands(this.config.user, this.config.support.id), { - body: guild_commands + body: commands } ); } else { @@ -184,9 +186,6 @@ class JaBa extends Client { * @param {String} file */ async loadCommand(dir, file) { - const commands = []; - const guild_commands = []; - const rest = new REST({ version: "9" }).setToken(this.config.token); const Command = require(path.join(dir, `${file}.js`)); if (Command.prototype instanceof BaseCommand) { const command = new Command(this); @@ -201,32 +200,9 @@ class JaBa extends Client { }); } - if (!this.config.production) guild_commands.push(command.command instanceof SlashCommandBuilder ? command.command.toJSON() : command.command, ...aliases); - else commands.push(command.command instanceof SlashCommandBuilder ? command.command.toJSON() : command.command, ...aliases); - if (command.onLoad || typeof command.onLoad === "function") await command.onLoad(this); this.logger.log(`Successfully loaded "${file}" command file. (Command: ${command.command.name})`); - try { - if (!this.config.production) { - await rest.put( - Routes.applicationGuildCommands(this.config.user, this.config.support.id), { - body: guild_commands - } - ); - } else { - await rest.put( - Routes.applicationCommands(this.config.user), { - body: commands - } - ); - } - - this.logger.log("Successfully registered application commands."); - } catch (err) { - this.logger.log("Cannot load commands: " + err.message, "error"); - } - return; } } @@ -412,70 +388,6 @@ class JaBa extends Client { } } } - - async resolveUser(search) { - let user = null; - if (!search || typeof search !== "string") return; - - // Try ID search - if (search.match(/^<@!?(\d+)>$/)) { - const id = search.match(/^<@!?(\d+)>$/)[1]; - user = this.users.fetch(id).catch(() => {}); - if (user) return user; - } - - // Try username search - if (search.match(/^!?(\w+)#(\d+)$/)) { - const username = search.match(/^!?(\w+)#(\d+)$/)[0]; - const discriminator = search.match(/^!?(\w+)#(\d+)$/)[1]; - user = this.users.find((u) => u.username === username && u.discriminator === discriminator); - if (user) return user; - } - user = await this.users.fetch(search).catch(() => {}); - - return user; - } - - async resolveMember(search, guild) { - let member = null; - if (!search || typeof search !== "string") return; - - // Try ID search - if (search.match(/^<@!?(\d+)>$/)) { - const id = search.match(/^<@!?(\d+)>$/)[1]; - member = await guild.members.fetch(id).catch(() => {}); - if (member) return member; - } - - // Try username search - if (search.match(/^!?(\w+)#(\d+)$/)) { - guild = await guild.fetch(); - member = guild.members.cache.find((m) => m.user.tag === search); - if (member) return member; - } - member = await guild.members.fetch(search).catch(() => {}); - - return member; - } - - async resolveRole(search, guild) { - let role = null; - if (!search || typeof search !== "string") return; - - // Try ID search - if (search.match(/^<@&!?(\d+)>$/)) { - const id = search.match(/^<@&!?(\d+)>$/)[1]; - role = guild.roles.cache.get(id); - if (role) return role; - } - - // Try name search - role = guild.roles.cache.find((r) => search === r.name); - if (role) return role; - role = guild.roles.cache.get(search); - - return role; - } } module.exports = JaBa; \ No newline at end of file diff --git a/commands/General/ping.js b/commands/General/ping.js new file mode 100644 index 00000000..470d6fd7 --- /dev/null +++ b/commands/General/ping.js @@ -0,0 +1,40 @@ +const { SlashCommandBuilder } = require("@discordjs/builders"); +const BaseCommand = require("../../base/BaseCommand"); + +class Ping extends BaseCommand { + /** + * + * @param {import("../base/JaBa")} client + */ + constructor(client) { + super({ + command: new SlashCommandBuilder() + .setName("ping") + .setDescription(client.translate("general/ping:DESCRIPTION")), + aliases: [], + dirname: __dirname, + guildOnly: true, + ownerOnly: false + }); + } + /** + * + * @param {import("../../base/JaBa")} client + */ + async onLoad() { + //... + } + /** + * + * @param {import("../../base/JaBa")} client + * @param {import("discord.js").CommandInteraction} interaction + * @param {Array} data + */ + async execute(client, interaction) { + interaction.replyT("general/ping:CONTENT", { + ping: Math.round(client.ws.ping) + }); + } +} + +module.exports = Ping; \ No newline at end of file diff --git a/commands/NSFW/nsfw.js b/commands/NSFW/nsfw.js new file mode 100644 index 00000000..2191d2ec --- /dev/null +++ b/commands/NSFW/nsfw.js @@ -0,0 +1,86 @@ + +const { SlashCommandBuilder } = require("@discordjs/builders"), + { MessageEmbed, MessageActionRow, MessageSelectMenu, InteractionCollector } = require("discord.js"); +const BaseCommand = require("../../base/BaseCommand"), + fetch = require("node-fetch"); + +class NSFW extends BaseCommand { + /** + * + * @param {import("../base/JaBa")} client + */ + constructor(client) { + super({ + command: new SlashCommandBuilder() + .setName("nsfw") + .setDescription(client.translate("nsfw/nsfw:DESCRIPTION")), + aliases: [], + dirname: __dirname, + guildOnly: true, + ownerOnly: false + }); + } + /** + * + * @param {import("../../base/JaBa")} client + */ + async onLoad() { + //... + } + /** + * + * @param {import("../../base/JaBa")} client + * @param {import("discord.js").CommandInteraction} interaction + * @param {Array} data + */ + async execute(client, interaction) { + if (!interaction.channel.nsfw) return interaction.replyT("misc:NSFW_COMMAND", null, { ephemeral: true }); + + const tags = ["hentai", "ecchi", "lewdanimegirls", "hentaifemdom", "animefeets", "animebooty", "biganimetiddies", "sideoppai", "ahegao"].map(tag => + JSON.parse(JSON.stringify({ + label: tag, + description: "", + value: tag + })) + ); + + const row = new MessageActionRow() + .addComponents( + new MessageSelectMenu() + .setCustomId("nsfw_select") + .setPlaceholder(client.translate("nsfw/nsfw:NOTHING_SELECTED")) + .addOptions(tags) + ); + + const msg = await interaction.reply({ + content: interaction.translate("nsfw/nsfw:AVAILABLE_CATEGORIES"), + ephemeral: true, + components: [row] + }); + + const collector = new InteractionCollector(client, { + message: msg, + time: 60 * 1000 + }); + + collector.on("collect", async (msg) => { + const tag = msg?.values[0]; + const res = await fetch(`https://meme-api.herokuapp.com/gimme/${tag}`).then(response => response.json()); + + const embed = new MessageEmbed() + .setColor(client.config.embed.color) + .setFooter({ + text: client.config.embed.footer + }) + .setTitle(`${res.title}\n${interaction.translate("fun/memes:SUBREDDIT")}: ${res.subreddit}\n${interaction.translate("common:AUTHOR")}: ${res.author}\n${interaction.translate("fun/memes:UPS")}: ${res.ups}`) + .setImage(res.url) + .setTimestamp(); + + msg.update({ + embeds: [embed] + }); + }); + } +} + +module.exports = NSFW; \ No newline at end of file diff --git a/commands/Owner/debug.js b/commands/Owner/debug.js new file mode 100644 index 00000000..4cdc1085 --- /dev/null +++ b/commands/Owner/debug.js @@ -0,0 +1,190 @@ +const { SlashCommandBuilder } = require("@discordjs/builders"); +const BaseCommand = require("../../base/BaseCommand"); + +class Debug extends BaseCommand { + /** + * + * @param {import("../base/JaBa")} client + */ + constructor(client) { + super({ + command: new SlashCommandBuilder() + .setName("debug") + .setDescription(client.translate("owner/debug:DESCRIPTION")) + .addSubcommand(subcommand => + subcommand.setName("set") + .setDescription(client.translate("owner/debug:SET")) + .addStringOption(option => + option.setName("type") + .setDescription(client.translate("owner/debug:TYPE")) + .setRequired(true) + .addChoices( + { name: client.translate("common:LEVEL"), value: "level" }, + { name: client.translate("common:XP"), value: "xp" }, + { name: client.translate("common:CREDITS"), value: "credits" }, + { name: client.translate("economy/transactions:BANK"), value: "bank" }, + { name: client.translate("common:REP"), value: "rep" }, + )) + .addUserOption(option => + option.setName("target") + .setDescription(client.translate("owner/debug:TARGET")) + .setRequired(true)) + .addIntegerOption(option => + option.setName("int") + .setDescription(client.translate("owner/debug:INT")) + .setRequired(true)) + ) + .addSubcommand(subcommand => + subcommand.setName("add") + .setDescription(client.translate("owner/debug:ADD")) + .addStringOption(option => + option.setName("type") + .setDescription(client.translate("owner/debug:TYPE")) + .setRequired(true) + .addChoices( + { name: client.translate("common:LEVEL"), value: "level" }, + { name: client.translate("common:XP"), value: "xp" }, + { name: client.translate("common:CREDITS"), value: "credits" }, + { name: client.translate("economy/transactions:BANK"), value: "bank" }, + { name: client.translate("common:REP"), value: "rep" }, + )) + .addUserOption(option => + option.setName("target") + .setDescription(client.translate("owner/debug:TARGET")) + .setRequired(true)) + .addIntegerOption(option => + option.setName("int") + .setDescription(client.translate("owner/debug:INT")) + .setRequired(true)) + ), + aliases: [], + dirname: __dirname, + guildOnly: true, + ownerOnly: true + }); + } + /** + * + * @param {import("../../base/JaBa")} client + */ + async onLoad() { + //... + } + /** + * + * @param {import("../../base/JaBa")} client + * @param {import("discord.js").CommandInteraction} interaction + * @param {Array} data + */ + async execute(client, interaction, data) { + const action = interaction.options.getSubcommand(); + + if (action === "set") { + const type = interaction.options.getString("type"); + const member = interaction.options.getMember("target"); + const int = interaction.options.getInteger("int"); + if (member.user.bot) return interaction.error("owner/debug:BOT"); + + switch (type) { + case "level": { + data.memberData.level = int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "xp": { + data.memberData.exp = int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "credits": { + data.memberData.money = int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "bank": { + data.memberData.bankSold = int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "rep": { + data.memberData.rep = int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + } + } else { + const type = interaction.options.getString("type"); + const member = interaction.options.getMember("target"); + const int = interaction.options.getInteger("int"); + if (member.user.bot) return interaction.error("owner/debug:BOT", { ephemeral: true }); + + switch (type) { + case "level": { + data.memberData.level += int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "xp": { + data.memberData.exp += int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "credits": { + data.memberData.money += int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "bank": { + data.memberData.bankSold += int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + + case "rep": { + data.memberData.rep += int; + await data.memberData.save(); + return interaction.success("owner/debug:SUCCESS_" + type.toUpperCase(), { + username: member.user.tag, + amount: int + }, { ephemeral: true }); + } + } + } + } +} + +module.exports = Debug; \ No newline at end of file diff --git a/commands/Owner/eval.js b/commands/Owner/eval.js index 86ab17d3..0e1ff34b 100644 --- a/commands/Owner/eval.js +++ b/commands/Owner/eval.js @@ -16,7 +16,7 @@ class Eval extends BaseCommand { option.setName("code") .setDescription(client.translate("owner/eval:USAGE")) .setRequired(true)), - aliases: ["e"], + aliases: [], dirname: __dirname, guildOnly: true, ownerOnly: true diff --git a/commands/Owner/reload.js b/commands/Owner/reload.js index bd533f5e..10e48a3c 100644 --- a/commands/Owner/reload.js +++ b/commands/Owner/reload.js @@ -37,11 +37,9 @@ class Reload extends BaseCommand { * @param {Array} data */ async execute(client, interaction) { - interaction.deferReply({ ephemeral: true }); - const command = interaction.options.getString("command"); const cmd = client.commands.get(command); - if (!cmd) return interaction.error("owner/reload:NOT_FOUND", { search: command }); + if (!cmd) return interaction.error("owner/reload:NOT_FOUND", { search: command }, { ephemeral: true }); await client.unloadCommand(`../commands/${cmd.category}`, cmd.command.name); await client.loadCommand(`../commands/${cmd.category}`, cmd.command.name); @@ -51,7 +49,7 @@ class Reload extends BaseCommand { interaction.success("owner/reload:SUCCESS", { command: cmd.command.name - }, { edit: true, ephemeral: true }); + }, { ephemeral: true }); } } diff --git a/commands/Owner/say.js b/commands/Owner/say.js new file mode 100644 index 00000000..e13243bf --- /dev/null +++ b/commands/Owner/say.js @@ -0,0 +1,75 @@ +const { SlashCommandBuilder } = require("@discordjs/builders"); +const BaseCommand = require("../../base/BaseCommand"); + +class Say extends BaseCommand { + /** + * + * @param {import("../base/JaBa")} client + */ + constructor(client) { + super({ + command: new SlashCommandBuilder() + .setName("say") + .setDescription(client.translate("owner/say:DESCRIPTION")) + .addStringOption(option => + option.setName("message") + .setDescription(client.translate("owner/say:MESSAGE")) + .setRequired(true)) + .addChannelOption(option => + option.setName("channel") + .setDescription(client.translate("owner/say:CHANNEL"))), + aliases: [], + dirname: __dirname, + guildOnly: true, + ownerOnly: true + }); + } + /** + * + * @param {import("../../base/JaBa")} client + */ + async onLoad() { + //... + } + /** + * + * @param {import("../../base/JaBa")} client + * @param {import("discord.js").CommandInteraction} interaction + * @param {Array} data + */ + async execute(client, interaction) { + interaction.deferReply({ ephemeral: true }); + const message = interaction.options.getString("message"); + const channel = interaction.options.getChannel("channel"); + + if (!channel) { + interaction.channel.sendTyping(); + + setTimeout(function () { + interaction.channel.send({ + content: message + }); + + interaction.replyT("owner/say:DONE", { + message, + channel: interaction.channel.toString() + }, { edit: true }); + }, 2000); + } else { + channel.sendTyping(); + + setTimeout(function () { + channel.send({ + content: message + }); + + interaction.replyT("owner/say:DONE", { + message, + channel: channel.toString() + }, { edit: true }); + }, 2000); + } + } +} + +module.exports = Say; \ No newline at end of file diff --git a/commands/Owner/servers.js b/commands/Owner/servers.js new file mode 100644 index 00000000..7039000d --- /dev/null +++ b/commands/Owner/servers.js @@ -0,0 +1,134 @@ +const { SlashCommandBuilder } = require("@discordjs/builders"), + { MessageEmbed } = require("discord.js"); +const BaseCommand = require("../../base/BaseCommand"); + +class Servers extends BaseCommand { + /** + * + * @param {import("../base/JaBa")} client + */ + constructor(client) { + super({ + command: new SlashCommandBuilder() + .setName("servers") + .setDescription(client.translate("owner/servers:DESCRIPTION")), + aliases: [], + dirname: __dirname, + guildOnly: true, + ownerOnly: true + }); + } + /** + * + * @param {import("../../base/JaBa")} client + */ + async onLoad() { + //... + } + /** + * + * @param {import("../../base/JaBa")} client + * @param {import("discord.js").CommandInteraction} interaction + * @param {Array} data + */ + async execute(client, interaction) { + let i0 = 0, + i1 = 10, + page = 1; + + let description = `${interaction.translate("common:SERVERS")}: ${client.guilds.cache.size}\n\n` + + client.guilds.cache + .sort((a, b) => b.memberCount - a.memberCount) + .map((r) => r) + .map((r, i) => `**${i + 1}** - ${r.name} | ${r.memberCount} ${client.getNoun(r.memberCount, interaction.translate("misc:NOUNS:MEMBERS:1"), interaction.translate("misc:NOUNS:MEMBERS:2"), interaction.translate("misc:NOUNS:MEMBERS:5"))}`) + .slice(0, 10) + .join("\n"); + + const embed = new MessageEmbed() + .setAuthor({ + name: interaction.user.tag, + iconURL: interaction.user.displayAvatarURL({ + size: 512, + dynamic: true, + format: "png" + }) + }) + .setColor(client.config.embed.color) + .setFooter({ + text: client.user.username + }) + .setTitle(`${interaction.translate("common:PAGE")}: ${page}/${client.guilds.cache.size}`) + .setDescription(description); + + await interaction.reply({ + embeds: [embed], + }); + + const msg = await interaction.fetchReply(); + + await msg.react("⬅"); + await msg.react("➡"); + await msg.react("❌"); + + const collector = msg.createReactionCollector({ + time: 60 * 1000 + }); + + collector.on("collect", async (reaction) => { + if (reaction._emoji.name === "⬅") { + i0 = i0 - 10; + i1 = i1 - 10; + page = page - 1; + + if (i0 < 0) return msg.delete(); + if (!i0 || !i1) return msg.delete(); + + description = `${interaction.translate("common:SERVERS")}: ${client.guilds.cache.size}\n\n` + + client.guilds.cache + .sort((a, b) => b.memberCount - a.memberCount) + .map((r) => r) + .map((r, i) => `**${i + 1}** - ${r.name} | ${r.memberCount} ${client.getNoun(r.memberCount, interaction.translate("misc:NOUNS:MEMBERS:1"), interaction.translate("misc:NOUNS:MEMBERS:2"), interaction.translate("misc:NOUNS:MEMBERS:5"))}`) + .slice(i0, i1) + .join("\n"); + + embed + .setTitle(`${interaction.translate("common:PAGE")}: ${page}/${client.guilds.cache.size}`) + .setDescription(description); + + msg.edit({ + embeds: [embed] + }); + } + + if (reaction._emoji.name === "➡") { + i0 = i0 + 10; + i1 = i1 + 10; + page = page + 1; + + if (i1 > client.guilds.cache.size + 10) return msg.delete(); + if (!i0 || !i1) return msg.delete(); + + description = `${interaction.translate("common:SERVERS")}: ${client.guilds.cache.size}\n\n` + + client.guilds.cache + .sort((a, b) => b.memberCount - a.memberCount) + .map((r) => r) + .map((r, i) => `**${i + 1}** - ${r.name} | ${r.memberCount} ${client.getNoun(r.memberCount, interaction.translate("misc:NOUNS:MEMBERS:1"), interaction.translate("misc:NOUNS:MEMBERS:2"), interaction.translate("misc:NOUNS:MEMBERS:5"))}`) + .slice(i0, i1) + .join("\n"); + + embed.setTitle(`${interaction.translate("common:PAGE")}: ${page}/${Math.round(client.guilds.cache.size / 10)}`) + .setDescription(description); + + msg.edit({ + embeds: [embed] + }); + } + + if (reaction._emoji.name === "❌") return msg.delete(); + + await reaction.users.remove(interaction.user.id); + }); + } +} + +module.exports = Servers; \ No newline at end of file diff --git a/events/ready.js b/events/ready.js index f7640c62..754d4b97 100644 --- a/events/ready.js +++ b/events/ready.js @@ -56,6 +56,7 @@ class Ready extends BaseEvent { ]; let i = 0; + setTimeout setInterval(async function () { hiddenGuild = await client.guilds.fetch("568120814776614924"); tUsers = client.users.cache.size - hiddenGuild.memberCount; diff --git a/helpers/autoUpdateDocs.js b/helpers/autoUpdateDocs.js index cb1f05fb..a350e11d 100644 --- a/helpers/autoUpdateDocs.js +++ b/helpers/autoUpdateDocs.js @@ -1,18 +1,23 @@ +const table = require("markdown-table"), + fs = require("fs"); + module.exports.update = function (client) { - const table = require("markdown-table"), - fs = require("fs"), - commands = [...new Map(client.commands.map(v => [v.constructor.name, v])).values()], + const commands = [...new Map(client.commands.map(v => [v.constructor.name, v])).values()], categories = []; + commands.forEach((cmd) => { if (!categories.includes(cmd.category)) categories.push(cmd.category); }); + let text = `# JaBa имеет **${commands.length} ${client.getNoun(commands.length, "команда", "команды", "команд")}** в **${categories.length} ${client.getNoun(categories.length, "категории", "категориях", "категориях")}**! \n\n#### Содержимое таблицы \n**Название**: Название команды \n**Описание**: Описание команды \n**Использование**: Использование команды ( [] - обязательно, () - необязательно ) \n**Разрешено использование**: Где можно использовать команду \n\n`; + // categories.sort(function(a, b) { // const aCmdsSize = commands.filter((cmd) => cmd.category === a).size; // const bCmdsSize = commands.filter((cmd) => cmd.category === b).size; // if (aCmdsSize > bCmdsSize) return -1; // else return 1; // }) + categories.sort().forEach((cat) => { const categoriesArray = [ ["Название", "Описание", "Использование", "Разрешено использование"] @@ -33,6 +38,7 @@ module.exports.update = function (client) { }); text += `${table(categoriesArray)}\n\n`; }); + if (!fs.existsSync("./dashboard/public/docs")) fs.mkdirSync("./dashboard/public/docs"); fs.writeFileSync("./dashboard/public/docs/commands.md", text); client.logger.log("Dashboard docs updated!"); diff --git a/helpers/birthdays.js b/helpers/birthdays.js index a8fd0982..69a95685 100644 --- a/helpers/birthdays.js +++ b/helpers/birthdays.js @@ -1,5 +1,5 @@ -const CronJob = require("cron").CronJob, - Discord = require("discord.js"); +const { CronJob } = require("cron"), + { MessageEmbed } = require("discord.js"); module.exports.init = async function (client) { new CronJob("0 5 * * *", async function () { @@ -26,7 +26,7 @@ module.exports.init = async function (client) { const age = currentYear - year; if (currentMonth === month && currentDay === day) { - const embed = new Discord.MessageEmbed() + const embed = new MessageEmbed() .setAuthor({ name: client.user.username, iconURL: client.user.displayAvatarURL({ diff --git a/helpers/checkReminds.js b/helpers/checkReminds.js index 57e8351a..bdc111a7 100644 --- a/helpers/checkReminds.js +++ b/helpers/checkReminds.js @@ -1,4 +1,4 @@ -const Discord = require("discord.js"); +const { MessageEmbed } = require("discord.js"); module.exports.init = function (client) { client.usersData @@ -18,7 +18,7 @@ module.exports.init = function (client) { const mustSent = reminds.filter((r) => r.sendAt < dateNow); if (mustSent.length > 0) { mustSent.forEach((r) => { - const embed = new Discord.MessageEmbed() + const embed = new MessageEmbed() .setAuthor({ name: client.translate("general/remindme:TITLE") }) diff --git a/helpers/checkUnmutes.js b/helpers/checkUnmutes.js index afd8fc52..9fac0be0 100644 --- a/helpers/checkUnmutes.js +++ b/helpers/checkUnmutes.js @@ -1,4 +1,4 @@ -const Discord = require("discord.js"); +const { MessageEmbed } = require("discord.js"); module.exports.init = async function (client) { client.membersData @@ -33,7 +33,7 @@ module.exports.init = async function (client) { }); } const user = member ? member.user : await client.users.fetch(memberData.id); - const embed = new Discord.MessageEmbed() + const embed = new MessageEmbed() .setDescription(guild.translate("moderation/unmute:SUCCESS_CASE", { user: user.toString(), usertag: user.tag, diff --git a/helpers/extenders.js b/helpers/extenders.js index b61a4b2c..8e061c84 100644 --- a/helpers/extenders.js +++ b/helpers/extenders.js @@ -11,7 +11,7 @@ Message.prototype.replyT = function (key, args, options = {}) { let string = this.translate(key, args, this.guild ? this.guild.data.language : "ru-RU"); if (options.prefixEmoji) string = `${this.client.customEmojis[options.prefixEmoji]} | ${string}`; - if (options.edit) return this.edit(string); + if (options.edit) return this.edit({ content: string }); else return this.reply({ content: string }); }; @@ -38,8 +38,8 @@ Interaction.prototype.replyT = function (key, args, options = {}) { let string = this.translate(key, args, this.guild ? this.guild.data.language : "ru-RU"); if (options.prefixEmoji) string = `${this.client.customEmojis[options.prefixEmoji]} | ${string}`; - if (options.edit) return this.editReply(string); - else return this.reply({ content: string, ephemeral: options.ephemeral || false, fetchReply: options.fetchReply || false }); + if (options.edit) return this.editReply({ content: string, ephemeral: options.ephemeral || false }); + else return this.reply({ content: string, ephemeral: options.ephemeral || false }); }; Interaction.prototype.error = function (key, args, options = {}) { diff --git a/helpers/functions.js b/helpers/functions.js index 6d8781bf..54717c05 100644 --- a/helpers/functions.js +++ b/helpers/functions.js @@ -10,10 +10,7 @@ module.exports = { const member = guild.me; const channel = guild.channels.cache.find((ch) => ch.permissionsFor(member.id).has(Permissions.FLAGS.CREATE_INSTANT_INVITE) && ch.type === "GUILD_TEXT" || ch.type === "GUILD_VOICE"); if (channel) { - const invite = await channel.createInvite({ - maxAge: 0, - maxUses: 5 - }).catch(() => {}); + const invite = await channel.createInvite(); return invite ? invite.url : "No URL"; } return "No channels found for invite"; diff --git a/helpers/resolvers.js b/helpers/resolvers.js index a45dced8..aa7ba46c 100644 --- a/helpers/resolvers.js +++ b/helpers/resolvers.js @@ -1,80 +1,96 @@ -const resolveChannel = async ({ message, search, channelType }) => { - const contentToCheck = search || message.content; - if (!contentToCheck || typeof contentToCheck !== "string") return; +/** + * + * @param {import("discord.js").Guild} guild + * @param {String} search + * @param {String} channelType + * @returns + */ +const resolveChannel = async ({ guild, search, channelType }) => { + if (!search || typeof search !== "string") return; // Try by parsing the search - if (contentToCheck.match(/^<#([0-9]{18})>/)) { - const [, channelId] = contentToCheck.match(/^<#([0-9]{18})>/); - const channelFound = message.guild.channels.cache.get(channelId); + if (search.match(/^<#([0-9]{18})>/)) { + const [, channelId] = search.match(/^<#([0-9]{18})>/); + const channelFound = guild.channels.cache.get(channelId); if (channelFound && channelType && channelFound.type === channelType) return channelFound; } // Try with ID - if (message.guild.channels.cache.has(search)) { - const channelFound = message.guild.channels.cache.get(search); + if (guild.channels.cache.has(search)) { + const channelFound = guild.channels.cache.get(search); if (channelFound && channelType && channelFound.type === channelType) return channelFound; } // Try with name with # - if (message.guild.channels.cache.some(channel => `#${channel.name}` === search || channel.name === search)) { - const channelFound = message.guild.channels.cache.find(channel => `#${channel.name}` === search || channel.name === search); + if (guild.channels.cache.some(channel => `#${channel.name}` === search || channel.name === search)) { + const channelFound = guild.channels.cache.find(channel => `#${channel.name}` === search || channel.name === search); if (channelFound && channelType && channelFound.type === channelType) return channelFound; } return; }; -const resolveMember = async ({ message, search, useMessageContent = true }) => { - const contentToCheck = search || (useMessageContent ? message.content : null); - if (!contentToCheck || typeof contentToCheck !== "string") return; +/** + * + * @param {import("discord.js").Guild} guild + * @param {String} search + * @returns + */ +const resolveMember = async ({ guild, search }) => { + if (!search || typeof search !== "string") return; // Try by parsing the search - if (contentToCheck.match(/^<@!?(\d+)>$/)) { - const [, userId] = contentToCheck.match(/^<@!?(\d+)>$/); - const memberFound = await message.guild.members.fetch(userId).catch(() => {}); + if (search.match(/^<@!?(\d+)>$/)) { + const [, userId] = search.match(/^<@!?(\d+)>$/); + const memberFound = await guild.members.fetch(userId).catch(() => {}); if (memberFound) return memberFound; } // Try with ID - if (await message.guild.members.fetch(search).catch(() => {})) { - const memberFound = await message.guild.members.fetch(search); + if (await guild.members.fetch(search).catch(() => {})) { + const memberFound = await guild.members.fetch(search); if (memberFound) return memberFound; } // Try with name with @ - await message.guild.members.fetch({ + await guild.members.fetch({ query: search }); - if (message.guild.members.cache.some(member => member.user.tag === search || member.user.username === search)) { - const memberFound = message.guild.members.cache.find(member => member.user.tag === search || member.user.username === search); + if (guild.members.cache.some(member => member.user.tag === search || member.user.username === search)) { + const memberFound = guild.members.cache.find(member => member.user.tag === search || member.user.username === search); if (memberFound) return memberFound; } return; }; -const resolveRole = async ({ message, search }) => { - const contentToCheck = search || message.content; - if (!contentToCheck || typeof contentToCheck !== "string") return; +/** + * + * @param {import("discord.js").Guild} guild + * @param {String} search + * @returns + */ +const resolveRole = async ({ guild, search }) => { + if (!search || typeof search !== "string") return; // Try by parsing the search - if (contentToCheck.match(/^<@&([0-9]{18})>/)) { - const [, roleId] = contentToCheck.match(/^<@&([0-9]{18})>/); - const roleFound = message.guild.roles.cache.get(roleId); + if (search.match(/^<@&([0-9]{18})>/)) { + const [, roleId] = search.match(/^<@&([0-9]{18})>/); + const roleFound = guild.roles.cache.get(roleId); if (roleFound) return roleFound; } // Try with ID - if (message.guild.roles.cache.has(search)) { - const roleFound = message.guild.roles.cache.get(search); + if (guild.roles.cache.has(search)) { + const roleFound = guild.roles.cache.get(search); if (roleFound) return roleFound; } // Try with name with @ - if (message.guild.roles.cache.some(role => `@${role.name}` === search || role.name === search)) { - const roleFound = message.guild.roles.cache.find(role => `@${role.name}` === search || role.name === search); + if (guild.roles.cache.some(role => `@${role.name}` === search || role.name === search)) { + const roleFound = guild.roles.cache.find(role => `@${role.name}` === search || role.name === search); if (roleFound) return roleFound; } diff --git a/helpers/tictactoe.js b/helpers/tictactoe.js index 7b5e37ed..92ac9f1a 100644 --- a/helpers/tictactoe.js +++ b/helpers/tictactoe.js @@ -8,89 +8,83 @@ const { MessageEmbed, MessageButton, MessageActionRow } = require("discord.js"); */ /** slash => Boolean - userSlash => String - resultBtn => Boolean - embedFoot => String embedColor => HexColor timeoutEmbedColor => HexColor - xEmoji => (Emoji ID) String - oEmoji => (Emoji ID) String - idleEmoji => (Emoji ID) String */ -async function tictactoe(message, options = []) { +async function tictactoe(interaction, options = {}) { // eslint-disable-next-line no-async-promise-executor return new Promise(async (resolve) => { try { - const { client } = message; + const { client } = interaction; let opponent; - if (message.commandId) { - opponent = message.options.getUser(options.userSlash || "user"); + if (interaction.commandId) { + opponent = interaction.options.getUser(options.userSlash || "user"); if (!opponent) - return message.reply({ - content: message.translate("economy/tictactoe:NO_USER"), + return interaction.reply({ + content: interaction.translate("economy/tictactoe:NO_USER"), ephemeral: true }); if (opponent.bot) - return message.reply({ - content: message.translate("economy/tictactoe:BOT_USER"), + return interaction.reply({ + content: interaction.translate("economy/tictactoe:BOT_USER"), ephemeral: true }); - if (opponent.id == (message.user ? message.user : message.author).id) - return message.reply({ - content: message.translate("economy/tictactoe:YOURSELF"), + if (opponent.id == (interaction.user ? interaction.user : interaction.author).id) + return interaction.reply({ + content: interaction.translate("economy/tictactoe:YOURSELF"), ephemeral: true }); - } else if (!message.commandId) { - opponent = message.mentions.members.first()?.user; + } else if (!interaction.commandId) { + opponent = interaction.mentions.members.first()?.user; if (!opponent) - return message.reply({ - content: message.translate("economy/tictactoe:NO_USER") + return interaction.reply({ + content: interaction.translate("economy/tictactoe:NO_USER") }); if (opponent.bot) - return message.reply({ - content: message.translate("economy/tictactoe:BOT_USER"), + return interaction.reply({ + content: interaction.translate("economy/tictactoe:BOT_USER"), ephemeral: true }); - if (opponent.id === message.member.id) - return message.reply({ - content: message.translate("economy/tictactoe:YOURSELF") + if (opponent.id === interaction.member.id) + return interaction.reply({ + content: interaction.translate("economy/tictactoe:YOURSELF") }); } const foot = options.embedFoot ? { text: options.embedFoot } : { text: "Удачи =)" }; const acceptEmbed = new MessageEmbed() - .setTitle(message.translate("economy/tictactoe:REQUEST_WAIT", { + .setTitle(interaction.translate("economy/tictactoe:REQUEST_WAIT", { user: opponent.tag })) .setAuthor({ - name: (message.user ? message.user : message.author).tag, - iconURL: (message.user ? message.user : message.author).displayAvatarURL() + name: (interaction.user ? interaction.user : interaction.author).tag, + iconURL: (interaction.user ? interaction.user : interaction.author).displayAvatarURL() }) .setColor(options.embedColor || "#075FFF") .setFooter(foot) .setTimestamp(); const accept = new MessageButton() - .setLabel(message.translate("economy/tictactoe:ACCEPT")) + .setLabel(interaction.translate("economy/tictactoe:ACCEPT")) .setStyle("SUCCESS") .setCustomId("acceptttt"); const decline = new MessageButton() - .setLabel(message.translate("economy/tictactoe:DECLINE")) + .setLabel(interaction.translate("economy/tictactoe:DECLINE")) .setStyle("DANGER") .setCustomId("declinettt"); @@ -101,17 +95,17 @@ async function tictactoe(message, options = []) { let m; - if (message.commandId) { - m = await message.reply({ - content: message.translate("economy/tictactoe:INVITE_USER", { + if (interaction.commandId) { + m = await interaction.reply({ + content: interaction.translate("economy/tictactoe:INVITE_USER", { opponent: opponent.id }), embeds: [acceptEmbed], components: [accep] }); - } else if (!message.commandId) { - m = await message.reply({ - content: message.translate("economy/tictactoe:INVITE_USER", { + } else if (!interaction.commandId) { + m = await interaction.reply({ + content: interaction.translate("economy/tictactoe:INVITE_USER", { opponent: opponent.id }), embeds: [acceptEmbed], @@ -125,7 +119,7 @@ async function tictactoe(message, options = []) { collector.on("collect", async (button) => { if (button.user.id !== opponent.id) return button.reply({ - content: message.translate("economy/tictactoe:REQUEST_SEND", { + content: interaction.translate("economy/tictactoe:REQUEST_SEND", { opponent: opponent.id }), ephemeral: true @@ -136,10 +130,10 @@ async function tictactoe(message, options = []) { return collector.stop("decline"); } else if (button.customId == "acceptttt") { collector.stop(); - if (message.commandId) button.message.delete(); + if (interaction.commandId) button.message.delete(); const fighters = [ - (message.user ? message.user : message.author).id, + (interaction.user ? interaction.user : interaction.author).id, opponent.id ].sort(() => (Math.random() > 0.5 ? 1 : -1)); @@ -199,28 +193,28 @@ async function tictactoe(message, options = []) { const { MessageActionRow, MessageButton } = require("discord.js"); const epm = new MessageEmbed() - .setTitle(message.translate("economy/tictactoe:DESCRIPTION")) + .setTitle(interaction.translate("economy/tictactoe:DESCRIPTION")) .setColor(options.embedColor || "#075FFF") .setFooter(foot) .setTimestamp(); let msg; - if (message.commandId) { - msg = await message.reply({ + if (interaction.commandId) { + msg = await interaction.reply({ embeds: [ epm.setDescription( - message.translate("economy/tictactoe:WAITING", { + interaction.translate("economy/tictactoe:WAITING", { user: Args.userid, emoji: client.emojis.cache.get(o_emoji) || "⭕" }) ) ] }); - } else if (!message.commandId) { + } else if (!interaction.commandId) { msg = await button.message.edit({ embeds: [ epm.setDescription( - message.translate("economy/tictactoe:WAITING", { + interaction.translate("economy/tictactoe:WAITING", { user: Args.userid, emoji: client.emojis.cache.get(o_emoji) || "⭕" }) @@ -347,7 +341,7 @@ async function tictactoe(message, options = []) { if (options.resultBtn === true) return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), @@ -355,7 +349,7 @@ async function tictactoe(message, options = []) { embeds: [ epm.setDescription( - message.translate("economy/tictactoe:WON", { + interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" }) @@ -368,14 +362,14 @@ async function tictactoe(message, options = []) { else if (!options.resultBtn || options.resultBtn === false) return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), embeds: [ epm.setDescription( - `${message.translate("economy/tictactoe:WON", { + `${interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" })}\n\`\`\`\n${Args.a1.emoji @@ -416,14 +410,14 @@ async function tictactoe(message, options = []) { if (options.resultBtn === true) return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), components: buttons, embeds: [ epm.setDescription( - message.translate("economy/tictactoe:WON", { + interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" }) @@ -436,14 +430,14 @@ async function tictactoe(message, options = []) { else if (!options.resultBtn || options.resultBtn === false) return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), embeds: [ epm.setDescription( - `${message.translate("economy/tictactoe:WON", { + `${interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" })}\n\`\`\`\n${Args.a1.emoji @@ -535,14 +529,14 @@ async function tictactoe(message, options = []) { if (options.resultBtn === true) return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), components: buttons, embeds: [ epm.setDescription( - message.translate("economy/tictactoe:WON", { + interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" }) @@ -555,13 +549,13 @@ async function tictactoe(message, options = []) { else if (!options.resultBtn || options.resultBtn === false) return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), embeds: [ epm.setDescription( - `${message.translate("economy/tictactoe:WON", { + `${interaction.translate("economy/tictactoe:WON", { winner: fighters[1], emoji: client.emojis.cache.get(o_emoji) || "⭕" })}\n\`\`\`\n${Args.a1.emoji @@ -602,14 +596,14 @@ async function tictactoe(message, options = []) { if (options.resultBtn === true) return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), components: buttons, embeds: [ epm.setDescription( - message.translate("economy/tictactoe:WON", { + interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" }) @@ -622,13 +616,13 @@ async function tictactoe(message, options = []) { else return m .edit({ - content: message.translate("economy/tictactoe:WON", { + content: interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" }), embeds: [ epm.setDescription( - `${message.translate("economy/tictactoe:WON", { + `${interaction.translate("economy/tictactoe:WON", { winner: fighters[0], emoji: client.emojis.cache.get(o_emoji) || "⭕" })}\n\`\`\`\n${Args.a1.emoji @@ -667,7 +661,7 @@ async function tictactoe(message, options = []) { content: `<@${Args.userid}>`, embeds: [ epm.setDescription( - message.translate("economy/tictactoe:WAITING", { + interaction.translate("economy/tictactoe:WAITING", { user: Args.userid, emoji: Args.user == 0 ? `${client.emojis.cache.get(o_emoji) || "⭕"}` : `${client.emojis.cache.get(x_emoji) || "❌"}` }) @@ -685,7 +679,7 @@ async function tictactoe(message, options = []) { collector.on("collect", (b) => { if (b.user.id !== Args.userid) { b.reply({ - content: message.translate("economy/tictactoe:CANT_PLAY"), + content: interaction.translate("economy/tictactoe:CANT_PLAY"), ephemeral: true }); @@ -781,8 +775,8 @@ async function tictactoe(message, options = []) { if (options.resultBtn === true) return m .edit({ - content: message.translate("economy/tictactoe:TIE"), - embeds: [epm.setDescription(message.translate("economy/tictactoe:TIE_DESC"))] + content: interaction.translate("economy/tictactoe:TIE"), + embeds: [epm.setDescription(interaction.translate("economy/tictactoe:TIE_DESC"))] }) .then((m) => { m.react(dashmoji); @@ -790,10 +784,10 @@ async function tictactoe(message, options = []) { else return m .edit({ - content: message.translate("economy/tictactoe:TIE"), + content: interaction.translate("economy/tictactoe:TIE"), embeds: [ epm.setDescription( - `${message.translate("economy/tictactoe:TIE_DESC")}!\n\`\`\`\n${Args.a1.emoji + `${interaction.translate("economy/tictactoe:TIE_DESC")}!\n\`\`\`\n${Args.a1.emoji .replace(o_emoji, "⭕") .replace(x_emoji, "❌")} | ${Args.a2.emoji .replace(o_emoji, "⭕") @@ -832,7 +826,7 @@ async function tictactoe(message, options = []) { collector.on("end", (collected, reason) => { if (collected.size === 0 && reason == "time") m.edit({ - content: message.translate("economy/tictactoe:NO_ANSWER", { + content: interaction.translate("economy/tictactoe:NO_ANSWER", { user: Args.userid }), components: [] @@ -845,17 +839,17 @@ async function tictactoe(message, options = []) { collector.on("end", (collected, reason) => { if (reason == "time") { const embed = new MessageEmbed() - .setTitle(message.translate("economy/tictactoe:NO_ANSWER_TITLE")) + .setTitle(interaction.translate("economy/tictactoe:NO_ANSWER_TITLE")) .setAuthor({ - name: (message.user ? message.user : message.author).tag, - iconURL: (message.user ? message.user : message.author).displayAvatarURL() + name: (interaction.user ? interaction.user : interaction.author).tag, + iconURL: (interaction.user ? interaction.user : interaction.author).displayAvatarURL() }) .setColor(options.timeoutEmbedColor || "#C90000") .setFooter(foot) .setTimestamp() - .setDescription(message.translate("economy/tictactoe:TIMES_UP")); + .setDescription(interaction.translate("economy/tictactoe:TIMES_UP")); m.edit({ - content: message.translate("economy/tictactoe:NOT_ANSWERED", { + content: interaction.translate("economy/tictactoe:NOT_ANSWERED", { user: opponent.id }), embeds: [embed], @@ -864,15 +858,15 @@ async function tictactoe(message, options = []) { } if (reason == "decline") { const embed = new MessageEmbed() - .setTitle(message.translate("economy/tictactoe:CANCELED")) + .setTitle(interaction.translate("economy/tictactoe:CANCELED")) .setAuthor({ - name: (message.user ? message.user : message.author).tag, - iconURL: (message.user ? message.user : message.author).displayAvatarURL() + name: (interaction.user ? interaction.user : interaction.author).tag, + iconURL: (interaction.user ? interaction.user : interaction.author).displayAvatarURL() }) .setColor(options.timeoutEmbedColor || "#C90000") .setFooter(foot) .setTimestamp() - .setDescription(message.translate("economy/tictactoe:CANCELED_DESC", { + .setDescription(interaction.translate("economy/tictactoe:CANCELED_DESC", { user: opponent.id })); m.edit({ diff --git a/languages/en-US/images/brazzers.json b/languages/en-US/images/brazzers.json index 31347855..0ace455d 100644 --- a/languages/en-US/images/brazzers.json +++ b/languages/en-US/images/brazzers.json @@ -1,4 +1,4 @@ -{ +z{ "DESCRIPTION": "Generates a \"dictator\" image", "USAGE": "dictator (@member)", "EXAMPLES": "dictator\ndictator @Jonny_Bro#4226" diff --git a/languages/ru-RU/common.json b/languages/ru-RU/common.json index 5e29dc74..615024c2 100644 --- a/languages/ru-RU/common.json +++ b/languages/ru-RU/common.json @@ -37,7 +37,8 @@ "LINKS": "Ссылки", "CREDITS": "Кредиты", "LEVEL": "Уровень", - "POINTS": "Очки", + "REP": "Очки репутации", + "XP": "Опыт", "VICTORY": "Победа", "DEFEAT": "Поражение", "MODERATOR": "Модератор", diff --git a/languages/ru-RU/economy/leaderboard.json b/languages/ru-RU/economy/leaderboard.json index ac9902a2..8fb626a7 100644 --- a/languages/ru-RU/economy/leaderboard.json +++ b/languages/ru-RU/economy/leaderboard.json @@ -6,8 +6,5 @@ "MOBILE": ":confused: Я заметил, что вы онлайн с телефона... Таблица лидеров может отображаться некорректно на маленьких экранах. Попробуйте позже с другого устройства!", "TABLE": "Таблица лидеров {{name}}", "TOP": "Топ 20", - "LEVEL": "Уровень", - "XP": "Опыт", - "CREDITS": "Кредиты", - "REP": "Репутация" + "XP": "Опыт" } \ No newline at end of file diff --git a/languages/ru-RU/nsfw/nsfw.json b/languages/ru-RU/nsfw/nsfw.json index cd1208b5..711d8c6d 100644 --- a/languages/ru-RU/nsfw/nsfw.json +++ b/languages/ru-RU/nsfw/nsfw.json @@ -1,9 +1,8 @@ { - "DESCRIPTION": "Получить NSFW изображение с выбранного или случайного сабреддита", - "USAGE": "nsfw (тег/list)", - "EXAMPLES": "nsfw\nnsfw list", - "SEARCHING": "Ищу изображение по тегу `{{tag}}`", - "SEARCHING_RANDOM": "Ищу случайное изображение", - "EMBED_TITLE": "Доступные категории", - "NOT_FOUND": "Данной категории не существует!" + "DESCRIPTION": "Найти NSFW изображение по тэгу", + "USAGE": "nsfw", + "EXAMPLES": "nsfw", + "AVAILABLE_CATEGORIES": "Доступные категории:", + "NOTHING_SELECTED": "Ничего не выбрано", + "TAG": "Тэг" } \ No newline at end of file diff --git a/languages/ru-RU/owner/debug.json b/languages/ru-RU/owner/debug.json index 6cafafc7..06b88eea 100644 --- a/languages/ru-RU/owner/debug.json +++ b/languages/ru-RU/owner/debug.json @@ -1,12 +1,13 @@ { - "DESCRIPTION": "Позволяет изменять многие данные пользователя!", - "USAGE": "debug [set/add] [level/xp/credits/bank/rep] [@пользователь] [значение]", + "DESCRIPTION": "Позволяет изменять многие данные пользователя", + "USAGE": "[действие] [тип] [@пользователь] [значение]", "EXAMPLES": "debug set level @Jonny_Bro#4226 10000", - "INVALID_MEMBER": "Вы должны упомянуть пользователя!", - "NO_ACTION": "Выберите действие: `set` или `add`!", - "NO_STATUS": "Выберите параметр: `level`, `xp`, `credits`, `rep` или `bank`!", - "BOT_USER": "Вы не можете изменить статистику бота!", - "INVALID_AMOUNT": "Укажите новое значение!", + "TYPE": "Тип данных", + "SET": "Установить значение", + "ADD": "Добавить к значению", + "TARGET": "Пользователь", + "INT": "Целое число", + "BOT": "Вы не можете изменить статистику бота!", "SUCCESS_LEVEL": "Уровень пользователя **{{username}}** изменён на **{{amount}}**!", "SUCCESS_XP": "XP пользователя **{{username}}** изменён на **{{amount}}**!", "SUCCESS_CREDITS": "Кредиты пользователя **{{username}}** изменены на **{{amount}}**!", diff --git a/languages/ru-RU/owner/eval.json b/languages/ru-RU/owner/eval.json index afb63f84..42dd44a8 100644 --- a/languages/ru-RU/owner/eval.json +++ b/languages/ru-RU/owner/eval.json @@ -1,5 +1,5 @@ { - "DESCRIPTION": "Выполнить код!", + "DESCRIPTION": "Выполнить код", "USAGE": "[код]", "EXAMPLES": "eval interaction.channel.send({ content: \"Hello World!\" })" } \ No newline at end of file diff --git a/languages/ru-RU/owner/say.json b/languages/ru-RU/owner/say.json index ea1e7cfa..05b5fa0e 100644 --- a/languages/ru-RU/owner/say.json +++ b/languages/ru-RU/owner/say.json @@ -1,5 +1,8 @@ { - "DESCRIPTION": "Написать сообщение от имени бота!", - "USAGE": "say [текст] ++ (ID/название-канала) ++ (ID/название-сервера)", - "EXAMPLES": "say Hello World!\nsay Hello World! ++ 123456789098765432" + "DESCRIPTION": "Написать сообщение от имени бота", + "USAGE": "[текст] (#канал)", + "EXAMPLES": "say Hello World!\nsay Hello World! #новости", + "DONE": "Сообщение `{{message}}` отправлено в {{channel}}!", + "MESSAGE": "Сообщение", + "CHANNEL": "Канал" } \ No newline at end of file diff --git a/languages/ru-RU/owner/servers-list.json b/languages/ru-RU/owner/servers.json similarity index 50% rename from languages/ru-RU/owner/servers-list.json rename to languages/ru-RU/owner/servers.json index 69a81a32..ac4e7df8 100644 --- a/languages/ru-RU/owner/servers-list.json +++ b/languages/ru-RU/owner/servers.json @@ -1,5 +1,5 @@ { - "DESCRIPTION": "Показать список серверов бота!", - "USAGE": "servers-list", - "EXAMPLES": "servers-list" + "DESCRIPTION": "Показать список серверов бота", + "USAGE": "servers", + "EXAMPLES": "servers" } \ No newline at end of file