new music system

This commit is contained in:
JonnyBro 2021-12-26 00:04:26 +05:00
parent 6f4e6db94b
commit 5565f7e86a
32 changed files with 172 additions and 342 deletions

View file

@ -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"
}

View file

@ -1,8 +0,0 @@
[
{
"name": "",
"description_french": "",
"description_english": "",
"link": ""
}
]

View file

@ -1,11 +1,13 @@
const { MessageEmbed, Util, Client, Collection } = require("discord.js"), const { MessageEmbed, Util, Client, Collection } = require("discord.js"),
{ GiveawaysManager } = require("discord-giveaways"), { GiveawaysManager } = require("discord-giveaways"),
{ Player } = require("discord-player"), { SoundCloudPlugin } = require("@distube/soundcloud"),
{ SpotifyPlugin } = require("@distube/spotify"),
{ Client: Joker } = require("blague.xyz"); { Client: Joker } = require("blague.xyz");
const util = require("util"), const util = require("util"),
AmeClient = require("amethyste-api"), AmeClient = require("amethyste-api"),
path = require("path"), path = require("path"),
DisTube = require("distube"),
moment = require("moment"); moment = require("moment");
moment.relativeTimeThreshold("s", 60); 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.amethyste) this.AmeAPI = new AmeClient(this.config.apiKeys.amethyste);
if (this.config.apiKeys.blagueXYZ) this.joker = new Joker(this.config.apiKeys.blagueXYZ, { defaultLanguage: "en" }); if (this.config.apiKeys.blagueXYZ) this.joker = new Joker(this.config.apiKeys.blagueXYZ, { defaultLanguage: "en" });
this.player = new Player(this, { this.player = new DisTube.default(this, {
ytdlDownloadOptions: { searchSongs: 10,
filter: "audio", searchCooldown: 30,
requestOptions: { leaveOnEmpty: true,
headers: { emptyCooldown: 0,
cookie: this.config.youtubeToken, leaveOnFinish: true,
quality: "highestaudio", leaveOnStop: true,
highWaterMark: 1 << 25 nsfw: true,
} plugins: [ new SoundCloudPlugin(), new SpotifyPlugin() ],
}
},
leaveOnEmpty: false,
enableLive: true
}); });
this.player this.player
.on("trackStart", (message, track) => { .on("playSong", (queue, song) => queue.textChannel.send(this.translate("music/play:NOW_PLAYING", { songName: song.name })))
message.success("music/play:NOW_PLAYING", { songName: track.title }); .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("playlistStart", (message, queue, playlist, track) => { .on("searchResult", (message, result) => {
message.channel.send(`${this.customEmojis.success} ${message.translate("music/play:PLAYING_PLAYLIST", { playlistTitle: playlist.title, playlistEmoji: this.customEmojis.playlist, songName: track.title })}`); let i = 0
})
.on("searchResults", (message, query, tracks) => {
if (tracks.length > 10) tracks = tracks.slice(0, 10);
const embed = new MessageEmbed() const embed = new MessageEmbed()
.setDescription(Util.escapeSpoiler(tracks.map((t, i) => `**${++i} -** ${t.title}`).join("\n"))) .setDescription(Util.escapeSpoiler(result.map(song => `**${++i} -** ${song.name}`).join("\n")))
.setFooter(message.translate("music/play:RESULTS_FOOTER")) .setFooter(this.translate("music/play:RESULTS_FOOTER"))
.setColor(this.config.embed.color); .setColor(this.config.embed.color);
message.channel.send(embed); message.channel.send(embed);
}) })
.on("searchInvalidResponse", (message, query, tracks, content, collector) => { .on("searchDone", () => {})
if (content === "cancel") { .on("searchCancel", message => message.error("misc:TIMES_UP"))
.on("searchInvalidAnswer", message => {
if (message.content === "cancel") {
collector.stop(); collector.stop();
return message.success("music/play:RESULTS_CANCEL"); return message.success("music/play:RESULTS_CANCEL");
}; };
message.error("misc:INVALID_NUMBER_RANGE", { min: 1, max: tracks.length }); message.error("misc:INVALID_NUMBER_RANGE", { min: 1, max: tracks.length });
}) })
.on("searchCancel", (message) => { .on("searchNoResult", message => message.error("music/play:NO_RESULT"))
message.error("misc:TIMES_UP"); .on("error", (textChannel, e) => {
console.error(e);
textChannel.send(this.translate("music/play:ERR_OCCURRED", { error: e.slice(0, 1900)}));
}) })
.on("botDisconnect", (message) => { .on("finish", queue => queue.textChannel.send(this.translate("music/play:QUEUE_ENDED")))
message.error("music/play:STOP_DISCONNECTED"); .on("disconnect", queue => queue.textChannel.send(this.translate("music/play:STOP_DISCONNECTED")))
}) .on("empty", queue => queue.textChannel.send(this.translate("music/play:STOP_EMPTY")));
.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;
};
});
this.giveawaysManager = new GiveawaysManager(this, { this.giveawaysManager = new GiveawaysManager(this, {
storage: "./giveaways.json", storage: "./giveaways.json",
@ -146,7 +104,7 @@ class JaBa extends Client {
}; };
get defaultLanguage() { get defaultLanguage() {
return this.languages.find((language) => language.default).name; return this.languages.find(language => language.default).name;
}; };
translate(key, args, locale) { translate(key, args, locale) {

View file

@ -17,17 +17,15 @@ class AutoPlay extends Command {
} }
async run (message) { async run (message) {
const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel; const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message);
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
// Gets the current song const autoplay = queue.toggleAutoplay()
await this.client.player.setAutoPlay(message, !queue.autoPlay);
// Send the embed in the current channel message.success(`music/autoplay:SUCCESS_${autoplay ? "ENABLED" : "DISABLED"}`);
message.success(`music/autoplay:SUCCESS_${queue.autoPlay ? "ENABLED" : "DISABLED"}`);
} }
}; };

View file

@ -18,14 +18,12 @@ class Back extends Command {
} }
async run (message, args, data) { async run (message, args, data) {
const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel; const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message);
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
if (!queue.previousTracks[0]) return message.error("music/back:NO_PREV_SONG"); if (!queue.previousSongs[0]) return message.error("music/back:NO_PREV_SONG");
const members = voice.members.filter((m) => !m.user.bot);
const embed = new Discord.MessageEmbed() const embed = new Discord.MessageEmbed()
.setAuthor(message.translate("music/back:DESCRIPTION")) .setAuthor(message.translate("music/back:DESCRIPTION"))
@ -35,51 +33,9 @@ class Back extends Command {
const m = await message.channel.send(embed); const m = await message.channel.send(embed);
if (args[0] && (args[0] === "force" || args[0] === "f")) { this.client.player.previous(message);
if (message.member.hasPermission("ADMINISTRATOR") || message.member.hasPermission("MANAGE_MESSAGES")) { embed.setDescription(message.translate("music/back:SUCCESS"));
this.client.player.back(message); m.edit(embed);
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);
};
} }
}; };

