mirror of
https://github.com/JonnyBro/JaBa.git
synced 2025-04-02 12:10:47 +05:00
Main music functionality done
This commit is contained in:
parent
b15aad7d6b
commit
43eff65314
23 changed files with 190 additions and 242 deletions
|
@ -1,41 +0,0 @@
|
||||||
const { SlashCommandBuilder } = require("discord.js");
|
|
||||||
const BaseCommand = require("../../base/BaseCommand");
|
|
||||||
|
|
||||||
class Skip extends BaseCommand {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../base/Client")} client
|
|
||||||
*/
|
|
||||||
constructor(client) {
|
|
||||||
super({
|
|
||||||
command: new SlashCommandBuilder()
|
|
||||||
.setName("skip")
|
|
||||||
.setDescription(client.translate("music/skip:DESCRIPTION"))
|
|
||||||
.setDescriptionLocalizations({
|
|
||||||
uk: client.translate("music/skip:DESCRIPTION", null, "uk-UA"),
|
|
||||||
ru: client.translate("music/skip:DESCRIPTION", null, "ru-RU"),
|
|
||||||
})
|
|
||||||
.setDMPermission(false),
|
|
||||||
dirname: __dirname,
|
|
||||||
ownerOnly: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../../base/Client")} client
|
|
||||||
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
|
||||||
*/
|
|
||||||
async execute(client, interaction) {
|
|
||||||
const voice = interaction.member.voice.channel;
|
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL");
|
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING");
|
|
||||||
|
|
||||||
queue.node.skip();
|
|
||||||
interaction.success("music/skip:SUCCESS");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Skip;
|
|
|
@ -1,59 +0,0 @@
|
||||||
const { SlashCommandBuilder } = require("discord.js");
|
|
||||||
const BaseCommand = require("../../base/BaseCommand");
|
|
||||||
|
|
||||||
class Skipto extends BaseCommand {
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../base/Client")} client
|
|
||||||
*/
|
|
||||||
constructor(client) {
|
|
||||||
super({
|
|
||||||
command: new SlashCommandBuilder()
|
|
||||||
.setName("skipto")
|
|
||||||
.setDescription(client.translate("music/skipto:DESCRIPTION"))
|
|
||||||
.setDescriptionLocalizations({
|
|
||||||
uk: client.translate("music/skipto:DESCRIPTION", null, "uk-UA"),
|
|
||||||
ru: client.translate("music/skipto:DESCRIPTION", null, "ru-RU"),
|
|
||||||
})
|
|
||||||
.setDMPermission(false)
|
|
||||||
.addIntegerOption(option =>
|
|
||||||
option
|
|
||||||
.setName("position")
|
|
||||||
.setDescription(client.translate("music/skipto:POSITION"))
|
|
||||||
.setDescriptionLocalizations({
|
|
||||||
uk: client.translate("music/skipto:POSITION", null, "uk-UA"),
|
|
||||||
ru: client.translate("music/skipto:POSITION", null, "ru-RU"),
|
|
||||||
})
|
|
||||||
.setRequired(true),
|
|
||||||
),
|
|
||||||
dirname: __dirname,
|
|
||||||
ownerOnly: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param {import("../../base/Client")} client
|
|
||||||
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
|
||||||
*/
|
|
||||||
async execute(client, interaction) {
|
|
||||||
const voice = interaction.member.voice.channel;
|
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL");
|
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING");
|
|
||||||
|
|
||||||
const position = interaction.options.getInteger("position");
|
|
||||||
if (position <= 0) return interaction.error("music/skipto:NO_PREV_SONG");
|
|
||||||
|
|
||||||
if (queue.tracks.at(position - 1)) {
|
|
||||||
queue.node.skipTo(queue.tracks.at(position - 1));
|
|
||||||
|
|
||||||
interaction.success("music/skipto:SUCCESS", {
|
|
||||||
track: queue.tracks.at(0).title,
|
|
||||||
});
|
|
||||||
} else return interaction.error("music/skipto:ERROR", { position });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Skipto;
|
|
|
@ -153,13 +153,14 @@ class Number extends BaseCommand {
|
||||||
client.on("interactionCreate", async interaction => {
|
client.on("interactionCreate", async interaction => {
|
||||||
if (!interaction.isButton()) return;
|
if (!interaction.isButton()) return;
|
||||||
|
|
||||||
await interaction.deferUpdate();
|
if (interaction.customId.startsWith("number_")) {
|
||||||
|
await interaction.deferUpdate();
|
||||||
|
|
||||||
if (interaction.customId === "number_delete_yes")
|
if (interaction.customId === "number_delete_yes") interaction.channel.delete();
|
||||||
interaction.channel.delete();
|
else if (interaction.customId === "number_delete_no") {
|
||||||
else if (interaction.customId === "number_delete_no") {
|
await interaction.message.delete();
|
||||||
await interaction.message.delete();
|
interaction.channel.setArchived(true);
|
||||||
interaction.channel.setArchived(true);
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
const { SlashCommandBuilder } = require("discord.js"),
|
const { SlashCommandBuilder } = require("discord.js");
|
||||||
{ QueueRepeatMode } = require("discord-player");
|
|
||||||
const BaseCommand = require("../../base/BaseCommand");
|
const BaseCommand = require("../../base/BaseCommand");
|
||||||
|
|
||||||
class Loop extends BaseCommand {
|
class Loop extends BaseCommand {
|
||||||
|
@ -27,10 +26,10 @@ class Loop extends BaseCommand {
|
||||||
})
|
})
|
||||||
.setRequired(true)
|
.setRequired(true)
|
||||||
.setChoices(
|
.setChoices(
|
||||||
{ name: client.translate("music/loop:AUTOPLAY"), value: "3" },
|
// { name: client.translate("music/loop:AUTOPLAY"), value: "3" },
|
||||||
{ name: client.translate("music/loop:QUEUE"), value: "2" },
|
{ name: client.translate("music/loop:QUEUE"), value: "queue" },
|
||||||
{ name: client.translate("music/loop:TRACK"), value: "1" },
|
{ name: client.translate("music/loop:TRACK"), value: "track" },
|
||||||
{ name: client.translate("music/loop:DISABLE"), value: "0" },
|
{ name: client.translate("music/loop:DISABLE"), value: "off" },
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
dirname: __dirname,
|
dirname: __dirname,
|
||||||
|
@ -44,25 +43,25 @@ class Loop extends BaseCommand {
|
||||||
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
||||||
*/
|
*/
|
||||||
async execute(client, interaction) {
|
async execute(client, interaction) {
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
const voice = interaction.member.voice.channel;
|
const voice = interaction.member.voice.channel;
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { edit: true });
|
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { edit: true });
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING", null, { edit: true });
|
if (!player) return interaction.error("music/play:NOT_PLAYING", null, { edit: true });
|
||||||
|
|
||||||
|
const type = interaction.options.getString("option");
|
||||||
|
|
||||||
const translated = {
|
const translated = {
|
||||||
"3": interaction.translate("music/loop:AUTOPLAY_ENABLED"),
|
// "3": interaction.translate("music/loop:AUTOPLAY_ENABLED"),
|
||||||
"2": interaction.translate("music/loop:QUEUE_ENABLED"),
|
"queue": interaction.translate("music/loop:QUEUE_ENABLED"),
|
||||||
"1": interaction.translate("music/loop:TRACK_ENABLED"),
|
"track": interaction.translate("music/loop:TRACK_ENABLED"),
|
||||||
"0": interaction.translate("music/loop:LOOP_DISABLED"),
|
"off": interaction.translate("music/loop:LOOP_DISABLED"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const type = interaction.options.getString("option"),
|
await player.setRepeatMode(type);
|
||||||
mode = type === "3" ? QueueRepeatMode.AUTOPLAY : type === "2" ? QueueRepeatMode.QUEUE : type === "1" ? QueueRepeatMode.TRACK : QueueRepeatMode.OFF;
|
interaction.editReply({ content: translated[type] });
|
||||||
|
|
||||||
queue.setRepeatMode(mode);
|
|
||||||
|
|
||||||
interaction.reply({ content: translated[type] });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,42 +29,37 @@ class PlayContext extends BaseCommand {
|
||||||
if (!links) return interaction.error("music/play:NO_LINK", null, { edit: true });
|
if (!links) return interaction.error("music/play:NO_LINK", null, { edit: true });
|
||||||
|
|
||||||
const query = links[0],
|
const query = links[0],
|
||||||
voice = interaction.member.voice.channel;
|
voice = interaction.member.voice;
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { edit: true });
|
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { edit: true });
|
||||||
|
|
||||||
const perms = voice.permissionsFor(client.user);
|
const perms = voice.channel.permissionsFor(client.user);
|
||||||
if (!perms.has(PermissionsBitField.Flags.Connect) || !perms.has(PermissionsBitField.Flags.Speak)) return interaction.error("music/play:VOICE_CHANNEL_CONNECT", null, { edit: true });
|
if (!perms.has(PermissionsBitField.Flags.Connect) || !perms.has(PermissionsBitField.Flags.Speak)) return interaction.error("music/play:VOICE_CHANNEL_CONNECT", null, { edit: true });
|
||||||
|
|
||||||
const searchResult = await client.player.search(query, {
|
const player = await client.lavalink.createPlayer({
|
||||||
requestedBy: interaction.user,
|
guildId: interaction.guildId,
|
||||||
|
voiceChannelId: voice.channelId,
|
||||||
|
textChannelId: interaction.channelId,
|
||||||
|
selfDeaf: true,
|
||||||
|
selfMute: false,
|
||||||
|
volume: 100,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!searchResult.hasTracks()) return interaction.error("music/play:NO_RESULT", { query }, { edit: true });
|
await player.connect();
|
||||||
else {
|
|
||||||
const { queue } = await client.player.play(interaction.member.voice.channel, searchResult, {
|
|
||||||
nodeOptions: {
|
|
||||||
metadata: interaction,
|
|
||||||
},
|
|
||||||
selfDeaf: true,
|
|
||||||
leaveOnEnd: false,
|
|
||||||
leaveOnStop: true,
|
|
||||||
skipOnNoStream: true,
|
|
||||||
maxSize: 200,
|
|
||||||
maxHistorySize: 50,
|
|
||||||
});
|
|
||||||
|
|
||||||
interaction.editReply({
|
const res = await player.search({ query }, interaction.member);
|
||||||
content: interaction.translate("music/play:ADDED_QUEUE", {
|
|
||||||
songName: searchResult.hasPlaylist() ? searchResult.playlist.title : searchResult.tracks[0].title,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (client.player.nodes.get(interaction.guildId).currentTrack.url === query && query.match(/&t=[[0-9]+/g) !== null) {
|
if (res.loadType === "playlist") await player.queue.add(res.tracks);
|
||||||
const time = query.match(/&t=[[0-9]+/g)[0].split("=")[1];
|
else if (res.loadType === "search") await player.queue.add(res.tracks[0]);
|
||||||
|
else if (res.loadType === "track") await player.queue.add(res.tracks[0]);
|
||||||
|
else console.log(res);
|
||||||
|
|
||||||
queue.node.seek(time * 1000);
|
if (!player.playing) await player.play();
|
||||||
}
|
|
||||||
}
|
interaction.editReply({
|
||||||
|
content: interaction.translate("music/play:ADDED_QUEUE", {
|
||||||
|
songName: res.loadType === "playlist" ? res.playlist.name : `${res.tracks[0].info.title} - ${res.tracks[0].info.author}`,
|
||||||
|
}),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,14 +59,16 @@ class Play extends BaseCommand {
|
||||||
|
|
||||||
const res = await player.search({ query }, interaction.member);
|
const res = await player.search({ query }, interaction.member);
|
||||||
|
|
||||||
await player.queue.add(res.tracks[0]);
|
if (res.loadType === "playlist") await player.queue.add(res.tracks);
|
||||||
|
else if (res.loadType === "search") await player.queue.add(res.tracks[0]);
|
||||||
|
else if (res.loadType === "track") await player.queue.add(res.tracks[0]);
|
||||||
|
else console.log(res);
|
||||||
|
|
||||||
if (!player.playing) await player.play();
|
if (!player.playing) await player.play();
|
||||||
|
|
||||||
interaction.editReply({
|
interaction.editReply({
|
||||||
content: interaction.translate("music/play:ADDED_QUEUE", {
|
content: interaction.translate("music/play:ADDED_QUEUE", {
|
||||||
// songName: searchResult.hasPlaylist() ? searchResult.playlist.title : `${searchResult.tracks[0].title} - ${searchResult.tracks[0].author}`,
|
songName: res.loadType === "playlist" ? res.playlist.name : `${res.tracks[0].info.title} - ${res.tracks[0].info.author}`,
|
||||||
songName: res.tracks[0].info.title,
|
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,12 @@ class Queue extends BaseCommand {
|
||||||
|
|
||||||
if (interaction.customId.startsWith("queue_")) {
|
if (interaction.customId.startsWith("queue_")) {
|
||||||
interaction.data = [];
|
interaction.data = [];
|
||||||
interaction.data.guld = await client.findOrCreateGuild(interaction.guildId);
|
interaction.data.guild = await client.findOrCreateGuild(interaction.guildId);
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING");
|
if (!player) return interaction.error("music/play:NOT_PLAYING");
|
||||||
|
|
||||||
const { embeds, size } = generateQueueEmbeds(interaction, queue);
|
const { embeds, size } = generateQueueEmbeds(interaction, player);
|
||||||
|
|
||||||
let currentPage = Number(interaction.message.content.match(/\d+/g)[0]) - 1 ?? 0;
|
let currentPage = Number(interaction.message.content.match(/\d+/g)[0]) - 1 ?? 0;
|
||||||
|
|
||||||
|
@ -124,10 +124,10 @@ class Queue extends BaseCommand {
|
||||||
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
||||||
*/
|
*/
|
||||||
async execute(client, interaction) {
|
async execute(client, interaction) {
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING");
|
if (!player) return interaction.error("music/play:NOT_PLAYING");
|
||||||
|
|
||||||
const { embeds, size } = generateQueueEmbeds(interaction, queue),
|
const { embeds, size } = generateQueueEmbeds(interaction, player),
|
||||||
row = new ActionRowBuilder().addComponents(
|
row = new ActionRowBuilder().addComponents(
|
||||||
new ButtonBuilder().setCustomId("queue_prev_page").setStyle(ButtonStyle.Primary).setEmoji("⬅️"),
|
new ButtonBuilder().setCustomId("queue_prev_page").setStyle(ButtonStyle.Primary).setEmoji("⬅️"),
|
||||||
new ButtonBuilder().setCustomId("queue_next_page").setStyle(ButtonStyle.Primary).setEmoji("➡️"),
|
new ButtonBuilder().setCustomId("queue_next_page").setStyle(ButtonStyle.Primary).setEmoji("➡️"),
|
||||||
|
@ -152,28 +152,28 @@ class Queue extends BaseCommand {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
||||||
* @param {import("discord-player").GuildQueue} queue
|
* @param {import("lavalink-client").Player} player
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function generateQueueEmbeds(interaction, queue) {
|
function generateQueueEmbeds(interaction, player) {
|
||||||
const embeds = [],
|
const embeds = [],
|
||||||
currentTrack = queue.currentTrack,
|
currentTrack = player.queue.current,
|
||||||
translated = {
|
translated = {
|
||||||
"3": interaction.translate("music/loop:AUTOPLAY"),
|
// "3": interaction.translate("music/loop:AUTOPLAY"),
|
||||||
"2": interaction.translate("music/loop:QUEUE"),
|
"queue": interaction.translate("music/loop:QUEUE"),
|
||||||
"1": interaction.translate("music/loop:TRACK"),
|
"track": interaction.translate("music/loop:TRACK"),
|
||||||
"0": interaction.translate("common:DISABLED"),
|
"off": interaction.translate("common:DISABLED"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let k = 10;
|
let k = 10;
|
||||||
|
|
||||||
if (!queue.tracks.size) {
|
if (!player.queue.tracks.length) {
|
||||||
const embed = interaction.client.embed({
|
const embed = interaction.client.embed({
|
||||||
title: interaction.translate("music/nowplaying:CURRENTLY_PLAYING"),
|
title: interaction.translate("music/nowplaying:CURRENTLY_PLAYING"),
|
||||||
thumbnail: currentTrack.thumbnail || null,
|
thumbnail: currentTrack.info.artworkUrl || null,
|
||||||
description: `${interaction.translate("music/nowplaying:REPEAT")}: \`${translated[queue.repeatMode]}\`\n${
|
description: `${interaction.translate("music/nowplaying:REPEAT")}: \`${translated[player.repeatMode]}\`\n${
|
||||||
currentTrack.url.startsWith("./clips") ? `${currentTrack.title} (clips)` : `[${currentTrack.title}](${currentTrack.url})`
|
currentTrack.info.uri.startsWith("./clips") ? `${currentTrack.info.title} (clips)` : `[${currentTrack.info.title}](${currentTrack.info.uri})`
|
||||||
}\n> ${interaction.translate("music/queue:ADDED")} ${currentTrack.requestedBy}\n\n**${interaction.translate("music/queue:NEXT")}**\n${interaction.translate("music/queue:NO_QUEUE")}`,
|
}\n> ${interaction.translate("music/queue:ADDED")} ${currentTrack.requester.toString()}\n\n**${interaction.translate("music/queue:NEXT")}**\n${interaction.translate("music/queue:NO_QUEUE")}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
embeds.push(embed);
|
embeds.push(embed);
|
||||||
|
@ -181,19 +181,19 @@ function generateQueueEmbeds(interaction, queue) {
|
||||||
return { embeds: embeds, size: embeds.length };
|
return { embeds: embeds, size: embeds.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < queue.getSize(); i += 10) {
|
for (let i = 0; i < player.queue.tracks.length; i += 10) {
|
||||||
const current = queue.tracks.toArray().slice(i, k);
|
const current = player.queue.tracks.slice(i, k);
|
||||||
let j = i;
|
let j = i;
|
||||||
k += 10;
|
k += 10;
|
||||||
|
|
||||||
const info = current.map(track => `${++j}. ${track.url.startsWith("./clips") ? `${track.title} (clips)` : `[${track.title}](${track.url})`}\n> ${interaction.translate("music/queue:ADDED")} ${track.requestedBy}`).join("\n");
|
const info = current.map(track => `${++j}. ${track.info.uri.startsWith("./clips") ? `${track.info.title} (clips)` : `[${track.info.title}](${track.info.uri})`}\n> ${interaction.translate("music/queue:ADDED")} ${track.requester.toString()}`).join("\n");
|
||||||
|
|
||||||
const embed = interaction.client.embed({
|
const embed = interaction.client.embed({
|
||||||
title: interaction.translate("music/nowplaying:CURRENTLY_PLAYING"),
|
title: interaction.translate("music/nowplaying:CURRENTLY_PLAYING"),
|
||||||
thumbnail: currentTrack.thumbnail || null,
|
thumbnail: currentTrack.info.artworkUrl || null,
|
||||||
description: `${interaction.translate("music/nowplaying:REPEAT")}: \`${translated[queue.repeatMode]}\`\n${
|
description: `${interaction.translate("music/nowplaying:REPEAT")}: \`${translated[player.repeatMode]}\`\n${
|
||||||
currentTrack.url.startsWith("./clips") ? `${currentTrack.title} (clips)` : `[${currentTrack.title}](${currentTrack.url})`
|
currentTrack.info.uri.startsWith("./clips") ? `${currentTrack.info.title} (clips)` : `[${currentTrack.info.title}](${currentTrack.info.uri})`
|
||||||
}\n * ${interaction.translate("music/queue:ADDED")} ${currentTrack.requestedBy}\n\n**${interaction.translate("music/queue:NEXT")}**\n${info}`,
|
}\n * ${interaction.translate("music/queue:ADDED")} ${currentTrack.requester.toString()}\n\n**${interaction.translate("music/queue:NEXT")}**\n${info}`,
|
||||||
});
|
});
|
||||||
|
|
||||||
embeds.push(embed);
|
embeds.push(embed);
|
|
@ -40,10 +40,11 @@ class Seek extends BaseCommand {
|
||||||
voice = interaction.member.voice.channel;
|
voice = interaction.member.voice.channel;
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL");
|
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL");
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING");
|
if (!player) return interaction.error("music/play:NOT_PLAYING");
|
||||||
|
|
||||||
|
await player.seek(time * 1000);
|
||||||
|
|
||||||
queue.node.seek(time * 1000);
|
|
||||||
interaction.success("music/seek:SUCCESS", {
|
interaction.success("music/seek:SUCCESS", {
|
||||||
time: `**${time}** ${client.functions.getNoun(time, interaction.translate("misc:NOUNS:SECONDS:1"), interaction.translate("misc:NOUNS:SECONDS:2"), interaction.translate("misc:NOUNS:SECONDS:5"))}`,
|
time: `**${time}** ${client.functions.getNoun(time, interaction.translate("misc:NOUNS:SECONDS:1"), interaction.translate("misc:NOUNS:SECONDS:2"), interaction.translate("misc:NOUNS:SECONDS:5"))}`,
|
||||||
});
|
});
|
|
@ -30,10 +30,10 @@ class Shuffle extends BaseCommand {
|
||||||
const voice = interaction.member.voice.channel;
|
const voice = interaction.member.voice.channel;
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { ephemeral: true });
|
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { ephemeral: true });
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING", null, { ephemeral: true });
|
if (!player) return interaction.error("music/play:NOT_PLAYING", null, { ephemeral: true });
|
||||||
|
|
||||||
queue.tracks.shuffle();
|
await player.queue.shuffle();
|
||||||
interaction.success("music/shuffle:SUCCESS");
|
interaction.success("music/shuffle:SUCCESS");
|
||||||
}
|
}
|
||||||
}
|
}
|
66
commands/Music/skip.js
Normal file
66
commands/Music/skip.js
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
const { SlashCommandBuilder } = require("discord.js");
|
||||||
|
const BaseCommand = require("../../base/BaseCommand");
|
||||||
|
|
||||||
|
class Skip extends BaseCommand {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("../base/Client")} client
|
||||||
|
*/
|
||||||
|
constructor(client) {
|
||||||
|
super({
|
||||||
|
command: new SlashCommandBuilder()
|
||||||
|
.setName("skip")
|
||||||
|
.setDescription(client.translate("music/skip:DESCRIPTION"))
|
||||||
|
.setDescriptionLocalizations({
|
||||||
|
uk: client.translate("music/skip:DESCRIPTION", null, "uk-UA"),
|
||||||
|
ru: client.translate("music/skip:DESCRIPTION", null, "ru-RU"),
|
||||||
|
})
|
||||||
|
.setDMPermission(false)
|
||||||
|
.addIntegerOption(option =>
|
||||||
|
option
|
||||||
|
.setName("position")
|
||||||
|
.setDescription(client.translate("music/skip:POSITION"))
|
||||||
|
.setDescriptionLocalizations({
|
||||||
|
uk: client.translate("music/skip:POSITION", null, "uk-UA"),
|
||||||
|
ru: client.translate("music/skip:POSITION", null, "ru-RU"),
|
||||||
|
})
|
||||||
|
.setRequired(false),
|
||||||
|
),
|
||||||
|
dirname: __dirname,
|
||||||
|
ownerOnly: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {import("../../base/Client")} client
|
||||||
|
* @param {import("discord.js").ChatInputCommandInteraction} interaction
|
||||||
|
*/
|
||||||
|
async execute(client, interaction) {
|
||||||
|
const voice = interaction.member.voice.channel;
|
||||||
|
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL");
|
||||||
|
|
||||||
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
|
if (!player) return interaction.error("music/play:NOT_PLAYING");
|
||||||
|
|
||||||
|
const position = interaction.options.getInteger("position");
|
||||||
|
|
||||||
|
if (position) {
|
||||||
|
if (position <= 0) return interaction.error("music/skip:NO_PREV_SONG");
|
||||||
|
|
||||||
|
if (player.queue.tracks[position]) {
|
||||||
|
await player.skip(position);
|
||||||
|
|
||||||
|
return interaction.success("music/skip:SUCCESS", {
|
||||||
|
track: player.queue.current.info.title,
|
||||||
|
});
|
||||||
|
} else return interaction.error("music/skip:ERROR", { position });
|
||||||
|
} else {
|
||||||
|
await player.skip();
|
||||||
|
interaction.success("music/skip:SUCCESS");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Skip;
|
|
@ -30,10 +30,10 @@ class Stop extends BaseCommand {
|
||||||
const voice = interaction.member.voice.channel;
|
const voice = interaction.member.voice.channel;
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL");
|
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL");
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING");
|
if (!player) return interaction.error("music/play:NOT_PLAYING");
|
||||||
|
|
||||||
queue.delete();
|
await player.destroy();
|
||||||
interaction.success("music/stop:SUCCESS");
|
interaction.success("music/stop:SUCCESS");
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
const { SlashCommandBuilder } = require("discord.js");
|
const { SlashCommandBuilder } = require("discord.js");
|
||||||
const BaseCommand = require("../../base/BaseCommand");
|
const BaseCommand = require("../../base/BaseCommand");
|
||||||
|
const numbers = Array.from({ length: 100 }, (_, k) => k + 1);
|
||||||
|
|
||||||
class Volume extends BaseCommand {
|
class Volume extends BaseCommand {
|
||||||
/**
|
/**
|
||||||
|
@ -41,13 +42,13 @@ class Volume extends BaseCommand {
|
||||||
const voice = interaction.member.voice.channel;
|
const voice = interaction.member.voice.channel;
|
||||||
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { ephemeral: true });
|
if (!voice) return interaction.error("music/play:NO_VOICE_CHANNEL", null, { ephemeral: true });
|
||||||
|
|
||||||
const queue = client.player.nodes.get(interaction.guildId);
|
const player = client.lavalink.getPlayer(interaction.guildId);
|
||||||
if (!queue) return interaction.error("music/play:NOT_PLAYING", null, { ephemeral: true });
|
if (!player) return interaction.error("music/play:NOT_PLAYING", null, { ephemeral: true });
|
||||||
|
|
||||||
const volume = interaction.options.getInteger("int");
|
const volume = interaction.options.getInteger("int");
|
||||||
if (volume <= 0 || volume > 100) return interaction.error("misc:INVALID_NUMBER_RANGE", { min: 1, max: 100 });
|
if (volume <= 0 || volume > 100) return interaction.error("misc:INVALID_NUMBER_RANGE", { min: 1, max: 100 });
|
||||||
|
|
||||||
queue.node.setVolume(volume);
|
await player.setVolume(volume);
|
||||||
interaction.success("music/volume:SUCCESS", {
|
interaction.success("music/volume:SUCCESS", {
|
||||||
volume,
|
volume,
|
||||||
});
|
});
|
||||||
|
@ -61,7 +62,7 @@ class Volume extends BaseCommand {
|
||||||
*/
|
*/
|
||||||
async autocompleteRun(client, interaction) {
|
async autocompleteRun(client, interaction) {
|
||||||
const int = interaction.options.getInteger("int"),
|
const int = interaction.options.getInteger("int"),
|
||||||
results = Array.from({ length: 100 }, (_, k) => k + 1).filter(i => i.toString().includes(int));
|
results = numbers.filter(i => i.toString().includes(int));
|
||||||
|
|
||||||
return await interaction.respond(
|
return await interaction.respond(
|
||||||
results.slice(0, 25).map(i => ({
|
results.slice(0, 25).map(i => ({
|
|
@ -29,9 +29,6 @@ class Ready extends BaseEvent {
|
||||||
const checkReminds = require("../helpers/checkReminds");
|
const checkReminds = require("../helpers/checkReminds");
|
||||||
checkReminds.init(client);
|
checkReminds.init(client);
|
||||||
|
|
||||||
await client.lavalink.init({ ...client.user });
|
|
||||||
client.on("raw", d => client.lavalink.sendRawData(d));
|
|
||||||
|
|
||||||
if (client.config.dashboard.enabled) await client.dashboard.load(client);
|
if (client.config.dashboard.enabled) await client.dashboard.load(client);
|
||||||
|
|
||||||
client.logger.ready(`Loaded a total of ${commands.length} command(s).`);
|
client.logger.ready(`Loaded a total of ${commands.length} command(s).`);
|
||||||
|
@ -64,6 +61,10 @@ class Ready extends BaseEvent {
|
||||||
if (status[i + 1]) i++;
|
if (status[i + 1]) i++;
|
||||||
else i = 0;
|
else i = 0;
|
||||||
}, 30 * 1000); // Every 30 seconds
|
}, 30 * 1000); // Every 30 seconds
|
||||||
|
|
||||||
|
await client.lavalink.init({ ...client.user });
|
||||||
|
client.on("raw", d => client.lavalink.sendRawData(d));
|
||||||
|
client.logger.ready("Lavalink ready.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ User.prototype.getUsername = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseInteraction.prototype.getLocale = function () {
|
BaseInteraction.prototype.getLocale = function () {
|
||||||
return this.guild ? this.data?.guild?.language : "en-US";
|
return this.data?.guild?.language ?? "en-US";
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseInteraction.prototype.translate = function (key, args) {
|
BaseInteraction.prototype.translate = function (key, args) {
|
||||||
|
@ -36,7 +36,7 @@ BaseInteraction.prototype.error = async function (key, args, options = {}) {
|
||||||
};
|
};
|
||||||
|
|
||||||
Message.prototype.getLocale = function () {
|
Message.prototype.getLocale = function () {
|
||||||
return this.guild ? this.data?.guild?.language : "en-US";
|
return this.data?.guild?.language ?? "en-US";
|
||||||
};
|
};
|
||||||
|
|
||||||
Message.prototype.translate = function (key, args) {
|
Message.prototype.translate = function (key, args) {
|
||||||
|
|
4
index.js
4
index.js
|
@ -21,8 +21,8 @@ const client = new Client({
|
||||||
client
|
client
|
||||||
.on("disconnect", () => client.logger.warn("Bot is disconnecting..."))
|
.on("disconnect", () => client.logger.warn("Bot is disconnecting..."))
|
||||||
.on("reconnecting", () => client.logger.warn("Bot reconnecting..."))
|
.on("reconnecting", () => client.logger.warn("Bot reconnecting..."))
|
||||||
.on("warn", warn => client.logger.warn(warn))
|
.on("warn", warn => console.log(warn))
|
||||||
.on("error", e => client.logger.error(`${e.message}\n${e.stack}`));
|
.on("error", e => console.log(e));
|
||||||
|
|
||||||
process
|
process
|
||||||
.on("unhandledRejection", e => console.log(e))
|
.on("unhandledRejection", e => console.log(e))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"DESCRIPTION": "Rewinds the current track to the specified position",
|
"DESCRIPTION": "Seeks the current track to the specified time",
|
||||||
"USAGE": "[time]",
|
"USAGE": "[time]",
|
||||||
"EXAMPLES": "seek time:60",
|
"EXAMPLES": "seek time:60",
|
||||||
"TIME": "Time in seconds",
|
"TIME": "Time in seconds",
|
||||||
"SUCCESS": "Track rewinded to {{time}}"
|
"SUCCESS": "Seeked to {{time}}"
|
||||||
}
|
}
|
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"DESCRIPTION": "Skips the current track",
|
"DESCRIPTION": "Jumps to a specified track",
|
||||||
"USAGE": "",
|
"USAGE": "[position]",
|
||||||
"EXAMPLES": "skip",
|
"EXAMPLES": "skipto position:3",
|
||||||
"SUCCESS": "Track skipped"
|
"POSITION": "Track number in the queue",
|
||||||
|
"SUCCESS": "Jumped to track **{{track}}**",
|
||||||
|
"ERROR": "Nothing found at position {{position}}",
|
||||||
|
"NO_PREV_SONG": "You cannot go back, use the `back` command for that"
|
||||||
}
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"DESCRIPTION": "Jumps to a specified track",
|
|
||||||
"USAGE": "[position]",
|
|
||||||
"EXAMPLES": "skipto position:3",
|
|
||||||
"POSITION": "Track number in the queue",
|
|
||||||
"SUCCESS": "Jumped to track **{{track}}**",
|
|
||||||
"ERROR": "Nothing found at position {{position}}",
|
|
||||||
"NO_PREV_SONG": "You cannot go back, use the `back` command for that"
|
|
||||||
}
|
|
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"DESCRIPTION": "Пропустить текущий трек",
|
"DESCRIPTION": "Пропустить текущий трек или перейти на заданный",
|
||||||
"USAGE": "",
|
"USAGE": "(position)",
|
||||||
"EXAMPLES": "skip",
|
"EXAMPLES": "skip position:3",
|
||||||
"SUCCESS": "Трек пропущен"
|
"POSITION": "Номер трека в очереди",
|
||||||
|
"SUCCESS": "Выполнен переход на трек **{{track}}**",
|
||||||
|
"ERROR": "На позиции {{position}} ничего не найдено",
|
||||||
|
"NO_PREV_SONG": "Вы не можете перейти назад, для этого используйте команду `back`"
|
||||||
}
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"DESCRIPTION": "Перейти на заданный трек",
|
|
||||||
"USAGE": "[position]",
|
|
||||||
"EXAMPLES": "skipto position:3",
|
|
||||||
"POSITION": "Номер трека в очереди",
|
|
||||||
"SUCCESS": "Выполнен переход на трек **{{track}}**",
|
|
||||||
"ERROR": "На позиции {{position}} ничего не найдено",
|
|
||||||
"NO_PREV_SONG": "Вы не можете перейти назад, для этого используйте команду `back`"
|
|
||||||
}
|
|
|
@ -1,6 +1,9 @@
|
||||||
{
|
{
|
||||||
"DESCRIPTION": "Пропустити поточний трек",
|
"DESCRIPTION": "Перейти на заданий трек",
|
||||||
"USAGE": "",
|
"USAGE": "[position]",
|
||||||
"EXAMPLES": "skip",
|
"EXAMPLES": "skipto position:3",
|
||||||
"SUCCESS": "Трек пропущено"
|
"POSITION": "Номер треку в черзі",
|
||||||
|
"SUCCESS": "Перехід на трек **{{track}}**",
|
||||||
|
"ERROR": "На позиції {{position}} нічого не знайдено",
|
||||||
|
"NO_PREV_SONG": "Ви не можете перейти назад, для цього використовуйте команду `back`"
|
||||||
}
|
}
|
|
@ -1,9 +0,0 @@
|
||||||
{
|
|
||||||
"DESCRIPTION": "Перейти на заданий трек",
|
|
||||||
"USAGE": "[position]",
|
|
||||||
"EXAMPLES": "skipto position:3",
|
|
||||||
"POSITION": "Номер треку в черзі",
|
|
||||||
"SUCCESS": "Перехід на трек **{{track}}**",
|
|
||||||
"ERROR": "На позиції {{position}} нічого не знайдено",
|
|
||||||
"NO_PREV_SONG": "Ви не можете перейти назад, для цього використовуйте команду `back`"
|
|
||||||
}
|
|
|
@ -8,7 +8,7 @@
|
||||||
"start": "node .",
|
"start": "node .",
|
||||||
"lint": "eslint . --ext .js --ignore-pattern \"dashboard-core/\""
|
"lint": "eslint . --ext .js --ignore-pattern \"dashboard-core/\""
|
||||||
},
|
},
|
||||||
"author": "Discord: @jonny_bro",
|
"author": "@jonny_bro",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/opus": "^0.9.0",
|
"@discordjs/opus": "^0.9.0",
|
||||||
"@discordjs/rest": "^2.2.0",
|
"@discordjs/rest": "^2.2.0",
|
||||||
|
|
Loading…
Add table
Reference in a new issue