Just another music package
Uses youtube to get audio
(Real docs soon)
npm i frost-music@latestIf you want to skip reading this and just install all of them at once (doesnt install ffmpeg)
npm i ytdl-core yt-stream @discordjs/voice @discordjs/opus sodium-nativeffmpeg is required for this package to work
You can download ffmpeg from here
Or if you would rather install it from npm you can run the following code
npm i ffmpeg-staticytdl-core- Download audioyt-stream- Search youtube
yt-stream would have been used to download, but it sometimes drops the data
npm i ytdl-core yt-streamThis pacakge requires:
- Discord.js voice wrapper
@discordjs/voice - Opus encoding library
@discordjs/opus(can be substituted foropusscript) - Encryption package
sodium-native(can be substituted forlibsodium-wrappers)
npm i @discordjs/voice @discordjs/opus sodium-nativeconst {Client, GatewayIntentBits: Intents, Events} = require('discord.js');
const MusicManager = require('frost-music');
let prefix = '!';
const client = new Client({
intents: [
Intents.Guilds,
Intents.GuildMessages,
Intents.MessageContent,
Intents.GuildVoiceStates
]
});const Music = new MusicManager(client, {
exludeBot: true, // Exlude bot accounts from member vc count
deaf: true, // Make bot deafen
errors: true, // Log errors
volume: 100, // Set default volume (starts to distort over 100)
maxVolume: 250, // Set maximum volume
loop: false // Set default looping
});// When song starts
Music.on(Music.Events.songStart, (data, player) => {
player.data.channels.text.send(`Now playing: \`${data.song.title} by ${data.song.author}\``);
});
// When song is skipped
Music.on(Music.Events.songSkip, (data, player) => {
player.data.channels.text.send(`Skipped \`${data.song.title} by ${data.song.author}\``);
});
// When song ends
Music.on(Music.Events.songEnd, (data, player) => {
player.data.channels.text.send(`Song: \`${data.song.title} by ${data.song.author}\` has ended`);
});
// When song is added to queue
Music.on(Music.Events.queueAdd, (data, player) => {
player.data.channels.text.send(`Added \`${data.song.title} by ${data.song.author}\` to the queue`);
});
// When song is removed from queue
Music.on(Music.Events.queueRemove, (data, player) => {
player.data.channels.text.send(`Removed \`${data.song.title} by ${data.song.author}\` from queue`);
});
// When queue is cleared
Music.on(Music.Events.queueClear, (player) => {
player.data.channels.text.send(`Queue cleared`);
});
// When queue is empty
Music.on(Music.Events.queueEnd, (player) => {
player.data.channels.text.send(`Nothing left to play`);
});
// Get when loop is toggled
Music.on(Music.Events.loopToggled, (looping, player) => {
player.data.channels.text.send(`Looping set to \`${looping}\``);
});
// Get when volume changes
Music.on(Music.Events.volumeChange, (volume, player) => {
player.data.channels.text.send(`Volume set to \`${volume}\``);
});
// Get when player is paused
Music.on(Music.Events.paused, (player) => {
player.data.channels.text.send(`Paused playback`);
});
// Get when player is unpaused
Music.on(Music.Events.unpaused, (player) => {
player.data.channels.text.send(`Resumed playback`);
});
// Get when bot leaves
Music.on(Music.Events.leave, (player) => {
player.data.channels.text.send(`Left`);
});
// When an error occours with the player
Music.on(Music.Events.error, (err, player) => {
console.log(`Error: ${err}`);
});This is seperate because its big and optional
// Get search results (big one bc it also adds)
Music.on(Music.Events.searchResult, (results, msg, player) => {
let list = [],
size = results.data.length > 10? 10: results.data.length;
for(let i = 0; i < size; i++){
let result = results.data[i];
list.push(`${i+1}. \`${result.title} by ${result.author}\``)
}
// Send results for user to see
msg.channel.send(list.join('\n'))
// Add collector to add song
const collectorFilter = m => (m.author.id == msg.author.id);
const collector = msg.channel.createMessageCollector({
filter: collectorFilter,
time: 15_000 // Give 15 seconds to choose
});
// Save if valid awnser has been given
let recived = false;
// Get messages
collector.on('collect', m => {
// Return if done, or not a number
if(recived || !Number(m.content)) return;
// Return if over 10 or less than 1
if(Number(m.content) > 10 || Number(m.content) < 1) return;
recived = true;
player.addFromSearch(Number(m.content)-1, m.author.id)
});
// End of 15 seconds
collector.on('end', () => {
// See if recived
if(recived) return;
// Didnt get anything :(
msg.channel.send('Didnt get a response on time')
});
});This is optional
// When user leaves voice
client.on(Events.VoiceStateUpdate, (oldState, newState) => {
if (!oldState.channel && newState.channel) return;
if (!Music.has(oldState.guild.id)) return;
if (Music.membercount(oldState.guild.id) < 1) {
Music.leave(oldState.guild.id);
}
});client.on(Events.MessageCreate, (msg) => {
if (!msg.content.toLowerCase().startsWith(prefix)) return;
let args = msg.content.slice(prefix.length).trim().split(/ +/g);
let command = args.shift().toLowerCase();
// Play song
if (command == 'play') {
// Check if message author is in voice channel
if (!msg.member.voice.channel) return msg.channel.send("You must be in a voice");
// Create the player for guild if there is none
if (!Music.has(msg.guild.id)) Music.create(msg.guild, msg.member.voice.channel, msg.channel);
let player = Music.get(msg.guild.id);
// Add song with who it was requested by
player.play(args.join(' '), msg.author.id);
}
// Search for song
if(command == 'search'){
// Check if message author is in voice channel
if (!msg.member.voice.channel) return msg.channel.send("You must be in a voice");
// Create the player for guild if there is none
if (!Music.has(msg.guild.id)) Music.create(msg.guild, msg.member.voice.channel, msg.channel);
let player = Music.get(msg.guild.id);
player.search(args.join(' '), msg);
}
// Rest require player before use
if(Music.has(msg.guild.id)){
let player = Music.get(msg.guild.id);
// Skip the current song
if(command == 'skip') player.skipSong();
// Pause the saong
if(command == 'pause') player.pause();
// Resume the song
if(command == 'unpause') player.unpause();
// Set volume of song
if(command == 'volume') player.setVolume(args[0])
// Loop current song
if(command == 'loop') player.loop();
// Leave channel and stopp all playback
if(command == 'leave') player.leave();
// Clear the queue
if(command == 'clear') player.clearQueue();
// Remove item from queue
if(command == 'remove') player.removeFromQueue(arg[0])
}
});client.on(Events.ClientReady, () => {
console.log(`Logged in as ${client.user.username}!`);
});client.login('token-here')-- More platforms may come soon --