From 5565f7e86a18e4fb8bb9cd200da3b6ce11b35e81 Mon Sep 17 00:00:00 2001 From: JonnyBro Date: Sun, 26 Dec 2021 00:04:26 +0500 Subject: [PATCH 01/10] new music system --- assets/json/filters.json | 15 ----- assets/json/partners.json | 8 --- base/JaBa.js | 104 +++++++++--------------------- commands/Music/autoplay.js | 8 +-- commands/Music/back.js | 54 ++-------------- commands/Music/clip.js | 7 +- commands/Music/filter.js | 24 +++---- commands/Music/filters.js | 9 ++- commands/Music/jump.js | 43 ++++++++++++ commands/Music/loop.js | 15 +---- commands/Music/np.js | 19 +++--- commands/Music/pause.js | 4 +- commands/Music/queue.js | 16 ++--- commands/Music/resume.js | 4 +- commands/Music/seek.js | 7 +- commands/Music/skip.js | 59 ++--------------- commands/Music/stop.js | 53 ++------------- languages/en-US/music/back.json | 1 - languages/en-US/music/filter.json | 4 +- languages/en-US/music/jump.json | 7 ++ languages/en-US/music/loop.json | 7 +- languages/en-US/music/np.json | 2 +- languages/en-US/music/play.json | 7 +- languages/en-US/music/skip.json | 1 - languages/ru-RU/music/back.json | 1 - languages/ru-RU/music/filter.json | 4 +- languages/ru-RU/music/jump.json | 7 ++ languages/ru-RU/music/loop.json | 7 +- languages/ru-RU/music/np.json | 2 +- languages/ru-RU/music/play.json | 5 +- languages/ru-RU/music/skip.json | 1 - package.json | 9 +-- 32 files changed, 172 insertions(+), 342 deletions(-) delete mode 100644 assets/json/filters.json delete mode 100644 assets/json/partners.json create mode 100644 commands/Music/jump.js create mode 100644 languages/en-US/music/jump.json create mode 100644 languages/ru-RU/music/jump.json diff --git a/assets/json/filters.json b/assets/json/filters.json deleted file mode 100644 index 31367264..00000000 --- a/assets/json/filters.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "bassboost": "Bassboost", - "8D": "8D", - "vaporwave": "Vaporwave", - "nightcore": "Nightcore", - "phaser": "Phaser", - "tremolo": "Tremolo", - "vibrato": "Vibrato", - "reverse": "Reverse", - "treble": "Treble", - "normalizer": "Normalizer", - "surrounding": "Surrounding", - "pulsator": "Pulsator", - "superequalizer": "Superequalizer" -} \ No newline at end of file diff --git a/assets/json/partners.json b/assets/json/partners.json deleted file mode 100644 index 761943ac..00000000 --- a/assets/json/partners.json +++ /dev/null @@ -1,8 +0,0 @@ -[ - { - "name": "", - "description_french": "", - "description_english": "", - "link": "" - } -] \ No newline at end of file diff --git a/base/JaBa.js b/base/JaBa.js index 8f5f01ad..16e76a3d 100644 --- a/base/JaBa.js +++ b/base/JaBa.js @@ -1,11 +1,13 @@ const { MessageEmbed, Util, Client, Collection } = require("discord.js"), { GiveawaysManager } = require("discord-giveaways"), - { Player } = require("discord-player"), + { SoundCloudPlugin } = require("@distube/soundcloud"), + { SpotifyPlugin } = require("@distube/spotify"), { Client: Joker } = require("blague.xyz"); const util = require("util"), AmeClient = require("amethyste-api"), path = require("path"), + DisTube = require("distube"), moment = require("moment"); moment.relativeTimeThreshold("s", 60); @@ -47,91 +49,47 @@ class JaBa extends Client { if (this.config.apiKeys.amethyste) this.AmeAPI = new AmeClient(this.config.apiKeys.amethyste); if (this.config.apiKeys.blagueXYZ) this.joker = new Joker(this.config.apiKeys.blagueXYZ, { defaultLanguage: "en" }); - this.player = new Player(this, { - ytdlDownloadOptions: { - filter: "audio", - requestOptions: { - headers: { - cookie: this.config.youtubeToken, - quality: "highestaudio", - highWaterMark: 1 << 25 - } - } - }, - leaveOnEmpty: false, - enableLive: true + this.player = new DisTube.default(this, { + searchSongs: 10, + searchCooldown: 30, + leaveOnEmpty: true, + emptyCooldown: 0, + leaveOnFinish: true, + leaveOnStop: true, + nsfw: true, + plugins: [ new SoundCloudPlugin(), new SpotifyPlugin() ], }); this.player - .on("trackStart", (message, track) => { - message.success("music/play:NOW_PLAYING", { songName: track.title }); - }) - .on("playlistStart", (message, queue, playlist, track) => { - message.channel.send(`${this.customEmojis.success} ${message.translate("music/play:PLAYING_PLAYLIST", { playlistTitle: playlist.title, playlistEmoji: this.customEmojis.playlist, songName: track.title })}`); - }) - .on("searchResults", (message, query, tracks) => { - if (tracks.length > 10) tracks = tracks.slice(0, 10); + .on("playSong", (queue, song) => queue.textChannel.send(this.translate("music/play:NOW_PLAYING", { songName: song.name }))) + .on("addSong", (queue, song) => queue.textChannel.send(this.translate("music/play:ADDED_QUEUE", { songName: song.name }))) + .on("addList", (queue, playlist) => queue.textChannel.send(this.translate("music/play:ADDED_QUEUE_COUNT", { songCount: playlist.songs.length }))) + .on("searchResult", (message, result) => { + let i = 0 const embed = new MessageEmbed() - .setDescription(Util.escapeSpoiler(tracks.map((t, i) => `**${++i} -** ${t.title}`).join("\n"))) - .setFooter(message.translate("music/play:RESULTS_FOOTER")) + .setDescription(Util.escapeSpoiler(result.map(song => `**${++i} -** ${song.name}`).join("\n"))) + .setFooter(this.translate("music/play:RESULTS_FOOTER")) .setColor(this.config.embed.color); message.channel.send(embed); }) - .on("searchInvalidResponse", (message, query, tracks, content, collector) => { - if (content === "cancel") { + .on("searchDone", () => {}) + .on("searchCancel", message => message.error("misc:TIMES_UP")) + .on("searchInvalidAnswer", message => { + if (message.content === "cancel") { collector.stop(); - return message.success("music/play:RESULTS_CANCEL"); }; message.error("misc:INVALID_NUMBER_RANGE", { min: 1, max: tracks.length }); }) - .on("searchCancel", (message) => { - message.error("misc:TIMES_UP"); + .on("searchNoResult", message => message.error("music/play:NO_RESULT")) + .on("error", (textChannel, e) => { + console.error(e); + textChannel.send(this.translate("music/play:ERR_OCCURRED", { error: e.slice(0, 1900)})); }) - .on("botDisconnect", (message) => { - message.error("music/play:STOP_DISCONNECTED"); - }) - .on("noResults", (message) => { - message.error("music/play:NO_RESULT"); - }) - .on("queueEnd", (message) => { - message.success("music/play:QUEUE_ENDED"); - }) - .on("playlistAdd", (message, queue, playlist) => { - message.success("music/play:ADDED_QUEUE_COUNT", { songCount: playlist.items.length }); - }) - .on("trackAdd", (message, queue, track) => { - message.success("music/play:ADDED_QUEUE", { songName: track.title }); - }) - .on("channelEmpty", () => { - // do nothing, leaveOnEmpty is not enabled - }) - .on("error", (error, message) => { - switch (error) { - case "NotConnected": - message.error("music/play:NO_VOICE_CHANNEL"); - break; - - case "UnableToJoin": - message.error("music/play:VOICE_CHANNEL_CONNECT"); - break; - - case "NotPlaying": - message.error("music/play:NOT_PLAYING"); - break; - - case "LiveVideo": - message.error("music/play:LIVE_VIDEO"); - break; - - default: - message.error("music/play:ERR_OCCURRED", { - error - }); - break; - }; - }); + .on("finish", queue => queue.textChannel.send(this.translate("music/play:QUEUE_ENDED"))) + .on("disconnect", queue => queue.textChannel.send(this.translate("music/play:STOP_DISCONNECTED"))) + .on("empty", queue => queue.textChannel.send(this.translate("music/play:STOP_EMPTY"))); this.giveawaysManager = new GiveawaysManager(this, { storage: "./giveaways.json", @@ -146,7 +104,7 @@ class JaBa extends Client { }; get defaultLanguage() { - return this.languages.find((language) => language.default).name; + return this.languages.find(language => language.default).name; }; translate(key, args, locale) { diff --git a/commands/Music/autoplay.js b/commands/Music/autoplay.js index f1c08db1..ea80407b 100644 --- a/commands/Music/autoplay.js +++ b/commands/Music/autoplay.js @@ -17,17 +17,15 @@ class AutoPlay extends Command { } async run (message) { - const queue = this.client.player.getQueue(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"); - // Gets the current song - await this.client.player.setAutoPlay(message, !queue.autoPlay); + const autoplay = queue.toggleAutoplay() - // Send the embed in the current channel - message.success(`music/autoplay:SUCCESS_${queue.autoPlay ? "ENABLED" : "DISABLED"}`); + message.success(`music/autoplay:SUCCESS_${autoplay ? "ENABLED" : "DISABLED"}`); } }; diff --git a/commands/Music/back.js b/commands/Music/back.js index 17f93aad..3c8ca2f1 100644 --- a/commands/Music/back.js +++ b/commands/Music/back.js @@ -18,14 +18,12 @@ class Back extends Command { } async run (message, args, data) { - const queue = this.client.player.getQueue(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"); - if (!queue.previousTracks[0]) return message.error("music/back:NO_PREV_SONG"); - - const members = voice.members.filter((m) => !m.user.bot); + if (!queue.previousSongs[0]) return message.error("music/back:NO_PREV_SONG"); const embed = new Discord.MessageEmbed() .setAuthor(message.translate("music/back:DESCRIPTION")) @@ -35,51 +33,9 @@ class Back extends Command { const m = await message.channel.send(embed); - if (args[0] && (args[0] === "force" || args[0] === "f")) { - if (message.member.hasPermission("ADMINISTRATOR") || message.member.hasPermission("MANAGE_MESSAGES")) { - this.client.player.back(message); - embed.setDescription(message.translate("music/back:SUCCESS")); - m.edit(embed); - } else message.error("misc:NO_PERMS"); - } else if (members.size > 1) { - m.react("👍"); - - const mustVote = Math.floor(members.size / 2); - - embed.setDescription(message.translate("music/back:VOTE_CONTENT", { songName: queue.tracks[0].name, voteCount: 0, requiredCount: mustVote })); - m.edit(embed); - - const filter = (reaction, user) => { - const member = message.guild.members.cache.get(user.id); - const voiceChannel = member.voice.channel; - if (voiceChannel) return voiceChannel.id === voice.id; - }; - - const collector = await m.createReactionCollector(filter, { - time: 25000 - }); - - collector.on("collect", (reaction) => { - const haveVoted = reaction.count - 1; - if (haveVoted >= mustVote) { - this.client.player.back(message); - embed.setDescription(message.translate("music/back:SUCCESS")); - m.edit(embed); - collector.stop(true); - } else { - embed.setDescription(message.translate("music/back:VOTE_CONTENT", { songName: queue.tracks[0].title, voteCount: haveVoted, requiredCount: mustVote })); - m.edit(embed); - } - }); - - collector.on("end", (collected, isDone) => { - if (!isDone) return message.error("misc:TIMES_UP"); - }); - } else { - this.client.player.back(message); - embed.setDescription(message.translate("music/back:SUCCESS")); - m.edit(embed); - }; + this.client.player.previous(message); + embed.setDescription(message.translate("music/back:SUCCESS")); + m.edit(embed); } }; diff --git a/commands/Music/clip.js b/commands/Music/clip.js index 07d8b5a0..cfece0a1 100644 --- a/commands/Music/clip.js +++ b/commands/Music/clip.js @@ -20,17 +20,18 @@ class Clip extends Command { async run (message, args) { const voice = message.member.voice.channel; const queue = this.client.player.getQueue(message); + const clip = args[0]; - if (!args[0]) return message.error("music/clip:NO_ARG"); - if (!fs.existsSync(`./clips/${args[0]}.mp3`)) return message.error("music/clip:NO_FILE", { file: args[0] }); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); 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 = await voice.join(); await connection.voice.setSelfDeaf(true); - connection.play(`./clips/${args[0]}.mp3`) + connection.play(`./clips/${clip}.mp3`) .on("finish", () => { voice.leave(); }) diff --git a/commands/Music/filter.js b/commands/Music/filter.js index 489ffe2e..e714a85c 100644 --- a/commands/Music/filter.js +++ b/commands/Music/filter.js @@ -1,5 +1,4 @@ -const Command = require("../../base/Command.js"), - FiltersList = require("../../assets/json/filters.json"); +const Command = require("../../base/Command.js") class Filter extends Command { constructor (client) { @@ -18,27 +17,22 @@ class Filter extends Command { } async run (message, args, data) { + const voice = message.member.voice.channel; const queue = this.client.player.getQueue(message); - const voice = message.member.voice.channel; if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!queue) return message.error("music/play:NOT_PLAYING"); const filter = args[0]; if (!filter) return message.error("music/filter:MISSING_FILTER", { prefix: data.guild.prefix }); - const filterToUpdate = Object.values(FiltersList).find((f) => f.toLowerCase() === filter.toLowerCase()); - - if (!filterToUpdate) return message.error("music/filter:UNKNOWN_FILTER", { prefix: data.guild.prefix }); - - const filterRealName = Object.keys(FiltersList).find((f) => FiltersList[f] === filterToUpdate); - const queueFilters = this.client.player.getQueue(message).filters; - const filtersUpdated = {}; - filtersUpdated[filterRealName] = queueFilters[filterRealName] ? false : true; - this.client.player.setFilters(message, filtersUpdated); - - if (filtersUpdated[filterRealName]) message.success("music/filter:ADDING_FILTER"); - else message.success("music/filter:REMOVING_FILTER"); + if (filter === "off" && queue.filters?.length) { + queue.setFilter(false); + message.success("music/filter:REMOVING_FILTER"); + } else if (Object.keys(this.client.player.filters).includes(args[0])) { + queue.setFilter(args[0]); + message.success("music/filter:ADDING_FILTER"); + } else if (args[0]) return message.error("music/filter:UNKNOWN_FILTER", { prefix: data.guild.prefix }); } }; diff --git a/commands/Music/filters.js b/commands/Music/filters.js index 41624424..5b229dd5 100644 --- a/commands/Music/filters.js +++ b/commands/Music/filters.js @@ -1,6 +1,5 @@ const Command = require("../../base/Command.js"), - Discord = require("discord.js"), - FiltersList = require("../../assets/json/filters.json"); + Discord = require("discord.js"); class Filters extends Command { constructor (client) { @@ -19,17 +18,17 @@ class Filters extends Command { } async run (message, args, data) { - const queue = this.client.player.getQueue(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 filtersStatuses = [ [], [] ]; - Object.keys(FiltersList).forEach((filterName) => { + Object.keys(this.client.player.filters).forEach((filterName) => { const array = filtersStatuses[0].length > filtersStatuses[1].length ? filtersStatuses[1] : filtersStatuses[0]; - array.push(FiltersList[filterName] + " : " + (this.client.player.getQueue(message).filters[filterName] ? this.client.customEmojis.success : this.client.customEmojis.error)); + array.push(FiltersList[filterName] + " : " + (queue.filters[filterName] ? this.client.customEmojis.success : this.client.customEmojis.error)); }); const list = new Discord.MessageEmbed() diff --git a/commands/Music/jump.js b/commands/Music/jump.js new file mode 100644 index 00000000..5fb39a77 --- /dev/null +++ b/commands/Music/jump.js @@ -0,0 +1,43 @@ +const Command = require("../../base/Command.js"), + Discord = require("discord.js"); + +class Jump extends Command { + constructor (client) { + super(client, { + name: "jump", + dirname: __dirname, + enabled: true, + guildOnly: true, + aliases: [], + 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(message.translate("music/jump:SUCCESS")) + .setThumbnail(queue.songs[number].thumbnail) + .setFooter(data.config.embed.footer) + .setColor(data.config.embed.color); + + const m = await message.channel.send(embed); + + this.client.player.jump(message, number); + embed.setDescription(message.translate("music/play:NOW_PLAYING", { songName: queue.songs[number].name })); + m.edit(embed); + } +}; + +module.exports = Jump; \ No newline at end of file diff --git a/commands/Music/loop.js b/commands/Music/loop.js index 717b53cb..1439bd17 100644 --- a/commands/Music/loop.js +++ b/commands/Music/loop.js @@ -12,7 +12,7 @@ class Loop extends Command { botPermissions: [ "SEND_MESSAGES" ], nsfw: false, ownerOnly: false, - cooldown: 3000 + cooldown: 1000 }); } @@ -20,21 +20,12 @@ class Loop extends Command { const voice = message.member.voice.channel; const queue = this.client.player.getQueue(message); - if (!args[0] || !["queue", "song"].includes(args[0])) return message.error("music/loop:NO_ARG"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!queue) return message.error("music/play:NOT_PLAYING"); - if (args[0].toLowerCase() === "queue") { - if (queue.repeatMode) this.client.player.setRepeatMode(message, false); + const mode = this.client.player.setRepeatMode(message); - this.client.player.setLoopMode(message, !queue.loopMode); - message.success(`music/loop:QUEUE_SUCCESS_${queue.loopMode ? "ENABLED" : "DISABLED"}`) - } else if (args[0].toLowerCase() === "song") { - if (queue.loopMode) this.client.player.setLoopMode(message, false); - - this.client.player.setRepeatMode(message, !queue.repeatMode); - message.success(`music/loop:SONG_SUCCESS_${queue.repeatMode ? "ENABLED" : "DISABLED"}`); - }; + message.success(`music/loop:${mode ? mode === 2 ? "QUEUE" : "SONG" : "DISABLED"}`) } }; diff --git a/commands/Music/np.js b/commands/Music/np.js index c9f588f1..1af7f0c1 100644 --- a/commands/Music/np.js +++ b/commands/Music/np.js @@ -18,28 +18,25 @@ class Np extends Command { } async run (message, args, data) { + const voice = message.member.voice.channel; const queue = this.client.player.getQueue(message); - const voice = message.member.voice.channel; if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); - if (!queue) return message.error("music/play:NOT_PLAYING"); // Gets the current song - const track = await this.client.player.nowPlaying(message); + const track = queue.songs[0]; // Generate discord embed to display song informations const embed = new Discord.MessageEmbed() - .setAuthor(message.translate("music/np:CURRENTLY_PLAYING")) + .setAuthor(message.translate("music/queue:TITLE")) .setThumbnail(track.thumbnail) - .addField(message.translate("music/np:T_TITLE"), track.title, true) - .addField(message.translate("music/np:T_CHANNEL"), track.author, true) - .addField(message.translate("music/np:T_DURATION"), message.convertTime(Date.now()+track.durationMS, "to", true), true) - .addField(message.translate("music/np:T_DESCRIPTION"), track.description ? (track.description.substring(0, 150) + "\n" + (message.translate("common:AND_MORE").toLowerCase())) : message.translate("music/np:NO_DESCRIPTION"), true) - .addField("\u200B", this.client.player.createProgressBar(message, { timecodes: true })) - .setTimestamp() + .addField(message.translate("music/np:T_TITLE"), track.name + `\n${track.url}`) + .addField(message.translate("music/np:T_CHANNEL"), track.uploader.name) + .addField(message.translate("music/np:T_DURATION"), message.convertTime(Date.now() + track.duration * 1000, "to", true)) .setColor(data.config.embed.color) - .setFooter(data.config.embed.footer); + .setFooter(data.config.embed.footer) + .setTimestamp(); // Send the embed in the current channel message.channel.send(embed); diff --git a/commands/Music/pause.js b/commands/Music/pause.js index 98aea16a..5db4ebef 100644 --- a/commands/Music/pause.js +++ b/commands/Music/pause.js @@ -17,16 +17,14 @@ class Pause extends Command { } async run (message) { + const voice = message.member.voice.channel; const queue = this.client.player.getQueue(message); - const voice = message.member.voice.channel; if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!queue) return message.error("music:play:NOT_PLAYING"); - // Gets the current song await this.client.player.pause(message); - // Send the embed in the current channel message.sendT("music/pause:SUCCESS"); } }; diff --git a/commands/Music/queue.js b/commands/Music/queue.js index 8bd2b0e9..5f311c31 100644 --- a/commands/Music/queue.js +++ b/commands/Music/queue.js @@ -20,19 +20,19 @@ class Queue extends Command { async run (message, args, data) { const voice = message.member.voice.channel; - if (!voice) return message.error("music/play:NO_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.tracks.length === 1) { + if (queue.songs.length === 1) { const embed = new Discord.MessageEmbed() - .setColor(data.config.embed.color) .setAuthor(message.translate("music/queue:TITLE"), message.guild.iconURL({ dynamic: true })) - .addField(message.translate("music/np:CURRENTLY_PLAYING"), `[${queue.tracks[0].title}](${queue.tracks[0].url})\n*Requested by ${queue.tracks[0].requestedBy}*\n`); + .addField(message.translate("music/np:CURRENTLY_PLAYING"), `[${queue.songs[0].name}](${queue.songs[0].url})\n*Добавил ${queue.songs[0].member}*\n`) + .setColor(data.config.embed.color); return message.channel.send(embed); }; + let i = 0; const FieldsEmbed = new Pagination.FieldsEmbed(); @@ -40,14 +40,14 @@ class Queue extends Command { FieldsEmbed.embed .setColor(data.config.embed.color) .setAuthor(message.translate("music/queue:TITLE"), message.guild.iconURL({ dynamic: true })) - .addField(message.translate("music/np:CURRENTLY_PLAYING"), `[${queue.tracks[0].title}](${queue.tracks[0].url})\n*Requested by ${queue.tracks[0].requestedBy}*\n`); + .addField(message.translate("music/np:CURRENTLY_PLAYING"), `[${queue.songs[0].name}](${queue.songs[0].url})\n*Добавил ${queue.songs[0].member}*\n`); - FieldsEmbed.setArray(queue.tracks[1] ? queue.tracks.slice(1, queue.tracks.length) : []) + FieldsEmbed.setArray(queue.songs[1] ? queue.songs.slice(1, queue.songs.length) : []) .setAuthorizedUsers([message.author.id]) .setChannel(message.channel) .setElementsPerPage(5) .setPageIndicator(true) - .formatField("Queue", (track) => `${++i}. [${track.title}](${track.url})\n*Requested by ${track.requestedBy}*\n`); + .formatField("Очередь", (track) => `${++i}. [${track.name}](${track.url})\n*Добавил ${track.member}*\n`); FieldsEmbed.build(); } diff --git a/commands/Music/resume.js b/commands/Music/resume.js index b5f548b4..d04519a0 100644 --- a/commands/Music/resume.js +++ b/commands/Music/resume.js @@ -17,16 +17,14 @@ class Resume extends Command { } async run (message) { + const voice = message.member.voice.channel; const queue = this.client.player.getQueue(message); - const voice = message.member.voice.channel; if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!queue) return message.error("music:play:NOT_PLAYING"); - // Gets the current song await this.client.player.resume(message); - // Send the embed in the current channel message.sendT("music/resume:SUCCESS"); } }; diff --git a/commands/Music/seek.js b/commands/Music/seek.js index c0b6ddcc..c9d30bcb 100644 --- a/commands/Music/seek.js +++ b/commands/Music/seek.js @@ -18,20 +18,17 @@ class Seek extends Command { } async run (message, args) { + const voice = message.member.voice.channel; const queue = this.client.player.getQueue(message); - const voice = message.member.voice.channel; if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); - if (!queue) return message.error("music/play:NOT_PLAYING"); const time = ms(args[0]); if (isNaN(time)) return message.error("music/seek:INVALID_TIME"); - // Change the song position - await this.client.player.setPosition(message, queue.currentStreamTime + time); + await this.client.player.seek(message, time); - // Send the embed in the current channel message.sendT("music/seek:SUCCESS"); } }; diff --git a/commands/Music/skip.js b/commands/Music/skip.js index aa11c758..f584ff47 100644 --- a/commands/Music/skip.js +++ b/commands/Music/skip.js @@ -18,69 +18,24 @@ class Skip extends Command { } async run (message, args, data) { - const queue = this.client.player.getQueue(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"); - if (!queue.tracks[0]) return message.error("music/skip:NO_NEXT_SONG"); - - const members = voice.members.filter((m) => !m.user.bot); + if (!queue.songs[1]) return message.error("music/skip:NO_NEXT_SONG"); const embed = new Discord.MessageEmbed() - .setAuthor(message.translate("music/skip:DESCRIPTION")) - .setThumbnail(queue.tracks[0].thumbnail) + .setAuthor(message.translate("music/skip:SUCCESS")) + .setThumbnail(queue.songs[1].thumbnail) .setFooter(data.config.embed.footer) .setColor(data.config.embed.color); const m = await message.channel.send(embed); - if (args[0] && (args[0] === "force" || args[0] === "f")) { - if (message.member.hasPermission("ADMINISTRATOR") || message.member.hasPermission("MANAGE_MESSAGES")) { - this.client.player.skip(message); - embed.setDescription(message.translate("music/skip:SUCCESS")); - m.edit(embed); - } else message.error("misc:NO_PERMS"); - } else if (members.size > 1) { - m.react("👍"); - - const mustVote = Math.floor(members.size / 2); - - embed.setDescription(message.translate("music/skip:VOTE_CONTENT", { songName: queue.tracks[0].name, voteCount: 0, requiredCount: mustVote })); - m.edit(embed); - - const filter = (reaction, user) => { - const member = message.guild.members.cache.get(user.id); - const voiceChannel = member.voice.channel; - if (voiceChannel) return voiceChannel.id === voice.id; - }; - - const collector = await m.createReactionCollector(filter, { - time: 25000 - }); - - collector.on("collect", (reaction) => { - const haveVoted = reaction.count - 1; - if (haveVoted >= mustVote) { - this.client.player.skip(message); - embed.setDescription(message.translate("music/skip:SUCCESS")); - m.edit(embed); - collector.stop(true); - } else { - embed.setDescription(message.translate("music/skip:VOTE_CONTENT", { songName: queue.tracks[0].title, voteCount: haveVoted, requiredCount: mustVote })); - m.edit(embed); - }; - }); - - collector.on("end", (collected, isDone) => { - if (!isDone) return message.error("misc:TIMES_UP"); - }); - - } else { - this.client.player.skip(message); - embed.setDescription(message.translate("music/skip:SUCCESS")); - m.edit(embed); - }; + this.client.player.skip(message); + embed.setDescription(message.translate("music/play:NOW_PLAYING", { songName: queue.songs[1].name })); + m.edit(embed); } }; diff --git a/commands/Music/stop.js b/commands/Music/stop.js index 73bae081..86dc75fb 100644 --- a/commands/Music/stop.js +++ b/commands/Music/stop.js @@ -18,14 +18,12 @@ class Stop extends Command { } async run (message, args, data) { - const queue = await this.client.player.getQueue(message); 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 members = voice.members.filter((m) => !m.user.bot); - const embed = new Discord.MessageEmbed() .setAuthor(message.translate("music/stop:DESCRIPTION")) .setFooter(data.config.embed.footer) @@ -33,52 +31,9 @@ class Stop extends Command { const m = await message.channel.send(embed); - if (args[0] && (args[0] === "force" || args[0] === "f")) { - if (message.member.hasPermission("ADMINISTRATOR") || message.member.hasPermission("MANAGE_MESSAGES")) { - this.client.player.stop(message); - embed.setDescription(message.translate("music/stop:SUCCESS")); - m.edit(embed); - } else message.error("misc:NO_PERMS"); - } else if (members.size > 1) { - m.react("👍"); - - const mustVote = Math.floor(members.size / 2); - - embed.setDescription(message.translate("music/stop:VOTE_CONTENT", { voteCount: 0, requiredCount: mustVote })); - m.edit(embed); - - const filter = (reaction, user) => { - const member = message.guild.members.cache.get(user.id); - const voiceChannel = member.voice.channel; - if (voiceChannel) return voiceChannel.id === voice.id; - }; - - const collector = await m.createReactionCollector(filter, { - time: 25000 - }); - - collector.on("collect", (reaction) => { - const haveVoted = reaction.count - 1; - if (haveVoted >= mustVote) { - this.client.player.stop(message); - embed.setDescription(message.translate("music/stop:SUCCESS")); - m.edit(embed); - collector.stop(true); - } else { - embed.setDescription(message.translate("music/stop:VOTE_CONTENT", { voteCount: haveVoted, requiredCount: mustVote })); - m.edit(embed); - } - }); - - collector.on("end", (collected, isDone) => { - if (!isDone) return message.error("misc:TIMES_UP"); - }); - - } else { - this.client.player.stop(message); - embed.setDescription(message.translate("music/stop:SUCCESS")); - m.edit(embed); - }; + this.client.player.stop(message); + embed.setDescription(message.translate("music/stop:SUCCESS")); + m.edit(embed); } }; diff --git a/languages/en-US/music/back.json b/languages/en-US/music/back.json index e465b37f..186d7c47 100644 --- a/languages/en-US/music/back.json +++ b/languages/en-US/music/back.json @@ -3,6 +3,5 @@ "USAGE": "{{prefix}}back", "EXAMPLES": "{{prefix}}back", "NO_PREV_SONG": "There was no song before this one!", - "VOTE_CONTENT": "Previous song: {{songName}}\nReact with 👍 to play the previous song! {{requiredCount}} more votes are required.", "SUCCESS": "Playing previous song!" } \ No newline at end of file diff --git a/languages/en-US/music/filter.json b/languages/en-US/music/filter.json index 619e1434..945cbb57 100644 --- a/languages/en-US/music/filter.json +++ b/languages/en-US/music/filter.json @@ -4,6 +4,6 @@ "EXAMPLES": "{{prefix}}filter vaporwave", "MISSING_FILTER": "Please specify a valid filter to enable or disable! (or send `{{prefix}}filters` to get the statuses of the filters)", "UNKNOWN_FILTER": "This filter doesn't exist! Send `{{prefix}}filters` to get the list!", - "ADDING_FILTER": "I'm adding the filter to the music, please wait... Note: the shorter the music, the faster it will be.", - "REMOVING_FILTER": "I'm removing the filter to the music, please wait... Note: the shorter the music, the faster it will be." + "ADDING_FILTER": "I'm adding the filter to the music, please wait...", + "REMOVING_FILTER": "I'm removing the filter to the music, please wait..." } \ No newline at end of file diff --git a/languages/en-US/music/jump.json b/languages/en-US/music/jump.json new file mode 100644 index 00000000..473c6733 --- /dev/null +++ b/languages/en-US/music/jump.json @@ -0,0 +1,7 @@ +{ + "DESCRIPTION": "Jump to the given track in the queue", + "USAGE": "{{prefix}}jump [number]", + "EXAMPLES": "{{prefix}}jump 3", + "NO_PREV_SONG": "You can't go back, use `{{prefix}}back`!", + "SUCCESS": "Playing selected track!" +} \ No newline at end of file diff --git a/languages/en-US/music/loop.json b/languages/en-US/music/loop.json index 43e9a074..2367d15e 100644 --- a/languages/en-US/music/loop.json +++ b/languages/en-US/music/loop.json @@ -1,8 +1,9 @@ { - "DESCRIPTION": "Turn on/off loop of queue/single track!", + "DESCRIPTION": "Turn on/off repeat of queue/current track!", "USAGE": "{{prefix}}loop [queue/song]", "EXAMPLES": "{{prefix}}loop queue\n{{prefix}}loop song", "NO_ARG": "Select: `queue` or `song`!", - "QUEUE": "Repeating queue is **{{loop}}**!", - "SONG": "Repeating current track is **{{loop}}**!" + "QUEUE": "Repeat of queue is **enabled**!", + "SONG": "Repeat of current track is **enabled**!", + "DISABLED": "Repeat now **disabled**!" } \ No newline at end of file diff --git a/languages/en-US/music/np.json b/languages/en-US/music/np.json index 75f20670..38cb7fc5 100644 --- a/languages/en-US/music/np.json +++ b/languages/en-US/music/np.json @@ -7,5 +7,5 @@ "T_CHANNEL": "Channel", "T_DURATION": "Duration", "T_DESCRIPTION": "Description", - "NO_DESCRIPTION": "No description..." + "NO_DESCRIPTION": "No description" } \ No newline at end of file diff --git a/languages/en-US/music/play.json b/languages/en-US/music/play.json index 28c9f1a5..ac48e871 100644 --- a/languages/en-US/music/play.json +++ b/languages/en-US/music/play.json @@ -12,10 +12,11 @@ "CANCELLED": "Selection cancelled", "NOT_PLAYING": "No songs are currently playing in this server.", "QUEUE_ENDED": "Queue has ended. No more music to play...", - "ADDED_QUEUE": "{{songName}} has been added to the queue!", - "ADDED_QUEUE_COUNT": "{{songCount}} songs added to the queue!", + "ADDED_QUEUE": "**{{songName}}** has been added to the queue!", + "ADDED_QUEUE_COUNT": "**{{songCount}}** songs added to the queue!", "STOP_DISCONNECTED": "I've just stopped the music as I have been disconnected from the channel.", + "STOP_EMPTY": "I've just stopped the music as everyone disconnected from the channel.", "RESULTS_CANCEL": "Search cancelled!", "LIVE_VIDEO": "Lives are not yet supported!", "ERR_OCCURRED": "An error occurred... Code: `{{error}}`" -} +} \ No newline at end of file diff --git a/languages/en-US/music/skip.json b/languages/en-US/music/skip.json index b7cbd824..7a368095 100644 --- a/languages/en-US/music/skip.json +++ b/languages/en-US/music/skip.json @@ -3,6 +3,5 @@ "USAGE": "{{prefix}}skip", "EXAMPLES": "{{prefix}}skip", "NO_NEXT_SONG": "There's no song after this one!", - "VOTE_CONTENT": "Next song: {{songName}}\nReact with 👍 to skip the music! {{requiredCount}} more votes are required.", "SUCCESS": "Song skipped!" } \ No newline at end of file diff --git a/languages/ru-RU/music/back.json b/languages/ru-RU/music/back.json index 59df716b..37a77dc1 100644 --- a/languages/ru-RU/music/back.json +++ b/languages/ru-RU/music/back.json @@ -3,6 +3,5 @@ "USAGE": "{{prefix}}back", "EXAMPLES": "{{prefix}}back", "NO_PREV_SONG": "Предыдущий трек отсутствует!", - "VOTE_CONTENT": "Предыдущий трек: {{songName}}\nОтреагируйте 👍, чтобы проголосовать за воспроизведение! Необходимо ещё {{requiredCount}} голосов.", "SUCCESS": "Играет предыдущий трек!" } \ No newline at end of file diff --git a/languages/ru-RU/music/filter.json b/languages/ru-RU/music/filter.json index 3c30a122..45cfc0ec 100644 --- a/languages/ru-RU/music/filter.json +++ b/languages/ru-RU/music/filter.json @@ -4,6 +4,6 @@ "EXAMPLES": "{{prefix}}filter vaporwave", "MISSING_FILTER": "Укажите фильтр для его включения или отключения! (или отправьте `{{prefix}}filters`, чтобы увидеть статусы фильтров)", "UNKNOWN_FILTER": "Данный фильтр не существует! Используйте `{{prefix}}filters`, чтобы увидеть список фильтров!", - "ADDING_FILTER": "Добавляю фильтр, пожалуйста подождите... Примечание: чем короче трек, тем быстрее это будет выполнено.", - "REMOVING_FILTER": "Удаляю фильтр, пожалуйста подождите... Примечание: чем короче трек, тем быстрее это будет выполнено." + "ADDING_FILTER": "Добавляю фильтр, пожалуйста подождите...", + "REMOVING_FILTER": "Удаляю фильтр, пожалуйста подождите..." } \ No newline at end of file diff --git a/languages/ru-RU/music/jump.json b/languages/ru-RU/music/jump.json new file mode 100644 index 00000000..b46e2708 --- /dev/null +++ b/languages/ru-RU/music/jump.json @@ -0,0 +1,7 @@ +{ + "DESCRIPTION": "Перейти на данный трек", + "USAGE": "{{prefix}}jump [номер-трека]", + "EXAMPLES": "{{prefix}}jump 3", + "NO_PREV_SONG": "Вы не можете перейти назад, для этого используйте команду `{{prefix}}back`!", + "SUCCESS": "Играет выбранный трек!" +} \ No newline at end of file diff --git a/languages/ru-RU/music/loop.json b/languages/ru-RU/music/loop.json index e85eccd9..76c005ef 100644 --- a/languages/ru-RU/music/loop.json +++ b/languages/ru-RU/music/loop.json @@ -3,8 +3,7 @@ "USAGE": "{{prefix}}loop [queue/song]", "EXAMPLES": "{{prefix}}loop queue\n{{prefix}}loop song", "NO_ARG": "Выберите: `queue` или `song`!", - "QUEUE_SUCCESS_ENABLED": "{{success}} Повтор очереди включён!", - "QUEUE_SUCCESS_DISABLED": "{{success}} Повтор очереди отключён!", - "SONG_SUCCESS_ENABLED" : "{{success}} Повтор текущего трека включён!", - "SONG_SUCCESS_DISABLED" : "{{success}} Повтор текущего трека отключён!" + "QUEUE": "Повтор очереди **включён**!", + "SONG": "Повтор текущего трека **включён**!", + "DISABLED": "Повтор **отключён**!" } \ No newline at end of file diff --git a/languages/ru-RU/music/np.json b/languages/ru-RU/music/np.json index 087a52a3..856f4363 100644 --- a/languages/ru-RU/music/np.json +++ b/languages/ru-RU/music/np.json @@ -7,5 +7,5 @@ "T_CHANNEL": "Канал", "T_DURATION": "Длительность", "T_DESCRIPTION": "Описание", - "NO_DESCRIPTION": "Нет описание..." + "NO_DESCRIPTION": "Описание отсутствует" } \ No newline at end of file diff --git a/languages/ru-RU/music/play.json b/languages/ru-RU/music/play.json index 4da155e1..400f285a 100644 --- a/languages/ru-RU/music/play.json +++ b/languages/ru-RU/music/play.json @@ -12,9 +12,10 @@ "CANCELLED": "Выбор отменён", "NOT_PLAYING": "На сервере сейчас ничего не воспроизводится.", "QUEUE_ENDED": "Очередь окончена.", - "ADDED_QUEUE": "{{songName}} добавлен в очередь!", - "ADDED_QUEUE_COUNT": "{{songCount}} трек(а/ов) добавлено в очередь!", + "ADDED_QUEUE": "**{songName}}** добавлен в очередь!", + "ADDED_QUEUE_COUNT": "**{{songCount}}** трек(а/ов) добавлено в очередь!", "STOP_DISCONNECTED": "Воспроизведение окончено, т.к. я вышел из голосового канала.", + "STOP_EMPTY": "Воспроизведение окончено, т.к. все вышли из голосового канала.", "RESULTS_CANCEL": "Поиск отменён!", "LIVE_VIDEO": "Прямые трансляции не поддерживаются!", "ERR_OCCURRED": "Произошла ошибка... Код ошибки: `{{error}}`" diff --git a/languages/ru-RU/music/skip.json b/languages/ru-RU/music/skip.json index e4853f43..8ce5a355 100644 --- a/languages/ru-RU/music/skip.json +++ b/languages/ru-RU/music/skip.json @@ -3,6 +3,5 @@ "USAGE": "{{prefix}}skip", "EXAMPLES": "{{prefix}}skip", "NO_NEXT_SONG": "После текущего трека больше нет треков!", - "VOTE_CONTENT": "Следующий трек: {{songName}}\nОтреагируйте 👍, чтобы проголосовать за пропуск трека! Необходимо ещё {{requiredCount}} голосов.", "SUCCESS": "Трек пропущен!" } \ No newline at end of file diff --git a/package.json b/package.json index eaf725ef..2787db8a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "jaba", - "version": "3.0.5", - "description": "A very complete Discord bot (more than 130 commands) that uses the Discord.js", + "version": "3.0.6", + "description": "A very complete Discord bot (more than 100 commands) that uses the Discord.js", "main": "index.js", "private": true, "scripts": { @@ -13,8 +13,9 @@ "author": "Jonny_Bro", "license": "ISC", "dependencies": { - "@discord-player/extractor": "^3.0.0", "@discordjs/opus": "^0.5.0", + "@distube/soundcloud": "^1.0.0", + "@distube/spotify": "^1.0.0", "@k3rn31p4nic/google-translate-api": "github:k3rn31p4nic/google-translate-api", "@sentry/node": "6.3.6", "@sindresorhus/slugify": "^1.1.0", @@ -32,9 +33,9 @@ "discord-canvas": "^1.3.2", "discord-giveaways": "^4.4.3", "discord-paginationembed": "^2.1.0", - "discord-player": "^4.1.4", "discord-together": "^1.3.25", "discord.js": "^12.5.3", + "distube": "^3.0.4", "ejs": "^3.1.3", "express": "^4.17.1", "express-session": "^1.17.0", From a278944a18f9924045f2005c59b16813c65345eb Mon Sep 17 00:00:00 2001 From: JonnyBro Date: Sun, 26 Dec 2021 00:18:58 +0500 Subject: [PATCH 02/10] check if live and uploader name --- commands/Music/np.js | 4 ++-- languages/en-US/music/play.json | 2 +- languages/ru-RU/music/play.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/commands/Music/np.js b/commands/Music/np.js index 1af7f0c1..d737935b 100644 --- a/commands/Music/np.js +++ b/commands/Music/np.js @@ -32,8 +32,8 @@ class Np extends Command { .setAuthor(message.translate("music/queue:TITLE")) .setThumbnail(track.thumbnail) .addField(message.translate("music/np:T_TITLE"), track.name + `\n${track.url}`) - .addField(message.translate("music/np:T_CHANNEL"), track.uploader.name) - .addField(message.translate("music/np:T_DURATION"), message.convertTime(Date.now() + track.duration * 1000, "to", true)) + .addField(message.translate("music/np:T_CHANNEL"), track.uploader.name ? track.uploader.name : "Отсутствует") + .addField(message.translate("music/np:T_DURATION"), track.isLive ? message.translate("music/play:LIVE") : message.convertTime(Date.now() + track.duration * 1000, "to", true)) .setColor(data.config.embed.color) .setFooter(data.config.embed.footer) .setTimestamp(); diff --git a/languages/en-US/music/play.json b/languages/en-US/music/play.json index ac48e871..a6aa5c46 100644 --- a/languages/en-US/music/play.json +++ b/languages/en-US/music/play.json @@ -17,6 +17,6 @@ "STOP_DISCONNECTED": "I've just stopped the music as I have been disconnected from the channel.", "STOP_EMPTY": "I've just stopped the music as everyone disconnected from the channel.", "RESULTS_CANCEL": "Search cancelled!", - "LIVE_VIDEO": "Lives are not yet supported!", + "LIVE": "◉ LIVE", "ERR_OCCURRED": "An error occurred... Code: `{{error}}`" } \ No newline at end of file diff --git a/languages/ru-RU/music/play.json b/languages/ru-RU/music/play.json index 400f285a..29c91140 100644 --- a/languages/ru-RU/music/play.json +++ b/languages/ru-RU/music/play.json @@ -12,11 +12,11 @@ "CANCELLED": "Выбор отменён", "NOT_PLAYING": "На сервере сейчас ничего не воспроизводится.", "QUEUE_ENDED": "Очередь окончена.", - "ADDED_QUEUE": "**{songName}}** добавлен в очередь!", + "ADDED_QUEUE": "**{{songName}}** добавлен в очередь!", "ADDED_QUEUE_COUNT": "**{{songCount}}** трек(а/ов) добавлено в очередь!", "STOP_DISCONNECTED": "Воспроизведение окончено, т.к. я вышел из голосового канала.", "STOP_EMPTY": "Воспроизведение окончено, т.к. все вышли из голосового канала.", "RESULTS_CANCEL": "Поиск отменён!", - "LIVE_VIDEO": "Прямые трансляции не поддерживаются!", + "LIVE": "◉ LIVE", "ERR_OCCURRED": "Произошла ошибка... Код ошибки: `{{error}}`" } \ No newline at end of file From 80f5dcf81be3501d5f75cea3cd70508114869d72 Mon Sep 17 00:00:00 2001 From: JonnyBro Date: Sun, 26 Dec 2021 00:25:39 +0500 Subject: [PATCH 03/10] v3.0.6 --- dashboard/views/docs.ejs | 14 +++++++++++++- languages/en-US/music/filter.json | 2 +- languages/ru-RU/economy/birthdate.json | 4 ++-- languages/ru-RU/music/filter.json | 4 ++-- languages/ru-RU/music/filters.json | 2 +- languages/ru-RU/music/jump.json | 2 +- 6 files changed, 20 insertions(+), 8 deletions(-) diff --git a/dashboard/views/docs.ejs b/dashboard/views/docs.ejs index d8b0004a..fa46e7c6 100644 --- a/dashboard/views/docs.ejs +++ b/dashboard/views/docs.ejs @@ -194,6 +194,18 @@
+									-----------------------------------------------------------------------------------------
+									JaBa v3.0.6
+									-----------------------------------------------------------------------------------------
+									Добавлено
+										- Команда jump - позволяет перейти на заданный трек из очереди.
+
+									Изменения
+										- Система музыки переписана (да, снова).
+										Теперь можно воспроизвести звук практически с любых источников, в том числе видео и MP3 из Discord, Vimeo, прямые ссылки на радио.
+										Список всех возможных источников можно найти тут: https://ytdl-org.github.io/youtube-dl/supportedsites.html
+										Надеюсь теперь будет меньше ошибок...
+
 									-----------------------------------------------------------------------------------------
 									JaBa v3.0.5
 									-----------------------------------------------------------------------------------------
@@ -202,7 +214,7 @@
 										- Команда debug - похожа на set, но доступна только владельцу JaBa.
 										Имеет расширенный функционал и обходит некоторые ограничения.
 										- Новая активность - Puttparty.
-										Доступна через activity puttparty
+										Доступна через activity puttparty.
 
 									Изменения
 										- В команде profile теперь видно необходимое кол-во опыта для следующего уровня.
diff --git a/languages/en-US/music/filter.json b/languages/en-US/music/filter.json
index 945cbb57..6235fca0 100644
--- a/languages/en-US/music/filter.json
+++ b/languages/en-US/music/filter.json
@@ -1,5 +1,5 @@
 {
-	"DESCRIPTION": "Enable or disable a filter!",
+	"DESCRIPTION": "Enable or disable a filter",
 	"USAGE": "{{prefix}}filter [filter]",
 	"EXAMPLES": "{{prefix}}filter vaporwave",
 	"MISSING_FILTER": "Please specify a valid filter to enable or disable! (or send `{{prefix}}filters` to get the statuses of the filters)",
diff --git a/languages/ru-RU/economy/birthdate.json b/languages/ru-RU/economy/birthdate.json
index ac492139..8dafe693 100644
--- a/languages/ru-RU/economy/birthdate.json
+++ b/languages/ru-RU/economy/birthdate.json
@@ -3,8 +3,8 @@
 	"USAGE": "{{prefix}}birthdate [дата]",
 	"EXAMPLES": "{{prefix}}birthdate 01/01/2010",
 	"MISSING_DATE": "Пожалуйста, укажите правильную дату! Например, 20/11/2003",
-	"INVALID_DATE": "Используйте данный фортам: ДД/ММ/ГГГГ. Например, `1 января 2010` будет `01/01/2010`.",
-	"INVALID_DATE_FORMAT": "Используйте данный фортам: ДД/ММ/ГГГГ. Например, `1 января 2010` будет `01/01/2010`.",
+	"INVALID_DATE": "Используйте данный формат: ДД/ММ/ГГГГ. Например, `1 января 2010` будет `01/01/2010`.",
+	"INVALID_DATE_FORMAT": "Используйте данный формат: ДД/ММ/ГГГГ. Например, `1 января 2010` будет `01/01/2010`.",
 	"DATE_TOO_HIGH": "Вы старше 80 лет? :eyes:",
 	"DATE_TOO_LOW": "Хммм... Вы ещё не родились!",
 	"SUCCESS": "Ваш день рождения установлен на {{date}}!"
diff --git a/languages/ru-RU/music/filter.json b/languages/ru-RU/music/filter.json
index 45cfc0ec..ef7f6041 100644
--- a/languages/ru-RU/music/filter.json
+++ b/languages/ru-RU/music/filter.json
@@ -1,9 +1,9 @@
 {
-	"DESCRIPTION": "Включить или отключить фильтр!",
+	"DESCRIPTION": "Включить или отключить фильтр",
 	"USAGE": "{{prefix}}filter [фильтр]",
 	"EXAMPLES": "{{prefix}}filter vaporwave",
 	"MISSING_FILTER": "Укажите фильтр для его включения или отключения! (или отправьте `{{prefix}}filters`, чтобы увидеть статусы фильтров)",
-	"UNKNOWN_FILTER": "Данный фильтр не существует! Используйте `{{prefix}}filters`, чтобы увидеть список фильтров!",
+	"UNKNOWN_FILTER": "Заданный фильтр не существует! Используйте `{{prefix}}filters`, чтобы увидеть список фильтров!",
 	"ADDING_FILTER": "Добавляю фильтр, пожалуйста подождите...",
 	"REMOVING_FILTER": "Удаляю фильтр, пожалуйста подождите..."
 }
\ No newline at end of file
diff --git a/languages/ru-RU/music/filters.json b/languages/ru-RU/music/filters.json
index 7c0c9bff..ae738e73 100644
--- a/languages/ru-RU/music/filters.json
+++ b/languages/ru-RU/music/filters.json
@@ -1,5 +1,5 @@
 {
-	"DESCRIPTION": "Получить список фильтров и их статусов",
+	"DESCRIPTION": "Получить список фильтров и их статусы",
 	"USAGE": "{{prefix}}filters",
 	"EXAMPLES": "{{prefix}}filters",
 	"TITLE": "**Фильтры**",
diff --git a/languages/ru-RU/music/jump.json b/languages/ru-RU/music/jump.json
index b46e2708..0cdbde5d 100644
--- a/languages/ru-RU/music/jump.json
+++ b/languages/ru-RU/music/jump.json
@@ -1,5 +1,5 @@
 {
-	"DESCRIPTION": "Перейти на данный трек",
+	"DESCRIPTION": "Перейти на заданный трек",
 	"USAGE": "{{prefix}}jump [номер-трека]",
 	"EXAMPLES": "{{prefix}}jump 3",
 	"NO_PREV_SONG": "Вы не можете перейти назад, для этого используйте команду `{{prefix}}back`!",

From ad325a0ec13f8f5dd10399c8fd0bf1a95d59917a Mon Sep 17 00:00:00 2001
From: JonnyBro 
Date: Sun, 26 Dec 2021 00:50:15 +0500
Subject: [PATCH 04/10] Live

---
 languages/en-US/music/play.json | 2 +-
 languages/ru-RU/music/play.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/languages/en-US/music/play.json b/languages/en-US/music/play.json
index a6aa5c46..4c5ae62a 100644
--- a/languages/en-US/music/play.json
+++ b/languages/en-US/music/play.json
@@ -17,6 +17,6 @@
 	"STOP_DISCONNECTED": "I've just stopped the music as I have been disconnected from the channel.",
 	"STOP_EMPTY": "I've just stopped the music as everyone disconnected from the channel.",
 	"RESULTS_CANCEL": "Search cancelled!",
-	"LIVE": "◉ LIVE",
+	"LIVE": "Live",
 	"ERR_OCCURRED": "An error occurred... Code: `{{error}}`"
 }
\ No newline at end of file
diff --git a/languages/ru-RU/music/play.json b/languages/ru-RU/music/play.json
index 29c91140..f320b702 100644
--- a/languages/ru-RU/music/play.json
+++ b/languages/ru-RU/music/play.json
@@ -17,6 +17,6 @@
 	"STOP_DISCONNECTED": "Воспроизведение окончено, т.к. я вышел из голосового канала.",
 	"STOP_EMPTY": "Воспроизведение окончено, т.к. все вышли из голосового канала.",
 	"RESULTS_CANCEL": "Поиск отменён!",
-	"LIVE": "◉ LIVE",
+	"LIVE": "Прямая трансляция",
 	"ERR_OCCURRED": "Произошла ошибка... Код ошибки: `{{error}}`"
 }
\ No newline at end of file

From 417b14651c4e6346bf57fa851cf351995066a8d0 Mon Sep 17 00:00:00 2001
From: JonnyBro 
Date: Sun, 26 Dec 2021 00:51:06 +0500
Subject: [PATCH 05/10] update examples

---
 languages/en-US/general/translate.json | 2 +-
 languages/ru-RU/general/translate.json | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/languages/en-US/general/translate.json b/languages/en-US/general/translate.json
index 7514ca76..0923dd3f 100644
--- a/languages/en-US/general/translate.json
+++ b/languages/en-US/general/translate.json
@@ -1,7 +1,7 @@
 {
 	"DESCRIPTION": "Translate your text!",
 	"USAGE": "{{prefix}}translate [language] [message]",
-	"EXAMPLES": "{{prefix}}translate fr How are you ?",
+	"EXAMPLES": "{{prefix}}translate russian How are you ?",
 	"LIST_SENT": "The languages list has just been sent to you by private messages!",
 	"MISSING_LANGUAGE": "Please enter a language! To display the languages list, type `{{prefix}}translate langs-list`!",
 	"INVALID_LANGUAGE": "The language `{{search}}` does not exist! To display the languages list, type `{{prefix}}translate langs-list`!",
diff --git a/languages/ru-RU/general/translate.json b/languages/ru-RU/general/translate.json
index 879fc4fb..54dcf4ce 100644
--- a/languages/ru-RU/general/translate.json
+++ b/languages/ru-RU/general/translate.json
@@ -1,7 +1,7 @@
 {
 	"DESCRIPTION": "Перевести текст!",
 	"USAGE": "{{prefix}}translate [язык] [текс]",
-	"EXAMPLES": "{{prefix}}translate en Как дела?",
+	"EXAMPLES": "{{prefix}}translate english Как дела?",
 	"LIST_SENT": "Список языков отправлен вам в ЛС!",
 	"MISSING_LANGUAGE": "Укажите язык! Чтобы получить список языков, введите `{{prefix}}translate langs-list`!",
 	"INVALID_LANGUAGE": "Язык `{{search}}` не найден! Чтобы получить список языков, введите `{{prefix}}translate langs-list`!",

From 1e903ffc3c3e4c6de3bc05b399b19579401431fe Mon Sep 17 00:00:00 2001
From: JonnyBro 
Date: Sun, 26 Dec 2021 00:56:47 +0500
Subject: [PATCH 06/10] highest role

---
 commands/General/translate.js         | 4 +---
 commands/General/userinfo.js          | 2 +-
 languages/ru-RU/general/userinfo.json | 1 +
 3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/commands/General/translate.js b/commands/General/translate.js
index ab2cb22a..60277232 100644
--- a/commands/General/translate.js
+++ b/commands/General/translate.js
@@ -22,7 +22,7 @@ class Translate extends Command {
 
 	async run (message, args, data) {
 		if (args[0] === "langs-list") {
-			const langsList = "```css\n" + (langs.map((l, i) => `#${i+1} - ${l}`).join("\n")) + "```";
+			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(() => {
@@ -34,8 +34,6 @@ class Translate extends Command {
 		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
diff --git a/commands/General/userinfo.js b/commands/General/userinfo.js
index f1699a9f..d9a97bdf 100644
--- a/commands/General/userinfo.js
+++ b/commands/General/userinfo.js
@@ -57,7 +57,7 @@ class Userinfo extends Command {
 		};
 
 		if (member) {
-			embed.addField(this.client.customEmojis.up + " " + message.translate("common:ROLE"), (member.roles.highest ? member.roles.highest : message.translate("general/userinfo:NO_ROLE")), true)
+			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"), message.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)
diff --git a/languages/ru-RU/general/userinfo.json b/languages/ru-RU/general/userinfo.json
index 4b9c74d8..ef99ba79 100644
--- a/languages/ru-RU/general/userinfo.json
+++ b/languages/ru-RU/general/userinfo.json
@@ -5,6 +5,7 @@
 	"INVALID_USER": "Пользователь с ID `{{search}}` не найден!",
 	"NO_GAME": "Не играет",
 	"NO_ROLE": "Нет роли",
+	"ROLE": "Высшая роль",
 	"NO_NICKNAME": "Нет никнейма",
 	"MORE_ROLES": "и ещё {{count}} роль(и/ей)",
 	"BOT_STATS": "**{{votes}}** голосов ([top.gg](https://top.gg))\n**{{servers}}** серверов\n**{{shards}}** шардов\nИспользует **{{lib}}**"

From b908016f3bf52374a4afd87b0911ab08901203dd Mon Sep 17 00:00:00 2001
From: JonnyBro 
Date: Sun, 26 Dec 2021 01:11:00 +0500
Subject: [PATCH 07/10] update again

---
 languages/ru-RU/common.json | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/languages/ru-RU/common.json b/languages/ru-RU/common.json
index 945a49c4..c7d0d75a 100644
--- a/languages/ru-RU/common.json
+++ b/languages/ru-RU/common.json
@@ -8,7 +8,7 @@
 	"CONTENT": "Содержимое",
 	"REASON": "Причина",
 	"USER": "Пользователь",
-	"CREATION": "Создание",
+	"CREATION": "Аккаунт создан",
 	"MEMBERS": "Участники",
 	"CHANNELS": "Каналы",
 	"ID": "ID",
@@ -18,7 +18,7 @@
 	"STATS": "Статистика",
 	"ROBOT": "Бот",
 	"AVATAR": "Аватар",
-	"GAME": "Игра",
+	"GAME": "Активность",
 	"STATUS": "Статус",
 	"STATUS_ONLINE": "Онлайн",
 	"STATUS_OFFLINE": "Оффлайн",
@@ -26,7 +26,7 @@
 	"STATUS_DND": "Не беспокоить",
 	"ROLE": "Роль",
 	"ROLES": "Роли",
-	"JOIN": "Присоедениться",
+	"JOIN": "Присоеденился",
 	"COLOR": "Цвет",
 	"NICKNAME": "Ник",
 	"DESCRIPTION": "Описание",

From 2151751e1b74f0b245119c00c0e209052e236f41 Mon Sep 17 00:00:00 2001
From: JonnyBro 
Date: Sun, 26 Dec 2021 02:51:35 +0500
Subject: [PATCH 08/10] alias for loop

---
 commands/Music/loop.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/commands/Music/loop.js b/commands/Music/loop.js
index 1439bd17..234ce986 100644
--- a/commands/Music/loop.js
+++ b/commands/Music/loop.js
@@ -7,7 +7,7 @@ class Loop extends Command {
 			dirname: __dirname,
 			enabled: true,
 			guildOnly: true,
-			aliases: [],
+			aliases: [ "repeat" ],
 			memberPermissions: [],
 			botPermissions: [ "SEND_MESSAGES" ],
 			nsfw: false,

From a45840803b40c0493e15e8e4e4ea75bf39f1cf68 Mon Sep 17 00:00:00 2001
From: JonnyBro 
Date: Sun, 26 Dec 2021 12:52:26 +0500
Subject: [PATCH 09/10] english language for new commands

---
 languages/en-US/administration/set.json | 13 +++++++++++++
 languages/en-US/owner/debug.json        | 15 +++++++++++++++
 2 files changed, 28 insertions(+)
 create mode 100644 languages/en-US/administration/set.json
 create mode 100644 languages/en-US/owner/debug.json

diff --git a/languages/en-US/administration/set.json b/languages/en-US/administration/set.json
new file mode 100644
index 00000000..806c3de6
--- /dev/null
+++ b/languages/en-US/administration/set.json
@@ -0,0 +1,13 @@
+{
+	"DESCRIPTION": "Change user's XP, level, credits or bank!",
+	"USAGE": "{{prefix}}set [level/xp/credits/bank] [@user] [value]",
+	"EXAMPLES": "{{prefix}}set level @Jonny_Bro#4226 10",
+	"INVALID_MEMBER": "You must mention the user!",
+	"NO_STATUS": "Select a parameter: `level`, `xp`, `credits` or `bank`",
+	"BOT_USER": "Bots don't have a profile!",
+	"INVALID_AMOUNT": "Enter a new value!",
+	"SUCCESS_LEVEL": "**{{username}}**'s level was changed to **{{amount}}**!",
+	"SUCCESS_XP": "**{{username}}**'s XP was changed to **{{amount}}**!",
+	"SUCCESS_CREDITS": "**{{username}}**'s credits was changed to **{{amount}}**!",
+	"SUCCESS_BANK": "**{{username}}**'s bank was changed to **{{amount}}**!"
+}
\ No newline at end of file
diff --git a/languages/en-US/owner/debug.json b/languages/en-US/owner/debug.json
new file mode 100644
index 00000000..579d2ebb
--- /dev/null
+++ b/languages/en-US/owner/debug.json
@@ -0,0 +1,15 @@
+{
+	"DESCRIPTION": "Allows to change user data!",
+	"USAGE": "{{prefix}}debug [set/add] [level/xp/credits/bank/rep] [@user] [value]",
+	"EXAMPLES": "{{prefix}}debug set level @Jonny_Bro#4226 10000",
+	"INVALID_MEMBER": "You must mention the user!",
+	"NO_ACTION": "Select an option: `set` or `add`!",
+	"NO_STATUS": "Select a parameter: `level`, `xp`, `credits`, `rep` или `bank`!",
+	"BOT_USER": "Bots don't have a profile!",
+	"INVALID_AMOUNT": "Enter a new value!",
+	"SUCCESS_LEVEL": "**{{username}}**'s level was changed to **{{amount}}**!",
+	"SUCCESS_XP": "**{{username}}**'s XP was changed to **{{amount}}**!",
+	"SUCCESS_CREDITS": "**{{username}}**'s credits was changed to **{{amount}}**!",
+	"SUCCESS_BANK": "**{{username}}**'s bank was changed to **{{amount}}**!",
+	"SUCCESS_REP": "*{{username}}**'s reputation points was changed to **{{amount}}**!"
+}
\ No newline at end of file

From 9fe12594cbb85ca3a28d3efd246353b797e0f620 Mon Sep 17 00:00:00 2001
From: JonnyBro 
Date: Sun, 26 Dec 2021 12:57:03 +0500
Subject: [PATCH 10/10] fix error

---
 commands/Music/play.js | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/commands/Music/play.js b/commands/Music/play.js
index b644c657..b315454e 100644
--- a/commands/Music/play.js
+++ b/commands/Music/play.js
@@ -27,7 +27,12 @@ class Play extends Command {
 		const perms = voice.permissionsFor(this.client.user);
 		if (!perms.has("CONNECT") || !perms.has("SPEAK")) return message.error("music/play:VOICE_CHANNEL_CONNECT");
 
-		await this.client.player.play(message, args.join(" "));
+		try {
+			await this.client.player.play(message, args.join(" "));
+		} catch (e) {
+			message.error("music/play:ERR_OCCURRED", { error: e });
+			console.error(e);
+		}
 	}
 };