diff --git a/.dockerignore b/.dockerignore index db15c59..3807759 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,8 @@ .devcontainer .git .vscode -dist/ +.yarn +dist node_modules scripts .dockerignore diff --git a/.gitignore b/.gitignore index 8f4b486..9582c1d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vscode/ +.yarn/ node_modules/* .env dist/ \ No newline at end of file diff --git a/.yarn/install-state.gz b/.yarn/install-state.gz deleted file mode 100644 index 8a4932d..0000000 Binary files a/.yarn/install-state.gz and /dev/null differ diff --git a/src/commands/music.ts b/src/commands/music.ts index 96cbed1..e4b4ef8 100644 --- a/src/commands/music.ts +++ b/src/commands/music.ts @@ -3,6 +3,11 @@ import { Command } from "interfaces" import play from "./music/play" import leave from "./music/leave" import queue from "./music/queue" +import volume from "./music/volume" +import skip from "./music/skip" +import nowplaying from "./music/nowplaying" +import pause from "./music/pause" +import unpause from "./music/unpause" export = { name: "music", @@ -24,10 +29,41 @@ export = { .setDescription("The song to play") .setAutocomplete(true) .setRequired(true))) + .addSubcommand(subcommand => + subcommand + .setName("volume") + .setDescription("Change the volume of the music") + .addNumberOption(option => + option + .setName("volume") + .setDescription("The volume to set") + .setMinValue(1) + .setMaxValue(100) + .setRequired(true))) + .addSubcommand(subcommand => + subcommand + .setName("skip") + .setDescription("Skip the current song") + .addNumberOption(option => + option + .setName("amount") + .setDescription("The amount of songs to skip"))) .addSubcommand(subcommand => subcommand .setName("queue") .setDescription("Show the queue")) + .addSubcommand(subcommand => + subcommand + .setName("nowplaying") + .setDescription("Show the currently playing song")) + .addSubcommand(subcommand => + subcommand + .setName("pause") + .setDescription("Pause the music")) + .addSubcommand(subcommand => + subcommand + .setName("unpause") + .setDescription("Unpause the music")) .addSubcommand(subcommand => subcommand .setName("leave") @@ -43,11 +79,36 @@ export = { return } + if (subcommand === "volume") { + volume(interaction) + return + } + + if (subcommand === "skip") { + skip(interaction) + return + } + if (subcommand === "queue") { queue(interaction) return } + if (subcommand === "nowplaying") { + nowplaying(interaction) + return + } + + if (subcommand === "pause") { + pause(interaction) + return + } + + if (subcommand === "unpause") { + unpause(interaction) + return + } + if (subcommand === "leave") { leave(interaction) return diff --git a/src/commands/music/leave.ts b/src/commands/music/leave.ts index e6c61eb..c223de2 100644 --- a/src/commands/music/leave.ts +++ b/src/commands/music/leave.ts @@ -15,7 +15,6 @@ export default async function leave(interaction: ChatInputCommandInteraction) { return } - queue.delete() await interaction.reply({ embeds: [{ diff --git a/src/commands/music/nowplaying.ts b/src/commands/music/nowplaying.ts new file mode 100644 index 0000000..4f0f255 --- /dev/null +++ b/src/commands/music/nowplaying.ts @@ -0,0 +1,45 @@ +import { embedColor } from "config/options" +import { useMainPlayer } from "discord-player" +import { ChatInputCommandInteraction } from "discord.js" + +export default async function nowplaying(interaction: ChatInputCommandInteraction) { + await interaction.deferReply() + + const player = useMainPlayer() + const queue = player.queues.get(interaction.guildId!) + + if (!queue) { + await interaction.editReply({ + embeds: [{ + description: "There is no music playing", + color: embedColor + }] + }) + return + } + + const current = queue.currentTrack + if (!current) { + await interaction.editReply({ + embeds: [{ + description: "There is no music playing", + color: embedColor + }] + }) + return + } + + await interaction.editReply({ + embeds: [{ + title: "Now Playing", + description: `[${current.title}](${current.url})`, + color: embedColor, + thumbnail: { + url: current.thumbnail + }, + footer: { + text: `Requested by ${current.requestedBy!.username} | ${current.duration}` + } + }] + }) +} \ No newline at end of file diff --git a/src/commands/music/pause.ts b/src/commands/music/pause.ts new file mode 100644 index 0000000..dc8c201 --- /dev/null +++ b/src/commands/music/pause.ts @@ -0,0 +1,38 @@ +import { embedColor } from "config/options" +import { useMainPlayer } from "discord-player" +import { ChatInputCommandInteraction } from "discord.js" + +export default async function pause(interaction: ChatInputCommandInteraction) { + await interaction.deferReply() + + const player = useMainPlayer() + const queue = player.queues.get(interaction.guildId!) + + if (!queue) { + await interaction.editReply({ + embeds: [{ + description: "There is no music playing", + color: embedColor + }] + }) + return + } + + if (queue.node.isPaused()) { + await interaction.editReply({ + embeds: [{ + description: "The music is already paused", + color: embedColor + }] + }) + return + } + + queue.node.setPaused(true) + await interaction.editReply({ + embeds: [{ + description: "Paused the music", + color: embedColor + }] + }) +} \ No newline at end of file diff --git a/src/commands/music/play.ts b/src/commands/music/play.ts index f7c24f6..c913eb5 100644 --- a/src/commands/music/play.ts +++ b/src/commands/music/play.ts @@ -18,10 +18,12 @@ export default async function play(interaction: ChatInputCommandInteraction) { return } + // const bitRate = channel.bitrate / 1000 + const { track } = await player.play(channel, query, { requestedBy: interaction.user, nodeOptions: { - volume: 50, + volume: 25, } }) diff --git a/src/commands/music/queue.ts b/src/commands/music/queue.ts index d9e1fd7..ea1e96b 100644 --- a/src/commands/music/queue.ts +++ b/src/commands/music/queue.ts @@ -5,26 +5,35 @@ import { ChatInputCommandInteraction } from "discord.js" export default async function queue(interaction: ChatInputCommandInteraction) { await interaction.deferReply() const player = useMainPlayer() - const queue = player.queues.get(interaction.guildId!) if (!queue) { - await interaction.editReply("There is nothing playing") + await interaction.editReply({ + embeds: [{ + description: "There is no queue", + color: embedColor + }] + }) return } const currentSong = queue.currentTrack - const nowPlaying = `Now playing: [${currentSong?.title}](${currentSong?.url})` - const tracks = queue.tracks.map((track, index) => { return `${index + 1}. [${track.title}](${track.url})` }) await interaction.editReply({ embeds: [{ + title: "Queue", description: nowPlaying + "\n\n" + tracks.join("\n"), - color: embedColor + thumbnail: { + url: currentSong?.thumbnail || "" + }, + color: embedColor, + footer: { + text: `Total tracks: ${queue.tracks.size}` + } }] }) } \ No newline at end of file diff --git a/src/commands/music/skip.ts b/src/commands/music/skip.ts new file mode 100644 index 0000000..952225b --- /dev/null +++ b/src/commands/music/skip.ts @@ -0,0 +1,44 @@ +import { embedColor } from "config/options" +import { useMainPlayer } from "discord-player" +import { ChatInputCommandInteraction } from "discord.js" + +export default async function skip(interaction: ChatInputCommandInteraction) { + await interaction.deferReply() + + const amount = interaction.options.getNumber("amount") ?? 1 + const player = useMainPlayer() + const queue = player.queues.get(interaction.guildId!) + + if (!queue) { + await interaction.editReply({ + embeds: [{ + description: "There is no queue", + color: embedColor + }] + }) + return + } + + if (amount > queue.size) { + await interaction.editReply({ + embeds: [{ + description: `There are only ${queue.size} song${queue.size === 1 ? "" : "s"} in the queue`, + color: embedColor + }] + }) + return + } + + if (amount === 1) { + queue.node.skip() + } else { + queue.node.skipTo(amount) + } + + await interaction.editReply({ + embeds: [{ + description: `Skipped ${amount === 1 ? "1 song" : `${amount} songs`}`, + color: embedColor + }] + }) +} \ No newline at end of file diff --git a/src/commands/music/unpause.ts b/src/commands/music/unpause.ts new file mode 100644 index 0000000..bf83909 --- /dev/null +++ b/src/commands/music/unpause.ts @@ -0,0 +1,38 @@ +import { embedColor } from "config/options" +import { useMainPlayer } from "discord-player" +import { ChatInputCommandInteraction } from "discord.js" + +export default async function pause(interaction: ChatInputCommandInteraction) { + await interaction.deferReply() + + const player = useMainPlayer() + const queue = player.queues.get(interaction.guildId!) + + if (!queue) { + await interaction.editReply({ + embeds: [{ + description: "There is no music playing", + color: embedColor + }] + }) + return + } + + if (!queue.node.isPaused()) { + await interaction.editReply({ + embeds: [{ + description: "The music is not paused", + color: embedColor + }] + }) + return + } + + queue.node.setPaused(false) + await interaction.editReply({ + embeds: [{ + description: "Unpaused the music", + color: embedColor + }] + }) +} \ No newline at end of file diff --git a/src/commands/music/volume.ts b/src/commands/music/volume.ts new file mode 100644 index 0000000..2e32c74 --- /dev/null +++ b/src/commands/music/volume.ts @@ -0,0 +1,29 @@ +import { embedColor } from "config/options" +import { useMainPlayer } from "discord-player" +import { ChatInputCommandInteraction } from "discord.js" + +export default async function volume(interaction: ChatInputCommandInteraction) { + await interaction.deferReply() + + const volume = interaction.options.getNumber("volume")! + const player = useMainPlayer() + const queue = player.queues.get(interaction.guildId!) + + if (!queue) { + await interaction.editReply({ + embeds: [{ + description: "There is no music playing", + color: embedColor + }] + }) + return + } + + queue.node.setVolume(volume) + await interaction.editReply({ + embeds: [{ + description: `Volume set to ${volume}`, + color: embedColor + }] + }) +} \ No newline at end of file diff --git a/src/components/autocomplete/music.ts b/src/components/autocomplete/music.ts index 241b135..bbdd851 100644 --- a/src/components/autocomplete/music.ts +++ b/src/components/autocomplete/music.ts @@ -23,7 +23,7 @@ export = { }) const results = tracks.map(track => ({ - name: track.title, + name: track.title.slice(0, 100), value: track.url }))