Creating functional loop, pause and unpause

This commit is contained in:
Azaaxin
2023-06-25 04:00:21 +02:00
parent 35eb54ab8c
commit dddbe81fab
12 changed files with 106 additions and 74 deletions

View File

@@ -1,8 +1,9 @@
const play = require('play-dl'); const play = require('play-dl');
if (play.is_expired()) { async function ReAuth() {
/*if (play.is_expired()) {
await play.refreshToken() await play.refreshToken()
} }*/
play.getFreeClientID().then((clientID) => { play.getFreeClientID().then((clientID) => {
play.setToken({ play.setToken({
@@ -15,4 +16,6 @@ play.getFreeClientID().then((clientID) => {
}) })
play.authorization(); play.authorization();
}
module.exports.ReAuth = ReAuth;

View File

@@ -1,17 +1,32 @@
const musicQueue = require('../musicQueue'); const musicQueue = require('../musicQueue');
async function loopCommand(interaction) { async function enableLooping(interaction) {
await interaction.deferReply(); await interaction.deferReply();
const guildId = interaction.guild.id;
const looping = interaction.options.getBoolean('looping'); musicQueue.enableLooping(guildId);
musicQueue.setLooping(interaction.guild.id, looping);
if (looping) {
interaction.followUp('Enabled looping for the current queue.'); interaction.followUp('Enabled looping for the current queue.');
} else { }
async function unloopCommand(interaction) {
await interaction.deferReply();
const guildId = interaction.guild.id;
musicQueue.disableLooping(guildId);
interaction.followUp('Disabled looping for the current queue.'); interaction.followUp('Disabled looping for the current queue.');
}
async function toggleLoopCommand(interaction) {
await interaction.deferReply();
const guildId = interaction.guild.id;
if (musicQueue.looping.has(guildId) && musicQueue.looping.get(guildId)) {
musicQueue.disableLooping(guildId, false);
interaction.followUp('Disabled looping for the current queue.');
} else {
musicQueue.enableLooping(guildId, true);
interaction.followUp('Enabled looping for the current queue.');
} }
} }
module.exports.loopCommand = loopCommand; module.exports.toggleLoopCommand = toggleLoopCommand;
module.exports.unloopCommand = unloopCommand;
module.exports.enableLooping = enableLooping;

24
commands/pause_resume.js Normal file
View File

@@ -0,0 +1,24 @@
const { getVoiceConnection } = require('@discordjs/voice');
async function pauseCommand(interaction) {
await interaction.deferReply();
const connection = getVoiceConnection(interaction.guild.id);
if (!connection) {
return interaction.followUp('There is no active music player in this server.');
}
connection.state.subscription.player.pause();
interaction.followUp('Paused the music.');
}
async function unpauseCommand(interaction) {
await interaction.deferReply();
const connection = getVoiceConnection(interaction.guild.id);
if (!connection) {
return interaction.followUp('There is no active music player in this server.');
}
connection.state.subscription.player.unpause();
interaction.followUp('Unpaused the music.');
}
module.exports.pauseCommand = pauseCommand;
module.exports.unpauseCommand = unpauseCommand;

View File

@@ -27,9 +27,7 @@ async function playCommand(interaction) {
selfMute: false selfMute: false
}); });
musicPlayer(interaction.guild.id, connection); musicPlayer(interaction.guild.id, connection, interaction);
interaction.followUp(`Added ${song.title} to the queue.`);
} }
module.exports.playCommand = playCommand; module.exports.playCommand = playCommand;

View File

@@ -2,9 +2,9 @@ const { Client, GatewayIntentBits } = require('discord.js');
const { registerCommands } = require('./utils/registerCommands'); const { registerCommands } = require('./utils/registerCommands');
const { playCommand } = require('./commands/play'); const { playCommand } = require('./commands/play');
const { queueCommand } = require('./commands/queue'); const { queueCommand } = require('./commands/queue');
const { pauseCommand } = require('./commands/pause'); const { pauseCommand, unpauseCommand } = require('./commands/pause_resume');
const { resumeCommand } = require('./commands/resume'); const { toggleLoopCommand } = require('./commands/loop');
const { loopCommand } = require('./commands/loop'); const { ReAuth } = require('./ReAuthenticate');
const process = require('dotenv').config(); const process = require('dotenv').config();
const clientId = process.parsed.clientId; const clientId = process.parsed.clientId;
@@ -37,12 +37,16 @@ client.on('interactionCreate', async (interaction) => {
} else if (commandName === 'pause') { } else if (commandName === 'pause') {
await pauseCommand(interaction); await pauseCommand(interaction);
} else if (commandName === 'resume') { } else if (commandName === 'resume') {
await resumeCommand(interaction); await unpauseCommand(interaction);
} else if (commandName === 'loop') { } else if (commandName === 'loop') {
await loopCommand(interaction); await toggleLoopCommand(interaction);
} }
}); });
client.on('messageCreate', async (message) => {
if(message.content == 'reauth') {
await ReAuth();
}
});
// client.login(process.env.TOKEN);
client.login(token); client.login(token);