View file

@ -20,17 +20,18 @@ class Clip extends Command {
async run (message, args) { async run (message, args) {
const voice = message.member.voice.channel; const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message); 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 (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (queue) return message.error("music/clip:ACTIVE_QUEUE"); 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 { try {
const connection = await voice.join(); const connection = await voice.join();
await connection.voice.setSelfDeaf(true); await connection.voice.setSelfDeaf(true);
connection.play(`./clips/${args[0]}.mp3`) connection.play(`./clips/${clip}.mp3`)
.on("finish", () => { .on("finish", () => {
voice.leave(); voice.leave();
}) })

View file

@ -1,5 +1,4 @@
const Command = require("../../base/Command.js"), const Command = require("../../base/Command.js")
FiltersList = require("../../assets/json/filters.json");
class Filter extends Command { class Filter extends Command {
constructor (client) { constructor (client) {
@ -18,27 +17,22 @@ class Filter extends Command {
} }
async run (message, args, data) { async run (message, args, data) {
const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message); const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel;
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
const filter = args[0]; const filter = args[0];
if (!filter) return message.error("music/filter:MISSING_FILTER", { prefix: data.guild.prefix }); 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 (filter === "off" && queue.filters?.length) {
queue.setFilter(false);
if (!filterToUpdate) return message.error("music/filter:UNKNOWN_FILTER", { prefix: data.guild.prefix }); message.success("music/filter:REMOVING_FILTER");
} else if (Object.keys(this.client.player.filters).includes(args[0])) {
const filterRealName = Object.keys(FiltersList).find((f) => FiltersList[f] === filterToUpdate); queue.setFilter(args[0]);
const queueFilters = this.client.player.getQueue(message).filters; message.success("music/filter:ADDING_FILTER");
const filtersUpdated = {}; } else if (args[0]) return message.error("music/filter:UNKNOWN_FILTER", { prefix: data.guild.prefix });
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");
} }
}; };

View file

@ -1,6 +1,5 @@
const Command = require("../../base/Command.js"), const Command = require("../../base/Command.js"),
Discord = require("discord.js"), Discord = require("discord.js");
FiltersList = require("../../assets/json/filters.json");
class Filters extends Command { class Filters extends Command {
constructor (client) { constructor (client) {
@ -19,17 +18,17 @@ class Filters extends Command {
} }
async run (message, args, data) { async run (message, args, data) {
const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel; const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message);
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
const filtersStatuses = [ [], [] ]; 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]; 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() const list = new Discord.MessageEmbed()

43
commands/Music/jump.js Normal file
View file

@ -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;

View file

@ -12,7 +12,7 @@ class Loop extends Command {
botPermissions: [ "SEND_MESSAGES" ], botPermissions: [ "SEND_MESSAGES" ],
nsfw: false, nsfw: false,
ownerOnly: false, ownerOnly: false,
cooldown: 3000 cooldown: 1000
}); });
} }
@ -20,21 +20,12 @@ class Loop extends Command {
const voice = message.member.voice.channel; const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message); 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 (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
if (args[0].toLowerCase() === "queue") { const mode = this.client.player.setRepeatMode(message);
if (queue.repeatMode) this.client.player.setRepeatMode(message, false);
this.client.player.setLoopMode(message, !queue.loopMode); message.success(`music/loop:${mode ? mode === 2 ? "QUEUE" : "SONG" : "DISABLED"}`)
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"}`);
};
} }
}; };

