Update music bot and fix event

master
Julius de Jeu 2018-10-14 22:20:47 +02:00
parent 2f9e50fd3e
commit f5a3cf5ba6
5 changed files with 140 additions and 56 deletions

View File

@ -23,8 +23,7 @@ dependencies {
compile 'com.jagrosh:jda-utilities:2.1.4' compile 'com.jagrosh:jda-utilities:2.1.4'
compile 'com.sedmelluq:lavaplayer:1.3.7' compile 'com.sedmelluq:lavaplayer:1.3.7'
compile 'com.sedmelluq:jda-nas:1.0.6' compile 'com.sedmelluq:jda-nas:1.0.6'
compile 'khttp:khttp:0.1.0'
} }
compileKotlin { compileKotlin {

View File

@ -13,7 +13,7 @@ object Events : ListenerAdapter() {
event.message.addReaction(e).queue() event.message.addReaction(e).queue()
} }
if (event.message.channel.idLong == 499628388659625995) { if (event.message.channel.idLong == 499628388659625995) {
if (event.message.mentionedMembers.contains(event.guild.getMember(event.jda.selfUser))) { if (event.message.mentionedMembers.contains(event.guild.getMember(event.jda.selfUser)) and (event.message.author != event.jda.selfUser)) {
if (event.message.contentStripped.toLowerCase().contains("hello")) { if (event.message.contentStripped.toLowerCase().contains("hello")) {
val i = random.nextInt(10) val i = random.nextInt(10)

View File

@ -1,9 +1,11 @@
package nl.voidcorp.dbot package nl.voidcorp.dbot
import com.jagrosh.jdautilities.command.CommandClient
import com.jagrosh.jdautilities.command.CommandClientBuilder import com.jagrosh.jdautilities.command.CommandClientBuilder
import com.jagrosh.jdautilities.examples.command.PingCommand import com.jagrosh.jdautilities.examples.command.PingCommand
import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory import com.sedmelluq.discord.lavaplayer.jdaudp.NativeAudioSendFactory
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager
import io.javalin.Javalin import io.javalin.Javalin
import io.javalin.json.FromJsonMapper import io.javalin.json.FromJsonMapper
@ -12,6 +14,7 @@ import io.javalin.json.ToJsonMapper
import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.EmbedBuilder
import net.dv8tion.jda.core.JDA import net.dv8tion.jda.core.JDA
import net.dv8tion.jda.core.JDABuilder import net.dv8tion.jda.core.JDABuilder
import net.dv8tion.jda.core.MessageBuilder
import net.dv8tion.jda.core.entities.Game import net.dv8tion.jda.core.entities.Game
import net.dv8tion.jda.webhook.WebhookClient import net.dv8tion.jda.webhook.WebhookClient
import net.dv8tion.jda.webhook.WebhookClientBuilder import net.dv8tion.jda.webhook.WebhookClientBuilder
@ -29,9 +32,11 @@ val cb = CommandClientBuilder()
val log = LoggerFactory.getLogger("UnityBot") val log = LoggerFactory.getLogger("UnityBot")
@Suppress("JoinDeclarationAndAssignment")
fun main(args: Array<String>) { fun main(args: Array<String>) {
playerManager.registerSourceManager(YoutubeAudioSourceManager(true)) playerManager.registerSourceManager(YoutubeAudioSourceManager(true))
playerManager.registerSourceManager(SoundCloudAudioSourceManager(true))
JavalinJson.apply { JavalinJson.apply {
toJsonMapper = object : ToJsonMapper { toJsonMapper = object : ToJsonMapper {
@ -83,18 +88,30 @@ fun main(args: Array<String>) {
ctx.status(200).result("OK") ctx.status(200).result("OK")
} }
lateinit var client: CommandClient
cb.setOwnerId("168743656738521088") cb.setOwnerId("168743656738521088")
cb.setPrefix("!") cb.setPrefix("!")
cb.setAlternativePrefix("+") cb.setAlternativePrefix("+")
cb.addCommand(PingCommand()) cb.addCommand(PingCommand())
cb.addCommand(helloCommand) cb.addCommand(helloCommand)
cb.setGame(Game.watching("fraud (and a broken music bot)")) cb.setGame(Game.watching("fraud and \uD83C\uDFB5"))
cb.setHelpConsumer { event ->
event.reply(MessageBuilder("Help for ${event.selfMember.asMention}\n").append {
var st = ""
for (c in client.commands) {
st += "`${c.name}`: ${c.help}${if (c.aliases.isNotEmpty()) " (alias: `${c.aliases.first()}`)" else ""}\n"
}
st
}.build()
)
}
initMusic() initMusic()
val client = cb.build() client = cb.build()
bot = JDABuilder(args[0]).addEventListener(client).addEventListener(nl.voidcorp.dbot.Events).setAudioSendFactory(NativeAudioSendFactory()).build() bot = JDABuilder(args[0]).addEventListener(client).addEventListener(nl.voidcorp.dbot.Events).setAudioSendFactory(NativeAudioSendFactory()).build()
} }

View File

@ -5,17 +5,19 @@ import com.jagrosh.jdautilities.command.CommandEvent
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer import com.sedmelluq.discord.lavaplayer.player.AudioPlayer
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioTrack
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException import com.sedmelluq.discord.lavaplayer.tools.FriendlyException
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist
import com.sedmelluq.discord.lavaplayer.track.AudioTrack import com.sedmelluq.discord.lavaplayer.track.AudioTrack
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame
import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.EmbedBuilder
import net.dv8tion.jda.core.audio.AudioSendHandler import net.dv8tion.jda.core.audio.AudioSendHandler
import net.dv8tion.jda.core.entities.Member
import nl.voidcorp.dbot.cb import nl.voidcorp.dbot.cb
import nl.voidcorp.dbot.log import nl.voidcorp.dbot.log
import nl.voidcorp.dbot.music.TrackScheduler import nl.voidcorp.dbot.music.TrackScheduler
import nl.voidcorp.dbot.playerManager import nl.voidcorp.dbot.playerManager
import java.awt.Color
import java.time.LocalDateTime import java.time.LocalDateTime
@ -51,7 +53,49 @@ fun initMusic() {
} }
override fun noMatches() { override fun noMatches() {
getLinkFromSearch(event, scheduler) getLinkFromSearch(event, scheduler, false)
}
override fun playlistLoaded(playlist: AudioPlaylist) {
for (t in playlist.tracks) {
scheduler.queue(t, event.member)
}
}
})
}
val ytCommand = CommandBuilder().setName("youtube").addAlias("yt").setHelp("Play a song from YouTube!").build { event ->
queueCommand.run(event)
}
val soundcloudCommand = CommandBuilder().setName("soundcloud").addAlias("sc").setHelp("Play a song from SoundCloud!").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, false, "scsearch")
} }
override fun playlistLoaded(playlist: AudioPlaylist) { override fun playlistLoaded(playlist: AudioPlaylist) {
@ -87,7 +131,7 @@ fun initMusic() {
} }
override fun noMatches() { override fun noMatches() {
getLinkFromSearch(event, scheduler) getLinkFromSearch(event, scheduler, true)
} }
override fun playlistLoaded(playlist: AudioPlaylist) { override fun playlistLoaded(playlist: AudioPlaylist) {
@ -101,6 +145,7 @@ fun initMusic() {
}) })
} }
val skipCommand = CommandBuilder().setName("skip").addAlias("s").setHelp("Skips the currently playing track").build { event -> val skipCommand = CommandBuilder().setName("skip").addAlias("s").setHelp("Skips the currently playing track").build { event ->
val scheduler = guildMusicMap[event.guild.idLong] val scheduler = guildMusicMap[event.guild.idLong]
if (scheduler == null) { if (scheduler == null) {
@ -112,42 +157,22 @@ fun initMusic() {
} }
cb.addCommands(playCommand, skipCommand, queueCommand) cb.addCommands(playCommand, skipCommand, queueCommand, ytCommand, soundcloudCommand)
} }
fun getLinkFromSearch(event: CommandEvent, scheduler: TrackScheduler) { fun getLinkFromSearch(event: CommandEvent, scheduler: TrackScheduler, shouldInsertFront: Boolean, searchPrefix: String = "ytsearch") {
log.info("Searching for '${event.args}'") log.info("Searching youtube 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
} playerManager.loadItem("$searchPrefix:${event.args}", object : AudioLoadResultHandler {
}
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) { override fun loadFailed(exception: FriendlyException) {
event.reply("Shit's fucked!") event.reply("Shit's fucked!")
} }
override fun trackLoaded(track: AudioTrack) { override fun trackLoaded(track: AudioTrack) {
scheduler.queue(track, event.member) if (shouldInsertFront)
scheduler.insertFront(track, event.member)
else
scheduler.queue(track, event.member)
/*event.reply( /*event.reply(
EmbedBuilder().setImage(r.snippet.thumbnails.high.url).setTitle(r.snippet.title, "https://youtu.be/$id") 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) .setAuthor(r.snippet.channelTitle).setFooter("Requested by ${event.member.effectiveName}", event.author.effectiveAvatarUrl)
@ -163,19 +188,41 @@ fun getLinkFromSearch(event: CommandEvent, scheduler: TrackScheduler) {
override fun playlistLoaded(playlist: AudioPlaylist) { override fun playlistLoaded(playlist: AudioPlaylist) {
if (!playlist.isSearchResult) if (!playlist.isSearchResult)
for (t in playlist.tracks) { for (t in playlist.tracks) {
scheduler.queue(t, event.member) if (shouldInsertFront)
scheduler.insertFront(t, event.member)
else
scheduler.queue(t, event.member)
} }
else { else {
val track = playlist.tracks.first() val track = playlist.tracks.first()
event.reply(EmbedBuilder() if (!scheduler.isQueueEmpty() or scheduler.isSongPlaying()) {
.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) if (track is SoundCloudAudioTrack) {
val scsm = track.sourceManager as SoundCloudAudioSourceManager
scsm.updateClientId()
val art = khttp.get("http://api.soundcloud.com/tracks/${track.info.identifier}?client_id=${scsm.clientId}",
headers = mapOf("Content-Type" to "application/json")).jsonObject["artwork_url"].toString().replace("large", "t300x300")
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(art)
.setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff8800")).build())
} else {
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")
.setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff0000")).build())
}
}
if (shouldInsertFront)
scheduler.insertFront(track, event.member)
else
scheduler.queue(track, event.member)
} }

View File

@ -2,10 +2,12 @@ package nl.voidcorp.dbot.music
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer import com.sedmelluq.discord.lavaplayer.player.AudioPlayer
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioSourceManager
import com.sedmelluq.discord.lavaplayer.source.soundcloud.SoundCloudAudioTrack
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioTrack
import com.sedmelluq.discord.lavaplayer.track.AudioTrack import com.sedmelluq.discord.lavaplayer.track.AudioTrack
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason
import net.dv8tion.jda.core.EmbedBuilder import net.dv8tion.jda.core.EmbedBuilder
import net.dv8tion.jda.core.MessageBuilder
import net.dv8tion.jda.core.entities.Guild import net.dv8tion.jda.core.entities.Guild
import net.dv8tion.jda.core.entities.Member import net.dv8tion.jda.core.entities.Member
import net.dv8tion.jda.core.entities.TextChannel import net.dv8tion.jda.core.entities.TextChannel
@ -13,6 +15,7 @@ import net.dv8tion.jda.core.entities.VoiceChannel
import nl.voidcorp.dbot.commands.AudioPlayerSendHandler import nl.voidcorp.dbot.commands.AudioPlayerSendHandler
import nl.voidcorp.dbot.commands.guildMusicMap import nl.voidcorp.dbot.commands.guildMusicMap
import nl.voidcorp.dbot.log import nl.voidcorp.dbot.log
import java.awt.Color
import java.time.LocalDateTime import java.time.LocalDateTime
import java.util.* import java.util.*
import kotlin.concurrent.thread import kotlin.concurrent.thread
@ -20,6 +23,7 @@ import kotlin.concurrent.thread
class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceChannel) : AudioEventAdapter() { class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceChannel) : AudioEventAdapter() {
val musicChannel: TextChannel val musicChannel: TextChannel
init { init {
player.addListener(this) player.addListener(this)
@ -42,7 +46,7 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh
override fun onTrackEnd(player: AudioPlayer, track: AudioTrack, endReason: AudioTrackEndReason) { override fun onTrackEnd(player: AudioPlayer, track: AudioTrack, endReason: AudioTrackEndReason) {
if (q.isNotEmpty()) { if (q.isNotEmpty()) {
player.playTrack(q.remove()) player.playTrack(q.poll())
} else { } else {
stopPlay(endReason) stopPlay(endReason)
player.destroy() player.destroy()
@ -50,12 +54,27 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh
} }
override fun onTrackStart(player: AudioPlayer, track: AudioTrack) { override fun onTrackStart(player: AudioPlayer, track: AudioTrack) {
if (track.userData is Member) if (track is YoutubeAudioTrack) {
musicChannel.sendMessage(EmbedBuilder() if (track.userData is Member)
.setFooter("Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member) musicChannel.sendMessage(EmbedBuilder()
.user.effectiveAvatarUrl).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri) .setFooter("Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member)
.setThumbnail("https://img.youtube.com/vi/${track.info.identifier}/hqdefault.jpg\n") .user.effectiveAvatarUrl).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri)
.setTimestamp(LocalDateTime.now()).build()).append("Now playing").queue() .setThumbnail("https://img.youtube.com/vi/${track.info.identifier}/hqdefault.jpg")
.setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff0000")).build()).append("Now playing").queue()
} else if (track is SoundCloudAudioTrack) {
val scsm = track.sourceManager as SoundCloudAudioSourceManager
scsm.updateClientId()
val art = khttp.get("http://api.soundcloud.com/tracks/${track.info.identifier}?client_id=${scsm.clientId}", headers = mapOf("Content-Type" to "application/json")).jsonObject["artwork_url"].toString().replace("large", "t300x300")
if (track.userData is Member)
musicChannel.sendMessage(EmbedBuilder()
.setFooter("Requested by ${(track.userData as Member).effectiveName}", (track.userData as Member)
.user.effectiveAvatarUrl).setAuthor(track.info.author).setTitle(track.info.title, track.info.uri)
.setThumbnail(art)
.setTimestamp(LocalDateTime.now()).setColor(Color.decode("#ff8800")).build()).append("Now playing").queue()
}
} }
@ -67,7 +86,7 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh
player.playTrack(track) player.playTrack(track)
} else { } else {
log.info("Track Queue'd") log.info("Track Queue'd")
q.addLast(track) q.offer(track)
} }
} }
@ -78,29 +97,31 @@ class TrackScheduler(val player: AudioPlayer, val guild: Guild, channel: VoiceCh
player.playTrack(track) player.playTrack(track)
} else { } else {
log.info("Track inserted") log.info("Track inserted")
q.addFirst(track) q.push(track)
} }
} }
fun skip() { fun skip() {
if (q.isNotEmpty()) { /*if (q.isNotEmpty()) {
log.info("skipped Track!") log.info("skipped Track!")
player.playTrack(q.remove()) player.playTrack(q.remove())
} else { } else {
stopPlay(AudioTrackEndReason.REPLACED) stopPlay(AudioTrackEndReason.REPLACED)
player.destroy() player.destroy()
} }*/
player.stopTrack()
} }
fun isQueueEmpty() = q.isEmpty() fun isQueueEmpty() = q.isEmpty()
fun isSongPlaying() = player.playingTrack != null
fun stopPlay(endReason: AudioTrackEndReason) { fun stopPlay(endReason: AudioTrackEndReason) {
if (endReason != AudioTrackEndReason.REPLACED) { if (endReason != AudioTrackEndReason.REPLACED) {
guildMusicMap.remove(guild.idLong) guildMusicMap.remove(guild.idLong)
musicChannel.sendMessage("Playlist has ended, leaving the voice channel!").queue() musicChannel.sendMessage(EmbedBuilder().setColor(musicChannel.guild.selfMember.color).setTitle("I'm done here").setDescription("There are no more songs left in the queue.").setTimestamp(LocalDateTime.now()).build()).queue()
thread { guild.audioManager.closeAudioConnection() } thread { guild.audioManager.closeAudioConnection() }
} }
} }