View File

@@ -1,3 +1,5 @@
const { getMusicStream } = require('./utils/getMusicStream');
class MusicQueue { class MusicQueue {
constructor() { constructor() {
this.queue = new Map(); this.queue = new Map();
@@ -12,7 +14,7 @@ class MusicQueue {
this.queue.get(guildId).push(song); this.queue.get(guildId).push(song);
} }
removeFromQueue(guildId) { async removeFromQueue(guildId) {
if (!this.queue.has(guildId)) { if (!this.queue.has(guildId)) {
return; return;
} }
@@ -20,7 +22,9 @@ class MusicQueue {
const serverQueue = this.queue.get(guildId); const serverQueue = this.queue.get(guildId);
if (this.looping.has(guildId) && this.looping.get(guildId)) { if (this.looping.has(guildId) && this.looping.get(guildId)) {
serverQueue.push(serverQueue.shift()); const song = serverQueue.shift();
const newSong = await getMusicStream(song.userInput);
serverQueue.push(newSong);
} else { } else {
serverQueue.shift(); serverQueue.shift();
} }
@@ -34,8 +38,12 @@ class MusicQueue {
return this.queue.get(guildId); return this.queue.get(guildId);
} }
setLooping(guildId, looping) { enableLooping(guildId) {
this.looping.set(guildId, looping); this.looping.set(guildId, true);
}
disableLooping(guildId) {
this.looping.set(guildId, false);
} }
} }

View File

@@ -6,7 +6,8 @@ async function getStream(query) {
return { return {
title: songInformation.name, title: songInformation.name,
stream: stream.stream, stream: stream.stream,
duration: songInformation.durationInSec duration: songInformation.durationInSec / 1000,
userInput: query
} }
} }

View File

@@ -6,33 +6,33 @@ async function getStream(query) {
const regex = /(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([^?&\n]+)/; const regex = /(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))([^?&\n]+)/;
const match = query.match(regex); const match = query.match(regex);
let videoId; let videoId;
let usingYtsr = false;
if(match == null) { if(match == null) {
const searchResults = await ytsr(query, { page: 1, type: 'video' }); let result = await playdl.search(query, { limit: 1});
videoId = searchResults.items[0].id; videoId = result[0].id;
// videoId = null;
console.log(searchResults.items[0].id)
if (videoId == null) { if (videoId == null) {
let result = await playdl.search(query, { limit: 1}) usingYtsr = true;
let videoUrl = result[0].url; const searchResults = await ytsr(query, { page: 1, type: 'video' });
videoId = videoUrl.match(regex)[1]; videoId = searchResults.items[0].id;
} }
} else { } else {
videoId = match[1]; videoId = match[1];
} }
const streamResult = await playdl.stream(`https://www.youtube.com/watch?v=${videoId}`, { quality: 2 }); const streamResult = await playdl.stream(`https://www.youtube.com/watch?v=${videoId}`, { quality: 2 });
const infoResult = await ytsr(`https://www.youtube.com/watch?v=${videoId}`, { limit: 1}); const infoResult = usingYtsr ? await ytsr(`https://www.youtube.com/watch?v=${videoId}`, { limit: 1}) : await playdl.video_info(`https://www.youtube.com/watch?v=${videoId}`);
console.log(infoResult)
console.log("\x1b[36m",' Id: ', videoId, 'Alternative search:', usingYtsr)
return { return {
title: infoResult.items[0].title ?? 'Unknown', title: (usingYtsr ? infoResult.items[0].title : infoResult.video_details.title) ?? 'Unknown, error fetching title.',
duration: infoResult.items[0].duration ?? 0, duration: (usingYtsr ? infoResult.items[0].duration : infoResult.video_details.durationInSec) ?? 'Unknown, error fetching duration.',
stream: streamResult.stream, stream: streamResult.stream,
type: streamResult.type type: streamResult.type,
userInput: query
}; };
} catch (error) { } catch (error) {
console.log("\x1b[31m", error);
return null; return null;
} }
} }