View file

@ -18,28 +18,25 @@ class Np extends Command {
} }
async run (message, args, data) { async run (message, args, data) {
const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message); const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel;
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
// Gets the current song // Gets the current song
const track = await this.client.player.nowPlaying(message); const track = queue.songs[0];
// Generate discord embed to display song informations // Generate discord embed to display song informations
const embed = new Discord.MessageEmbed() const embed = new Discord.MessageEmbed()
.setAuthor(message.translate("music/np:CURRENTLY_PLAYING")) .setAuthor(message.translate("music/queue:TITLE"))
.setThumbnail(track.thumbnail) .setThumbnail(track.thumbnail)
.addField(message.translate("music/np:T_TITLE"), track.title, true) .addField(message.translate("music/np:T_TITLE"), track.name + `\n${track.url}`)
.addField(message.translate("music/np:T_CHANNEL"), track.author, true) .addField(message.translate("music/np:T_CHANNEL"), track.uploader.name)
.addField(message.translate("music/np:T_DURATION"), message.convertTime(Date.now()+track.durationMS, "to", true), true) .addField(message.translate("music/np:T_DURATION"), message.convertTime(Date.now() + track.duration * 1000, "to", 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()
.setColor(data.config.embed.color) .setColor(data.config.embed.color)
.setFooter(data.config.embed.footer); .setFooter(data.config.embed.footer)
.setTimestamp();
// Send the embed in the current channel // Send the embed in the current channel
message.channel.send(embed); message.channel.send(embed);

View file

@ -17,16 +17,14 @@ class Pause extends Command {
} }
async run (message) { async run (message) {
const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message); const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel;
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music:play:NOT_PLAYING"); if (!queue) return message.error("music:play:NOT_PLAYING");
// Gets the current song
await this.client.player.pause(message); await this.client.player.pause(message);
// Send the embed in the current channel
message.sendT("music/pause:SUCCESS"); message.sendT("music/pause:SUCCESS");
} }
}; };

