Pause resume loop

This commit is contained in:
Myx
2023-06-23 10:34:55 +02:00
parent d9408907dd
commit 8c08c088f1
10 changed files with 199 additions and 59 deletions

2
.env Normal file
View File

@@ -0,0 +1,2 @@
token="MTExOTYyOTQwNzk5NzQwNzMwMg.GOuub1.r8FZ_DWaouO17vO2QpgcDI-zTh4iTuUrgNZRbY"
clientId="1119629407997407302"

17
commands/loop.js Normal file
View File

@@ -0,0 +1,17 @@
const musicQueue = require('../musicQueue');
async function loopCommand(interaction) {
await interaction.deferReply();
const looping = interaction.options.getBoolean('looping');
musicQueue.setLooping(interaction.guild.id, looping);
if (looping) {
interaction.followUp('Enabled looping for the current queue.');
} else {
interaction.followUp('Disabled looping for the current queue.');
}
}
module.exports.loopCommand = loopCommand;

32
commands/pause.js Normal file
View File

@@ -0,0 +1,32 @@
const { musicPlayer } = require('../utils/musicPlayer');
const { AudioPlayerStatus, joinVoiceChannel, AudioPlayerState } = require('@discordjs/voice');
async function pauseCommand(interaction) {
await interaction.deferReply();
const voiceChannel = interaction.member.voice.channel;
const connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guild.id,
adapterCreator: interaction.guild.voiceAdapterCreator,
selfDeaf: false,
selfMute: false
});
let player = await musicPlayer(interaction.guild.id, connection, false);
if (!voiceChannel) {
return interaction.followUp('You must be in a voice channel to use this command.');
}
if (!player) {
return interaction.followUp('I am not currently playing music in a voice channel.');
}
// player.pause();
interaction.followUp('Paused the music.');
}
module.exports.pauseCommand = pauseCommand;

35
commands/play.js Normal file
View File

@@ -0,0 +1,35 @@
const { getMusicStream } = require('./../utils/getMusicStream');
const musicQueue = require('../musicQueue');
const { musicPlayer } = require('../utils/musicPlayer');
const {
joinVoiceChannel,
} = require('@discordjs/voice');
async function playCommand(interaction) {
await interaction.deferReply();
const query = interaction.options.getString('input');
const voiceChannel = interaction.member.voice.channel;
if (!voiceChannel) {
return interaction.followUp('You must be in a voice channel to use this command.');
}
const song = await getMusicStream(query);
musicQueue.addToQueue(interaction.guild.id, song);
const connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guild.id,
adapterCreator: interaction.guild.voiceAdapterCreator,
selfDeaf: false,
selfMute: false
});
musicPlayer(interaction.guild.id, connection);
interaction.followUp(`Added ${song.title} to the queue.`);
}
module.exports.playCommand = playCommand;

32
commands/resume.js Normal file
View File

@@ -0,0 +1,32 @@
const { musicPlayer } = require('../utils/musicPlayer');
const { joinVoiceChannel } = require('@discordjs/voice');
async function resumeCommand(interaction) {
await interaction.deferReply();
const voiceChannel = interaction.member.voice.channel;
const connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guild.id,
adapterCreator: interaction.guild.voiceAdapterCreator,
selfDeaf: false,
selfMute: false
});
let player = await musicPlayer(interaction.guild.id, connection, false);
if (!voiceChannel) {
return interaction.followUp('You must be in a voice channel to use this command.');
}
if (!player) {
return interaction.followUp('I am not currently playing music in a voice channel.');
}
player.unpause();
interaction.followUp('Resumed the music.');
}
module.exports.resumeCommand = resumeCommand;

View File

@@ -1,9 +1,12 @@
const { playCommand } = require('./play.js');
const { Client, GatewayIntentBits } = require('discord.js'); const { Client, GatewayIntentBits } = require('discord.js');
const { queueCommand } = require('./commands/queue');
const { registerCommands } = require('./utils/registerCommands'); const { registerCommands } = require('./utils/registerCommands');
const process = require('dotenv').config(); const { playCommand } = require('./commands/play');
const { queueCommand } = require('./commands/queue');
const { pauseCommand } = require('./commands/pause');
const { resumeCommand } = require('./commands/resume');
const { loopCommand } = require('./commands/loop');
const process = require('dotenv').config();
const clientId = process.parsed.clientId; const clientId = process.parsed.clientId;
const token = process.parsed.token; const token = process.parsed.token;
@@ -31,8 +34,14 @@ client.on('interactionCreate', async (interaction) => {
await playCommand(interaction); await playCommand(interaction);
} else if (commandName === 'queue') { } else if (commandName === 'queue') {
await queueCommand(interaction); await queueCommand(interaction);
} else if (commandName === 'pause') {
await pauseCommand(interaction);
} else if (commandName === 'resume') {
await resumeCommand(interaction);
} else if (commandName === 'loop') {
await loopCommand(interaction);
} }
}); });
// client.login(process.env.TOKEN); // client.login(process.env.TOKEN);

View File

