Skip to content

Commit

Permalink
Music fix (#1046)
Browse files Browse the repository at this point in the history
* Music fix

Bunch of action fixes

* Fix prettier

* No longer needed

* Fix lint

* Updated
  • Loading branch information
GoodOne120 authored Jul 4, 2024
1 parent 2c9a087 commit bef206a
Show file tree
Hide file tree
Showing 7 changed files with 297 additions and 235 deletions.
32 changes: 20 additions & 12 deletions actions/control_music_MOD.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ module.exports = {
authorUrl: 'https://github.com/dbm-network/mods',
downloadURL: 'https://github.com/dbm-network/mods/blob/master/actions/control_music_MOD.js',
},
requiresAudioLibraries: true,
fields: ['action', 'volume', 'bitrate'],

subtitle(data) {
Expand Down Expand Up @@ -92,7 +91,7 @@ module.exports = {
action(cache) {
const { Bot } = this.getDBM();
const data = cache.actions[cache.index];
const queue = Bot.bot.player.getQueue(cache.server);
const server = cache.server;
const action = parseInt(data.action, 10);
const volume = parseInt(this.evalMessage(data.volume, cache), 10);
const bitrate = this.evalMessage(data.bitrate, cache);
Expand All @@ -102,36 +101,45 @@ module.exports = {
return this.callNexAction(cache);
}

if (!Bot.bot.queue) return this.callNextAction(cache);

const queue = Bot.bot.queue.get(server.id);
if (!queue) return this.callNextAction(cache);

try {
switch (action) {
case 0:
queue.destroy();
queue.connection.disconnect();
break;
case 1:
queue.setPaused(true);
queue.player.pause();
break;
case 2:
queue.setPaused(false);
queue.player.unpause();
break;
case 3:
queue.skip();
queue.player.stop();
break;
case 4:
queue.back();
queue.currentIndex -= 2;
queue.player.stop();
break;
case 5:
queue.destroy(false);
queue.songs = [];
break;
case 6:
queue.shuffle();
case 6: {
const currentIndex = queue.currentIndex + 1;
for (let i = queue.songs.length - 1; i > currentIndex; i--) {
const j = Math.floor(Math.random() * (i - currentIndex + 1)) + currentIndex;
[queue.songs[i], queue.songs[j]] = [queue.songs[j], queue.songs[i]];
}
break;
}
case 7:
queue.setVolume(volume);
queue.player.state.resource.volume.setVolume(volume / 100);
break;
case 8:
queue.setBitrate(bitrate);
queue.player.state.resource.encoder.setBitrate(bitrate);
break;
}
} catch (err) {
Expand Down
210 changes: 165 additions & 45 deletions actions/play_music_MOD.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ module.exports = {
authorUrl: 'https://github.com/dbm-network/mods',
downloadURL: 'https://github.com/dbm-network/mods/blob/master/actions/play_music_MOD.js',
},
requiresAudioLibraries: true,
fields: ['query', 'voiceChannel', 'varName', 'storage', 'varName2', 'type', 'volume', 'leaveOnEmpty', 'leaveOnEnd'],

subtitle(data) {
Expand All @@ -24,8 +23,8 @@ module.exports = {
return `
<div style="max-height: 350px; overflow-y: scroll;">
<div style="padding-top: 8px;">
<span class="dbminputlabel">YouTube Search</span><br>
<input id="query" class="round" type="text" placeholder="Search for a song from youtube"><br>
<span class="dbminputlabel">YouTube URL</span><br>
<input id="query" class="round" type="text" placeholder="Play URL from YouTube"><br>
</div>
<div>
Expand Down Expand Up @@ -61,10 +60,7 @@ module.exports = {
<br><br><br>
<p>
<u><b><span style="color: white;">NOTE:</span></b></u><br>
Youtube URLs and IDs are hit and miss due to using ytdl-core.<br>
In theory you should be able to use the following:<br>
Soundcloud URL, YouTube Search, YouTube song/playlist URL, YouTube ID,<br>
Spotify Song/playlist/album, vimeo, facebook and reverbnation.
Supports both videos and playlists.<br>
</p>
</div>
`;
Expand All @@ -75,66 +71,190 @@ module.exports = {
async action(cache) {
const data = cache.actions[cache.index];
const server = cache.server;
const channel = cache.msg?.channel ?? cache.interaction?.channel;
const { Bot, Files } = this.getDBM();
const Mods = this.getMods();
const playdl = Mods.require('play-dl');
const player = Bot.bot.player;
const ytdl = Mods.require('@distube/ytdl-core');
const ytpl = Mods.require('@distube/ytpl');
const {
joinVoiceChannel,
createAudioPlayer,
createAudioResource,
AudioPlayerStatus,
VoiceConnectionStatus,
} = require('@discordjs/voice');
const voiceChannel = await this.getVoiceChannelFromData(data.voiceChannel, data.varName, cache);

let volume = 80;
if (data.volume) volume = parseInt(this.evalMessage(data.volume, cache), 10) || 80;
if (!Bot.bot.queue) Bot.bot.queue = new Map();

// leaveOnEnd & leaveOnEmpty Cooldowns from DBM Settings
const volume = parseInt(this.evalMessage(data.volume, cache), 10) || 80;
const leaveOnEnd = data.leaveOnEnd;
const leaveOnEmpty = data.leaveOnEmpty;
const autoDeafen = (Files.data.settings.autoDeafen ?? 'true') === 'true';
const leaveVoiceTimeout = Files.data.settings.leaveVoiceTimeout ?? '10';
let seconds = parseInt(leaveVoiceTimeout, 10);

if (isNaN(seconds) || seconds < 0) seconds = 0;
if (leaveVoiceTimeout === '' || !isFinite(seconds)) seconds = 0;
// Needs to be converted to Milliseconds, keeping the same variable.
if (seconds > 0) seconds *= 1000;

const query = this.evalMessage(data.query, cache);
const queue = player.createQueue(server, {
metadata: {
channel,
},
autoSelfDeaf: (Files.data.settings.autoDeafen ?? 'true') === 'true',
initialVolume: volume,
leaveOnEmpty: data.leaveOnEmpty,
leaveOnEmptyCooldown: seconds,
leaveOnEnd: data.leaveOnEnd,
async onBeforeCreateStream(track, source) {
if (source === 'youtube') {
return (await playdl.stream(track.url, { discordPlayerCompatibility: true })).stream;
}
},
});

const track = await player.search(query, {
requestedBy: cache.getUser(),
});
const serverQueue = Bot.bot.queue.get(server.id);

let songs = [];

if (ytpl.validateID(query)) {
let playlist;
try {
playlist = await ytpl(query);
} catch (error) {
console.log(error);
return this.callNextAction(cache);
}

songs = playlist.items.map((item) => ({
title: item.title,
thumbnail: item.thumbnail,
url: item.shortUrl,
author: item.author.name,
duration: item.duration.split(':').reduce((acc, time) => 60 * acc + Number(time)),
requestedBy: cache.getUser().id,
}));
} else {
let songInfo;
try {
songInfo = await ytdl.getInfo(query);
} catch (error) {
console.log(error);
return this.callNextAction(cache);
}

songs.push({
title: songInfo.videoDetails.title,
thumbnail: songInfo.videoDetails.thumbnails[songInfo.videoDetails.thumbnails.length - 1].url,
url: songInfo.videoDetails.video_url,
author: songInfo.videoDetails.author.name,
duration: songInfo.videoDetails.lengthSeconds,
requestedBy: cache.getUser().id,
});
}

if (!serverQueue) {
const queueData = {
connection: null,
player: createAudioPlayer(),
songs: [],
currentIndex: 0,
repeatMode: 0,
};

Bot.bot.queue.set(server.id, queueData);
queueData.songs.push(...songs);

if (track.tracks.length > 0) {
let connection;
try {
if (!queue.connection) await queue.connect(voiceChannel);
connection = joinVoiceChannel({
channelId: voiceChannel.id,
guildId: server.id,
adapterCreator: server.voiceAdapterCreator,
selfDeaf: autoDeafen,
});
} catch {
queue.destroy();
console.log('Could not join voice channel');
queueData.player.stop();
queueData.player.removeAllListeners();
Bot.bot.queue.delete(server.id);
return this.callNextAction(cache);
}

track.playlist ? queue.addTracks(track.tracks) : queue.addTrack(track.tracks[0]);
if (data.type === '1') {
await queue.play();
}
if (data.type === '0') {
if (!queue.playing) await queue.play();
queueData.connection = connection;
connection.subscribe(queueData.player);

const stream = ytdl(queueData.songs[queueData.currentIndex].url, {
filter: 'audioonly',
fmt: 'mp3',
highWaterMark: 1 << 30,
liveBuffer: 20000,
dlChunkSize: 1024 * 1024,
quality: 'lowestaudio',
bitrate: 128,
});
const resource = createAudioResource(stream, { inlineVolume: true });
resource.volume.setVolume(volume / 100);
queueData.player.play(resource);

queueData.player.on(AudioPlayerStatus.Idle, async () => {
let nextSongUrl;
if (queueData.repeatMode === 1) {
nextSongUrl = queueData.songs[queueData.currentIndex].url;
} else if (queueData.repeatMode === 2 && queueData.songs.length > 0) {
queueData.currentIndex = (queueData.currentIndex + 1) % queueData.songs.length;
nextSongUrl = queueData.songs[queueData.currentIndex].url;
} else {
queueData.currentIndex += 1;
if (queueData.currentIndex < queueData.songs.length) {
nextSongUrl = queueData.songs[queueData.currentIndex].url;
} else {
if (leaveOnEnd) {
connection.disconnect();
}
return;
}
}

const nextStream = ytdl(nextSongUrl, {
filter: 'audioonly',
fmt: 'mp3',
highWaterMark: 1 << 30,
liveBuffer: 20000,
dlChunkSize: 1024 * 1024,
quality: 'lowestaudio',
bitrate: 128,
});
const nextResource = createAudioResource(nextStream, { inlineVolume: true });
nextResource.volume.setVolume(volume / 100);
queueData.player.play(nextResource);
});

if (leaveOnEmpty) {
Bot.bot.on('voiceStateUpdate', (oldState, newState) => {
const botChannel = connection.joinConfig.channelId;
if (!botChannel) return;

const botVoiceChannel = server.channels.cache.get(botChannel);
if (botVoiceChannel && botVoiceChannel.members.size === 1) {
setTimeout(() => {
if (botVoiceChannel.members.size === 1) {
connection.disconnect();
}
}, seconds);
}
});
}
const storage = parseInt(data.storage, 10);
const varName2 = this.evalMessage(data.varName2, cache);
this.storeValue(track, storage, varName2, cache);

Bot.bot.on('voiceStateUpdate', (oldState, newState) => {
if (oldState.channelId && !newState.channelId && oldState.member.id === Bot.bot.user.id) {
connection.disconnect();
}
});

connection.on(VoiceConnectionStatus.Disconnected, () => {
connection.destroy();
queueData.player.stop();
queueData.player.removeAllListeners();
Bot.bot.queue.delete(server.id);
});
} else if (data.type === '1') {
const currentSong = serverQueue.songs[serverQueue.currentIndex];
serverQueue.songs.splice(serverQueue.currentIndex + 1, 0, songs[0]);
serverQueue.songs.splice(serverQueue.currentIndex + 2, 0, currentSong);
serverQueue.player.stop();
} else {
serverQueue.songs.push(...songs);
}

const storage = parseInt(data.storage, 10);
const varName2 = this.evalMessage(data.varName2, cache);
this.storeValue(songs[0], storage, varName2, cache);
this.callNextAction(cache);
},

Expand Down
Loading

0 comments on commit bef206a

Please sign in to comment.