View file

@ -20,19 +20,19 @@ class Queue extends Command {
async run (message, args, data) { async run (message, args, data) {
const voice = message.member.voice.channel; const voice = message.member.voice.channel;
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
const queue = this.client.player.getQueue(message); 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) return message.error("music/play:NOT_PLAYING");
if (queue.tracks.length === 1) { if (queue.songs.length === 1) {
const embed = new Discord.MessageEmbed() const embed = new Discord.MessageEmbed()
.setColor(data.config.embed.color)
.setAuthor(message.translate("music/queue:TITLE"), message.guild.iconURL({ dynamic: true })) .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); return message.channel.send(embed);
}; };
let i = 0; let i = 0;
const FieldsEmbed = new Pagination.FieldsEmbed(); const FieldsEmbed = new Pagination.FieldsEmbed();
@ -40,14 +40,14 @@ class Queue extends Command {
FieldsEmbed.embed FieldsEmbed.embed
.setColor(data.config.embed.color) .setColor(data.config.embed.color)
.setAuthor(message.translate("music/queue:TITLE"), message.guild.iconURL({ dynamic: true })) .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]) .setAuthorizedUsers([message.author.id])
.setChannel(message.channel) .setChannel(message.channel)
.setElementsPerPage(5) .setElementsPerPage(5)
.setPageIndicator(true) .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(); FieldsEmbed.build();
} }

View file

@ -17,16 +17,14 @@ class Resume extends Command {
} }
async run (message) { async run (message) {
const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message); const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel;
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music:play:NOT_PLAYING"); if (!queue) return message.error("music:play:NOT_PLAYING");
// Gets the current song
await this.client.player.resume(message); await this.client.player.resume(message);
// Send the embed in the current channel
message.sendT("music/resume:SUCCESS"); message.sendT("music/resume:SUCCESS");
} }
}; };

View file

@ -18,20 +18,17 @@ class Seek extends Command {
} }
async run (message, args) { async run (message, args) {
const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message); const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel;
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
const time = ms(args[0]); const time = ms(args[0]);
if (isNaN(time)) return message.error("music/seek:INVALID_TIME"); if (isNaN(time)) return message.error("music/seek:INVALID_TIME");
// Change the song position await this.client.player.seek(message, time);
await this.client.player.setPosition(message, queue.currentStreamTime + time);
// Send the embed in the current channel
message.sendT("music/seek:SUCCESS"); message.sendT("music/seek:SUCCESS");
} }
}; };

View file

@ -18,69 +18,24 @@ class Skip extends Command {
} }
async run (message, args, data) { async run (message, args, data) {
const queue = this.client.player.getQueue(message);
const voice = message.member.voice.channel; const voice = message.member.voice.channel;
const queue = this.client.player.getQueue(message);
if (!voice) return message.error("music/play:NO_VOICE_CHANNEL"); if (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
if (!queue.tracks[0]) return message.error("music/skip:NO_NEXT_SONG"); if (!queue.songs[1]) return message.error("music/skip:NO_NEXT_SONG");
const members = voice.members.filter((m) => !m.user.bot);
const embed = new Discord.MessageEmbed() const embed = new Discord.MessageEmbed()
.setAuthor(message.translate("music/skip:DESCRIPTION")) .setAuthor(message.translate("music/skip:SUCCESS"))
.setThumbnail(queue.tracks[0].thumbnail) .setThumbnail(queue.songs[1].thumbnail)
.setFooter(data.config.embed.footer) .setFooter(data.config.embed.footer)
.setColor(data.config.embed.color); .setColor(data.config.embed.color);
const m = await message.channel.send(embed); const m = await message.channel.send(embed);
if (args[0] && (args[0] === "force" || args[0] === "f")) { this.client.player.skip(message);
if (message.member.hasPermission("ADMINISTRATOR") || message.member.hasPermission("MANAGE_MESSAGES")) { embed.setDescription(message.translate("music/play:NOW_PLAYING", { songName: queue.songs[1].name }));
this.client.player.skip(message); m.edit(embed);
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);
};
} }
}; };

