OttoBot/src/main/kotlin/nl/voidcorp/dbot/commands/Music.kt

205 lines
6.8 KiB
Kotlin

package nl.voidcorp.dbot.commands
import com.jagrosh.jdautilities.command.CommandBuilder
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.EmbedBuilder
import net.dv8tion.jda.core.audio.AudioSendHandler
import net.dv8tion.jda.core.entities.Member
import nl.voidcorp.dbot.cb
import nl.voidcorp.dbot.log
import nl.voidcorp.dbot.music.TrackScheduler
import nl.voidcorp.dbot.playerManager
import java.time.LocalDateTime
val guildMusicMap = mutableMapOf<Long, TrackScheduler>()
fun initMusic() {
AudioSourceManagers.registerRemoteSources(playerManager)
val queueCommand = CommandBuilder().setName("queue").addAlias("q").setHelp("Queue's a song").build { event ->
val scheduler = if (guildMusicMap.containsKey(event.guild.idLong)) guildMusicMap[event.guild.idLong]!! else {
val channel = event.guild.voiceChannels.firstOrNull { it.members.contains(event.member) }
if (channel == null) {
event.reply("Join a voice Channel please!")
return@build
}
val s = TrackScheduler(playerManager.createPlayer(), event.guild, channel)
guildMusicMap[event.guild.idLong] = s
s
}
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)
}
override fun playlistLoaded(playlist: AudioPlaylist) {
for (t in playlist.tracks) {
scheduler.queue(t, event.member)
}
}
})
}
val playCommand = CommandBuilder().setName("play").addAlias("p").setHelp("Plays the song instantly").build { event ->
val scheduler = if (guildMusicMap.containsKey(event.guild.idLong)) guildMusicMap[event.guild.idLong]!! else {
val channel = event.guild.voiceChannels.firstOrNull { it.members.contains(event.member) }
if (channel == null) {
event.reply("Join a voice Channel please!")
return@build
}
val s = TrackScheduler(playerManager.createPlayer(), event.guild, channel)
guildMusicMap[event.guild.idLong] = s
s
}
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() {
getLinkFromSearch(event, scheduler)
}
override fun playlistLoaded(playlist: AudioPlaylist) {
for (t in playlist.tracks) {
scheduler.insertFront(t, event.member)
}
}
})
}
val skipCommand = CommandBuilder().setName("skip").addAlias("s").setHelp("Skips the currently playing track").build { event ->
val scheduler = guildMusicMap[event.guild.idLong]
if (scheduler == null) {
event.reply("There is no music playing?")
} else {
scheduler.skip()
}
}
cb.addCommands(playCommand, skipCommand, queueCommand)
}
fun getLinkFromSearch(event: CommandEvent, scheduler: TrackScheduler) {
log.info("Searching for '${event.args}'")
/*val search = yt.search().list("id,snippet")
search.key = "AIzaSyDiEYrQNT-eDRZKy6JvQHBDymttwaLd7Mg"
search.q = event.args
search.type = "video"
search.fields = "items(id/kind,id/videoId,snippet/title,snippet/thumbnails/high/url,snippet/description,snippet/channelTitle)"
search.maxResults = 10
val res = search.execute()
if (res.isEmpty()) {
event.reply("Really nothing was found...")
} else {
var found = false
for (r in res.items) {
if (r.id.kind == "youtube#video" && !found) {
found = true
val id = r.id.videoId
}
}
if (!found) {
event.replyError("I could really not find anything for '${event.args}'")
}
}*/
playerManager.loadItem("ytsearch:${event.args}", object : AudioLoadResultHandler {
override fun loadFailed(exception: FriendlyException) {
event.reply("Shit's fucked!")
}
override fun trackLoaded(track: AudioTrack) {
scheduler.queue(track, event.member)
/*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) {
scheduler.queue(t, event.member)
}
else {
val track = playlist.tracks.first()
event.reply(EmbedBuilder()
.setFooter("Requested by ${event.member.effectiveName}", event.member.user.effectiveAvatarUrl)
.setAuthor(track.info.author).setTitle(track.info.title, track.info.uri)
.setThumbnail("https://img.youtube.com/vi/${track.info.identifier}/hqdefault.jpg\n")
.setTimestamp(LocalDateTime.now()).build())
scheduler.queue(track, event.member)
}
}
})
}
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
}
}