View File

@@ -4,7 +4,8 @@
"description": "Discord music bot", "description": "Discord music bot",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" "test": "echo \"Error: no test specified\" && exit 1",
"start": "node index.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@@ -25,11 +26,8 @@
"discord.js": "^14.11.0", "discord.js": "^14.11.0",
"dotenv": "^16.3.1", "dotenv": "^16.3.1",
"ffmpeg-static": "^4.2.7", "ffmpeg-static": "^4.2.7",
"libsodium-wrappers": "^0.7.11",
"opusscript": "^0.1.0", "opusscript": "^0.1.0",
"play-dl": "^1.9.6", "play-dl": "^1.9.6",
"sodium": "^3.0.2",
"sodium-native": "^4.0.4",
"soundcloud-scraper": "^5.0.3", "soundcloud-scraper": "^5.0.3",
"spotify-web-api-node": "^5.0.2", "spotify-web-api-node": "^5.0.2",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",

View File

@@ -9,6 +9,7 @@ async function getMusicStream(query) {
let songTitle; let songTitle;
let songDuration; let songDuration;
let type = StreamType.Opus; let type = StreamType.Opus;
let userInput = query;
if (query.includes('spotify.com')) { if (query.includes('spotify.com')) {
stream = await spotify.getStream(query); stream = await spotify.getStream(query);
@@ -34,6 +35,7 @@ async function getMusicStream(query) {
return { return {
title: songTitle, title: songTitle,
duration: songDuration, duration: songDuration,
userInput: userInput,
stream: stream, stream: stream,
type: type type: type
}; };

View File

@@ -6,7 +6,7 @@ const {
} = require('@discordjs/voice'); } = require('@discordjs/voice');
const musicQueue = require('../musicQueue'); const musicQueue = require('../musicQueue');
async function musicPlayer(guildId, connection) { async function musicPlayer(guildId, connection, interaction) {
const serverQueue = musicQueue.getQueue(guildId); const serverQueue = musicQueue.getQueue(guildId);
if (serverQueue.length === 0) { if (serverQueue.length === 0) {
@@ -31,37 +31,21 @@ async function musicPlayer(guildId, connection) {
noSubscriber: NoSubscriberBehavior.Play noSubscriber: NoSubscriberBehavior.Play
} }
}) })
player.play(resource) player.play(resource)
connection.subscribe(player) connection.subscribe(player)
interaction.followUp(`Added **${song.title}** to the queue.`).then(message =>
player.on(AudioPlayerStatus.Idle, () => { setTimeout(() =>
message.delete(),
song.duration + 10000));
player.on(AudioPlayerStatus.Idle, async () => {
console.log('Song ended:', song.title); console.log('Song ended:', song.title);
musicQueue.removeFromQueue(guildId); await musicQueue.removeFromQueue(guildId)
musicPlayer(guildId, connection);
}); });
return player; return player;
}
// TODO: USE THIS AGAIN
function convertToMilliseconds(songLenth) {
try {
let time = songLenth.split(':')
let milliseconds = 0;
if(time.length == 3) {
milliseconds = (parseInt(time[0]) * 60 * 60 * 1000) + (parseInt(time[1]) * 60 * 1000) + (parseInt(time[2]) * 1000)
} else if(time.length == 2) {
milliseconds = (parseInt(time[0]) * 60 * 1000) + (parseInt(time[1]) * 1000)
} else if(time.length == 1) {
milliseconds = (parseInt(time[0]) * 1000)
}
return milliseconds
} catch (error) {
return 10000;
}
} }
module.exports.musicPlayer = musicPlayer; module.exports.musicPlayer = musicPlayer;

View File

@@ -28,12 +28,7 @@ async function registerCommands(clientId, token) {
.setDescription('Resumes the current song!'), .setDescription('Resumes the current song!'),
new SlashCommandBuilder() new SlashCommandBuilder()
.setName('loop') .setName('loop')
.setDescription('Loops the current song!') .setDescription('Loops the current song! (toggle)'),
.addBooleanOption(option =>
option.setName('looping')
.setDescription('Enable or disable looping')
.setRequired(true)
)
]; ];
const rest = new REST({ version: '9' }).setToken(token); const rest = new REST({ version: '9' }).setToken(token);