View file

@ -18,14 +18,12 @@ class Stop extends Command {
} }
async run (message, args, data) { async run (message, args, data) {
const queue = await this.client.player.getQueue(message);
const voice = message.member.voice.channel; 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 (!voice) return message.error("music/play:NO_VOICE_CHANNEL");
if (!queue) return message.error("music/play:NOT_PLAYING"); if (!queue) return message.error("music/play:NOT_PLAYING");
const members = voice.members.filter((m) => !m.user.bot);
const embed = new Discord.MessageEmbed() const embed = new Discord.MessageEmbed()
.setAuthor(message.translate("music/stop:DESCRIPTION")) .setAuthor(message.translate("music/stop:DESCRIPTION"))
.setFooter(data.config.embed.footer) .setFooter(data.config.embed.footer)
@ -33,52 +31,9 @@ class Stop extends Command {
const m = await message.channel.send(embed); const m = await message.channel.send(embed);
if (args[0] && (args[0] === "force" || args[0] === "f")) { this.client.player.stop(message);
if (message.member.hasPermission("ADMINISTRATOR") || message.member.hasPermission("MANAGE_MESSAGES")) { embed.setDescription(message.translate("music/stop:SUCCESS"));
this.client.player.stop(message); m.edit(embed);
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);
};
} }
}; };

View file

@ -3,6 +3,5 @@
"USAGE": "{{prefix}}back", "USAGE": "{{prefix}}back",
"EXAMPLES": "{{prefix}}back", "EXAMPLES": "{{prefix}}back",
"NO_PREV_SONG": "There was no song before this one!", "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!" "SUCCESS": "Playing previous song!"
} }

View file

@ -4,6 +4,6 @@
"EXAMPLES": "{{prefix}}filter vaporwave", "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)", "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!", "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.", "ADDING_FILTER": "I'm adding the filter to the music, please wait...",
"REMOVING_FILTER": "I'm removing 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..."
} }

View file

@ -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!"
}

View file

@ -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]", "USAGE": "{{prefix}}loop [queue/song]",
"EXAMPLES": "{{prefix}}loop queue\n{{prefix}}loop song", "EXAMPLES": "{{prefix}}loop queue\n{{prefix}}loop song",
"NO_ARG": "Select: `queue` or `song`!", "NO_ARG": "Select: `queue` or `song`!",
"QUEUE": "Repeating queue is **{{loop}}**!", "QUEUE": "Repeat of queue is **enabled**!",
"SONG": "Repeating current track is **{{loop}}**!" "SONG": "Repeat of current track is **enabled**!",
"DISABLED": "Repeat now **disabled**!"
} }

View file

@ -7,5 +7,5 @@
"T_CHANNEL": "Channel", "T_CHANNEL": "Channel",
"T_DURATION": "Duration", "T_DURATION": "Duration",
"T_DESCRIPTION": "Description", "T_DESCRIPTION": "Description",
"NO_DESCRIPTION": "No description..." "NO_DESCRIPTION": "No description"
} }

View file

@ -12,9 +12,10 @@
"CANCELLED": "Selection cancelled", "CANCELLED": "Selection cancelled",
"NOT_PLAYING": "No songs are currently playing in this server.", "NOT_PLAYING": "No songs are currently playing in this server.",
"QUEUE_ENDED": "Queue has ended. No more music to play...", "QUEUE_ENDED": "Queue has ended. No more music to play...",
"ADDED_QUEUE": "{{songName}} has been added to the queue!", "ADDED_QUEUE": "**{{songName}}** has been added to the queue!",
"ADDED_QUEUE_COUNT": "{{songCount}} songs 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_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!", "RESULTS_CANCEL": "Search cancelled!",
"LIVE_VIDEO": "Lives are not yet supported!", "LIVE_VIDEO": "Lives are not yet supported!",
"ERR_OCCURRED": "An error occurred... Code: `{{error}}`" "ERR_OCCURRED": "An error occurred... Code: `{{error}}`"