@@ -1,24 +1,42 @@
class MusicQueue { class MusicQueue {
constructor() { constructor() {
this.queue = new Map(); this.queue = new Map();
} this.looping = new Map();
getQueue(guildId) {
if (!this.queue.has(guildId)) {
this.queue.set(guildId, []);
}
return this.queue.get(guildId);
} }
addToQueue(guildId, song) { addToQueue(guildId, song) {
const serverQueue = this.getQueue(guildId); if (!this.queue.has(guildId)) {
serverQueue.push(song); this.queue.set(guildId, []);
}
this.queue.get(guildId).push(song);
} }
removeFromQueue(guildId) { removeFromQueue(guildId) {
const serverQueue = this.getQueue(guildId); if (!this.queue.has(guildId)) {
return;
}
const serverQueue = this.queue.get(guildId);
if (this.looping.has(guildId) && this.looping.get(guildId)) {
serverQueue.push(serverQueue.shift());
} else {
serverQueue.shift(); serverQueue.shift();
} }
} }
module.exports = new MusicQueue(); getQueue(guildId) {
if (!this.queue.has(guildId)) {
return [];
}
return this.queue.get(guildId);
}
setLooping(guildId, looping) {
this.looping.set(guildId, looping);
}
}
module.exports = new MusicQueue();

View File

@@ -24,10 +24,10 @@ async function getMusicStream(query) {
type = StreamType.OggOpus; type = StreamType.OggOpus;
} else { } else {
stream = await youtube.getStream(query); stream = await youtube.getStream(query)
songTitle = stream.title ?? 'Unknown'; songTitle = stream?.title ?? 'Unknown';
songDuration = stream.duration ?? 'Unknown'; songDuration = stream?.duration ?? 'Unknown';
stream = stream.stream; stream = stream?.stream;
type = StreamType.Opus; type = StreamType.Opus;
} }

View File

@@ -1,40 +1,12 @@
const { const {
joinVoiceChannel,
createAudioResource, createAudioResource,
createAudioPlayer, createAudioPlayer,
NoSubscriberBehavior, NoSubscriberBehavior,
AudioPlayerStatus, AudioPlayerStatus,
} = require('@discordjs/voice'); } = require('@discordjs/voice');
const musicQueue = require('./musicQueue'); const musicQueue = require('../musicQueue');
const { getMusicStream } = require('./utils/getMusicStream');
async function playCommand(interaction) { async function musicPlayer(guildId, connection) {
await interaction.deferReply();
const query = interaction.options.getString('input');
const voiceChannel = interaction.member.voice.channel;
if (!voiceChannel) {
return interaction.followUp('You must be in a voice channel to use this command.');
}
const song = await getMusicStream(query);
musicQueue.addToQueue(interaction.guild.id, song);
const connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: interaction.guild.id,
adapterCreator: interaction.guild.voiceAdapterCreator,
selfDeaf: false,
selfMute: false
});
playSong(interaction.guild.id, connection);
interaction.followUp(`Added ${song.title} to the queue.`);
}
async function playSong(guildId, connection) {
const serverQueue = musicQueue.getQueue(guildId); const serverQueue = musicQueue.getQueue(guildId);
if (serverQueue.length === 0) { if (serverQueue.length === 0) {
@@ -44,6 +16,12 @@ async function playCommand(interaction) {
const song = serverQueue[0]; const song = serverQueue[0];
if(song.stream == null){
musicQueue.removeFromQueue(guildId);
musicPlayer(guildId, connection);
return;
}
let resource = createAudioResource(song.stream, { let resource = createAudioResource(song.stream, {
inputType: song.type inputType: song.type
}) })
@@ -54,6 +32,7 @@ async function playCommand(interaction) {
} }
}) })
player.play(resource) player.play(resource)
connection.subscribe(player) connection.subscribe(player)
@@ -61,8 +40,10 @@ async function playCommand(interaction) {
player.on(AudioPlayerStatus.Idle, () => { player.on(AudioPlayerStatus.Idle, () => {
console.log('Song ended:', song.title); console.log('Song ended:', song.title);
musicQueue.removeFromQueue(guildId); musicQueue.removeFromQueue(guildId);
playSong(guildId, connection); musicPlayer(guildId, connection);
}); });
return player;
} }
// TODO: USE THIS AGAIN // TODO: USE THIS AGAIN
@@ -83,4 +64,4 @@ function convertToMilliseconds(songLenth) {
} }
} }
module.exports.playCommand = playCommand; module.exports.musicPlayer = musicPlayer;

View File

@@ -19,6 +19,20 @@ async function registerCommands(clientId, token) {
option.setName('song') option.setName('song')
.setDescription('Add song from YouTube, Spotify, SoundCloud, etc. to the queue') .setDescription('Add song from YouTube, Spotify, SoundCloud, etc. to the queue')
.setRequired(true) .setRequired(true)
),
new SlashCommandBuilder()
.setName('pause')
.setDescription('Pauses the current song!'),
new SlashCommandBuilder()
.setName('resume')
.setDescription('Resumes the current song!'),
new SlashCommandBuilder()
.setName('loop')
.setDescription('Loops the current song!')
.addBooleanOption(option =>
option.setName('looping')
.setDescription('Enable or disable looping')
.setRequired(true)
) )
]; ];