@kyometori/djsmusic
v0.8.5
Published
A simple wrapper of @discordjs/voice library. This can help you make music bot easier
Downloads
20
Maintainers
Readme
@kyometori/djsmusic
Warning
This package is still under heavy development, so there might be some breaking changes. We'll try to make breaking changes as less as we can, but if there's any, we're sorry about that.
Introduction
This is a simple wrapper of @discordjs/voice library.
You can use this package to build a music bot with your discord.js client easily.
We also have our own Classes and wrapper of ytdl, ytsr to help you process data easier, more logical, and faster. The current support sites are Youtube and SoundCloud (under development).
const { Client } = require('discord.js');
const { createMusicManager } = require('@kyometori/djsmusic');
const client = new Client({ intents: ['GUILDS', 'GUILD_VOICE_STATES'] });
client.once('ready', () => {
createMusicManager(client);
console.log('Everything is ready!');
});
client.on('interactionCreate', interaction => {
if (!interaction.isCommand()) return;
if (interaction.commandName === 'join') {
interaction.client.music.join({
channel: interaction.member.voice.channel
});
}
if (interaction.commandName === 'play') {
const url = interaction.options.getString('url');
interaction.client.music.get(interaction.guild.id).play(url, {
player: interaction.member
});
}
});
client.login('your-token-goes-here');
Table of contents
Requirements
To use this package, you must meet these requirements:
- discord.js version > 13
- FFmpeg Dependency. Can be one of those below:
FFmpeg
(installed and added to environment)ffmpeg-static
(npm install)
Documentation
createMusicManager
createMusicManager (Client client, Object options, String property)
Build a music manager on client[property]
. If no property supply, it'll automatically use music
. The options
will be automatically applied to the Manager options.
This is the most important object in this package. For most usage you only need to import this (and some utils below) for your bot.
ClientMusicManager
constructor
new ClientMusicManager (Client client, {
Number defaultMaxQueueSize, // the default maximum size of queue, will be automatically applied to all its `GuildMusicManager`
Boolean enableQueue, // whether we should enable the default queue system
Boolean enableAutoplay, // if set to `false`, it won't automatically play the next song of the queue
Boolean enableInlineVolume, // whether should inline volume be enable
Boolean disableWarning, // whether we should show warnings
Object enableService : { // determine which service should be enable
Boolean rawFile, // ability to play raw file
Boolean youtube // ability to play youtube link directly
}
})
Every boolean property is set to true
except enableInlineVolume
due to better performance. If you want to have the feature of 'adjust volumen during playing' you have to set this to true.
In default defaultMaxQueueSize
is 99. Can set to Infinity
if you don't want a limit.
The enableService
is for you to enable or disable some service if you don't want your bot to play that.
properties
client
: the client that instantiated thisconnections
: (readonly) A Map contains all this manager'sGuildMusicManager
, mapped by their id.
methods
has(Snowflake id)
: if we have connection of the guild of given id in our dataget(Snowflake id)
: get the GuildMusicManager object that handle the guild of given idjoin({ VoiceChannel channel, Boolean setMute, Boolean setDeaf, Number maxQueueSize })
: join the given voice channel and self mute or deaf if given. Returns aPromise<GuildMusicManager>
which is the manager of joined guild.leave(Snowflake id)
: leave the guild of given id.
events
join
: Emit after your client joined a channel.- Params:
Guild guild
the guild of joined channel.
- Params:
leave
: Emit after your client left a channel.- Params:
Guild guild
the guild of left channel.
- Params:
GuildMusicManager
constructor
new GuildMusicManager ({
Client client, // client of your bot
ClientMusicManager manager, // music manager of your client
VoiceChannel channel, // the voice channel joined
Number maxQueueSize // the max size of this manager's queue
})
properties
client
: the Client that instantiated thisguild
: the guild of this managerchannel
: the VoiceChannel that instantiated thismanager
: the ClientMusicManager that instantiated thisvoiceState
: the voiceState of Clientplayer
: the player of this managerqueue
: the queue of this managerMAX_QUEUE_SIZE
: the max size of this manager's queueisPlaying
: is this manager's player playingnowPlaying
: empty object if nothing is playing, or aTrack
object when there's something
methods
play(String url, Object customMetadata, Boolean force)
: The url of music you want to play. If the url is unsupported, it'll throw aUNSUPPORTED_URL_TYPE
Error.customMetadata
can be access throughTrack
andTrack#details
. Force is to determine to skip what's playing now or queue this song if there are already something playing. Returns aPromise<[Track, Boolean]>
. TheTrack
object is the song you just queue or play, and theBoolean
is this song is queued or not (playing directly).next()
: Get and remove the first song of the queue. If it's looping, it'll return what's playing now.hasNext()
: Does this manager has next song. If current track is looping it always returns true.seek(Number time)
: Seek a specific time of current song. Time is in milliseconds. If the number is larger than the total time it'll throw aINVALID_SEEK_TIME
Error.getVolume()
: get current volume. If it's2
means the volume is2x
louder than default.setVolume(Number number)
: set the volume of current track. You have to enable inline volume in theClientMusicManager
to use this function.setOnStage(Boolean yes)
: let the bot be on the stage if set to true, or not if set to falsesetLoop(Boolean loop)
: loop the current track or not, set to true to looppause()
: pause what's playingresume()
: unpause what's playingskip()
: skip what's playingleave()
: leave the voice channel and kill this manager
events
play
: emit after a track started playing- Params:
Track track
the track is played
- Params:
leave
: emit after client left this guild- Params:
Guild guild
the guild of this manager
- Params:
end
: emit when a song is finished playing (same as Track#end)- Params:
Track next
the track that's gonna play after this track. If no then it will beundefined
.
- Params:
finish
: emit after every song in queue finished playing
Track
constructor
new Track({
audioUrl, // the audio resource url of this track
manager, // the GuildMusicManager playing this track
metadata: {
title // title of this track, default unknown
lengthSeconds // length of this track, default Infinity
player // the one choose play this song, required
details // Other metadata of this track, default empty object
}
})
When track is construct automatically by given Youtube URL in GuildMusicManager
, its details
property will includes:
from
: Always'Youtube'
. You can use this to determine where this track is.data
: AYoutubeVideoData
object. You can find its properties below.
properties
manager
: the manager that instantiated this.title
: the title of this tracklengthSeconds
: the length of this song, in seconds.player
: who pick this song. this is required but can be anything such as 'unknown', aGuildMember
Object etc.details
: the detail metadata of this trackisLooping
: whether this track looping or notplayedMs
: (readonly) how many milliseconds the track played
events
end
: emits after this track finish playing
YoutubeUtils
methods
isYoutubeLink(String link)
: (static) check if the link is a Youtube link.isPlaylistLink(String link)
: (static) check if the link is a Youtube playlist link.getVideoData(String link)
: (static) get the data of the video. Returns aYoutubeVideoData
object if find it, or throw an Error when no data have been found.getPlaylistData(String link, Number page)
: (static) get the data of the playlist.page
determine how many pages of this playlist should be fetched. DefaultInfinity
. Returns aYoutubePlaylistData
object if find it, or throw an Error when no data have been found.searchFirstVideo(String keywords)
: (static) Use the keywords to search, and return the first (most related) video. Returns aYoutubeVideoData
Object.search(String keywords, Number max, { Boolean disableChannel, Boolean disablePlaylist, Boolean disableVideo })
: (static) Use the keywords to search, and return at mostmax
results. You can usedisableSomething
to pull the type you don't want from results. In default only video is enable. Returns an Array ofYoutubeObjectData
, which is one ofYoutubeVideoData
,YoutubeChannelData
,YoutubePlaylistData
.
YoutubeVideoData
constructor
new YoutubeVideoData(rawData) // raw data from ytsr
// you can construct this by passing your own data, but you need `type: 'video'` guard in the data or will cause an Error.
properties
type
: always'video'
title
: title of this videourl
: youtube url of this videoisCrawlable
: can this video be crawl.thumbnailUrl
: url of this video's thumbnailuploadDate
: the date this video uploaded, formatted inyyyy-mm-dd
.viewCount
: the viewCount of this video.audioUrl
: the original audio file url of this video.channel
: channel uploaded this video. This is aYoutubeChannelData
Object.
methods
play(GuildMusicManager manager, Object customMetadata, Boolean force)
: Play this video. This behave same asGuildMusicManager#play
. Returns same thing withGuildMusicManager#play
.fetch()
: Fetch this video and fullfill thoseundefined
properties.
YoutubeChannelData
constructor
new YoutubeChannelData(rawData) // raw data from ytsr
// you can construct this by passing your own data, but you need `type: 'channel'` guard in the data or will cause an Error.
properties
type
: always'channel'
name
: name of this channelchannelId
: id of this channelurl
: url to this channeldescriptionShort
: short description of this channel, if any. Notice that if this is fromYoutubeVideoData#channel
orYoutubePlaylistData#channel
, you have to fetch to get this.avatarUrl
: url to avatar of this channel. Notice that if this is fromYoutubePlaylistData#channel
, you have to fetch to get this.verified
: whether this channel is verified or not
methods
fetch()
: Fetch this channel to get missing properties. ReturnPromise<YoutubeChannelData>
. Notice this usename
andchannelId
to get data. An error will occurred when one missing. Also it will refresh all data of this object if the fetched data is different from your original data (most happened in construct this object manually).
YoutubePlaylistData
constructor
new YoutubePlaylistData(rawData) // raw data from ytsr
// you can construct this by passing your own data, but you need `type: 'playlist'` guard in the data or will cause an Error.
properties
type
: alwaysplaylist
.title
: the title of this playlist.data
: aArray<YoutubeVideoData>
, contains all crawlable video inside.url
: url of this playlist.firstVideoThumbnailUrl
: thumbnail of this playlist's first videochannel
: channel created this playlist. This is aYoutubeChannelData
Object.
methods
fetch(Number page)
: fetch this playlist and fullfill the properties with its url. Thepage
determine how many pages of the playlist should be fetched. DefaultInfinity
.
SoundCloudUtils
methods
isSoundCloudLink(String link)
: (static) check if the link is a kind of SoundCloud link;getTrackData(String link)
: (static) get a track's data by its link. Returns aPromise<SoundCloudTrackData>
SoundCloudTrackData
constructor
new SoundCloudTrackData(rawData) // raw data from soundcloud-scraper
// you can construct this data manually and fetch it to get more informations
properties
type
: always'track'
id
: the id of this tracktitle
: the title of this trackdescription
: the description of this tracklengthSeconds
: how long is this track, in secondsthumbnail
: thumbnail of this trackurl
: url of this trackplayCount
: the play count of this trackgenre
: the genre of this track
Examples
Examples can be found here.
Example usages
These examples assume:
<Client>
: Your bot's client<Channel>
: the target channel<Id>
: the target guild id<Url>
: the links<User>
: the one pick this song<Time>
: a time in unit milliseconds<Keywords>
: Search keywords
Also we assume your ClientMusicManager
is on <Client>.music
.
Join and Leave
// join
<Client>.music.join({ channel: <Channel> });
// leave #1
<Client>.music.leave(<Id>);
// leave #2
<Client>.music.get(<id>).leave();
Play
// Normal playing
<Client>.music.get(<Id>).play(<Url>, { player: <User> });
// With promise
<Client>.music
.get(<Id>)
.play(<Url>, { player: <User> })
.then(([track, queued]) => {
if (queued) console.log(`${track.title} is queued!`);
else console.log(`${track.title} is playing!`);
});
The url
parameter of the play
method accept following urls:
- Raw
mp3
,mp4
,wav
,ogg
,aac
,flac
files. The url must ended with.(file extension)
- A Youtube link.
Pause and Resume
<Client>.music.get(<Id>).pause();
<Client>.music.get(<Id>).resume();
Toggle Looping
const manager = <Client>.music.get(<id>);
manager.setLoop(!manager.nowPlaying.isLooping);
Seek a time
<Client>.music.get(<Id>).seek(<Time>);
Get NowPlaying Data
// If anything is playing, this will be a Track object
// Otherwise it's an empty Object
<Client>.music.get(<Id>).nowPlaying;
Volume Increase
const manager = <Client>.music.get(<id>);
manager.setVolume(manager.getVolume() + 0.1);
Notice you have to enable inline volume when create your ClientMusicManager
to use this feature.
Logging when song is finished
const manager = <Client>.music.get(<Id>);
manager.on('end', next => {
if (!next) console.log('Finish all queued songs!');
else console.log('Start playing next song...');
});
Leave when queue is finished
<Client>.music
.join({ channel: <Channel> })
.then(manager => {
manager.once('finish', () => {
manager.leave();
});
});
This code implements both join and set up leave-when-finished.
Search and play the most related song by keywords
YoutubeUtils.searchFirstVideo(<Keywords>)
.then(data => {
data.play(<Client>.music.get(<Id>), { player: <User> });
})
.catch(err => {
console.log(err);
});
For more examples you can look at our examples or look up our Documentation and create features yourself!
Thanks
Junior HiZollo : My another project which is a Discord bot with music feature. This library is basically rewriting its music (which was also written by me) and make it generic.