View file

@ -3,6 +3,5 @@
"USAGE": "{{prefix}}skip", "USAGE": "{{prefix}}skip",
"EXAMPLES": "{{prefix}}skip", "EXAMPLES": "{{prefix}}skip",
"NO_NEXT_SONG": "There's no song after this one!", "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!" "SUCCESS": "Song skipped!"
} }

View file

@ -3,6 +3,5 @@
"USAGE": "{{prefix}}back", "USAGE": "{{prefix}}back",
"EXAMPLES": "{{prefix}}back", "EXAMPLES": "{{prefix}}back",
"NO_PREV_SONG": "Предыдущий трек отсутствует!", "NO_PREV_SONG": "Предыдущий трек отсутствует!",
"VOTE_CONTENT": "Предыдущий трек: {{songName}}\nОтреагируйте 👍, чтобы проголосовать за воспроизведение! Необходимо ещё {{requiredCount}} голосов.",
"SUCCESS": "Играет предыдущий трек!" "SUCCESS": "Играет предыдущий трек!"
} }

View file

@ -4,6 +4,6 @@
"EXAMPLES": "{{prefix}}filter vaporwave", "EXAMPLES": "{{prefix}}filter vaporwave",
"MISSING_FILTER": "Укажите фильтр для его включения или отключения! (или отправьте `{{prefix}}filters`, чтобы увидеть статусы фильтров)", "MISSING_FILTER": "Укажите фильтр для его включения или отключения! (или отправьте `{{prefix}}filters`, чтобы увидеть статусы фильтров)",
"UNKNOWN_FILTER": "Данный фильтр не существует! Используйте `{{prefix}}filters`, чтобы увидеть список фильтров!", "UNKNOWN_FILTER": "Данный фильтр не существует! Используйте `{{prefix}}filters`, чтобы увидеть список фильтров!",
"ADDING_FILTER": "Добавляю фильтр, пожалуйста подождите... Примечание: чем короче трек, тем быстрее это будет выполнено.", "ADDING_FILTER": "Добавляю фильтр, пожалуйста подождите...",
"REMOVING_FILTER": "Удаляю фильтр, пожалуйста подождите... Примечание: чем короче трек, тем быстрее это будет выполнено." "REMOVING_FILTER": "Удаляю фильтр, пожалуйста подождите..."
} }

View file

@ -0,0 +1,7 @@
{
"DESCRIPTION": "Перейти на данный трек",
"USAGE": "{{prefix}}jump [номер-трека]",
"EXAMPLES": "{{prefix}}jump 3",
"NO_PREV_SONG": "Вы не можете перейти назад, для этого используйте команду `{{prefix}}back`!",
"SUCCESS": "Играет выбранный трек!"
}

View file

@ -3,8 +3,7 @@
"USAGE": "{{prefix}}loop [queue/song]", "USAGE": "{{prefix}}loop [queue/song]",
"EXAMPLES": "{{prefix}}loop queue\n{{prefix}}loop song", "EXAMPLES": "{{prefix}}loop queue\n{{prefix}}loop song",
"NO_ARG": "Выберите: `queue` или `song`!", "NO_ARG": "Выберите: `queue` или `song`!",
"QUEUE_SUCCESS_ENABLED": "{{success}} Повтор очереди включён!", "QUEUE": "Повтор очереди **включён**!",
"QUEUE_SUCCESS_DISABLED": "{{success}} Повтор очереди отключён!", "SONG": "Повтор текущего трека **включён**!",
"SONG_SUCCESS_ENABLED" : "{{success}} Повтор текущего трека включён!", "DISABLED": "Повтор **отключён**!"
"SONG_SUCCESS_DISABLED" : "{{success}} Повтор текущего трека отключён!"
} }

View file

