Added music commands

This commit is contained in:
2024-02-09 20:09:27 +01:00
parent d45c9fa299
commit d167e90316
6 changed files with 193 additions and 3 deletions

56
src/commands/music.ts Normal file
View File

@@ -0,0 +1,56 @@
import { PermissionFlagsBits, SlashCommandBuilder } from "discord.js"
import { Command } from "interfaces"
import play from "./music/play"
import leave from "./music/leave"
import queue from "./music/queue"
export = {
name: "music",
description: "Subcommands for music commands",
dev: true,
public: false,
subcommands: true,
data: new SlashCommandBuilder()
.setName("music")
.setDescription("Subcommands for music commands")
.addSubcommand(subcommand =>
subcommand
.setName("play")
.setDescription("Play a song")
.addStringOption(option =>
option
.setName("query")
.setDescription("The song to play")
.setAutocomplete(true)
.setRequired(true)))
.addSubcommand(subcommand =>
subcommand
.setName("queue")
.setDescription("Show the queue"))
.addSubcommand(subcommand =>
subcommand
.setName("leave")
.setDescription("Leave the voice channel"))
.setDMPermission(false)
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
async execute(interaction) {
const subcommand = interaction.options.getSubcommand()
if (subcommand === "play") {
play(interaction)
return
}
if (subcommand === "queue") {
queue(interaction)
return
}
if (subcommand === "leave") {
leave(interaction)
return
}
}
} as Command

View File

@@ -0,0 +1,26 @@
import { embedColor } from "config/options"
import { useMainPlayer } from "discord-player"
import { ChatInputCommandInteraction } from "discord.js"
export default async function leave(interaction: ChatInputCommandInteraction) {
const player = useMainPlayer()
const queue = player.queues.get(interaction.guildId!)
if (!queue) {
await interaction.reply({
embeds: [{
description: "There is no music playing",
color: embedColor
}]
})
return
}
queue.delete()
await interaction.reply({
embeds: [{
description: "Left the voice channel",
color: embedColor
}]
})
}

View File

@@ -0,0 +1,41 @@
import { embedColor } from "config/options"
import { useMainPlayer } from "discord-player"
import { ChatInputCommandInteraction, GuildMember } from "discord.js"
export default async function play(interaction: ChatInputCommandInteraction) {
await interaction.deferReply()
const query = interaction.options.getString("query")!
const channel = (interaction.member as GuildMember).voice.channel
const player = useMainPlayer()
if (!channel) {
await interaction.editReply({
embeds: [{
description: "You need to be in a voice channel to play music",
color: embedColor
}]
})
return
}
const { track } = await player.play(channel, query, {
requestedBy: interaction.user,
nodeOptions: {
volume: 50,
}
})
await interaction.editReply({
embeds: [{
description: `Playing [${track.title}](${track.url})`,
thumbnail: {
url: track.thumbnail
},
color: embedColor,
footer: {
text: track.duration + " minutes",
icon_url: interaction.user.avatarURL()!
}
}]
})
}

View File

@@ -0,0 +1,30 @@
import { embedColor } from "config/options"
import { useMainPlayer } from "discord-player"
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")
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: [{
description: nowPlaying + "\n\n" + tracks.join("\n"),
color: embedColor
}]
})
}

View File

@@ -0,0 +1,32 @@
import { QueryType, useMainPlayer } from "discord-player"
import { Autocomplete } from "interfaces"
export = {
name: "music",
description: "Music",
async execute(interaction) {
const focusedOption = interaction.options.getFocused(true)
if (interaction.options.getSubcommand() !== "play" && focusedOption.name !== "query") return
if (focusedOption.value === "") {
await interaction.respond([{
name: "Please start typing a song to play",
value: "none"
}])
return
}
const player = useMainPlayer()
const { tracks } = await player.search(focusedOption.value, {
searchEngine: QueryType.YOUTUBE_SEARCH
})
const results = tracks.map(track => ({
name: track.title,
value: track.url
}))
await interaction.respond(results.slice(0, 25)).catch()
}
} as Autocomplete

View File

@@ -4,8 +4,12 @@ import { Redis } from "ioredis"
import env from "utils/Env" import env from "utils/Env"
import { connect } from "mongoose" import { connect } from "mongoose"
import loadAllEvents from "./Events" import loadAllEvents from "./Events"
import { Player } from "discord-player"
const client = new Client() const client = new Client()
const redis = new Redis(env.prod.redisURI!) const redis = new Redis(env.prod.redisURI!)
const player = new Player(client)
let ft: "js" | "ts" let ft: "js" | "ts"
if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") { if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") {
ft = "ts" ft = "ts"
@@ -15,10 +19,11 @@ if (process.env.NODE_ENV === "dev" && process.env.TYPESCRIPT === "true") {
class Illegitimate { class Illegitimate {
async start() { async start() {
this.init() await this.init()
loadAllEvents(client, ft) loadAllEvents(client, ft)
client.start() await player.extractors.loadDefault()
this.databases() await client.start()
await this.databases()
} }
private async databases() { private async databases() {