2018-10-14 14:16:14 +02:00
package nl.voidcorp.dbot.commands
import com.jagrosh.jdautilities.command.CommandEvent
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist
import com.sedmelluq.discord.lavaplayer.track.AudioTrack
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame
import net.dv8tion.jda.core.audio.AudioSendHandler
2018-10-15 22:25:51 +02:00
import nl.voidcorp.dbot.addAll
import nl.voidcorp.dbot.commands
2018-10-14 14:16:14 +02:00
import nl.voidcorp.dbot.log
import nl.voidcorp.dbot.music.TrackScheduler
import nl.voidcorp.dbot.playerManager
val guildMusicMap = mutableMapOf < Long , TrackScheduler > ( )
fun initMusic ( ) {
AudioSourceManagers . registerRemoteSources ( playerManager )
2018-10-25 13:47:54 +02:00
val queueCommand = UnityMusicCommand ( " queue " , aliases = * arrayOf ( " q " ) , help = " Use this command to queue a song, if you don't add a link it will search on youtube with the specified arguments \n \n Execute with no arguments to view the current queue! " , howTo = " q [link] " ) { event , scheduler ->
2018-10-14 14:16:14 +02:00
2018-10-15 22:25:51 +02:00
if ( event . args . isEmpty ( ) ) {
if ( ! guildMusicMap . containsKey ( event . guild . idLong ) || ( guildMusicMap [ event . guild . idLong ] !! . player . playingTrack == null ) )
event . reply ( " The track list is empty " ) else
event . reply ( guildMusicMap [ event . guild . idLong ] !! . getTrackList ( event . member ) )
2018-10-17 21:15:09 +02:00
return @UnityMusicCommand
2018-10-15 22:25:51 +02:00
}
2018-10-14 14:16:14 +02:00
playerManager . loadItem ( event . args , object : AudioLoadResultHandler {
override fun loadFailed ( exception : FriendlyException ) {
event . reply ( " Shit's fucked! " )
}
override fun trackLoaded ( track : AudioTrack ) {
scheduler . queue ( track , event . member )
}
override fun noMatches ( ) {
2018-10-14 22:20:47 +02:00
getLinkFromSearch ( event , scheduler , false )
}
override fun playlistLoaded ( playlist : AudioPlaylist ) {
for ( t in playlist . tracks ) {
scheduler . queue ( t , event . member )
}
}
} )
}
2018-10-25 13:47:54 +02:00
val ytCommand = UnityMusicCommand ( " youtube " , aliases = * arrayOf ( " yt " ) , help = " Search YouTube for a song! " , howTo = " youtube <search term or link> " ) { event , scheduler ->
2018-10-17 21:15:09 +02:00
if ( event . args . isEmpty ( ) ) {
event . reply ( " Please supply a song name or URL! " )
return @UnityMusicCommand
}
playerManager . loadItem ( event . args , object : AudioLoadResultHandler {
override fun loadFailed ( exception : FriendlyException ) {
event . reply ( " Shit's fucked! " )
}
override fun trackLoaded ( track : AudioTrack ) {
scheduler . queue ( track , event . member )
}
override fun noMatches ( ) {
getLinkFromSearch ( event , scheduler , false )
}
override fun playlistLoaded ( playlist : AudioPlaylist ) {
for ( t in playlist . tracks ) {
scheduler . queue ( t , event . member )
}
}
} )
2018-10-14 22:20:47 +02:00
}
2018-10-25 13:47:54 +02:00
val soundcloudCommand = UnityMusicCommand ( " soundcloud " , help = " Play a song via SoundCloud! " , aliases = * arrayOf ( " sc " ) , howTo = " sc <link or search term> " ) { event , scheduler ->
2018-10-17 21:15:09 +02:00
if ( event . args . isEmpty ( ) ) {
event . reply ( " Please supply a song name or URL! " )
return @UnityMusicCommand
}
2018-10-14 22:20:47 +02:00
playerManager . loadItem ( event . args , object : AudioLoadResultHandler {
override fun loadFailed ( exception : FriendlyException ) {
event . reply ( " Shit's fucked! " )
}
override fun trackLoaded ( track : AudioTrack ) {
scheduler . queue ( track , event . member )
}
override fun noMatches ( ) {
getLinkFromSearch ( event , scheduler , false , " scsearch " )
2018-10-14 14:16:14 +02:00
}
override fun playlistLoaded ( playlist : AudioPlaylist ) {
for ( t in playlist . tracks ) {
scheduler . queue ( t , event . member )
}
}
} )
}
2018-10-25 13:47:54 +02:00
val playCommand = UnityMusicCommand ( " play " , " Force this song to be the next! " , aliases = * arrayOf ( " p " ) , howTo = " play <url> " ) { event , scheduler ->
2018-10-17 21:15:09 +02:00
if ( event . args . isEmpty ( ) ) {
event . reply ( " Please supply a song name or URL! " )
return @UnityMusicCommand
}
2018-10-14 14:16:14 +02:00
playerManager . loadItem ( event . args , object : AudioLoadResultHandler {
override fun loadFailed ( exception : FriendlyException ) {
event . reply ( " Shit's fucked! " )
}
override fun trackLoaded ( track : AudioTrack ) {
scheduler . insertFront ( track , event . member )
}
override fun noMatches ( ) {
2018-10-14 22:20:47 +02:00
getLinkFromSearch ( event , scheduler , true )
2018-10-14 14:16:14 +02:00
}
override fun playlistLoaded ( playlist : AudioPlaylist ) {
for ( t in playlist . tracks ) {
scheduler . insertFront ( t , event . member )
}
}
} )
}
2018-10-14 22:20:47 +02:00
2018-10-15 22:25:51 +02:00
val skipCommand = UnityCommand ( " skip " , help = " Skip the current song " , aliases = * arrayOf ( " s " ) , category = musicCategory ) { event ->
2018-10-14 14:16:14 +02:00
val scheduler = guildMusicMap [ event . guild . idLong ]
if ( scheduler == null ) {
event . reply ( " There is no music playing? " )
} else {
scheduler . skip ( )
}
2018-10-15 22:25:51 +02:00
}
val npCommand = UnityMusicCommand ( " nowplaying " , aliases = * arrayOf ( " np " ) , help = " Show the currently playing song " ) { event , scheduler ->
if ( ! scheduler . isSongPlaying ( ) ) {
event . reply ( " There is no song playing? " )
} else {
event . reply ( scheduler . getCurrentTrackInfo ( ) )
}
}
2018-10-17 21:15:09 +02:00
val attachmentPlay = UnityMusicCommand ( " attachment " , help = " Play any attached song, if it is in a normal format that is... \n \n `just drag and drop the song on your Discord window and in the optional comment add !attach(ment)` " , aliases = * arrayOf ( " attach " ) ) { event , scheduler ->
2018-10-15 22:25:51 +02:00
val attach = event . message . attachments . firstOrNull ( )
if ( attach == null ) {
event . reply ( " I can't play an attachment without an attachment... " )
} else {
playerManager . loadItem ( attach . url , object : AudioLoadResultHandler {
override fun loadFailed ( exception : FriendlyException ) {
event . reply ( " Shit's fucked! " )
}
2018-10-14 14:16:14 +02:00
2018-10-15 22:25:51 +02:00
override fun trackLoaded ( track : AudioTrack ) {
scheduler . queue ( track , event . member )
if ( ! scheduler . isQueueEmpty ( ) or scheduler . isSongPlaying ( ) ) {
scheduler . getTrackInfo ( track )
}
}
override fun noMatches ( ) {
}
override fun playlistLoaded ( playlist : AudioPlaylist ) {
for ( t in playlist . tracks ) {
scheduler . queue ( t , event . member )
}
}
} )
}
2018-10-14 14:16:14 +02:00
}
2018-10-15 22:25:51 +02:00
commands . addAll ( playCommand , skipCommand , queueCommand , ytCommand , soundcloudCommand , npCommand , attachmentPlay )
2018-10-14 14:16:14 +02:00
}
2018-10-14 22:20:47 +02:00
fun getLinkFromSearch ( event : CommandEvent , scheduler : TrackScheduler , shouldInsertFront : Boolean , searchPrefix : String = " ytsearch " ) {
log . info ( " Searching youtube for ' ${event.args} ' " )
2018-10-14 14:16:14 +02:00
2018-10-14 22:20:47 +02:00
playerManager . loadItem ( " $searchPrefix : ${event.args} " , object : AudioLoadResultHandler {
2018-10-14 14:16:14 +02:00
override fun loadFailed ( exception : FriendlyException ) {
event . reply ( " Shit's fucked! " )
}
override fun trackLoaded ( track : AudioTrack ) {
2018-10-14 22:20:47 +02:00
if ( shouldInsertFront )
scheduler . insertFront ( track , event . member )
else
scheduler . queue ( track , event . member )
2018-10-14 14:16:14 +02:00
/ * event . reply (
EmbedBuilder ( ) . setImage ( r . snippet . thumbnails . high . url ) . setTitle ( r . snippet . title , " https://youtu.be/ $id " )
. setAuthor ( r . snippet . channelTitle ) . setFooter ( " Requested by ${event.member.effectiveName} " , event . author . effectiveAvatarUrl )
. setDescription ( r . snippet . description ) . build ( )
) * /
}
override fun noMatches ( ) {
}
override fun playlistLoaded ( playlist : AudioPlaylist ) {
if ( ! playlist . isSearchResult )
for ( t in playlist . tracks ) {
2018-10-14 22:20:47 +02:00
if ( shouldInsertFront )
scheduler . insertFront ( t , event . member )
else
scheduler . queue ( t , event . member )
2018-10-14 14:16:14 +02:00
}
else {
val track = playlist . tracks . first ( )
2018-10-14 22:20:47 +02:00
2018-10-14 14:16:14 +02:00
2018-10-14 22:20:47 +02:00
if ( shouldInsertFront )
scheduler . insertFront ( track , event . member )
else
scheduler . queue ( track , event . member )
2018-10-14 14:16:14 +02:00
2018-10-15 22:25:51 +02:00
if ( ! scheduler . isQueueEmpty ( ) or scheduler . isSongPlaying ( ) ) {
if ( scheduler . player . playingTrack != track )
event . reply ( scheduler . getTrackInfo ( track ) )
}
2018-10-14 14:16:14 +02:00
}
}
} )
}
class AudioPlayerSendHandler ( private val audioPlayer : AudioPlayer ) : AudioSendHandler {
private var lastFrame : AudioFrame ? = null
override fun canProvide ( ) : Boolean {
lastFrame = audioPlayer . provide ( )
return lastFrame != null
}
override fun provide20MsAudio ( ) : ByteArray {
return lastFrame !! . data
}
override fun isOpus ( ) : Boolean {
return true
}
}