@ -7,5 +7,5 @@
"T_CHANNEL": "Канал", "T_CHANNEL": "Канал",
"T_DURATION": "Длительность", "T_DURATION": "Длительность",
"T_DESCRIPTION": "Описание", "T_DESCRIPTION": "Описание",
"NO_DESCRIPTION": "Нет описание..." "NO_DESCRIPTION": "Описание отсутствует"
} }

View file

@ -12,9 +12,10 @@
"CANCELLED": "Выбор отменён", "CANCELLED": "Выбор отменён",
"NOT_PLAYING": "На сервере сейчас ничего не воспроизводится.", "NOT_PLAYING": "На сервере сейчас ничего не воспроизводится.",
"QUEUE_ENDED": "Очередь окончена.", "QUEUE_ENDED": "Очередь окончена.",
"ADDED_QUEUE": "{{songName}} добавлен в очередь!", "ADDED_QUEUE": "**{songName}}** добавлен в очередь!",
"ADDED_QUEUE_COUNT": "{{songCount}} трек(а/ов) добавлено в очередь!", "ADDED_QUEUE_COUNT": "**{{songCount}}** трек(а/ов) добавлено в очередь!",
"STOP_DISCONNECTED": "Воспроизведение окончено, т.к. я вышел из голосового канала.", "STOP_DISCONNECTED": "Воспроизведение окончено, т.к. я вышел из голосового канала.",
"STOP_EMPTY": "Воспроизведение окончено, т.к. все вышли из голосового канала.",
"RESULTS_CANCEL": "Поиск отменён!", "RESULTS_CANCEL": "Поиск отменён!",
"LIVE_VIDEO": "Прямые трансляции не поддерживаются!", "LIVE_VIDEO": "Прямые трансляции не поддерживаются!",
"ERR_OCCURRED": "Произошла ошибка... Код ошибки: `{{error}}`" "ERR_OCCURRED": "Произошла ошибка... Код ошибки: `{{error}}`"

View file

@ -3,6 +3,5 @@
"USAGE": "{{prefix}}skip", "USAGE": "{{prefix}}skip",
"EXAMPLES": "{{prefix}}skip", "EXAMPLES": "{{prefix}}skip",
"NO_NEXT_SONG": "После текущего трека больше нет треков!", "NO_NEXT_SONG": "После текущего трека больше нет треков!",
"VOTE_CONTENT": "Следующий трек: {{songName}}\nОтреагируйте 👍, чтобы проголосовать за пропуск трека! Необходимо ещё {{requiredCount}} голосов.",
"SUCCESS": "Трек пропущен!" "SUCCESS": "Трек пропущен!"
} }

View file

@ -1,7 +1,7 @@
{ {
"name": "jaba", "name": "jaba",
"version": "3.0.5", "version": "3.0.6",
"description": "A very complete Discord bot (more than 130 commands) that uses the Discord.js", "description": "A very complete Discord bot (more than 100 commands) that uses the Discord.js",
"main": "index.js", "main": "index.js",
"private": true, "private": true,
"scripts": { "scripts": {
@ -13,8 +13,9 @@
"author": "Jonny_Bro", "author": "Jonny_Bro",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@discord-player/extractor": "^3.0.0",
"@discordjs/opus": "^0.5.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", "@k3rn31p4nic/google-translate-api": "github:k3rn31p4nic/google-translate-api",
"@sentry/node": "6.3.6", "@sentry/node": "6.3.6",
"@sindresorhus/slugify": "^1.1.0", "@sindresorhus/slugify": "^1.1.0",
@ -32,9 +33,9 @@
"discord-canvas": "^1.3.2", "discord-canvas": "^1.3.2",
"discord-giveaways": "^4.4.3", "discord-giveaways": "^4.4.3",
"discord-paginationembed": "^2.1.0", "discord-paginationembed": "^2.1.0",
"discord-player": "^4.1.4",
"discord-together": "^1.3.25", "discord-together": "^1.3.25",
"discord.js": "^12.5.3", "discord.js": "^12.5.3",
"distube": "^3.0.4",
"ejs": "^3.1.3", "ejs": "^3.1.3",
"express": "^4.17.1", "express": "^4.17.1",
"express-session": "^1.17.0", "express-session": "^1.17.0",