diff --git a/dockerfile b/Dockerfile similarity index 100% rename from dockerfile rename to Dockerfile diff --git a/README.md b/README.md index 33739da..8455c81 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ A Discord music bot, written in Kotlin using the kord library. ## Special Thanks to -- HopeBaron for taking the time to help me fix this pos. +- HopeBaron for helping me a whole lot ## Commands @@ -27,6 +27,11 @@ A Discord music bot, written in Kotlin using the kord library. ## How to self-host (using the Docker container) +1. Pull the container +2. Map /data/ to a folder on disk +3. Run the Bot once +4. Follow step 4 - 7 of "How to self-host (using the JAR)" + ## How to self-host (using the JAR) 1. Download the latest release from the Package Registry ("Packages and registries" > "Package Registry") diff --git a/build.gradle.kts b/build.gradle.kts index 5e69edf..2413c18 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,7 +33,7 @@ val ownerID = 372703841151614976L group = "de.limited_dev.botendo" version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" } ?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" } - ?: "6.1.1" + ?: "6.2.0" val kordver = "1.5.6" val lavaver = "3.8.0" @@ -44,7 +44,6 @@ project.base.archivesName.set(mavenArtifact) repositories { mavenCentral() - maven("https://m2.dv8tion.net/releases") maven { name = "Gitlab" val projectId = System.getenv("CI_PROJECT_ID") diff --git a/src/main/kotlin/de/limited_dev/botendo/Bot.kt b/src/main/kotlin/de/limited_dev/botendo/Bot.kt index 96b4ce0..296088e 100644 --- a/src/main/kotlin/de/limited_dev/botendo/Bot.kt +++ b/src/main/kotlin/de/limited_dev/botendo/Bot.kt @@ -20,11 +20,15 @@ package de.limited_dev.botendo import com.kotlindiscord.kord.extensions.ExtensibleBot +import de.limited_dev.botendo.buttons.ButtonManager import de.limited_dev.botendo.extensions.music.* import de.limited_dev.botendo.extensions.util.InfoExtension import de.limited_dev.botendo.extensions.util.PotatoExtension import de.limited_dev.botendo.util.CredentialManager import de.limited_dev.botendo.util.Logger +import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color +import dev.kord.core.behavior.interaction.response.respond import dev.kord.core.event.interaction.ButtonInteractionCreateEvent import dev.kord.core.on import dev.schlaubi.lavakord.LavaKord @@ -62,6 +66,10 @@ object Bot { add(::QueueExtension) add(::PotatoExtension) } + + this.presence { + this.streaming("music", "https://twitch.tv/limited_dev") + } } //Add LavaLink @@ -72,7 +80,29 @@ object Bot { //Register Button presses bot.kordRef.on { - + val inter = this.interaction + val response = inter.deferPublicResponse() + val u = inter.user + val g = this.interaction.getOriginalInteractionResponse().getGuild() + var flag = false + for (b in ButtonManager.buttons) { + if (b.id != inter.componentId || flag) + continue + b.onInteraction(response, g, u) + flag = true + } + if (!flag) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Error", + "Could not find button with id \"${inter.componentId}\".\nPlease report this.", + u.asUser().username + "#" + u.asUser().discriminator + ) + ) + } + } } //Start the bot diff --git a/src/main/kotlin/de/limited_dev/botendo/buttons/Button.kt b/src/main/kotlin/de/limited_dev/botendo/buttons/Button.kt new file mode 100644 index 0000000..0511e2e --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/buttons/Button.kt @@ -0,0 +1,35 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.buttons + +import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User + +open class Button(val id: String) { + + open suspend fun onInteraction( + response: DeferredPublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + + } +} diff --git a/src/main/kotlin/de/limited_dev/botendo/buttons/ButtonManager.kt b/src/main/kotlin/de/limited_dev/botendo/buttons/ButtonManager.kt new file mode 100644 index 0000000..614858d --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/buttons/ButtonManager.kt @@ -0,0 +1,26 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.buttons + +import de.limited_dev.botendo.buttons.music.* + +object ButtonManager { + val buttons = listOf(RepeatButton(), PauseButton(), SkipButton(), QueueButton(), StopButton()) +} diff --git a/src/main/kotlin/de/limited_dev/botendo/buttons/music/PauseButton.kt b/src/main/kotlin/de/limited_dev/botendo/buttons/music/PauseButton.kt new file mode 100644 index 0000000..f23ed45 --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/buttons/music/PauseButton.kt @@ -0,0 +1,105 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.buttons.music + +import de.limited_dev.botendo.Bot +import de.limited_dev.botendo.buttons.Button +import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.ButtonUtil +import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color +import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior +import dev.kord.core.behavior.interaction.response.respond +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User +import dev.kord.rest.builder.message.modify.actionRow +import dev.schlaubi.lavakord.audio.Link + +class PauseButton : Button("btn.music.pause") { + override suspend fun onInteraction( + response: DeferredPublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + val guildId = guild.id + val link = Bot.lava.getLink(guildId.toString()) + val player = link.player + val voiceState = user.asMember(guildId).getVoiceStateOrNull() + if (voiceState == null) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not connected to a VC", + "Please connect to a VC", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + val channelId = voiceState.channelId + if (link.state == Link.State.NOT_CONNECTED) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Not connected", + "I'm not in a VC and therefore, I am not playing anything.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not in my VC", + "We are not in the same VC and therefore, you cannot control the music", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + player.pause(!player.paused) + + val gts = MusicManager.getGuildTrackScheduler(guild, player) + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0x52E01A), + if (player.paused) "I paused" else "I'm continuing", + if (player.paused) "I paused the song" else "I'm continuing to play the song.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + + + this.actionRow { + this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components) + } + } + } +} diff --git a/src/main/kotlin/de/limited_dev/botendo/buttons/music/QueueButton.kt b/src/main/kotlin/de/limited_dev/botendo/buttons/music/QueueButton.kt new file mode 100644 index 0000000..6a7615c --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/buttons/music/QueueButton.kt @@ -0,0 +1,96 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.buttons.music + +import de.limited_dev.botendo.Bot +import de.limited_dev.botendo.buttons.Button +import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.ButtonUtil +import de.limited_dev.botendo.util.MessageUtil +import de.limited_dev.botendo.util.TimeUtil +import dev.kord.common.Color +import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior +import dev.kord.core.behavior.interaction.response.respond +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User +import dev.kord.rest.builder.message.modify.actionRow +import dev.schlaubi.lavakord.audio.Link + +class QueueButton : Button("btn.music.queue") { + override suspend fun onInteraction( + response: DeferredPublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + val guildId = guild.id + val link = Bot.lava.getLink(guildId.toString()) + val player = link.player + if (link.state == Link.State.NOT_CONNECTED) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Not connected", + "I'm not in a VC and therefore, I am not playing anything.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + val track = player.playingTrack + if (track == null) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Not playing", + "I'm not playing anything currently", user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + val gts = MusicManager.getGuildTrackScheduler(guild.asGuild(), player) + val q = gts.getQueue() + var desc = + """${"**" + track.title + " - " + TimeUtil.getTimeFormatedShortend(track.length.inWholeMilliseconds)} (${track.author})**""" + "\n" + for ((i, tr) in q.withIndex()) { + if (i >= 14) + continue + desc += tr.info.title + " - " + TimeUtil.getTimeFormatedShortend(tr.info.length) + " (" + tr.info.author + ")\n" + } + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0x52E01A), + "Queue", + desc, + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + + this.actionRow { + this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components) + } + } + } +} diff --git a/src/main/kotlin/de/limited_dev/botendo/buttons/music/RepeatButton.kt b/src/main/kotlin/de/limited_dev/botendo/buttons/music/RepeatButton.kt new file mode 100644 index 0000000..d354134 --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/buttons/music/RepeatButton.kt @@ -0,0 +1,104 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.buttons.music + +import de.limited_dev.botendo.Bot +import de.limited_dev.botendo.buttons.Button +import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.ButtonUtil +import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color +import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior +import dev.kord.core.behavior.interaction.response.respond +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User +import dev.kord.rest.builder.message.modify.actionRow +import dev.schlaubi.lavakord.audio.Link + +class RepeatButton : Button("btn.music.repeat") { + override suspend fun onInteraction( + response: DeferredPublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + val guildId = guild.id + val link = Bot.lava.getLink(guildId.toString()) + val player = link.player + val voiceState = user.asMember(guildId).getVoiceStateOrNull() + if (voiceState == null) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not connected to a VC", + "Please connect to a VC", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + val channelId = voiceState.channelId + if (link.state == Link.State.NOT_CONNECTED) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Not connected", + "I'm not in a VC and therefore, I am not playing anything.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not in my VC", + "We are not in the same VC and therefore, you cannot control the music", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + val gts = MusicManager.getGuildTrackScheduler(guild, player) + gts.repeating = !gts.repeating + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0x52E01A), + if (gts.repeating) "Now Repeating" else "Now Continuing", + if (gts.repeating) "The current track will now loop" else "The next track will play when this song finishes", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + + + this.actionRow { + this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components) + } + } + } +} diff --git a/src/main/kotlin/de/limited_dev/botendo/buttons/music/SkipButton.kt b/src/main/kotlin/de/limited_dev/botendo/buttons/music/SkipButton.kt new file mode 100644 index 0000000..38c1992 --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/buttons/music/SkipButton.kt @@ -0,0 +1,147 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.buttons.music + +import de.limited_dev.botendo.Bot +import de.limited_dev.botendo.buttons.Button +import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.ButtonUtil +import de.limited_dev.botendo.util.MessageUtil +import de.limited_dev.botendo.util.TimeUtil +import de.limited_dev.botendo.util.UrlUtil +import dev.kord.common.Color +import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior +import dev.kord.core.behavior.interaction.response.respond +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User +import dev.kord.rest.builder.message.modify.actionRow +import dev.schlaubi.lavakord.audio.Link + +class SkipButton : Button("btn.music.skip") { + override suspend fun onInteraction( + response: DeferredPublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + val guildId = guild.id + val link = Bot.lava.getLink(guildId.toString()) + val player = link.player + val voiceState = user.asMember(guildId).getVoiceStateOrNull() + if (voiceState == null) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not connected to a VC", + "Please connect to a VC", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + val channelId = voiceState.channelId + if (link.state == Link.State.NOT_CONNECTED) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Not connected", + "I'm not in a VC and therefore, I am not playing anything.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not in my VC", + "We are not in the same VC and therefore, you cannot control the music", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + var track = player.playingTrack + if (track == null) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Not playing", + "I'm not playing anything currently", user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + val gts = MusicManager.getGuildTrackScheduler(guild.asGuild(), player) + if (!gts.isEmpty()) { + track = gts.getHead().toTrack() + gts.playNext() + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbedWithImage( + Color(0x52E01A), + "Skipped song; now playing", + "**${track.title}**\n*Now Playing*\nby ${track.author} :: ${ + TimeUtil.getTimeFormatedRaw( + track.length.inWholeMilliseconds + ) + }\n" + + ">>>${track.uri}", + "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + + this.actionRow { + this.components.addAll( + ButtonUtil.getMusicControllerButtons( + player.paused, + gts.repeating + ).components + ) + } + } + return + } + player.stopTrack() + + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0x52E01A), + "Skipped song; now playing", + "Nothing", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + this.actionRow { + this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components) + } + } + } +} diff --git a/src/main/kotlin/de/limited_dev/botendo/buttons/music/StopButton.kt b/src/main/kotlin/de/limited_dev/botendo/buttons/music/StopButton.kt new file mode 100644 index 0000000..fabc991 --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/buttons/music/StopButton.kt @@ -0,0 +1,98 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.buttons.music + +import de.limited_dev.botendo.Bot +import de.limited_dev.botendo.buttons.Button +import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color +import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior +import dev.kord.core.behavior.interaction.response.respond +import dev.kord.core.entity.Guild +import dev.kord.core.entity.User +import dev.schlaubi.lavakord.audio.Link + +class StopButton : Button("btn.music.stop") { + override suspend fun onInteraction( + response: DeferredPublicMessageInteractionResponseBehavior, + guild: Guild, + user: User + ) { + val guildId = guild.id + val link = Bot.lava.getLink(guildId.toString()) + val player = link.player + val voiceState = user.asMember(guildId).getVoiceStateOrNull() + if (voiceState == null) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not connected to a VC", + "Please connect to a VC", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + val channelId = voiceState.channelId + if (link.state == Link.State.NOT_CONNECTED) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "Not connected", + "I'm not in a VC and therefore, I am not playing anything.", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) { + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0xE0311A), + "You are not in my VC", + "We are not in the same VC and therefore, you cannot control the music", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + return + } + + player.stopTrack() + link.destroy() + MusicManager.getGuildTrackScheduler(guild.asGuild(), player).clear() + response.respond { + this.embeds = mutableListOf( + MessageUtil.getEmbed( + Color(0x52E01A), + "I stopped and left", + "just like your girlfriend", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + } + } +} diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/music/NowPlayingExtension.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/music/NowPlayingExtension.kt index c44cacb..cb0f1d5 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/music/NowPlayingExtension.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/music/NowPlayingExtension.kt @@ -21,10 +21,15 @@ package de.limited_dev.botendo.extensions.music import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand +import com.kotlindiscord.kord.extensions.types.respond import de.limited_dev.botendo.Bot +import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.ButtonUtil import de.limited_dev.botendo.util.MessageUtil import de.limited_dev.botendo.util.TimeUtil import de.limited_dev.botendo.util.UrlUtil +import dev.kord.common.Color +import dev.kord.rest.builder.message.create.actionRow import dev.schlaubi.lavakord.audio.Link import dev.schlaubi.lavakord.kord.getLink @@ -41,6 +46,7 @@ class NowPlayingExtension : Extension() { if (link.state == Link.State.NOT_CONNECTED) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0A81A), "Not connected", "I'm not in a VC and therefore, I am not playing anything." ) @@ -50,26 +56,38 @@ class NowPlayingExtension : Extension() { if (track == null) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0A81A), "Not Playing", "I'm not playing anything currently" ) return@action } - MessageUtil.sendEmbedForPublicSlashCommandWithImage( - this, - "Currently playing", - "**${track.title}**\n*Now Playing*\nby ${track.author} :${ - TimeUtil.getTimeFormatedRaw( - track.position.inWholeMilliseconds + val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player) + + this.respond { + this.embeds.add( + MessageUtil.getEmbedWithImage( + Color(0x52E01A), + "Currently playing", + "**${track.title}**\n*Now Playing*\nby ${track.author} :${ + TimeUtil.getTimeFormatedRaw( + track.position.inWholeMilliseconds + ) + }: ${ + TimeUtil.getTimeFormatedRaw( + track.length.inWholeMilliseconds + ) + }\n" + + ">>>${track.uri}", + "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg", + user.asUser().username + "#" + user.asUser().discriminator ) - }: ${ - TimeUtil.getTimeFormatedRaw( - track.length.inWholeMilliseconds - ) - }\n" + - ">>>${track.uri}", - "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg" - ) + ) + + this.actionRow { + ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating) + } + } } } } diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/music/PlayExtension.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/music/PlayExtension.kt index 851ff60..137c16e 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/music/PlayExtension.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/music/PlayExtension.kt @@ -27,6 +27,7 @@ import com.kotlindiscord.kord.extensions.types.respond import de.limited_dev.botendo.Bot import de.limited_dev.botendo.extensions.music.components.MusicManager import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color import dev.schlaubi.lavakord.audio.Link import dev.schlaubi.lavakord.kord.getLink @@ -48,6 +49,7 @@ class PlayExtension : Extension() { this.respond { embeds.add( MessageUtil.getEmbed( + Color(0xE0311A), "You are not connected to a VC", "Please connect to a VC", u.asUser().username + "#" + u.asUser().discriminator @@ -65,6 +67,7 @@ class PlayExtension : Extension() { this.respond { embeds.add( MessageUtil.getEmbed( + Color(0xE0311A), "You are not in my VC", "We are not in the same VC and therefore, you cannot play any music", u.asUser().username + "#" + u.asUser().discriminator @@ -83,6 +86,7 @@ class PlayExtension : Extension() { this.respond { embeds.add( MessageUtil.getEmbed( + Color(0xE0A81A), "Searching...", "We are looking for $query", u.asUser().username + "#" + u.asUser().discriminator diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/music/QueueExtension.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/music/QueueExtension.kt index 606db73..69bb99f 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/music/QueueExtension.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/music/QueueExtension.kt @@ -21,10 +21,14 @@ package de.limited_dev.botendo.extensions.music import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand +import com.kotlindiscord.kord.extensions.types.respond import de.limited_dev.botendo.Bot import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.ButtonUtil import de.limited_dev.botendo.util.MessageUtil import de.limited_dev.botendo.util.TimeUtil +import dev.kord.common.Color +import dev.kord.rest.builder.message.create.actionRow import dev.schlaubi.lavakord.audio.Link class QueueExtension : Extension() { @@ -40,6 +44,7 @@ class QueueExtension : Extension() { if (link.state == Link.State.NOT_CONNECTED) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0311A), "Not connected", "I'm not in a VC and therefore, I am not playing anything." ) @@ -49,6 +54,7 @@ class QueueExtension : Extension() { if (track == null) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0A81A), "Queue empty", "I'm not playing anything currently" ) @@ -63,8 +69,20 @@ class QueueExtension : Extension() { continue desc += tr.info.title + " - " + TimeUtil.getTimeFormatedShortend(tr.info.length) + " (" + tr.info.author + ")\n" } - MessageUtil.sendEmbedForPublicSlashCommand(this, "Queue", desc) + this.respond { + this.embeds.add( + MessageUtil.getEmbed( + Color(0x52E01A), + "Queue", + desc, + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + this.actionRow { + ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating) + } + } } } } diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/music/SkipExtension.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/music/SkipExtension.kt index ddcf6ab..039f4e9 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/music/SkipExtension.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/music/SkipExtension.kt @@ -21,11 +21,15 @@ package de.limited_dev.botendo.extensions.music import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand +import com.kotlindiscord.kord.extensions.types.respond import de.limited_dev.botendo.Bot import de.limited_dev.botendo.extensions.music.components.MusicManager +import de.limited_dev.botendo.util.ButtonUtil import de.limited_dev.botendo.util.MessageUtil import de.limited_dev.botendo.util.TimeUtil import de.limited_dev.botendo.util.UrlUtil +import dev.kord.common.Color +import dev.kord.rest.builder.message.create.actionRow import dev.schlaubi.lavakord.audio.Link class SkipExtension : Extension() { @@ -43,6 +47,7 @@ class SkipExtension : Extension() { if (voiceState == null) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0311A), "You are not connected to a VC", "Please connect to a VC" ) @@ -53,6 +58,7 @@ class SkipExtension : Extension() { if (link.state == Link.State.NOT_CONNECTED) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0311A), "Not connected", "I'm not in a VC and therefore, I am not playing anything." ) @@ -60,6 +66,7 @@ class SkipExtension : Extension() { } else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0311A), "You are not in my VC", "We are not in the same VC and therefore, you cannot control the music" ) @@ -69,26 +76,41 @@ class SkipExtension : Extension() { if (track == null) { MessageUtil.sendEmbedForPublicSlashCommand( this, + Color(0xE0311A), "Not playing", "I'm not playing anything currently" ) return@action } val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player) - track = gts.getHead().toTrack() - gts.playNext() - MessageUtil.sendEmbedForPublicSlashCommandWithImage( - this, - "Skipped song; now playing", - "**${track.title}**\n*Now Playing*\nby ${track.author} :: ${ - TimeUtil.getTimeFormatedRaw( - track.length.inWholeMilliseconds - ) - }\n" + - ">>>${track.uri}", - "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg" + if (!gts.isEmpty()) { + track = gts.getHead().toTrack() + gts.playNext() + } else { + player.stopTrack() + } - ) + + this.respond { + this.embeds.add( + MessageUtil.getEmbedWithImage( + Color(0x52E01A), + "Skipped song; now playing", + "**${track.title}**\n*Now Playing*\nby ${track.author} :: ${ + TimeUtil.getTimeFormatedRaw( + track.length.inWholeMilliseconds + ) + }\n" + + ">>>${track.uri}", + "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg", + user.asUser().username + "#" + user.asUser().discriminator + ) + ) + + this.actionRow { + ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating) + } + } } } } diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/music/StopExtension.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/music/StopExtension.kt index ecfc52d..7c361ba 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/music/StopExtension.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/music/StopExtension.kt @@ -25,6 +25,7 @@ import com.kotlindiscord.kord.extensions.types.respond import de.limited_dev.botendo.Bot import de.limited_dev.botendo.extensions.music.components.MusicManager import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color import dev.schlaubi.lavakord.audio.Link import dev.schlaubi.lavakord.kord.getLink @@ -44,6 +45,7 @@ class StopExtension : Extension() { this.respond { this.embeds.add( MessageUtil.getEmbed( + Color(0xE0311A), "You are not connected to a VC", "Please connect to my VC", u.asUser().username + "#" + u.asUser().discriminator ) @@ -56,6 +58,7 @@ class StopExtension : Extension() { this.respond { this.embeds.add( MessageUtil.getEmbed( + Color(0xE0311A), "Not connected", "I'm not in a VC and therefore, I am not playing anything.", u.asUser().username + "#" + u.asUser().discriminator @@ -67,6 +70,7 @@ class StopExtension : Extension() { this.respond { this.embeds.add( MessageUtil.getEmbed( + Color(0xE0311A), "You are not in my VC", "We are not in the same VC", u.asUser().username + "#" + u.asUser().discriminator ) @@ -80,6 +84,7 @@ class StopExtension : Extension() { this.respond { this.embeds.add( MessageUtil.getEmbed( + Color(0x52E01A), "I stopped and left", "just like your girlfriend", u.asUser().username + "#" + u.asUser().discriminator diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/GuildTrackScheduler.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/GuildTrackScheduler.kt index 0cd329f..420eae7 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/GuildTrackScheduler.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/GuildTrackScheduler.kt @@ -109,5 +109,9 @@ class GuildTrackScheduler(val pl: Player) { fun getHead(): TrackResponse.PartialTrack { return queue.first() } + + fun isEmpty(): Boolean { + return queue.isEmpty() + } } diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/MusicManager.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/MusicManager.kt index 5e2a8b6..f81b07e 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/MusicManager.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/music/components/MusicManager.kt @@ -23,11 +23,14 @@ import com.kotlindiscord.kord.extensions.commands.application.slash.PublicSlashC import com.kotlindiscord.kord.extensions.components.forms.ModalForm import com.kotlindiscord.kord.extensions.types.respond import de.limited_dev.botendo.extensions.music.PlayExtension +import de.limited_dev.botendo.util.ButtonUtil import de.limited_dev.botendo.util.MessageUtil import de.limited_dev.botendo.util.TimeUtil import de.limited_dev.botendo.util.UrlUtil +import dev.kord.common.Color import dev.kord.common.entity.Snowflake import dev.kord.core.entity.Guild +import dev.kord.rest.builder.message.create.actionRow import dev.schlaubi.lavakord.audio.Link import dev.schlaubi.lavakord.audio.player.Player import dev.schlaubi.lavakord.rest.TrackResponse @@ -71,6 +74,7 @@ object MusicManager { ctx.respond { this.embeds.add( MessageUtil.getEmbedWithImage( + Color(0x52E01A), "Queuing track from link", "**${item.track.info.title}**\n*Queue*\nby ${item.track.info.author} :: ${ TimeUtil.getTimeFormatedRaw( @@ -81,6 +85,15 @@ object MusicManager { "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.track.info.uri) + "/maxresdefault.jpg" ) ) + + this.actionRow { + this.components.addAll( + ButtonUtil.getMusicControllerButtons( + player.paused, + gts.repeating + ).components + ) + } } } @@ -93,6 +106,7 @@ object MusicManager { ctx.respond { this.embeds.add( MessageUtil.getEmbedWithImage( + Color(0x52E01A), "Queuing playlist from link", "**${item.tracks.first().info.title}**\n*${item.playlistInfo.name}*\nby ${item.tracks.first().info.author} :: ${ TimeUtil.getTimeFormatedRaw( @@ -103,6 +117,15 @@ object MusicManager { "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.track.info.uri) + "/maxresdefault.jpg" ) ) + + this.actionRow { + this.components.addAll( + ButtonUtil.getMusicControllerButtons( + player.paused, + gts.repeating + ).components + ) + } } } @@ -112,6 +135,7 @@ object MusicManager { ctx.respond { this.embeds.add( MessageUtil.getEmbedWithImage( + Color(0x52E01A), "Queuing track from query", "**${item.tracks.first().info.title}**\n*Queue*\nby ${item.tracks.first().info.author} :: ${ TimeUtil.getTimeFormatedRaw( @@ -122,6 +146,15 @@ object MusicManager { "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.tracks.first().info.uri) + "/maxresdefault.jpg" ) ) + + this.actionRow { + this.components.addAll( + ButtonUtil.getMusicControllerButtons( + player.paused, + gts.repeating + ).components + ) + } } } @@ -130,6 +163,7 @@ object MusicManager { ctx.respond { this.embeds.add( MessageUtil.getEmbed( + Color(0xE0311A), "Not found", "There were no matches.", u.username + "#" + u.discriminator @@ -143,6 +177,7 @@ object MusicManager { ctx.respond { this.embeds.add( MessageUtil.getEmbed( + Color(0xE0311A), "Load failed", "There was an error while loading.", u.username + "#" + u.discriminator ) diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/util/InfoExtension.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/util/InfoExtension.kt index 47feb40..347533a 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/util/InfoExtension.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/util/InfoExtension.kt @@ -23,6 +23,7 @@ import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import de.limited_dev.botendo.build.BuildConstants import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color class InfoExtension : Extension() { override val name = "info" @@ -32,9 +33,9 @@ class InfoExtension : Extension() { description = "Show infos about the bot" this.action { MessageUtil.sendEmbedForPublicSlashCommand( - this, "Botendo", + this, Color(0x52E01A), "Botendo", "Botendo ***v." + BuildConstants.version + "***\n" + - "kord-extensions ***v." + BuildConstants.kordVersion + "***\n" + + "Kord-Extensions ***v." + BuildConstants.kordVersion + "***\n" + "lavalink.kt ***v." + BuildConstants.lavaVersion + "***\n" + "Coroutines ***v." + BuildConstants.coroutinesVersion + "***" ) diff --git a/src/main/kotlin/de/limited_dev/botendo/extensions/util/PotatoExtension.kt b/src/main/kotlin/de/limited_dev/botendo/extensions/util/PotatoExtension.kt index dcfd92b..2f46c5b 100644 --- a/src/main/kotlin/de/limited_dev/botendo/extensions/util/PotatoExtension.kt +++ b/src/main/kotlin/de/limited_dev/botendo/extensions/util/PotatoExtension.kt @@ -22,6 +22,7 @@ package de.limited_dev.botendo.extensions.util import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import de.limited_dev.botendo.util.MessageUtil +import dev.kord.common.Color class PotatoExtension : Extension() { override val name = "potato" @@ -31,7 +32,7 @@ class PotatoExtension : Extension() { description = "Potato" this.action { MessageUtil.sendEmbedForPublicSlashCommandWithImage( - this, "Potato", + this, Color(0xE0311A), "Potato", "Potato", "https://static.tumblr.com/c06d8e0928395746a63b9c5d3cb1ce66/sl9iajp/gxFmqk38z/tumblr_static_potato-equality.jpg" ) diff --git a/src/main/kotlin/de/limited_dev/botendo/util/ButtonUtil.kt b/src/main/kotlin/de/limited_dev/botendo/util/ButtonUtil.kt new file mode 100644 index 0000000..e92434d --- /dev/null +++ b/src/main/kotlin/de/limited_dev/botendo/util/ButtonUtil.kt @@ -0,0 +1,46 @@ +/* + * Botendo + * Copyright (C) 2023 limited_dev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package de.limited_dev.botendo.util + +import dev.kord.common.entity.ButtonStyle +import dev.kord.rest.builder.component.ActionRowBuilder + +object ButtonUtil { + fun getMusicControllerButtons(isPaused: Boolean, isRepeating: Boolean): ActionRowBuilder { + val ar = ActionRowBuilder() + ar.interactionButton(ButtonStyle.Secondary, "btn.music.repeat") { + this.label = if (isRepeating) "Stop Repeating" else "Repeat" + } + ar.interactionButton(ButtonStyle.Success, "btn.music.pause") { + this.label = if (isPaused) "Continue" else "Pause" + } + ar.interactionButton(ButtonStyle.Primary, "btn.music.skip") { + this.label = "Skip" + } + ar.interactionButton(ButtonStyle.Secondary, "btn.music.queue") { + this.label = "Queue" + } + ar.interactionButton(ButtonStyle.Danger, "btn.music.stop") { + this.label = "Stop" + } + return ar + } + +} diff --git a/src/main/kotlin/de/limited_dev/botendo/util/MessageUtil.kt b/src/main/kotlin/de/limited_dev/botendo/util/MessageUtil.kt index cc8aeef..5085188 100644 --- a/src/main/kotlin/de/limited_dev/botendo/util/MessageUtil.kt +++ b/src/main/kotlin/de/limited_dev/botendo/util/MessageUtil.kt @@ -23,6 +23,7 @@ import com.kotlindiscord.kord.extensions.commands.Arguments import com.kotlindiscord.kord.extensions.commands.application.slash.PublicSlashCommandContext import com.kotlindiscord.kord.extensions.components.forms.ModalForm import com.kotlindiscord.kord.extensions.types.respond +import dev.kord.common.Color import dev.kord.rest.builder.message.EmbedBuilder import java.time.LocalDateTime import java.time.format.DateTimeFormatter @@ -30,14 +31,17 @@ import java.time.format.DateTimeFormatter object MessageUtil { private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy @ HH:mm:ss") + ///Send an embedded message as a reply suspend fun sendEmbedForPublicSlashCommand( ctx: PublicSlashCommandContext, + color: Color, title: String, description: String ) { ctx.respond { embeds.add( getEmbed( + color, title, description, ctx.user.asUser().username + "#" + ctx.user.asUser().discriminator @@ -46,8 +50,10 @@ object MessageUtil { } } + ///Send an embedded message with an image as a reply suspend fun sendEmbedForPublicSlashCommandWithImage( ctx: PublicSlashCommandContext, + color: Color, title: String, description: String, thumbnailUrl: String @@ -55,6 +61,7 @@ object MessageUtil { ctx.respond { embeds.add( getEmbedWithImage( + color, title, description, ctx.user.asUser().username + "#" + ctx.user.asUser().discriminator, @@ -64,23 +71,32 @@ object MessageUtil { } } - fun getEmbed(title: String, description: String, source: String): EmbedBuilder { + ///Get an embedded msg with title, description and a src + fun getEmbed( + color: Color, + title: String, + description: String, + source: String + ): EmbedBuilder { val now: LocalDateTime = LocalDateTime.now() val ebb = EmbedBuilder() ebb.title = title ebb.description = description ebb.footer = EmbedBuilder.Footer() ebb.footer!!.text = ">" + dtf.format(now) + " - $source" + ebb.color = color return ebb } + ///Get an embedded msg with image, title, description and a src fun getEmbedWithImage( + color: Color, title: String, description: String, source: String, thumbnailUrl: String ): EmbedBuilder { - val ebb = getEmbed(title, description, source) + val ebb = getEmbed(color, title, description, source) ebb.thumbnail = EmbedBuilder.Thumbnail() ebb.thumbnail!!.url = thumbnailUrl return ebb diff --git a/src/main/kotlin/de/limited_dev/botendo/util/TimeUtil.kt b/src/main/kotlin/de/limited_dev/botendo/util/TimeUtil.kt index 7365f16..d2a9676 100644 --- a/src/main/kotlin/de/limited_dev/botendo/util/TimeUtil.kt +++ b/src/main/kotlin/de/limited_dev/botendo/util/TimeUtil.kt @@ -22,7 +22,8 @@ package de.limited_dev.botendo.util import java.util.concurrent.TimeUnit object TimeUtil { - fun getTimeFormatedShortend(time: Long): String? { + ///Convert Miliseconds to xdays xhours xmins xsecs + fun getTimeFormatedShortend(time: Long): String { var time = time val days = TimeUnit.MILLISECONDS .toDays(time) @@ -54,7 +55,7 @@ object TimeUtil { return s } - fun getTimeFormatedRaw(time: Long): String? { + fun getTimeFormatedRaw(time: Long): String { var time = time val days = TimeUnit.MILLISECONDS .toDays(time) diff --git a/src/main/kotlin/de/limited_dev/botendo/util/UrlUtil.kt b/src/main/kotlin/de/limited_dev/botendo/util/UrlUtil.kt index 14e95a6..ed67935 100644 --- a/src/main/kotlin/de/limited_dev/botendo/util/UrlUtil.kt +++ b/src/main/kotlin/de/limited_dev/botendo/util/UrlUtil.kt @@ -20,6 +20,7 @@ package de.limited_dev.botendo.util object UrlUtil { + ///Strip the video ID from a YouTube link fun getYtThumbnailUrl(uri: String): String { return uri.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] }