Merge branch 'master' into 'stable'

chore: changed Ext to Extension, added Potatoes

See merge request limited_dev/botendo!2
This commit is contained in:
limited_dev 2023-04-26 16:13:55 +00:00
commit b3ff6b334f
24 changed files with 922 additions and 54 deletions

View file

@ -17,7 +17,7 @@ A Discord music bot, written in Kotlin using the kord library.
## Special Thanks to ## Special Thanks to
- HopeBaron for taking the time to help me fix this pos. - HopeBaron for helping me a whole lot
## Commands ## Commands
@ -27,6 +27,11 @@ A Discord music bot, written in Kotlin using the kord library.
## How to self-host (using the Docker container) ## 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) ## How to self-host (using the JAR)
1. Download the latest release from the Package Registry ("Packages and registries" > "Package Registry") 1. Download the latest release from the Package Registry ("Packages and registries" > "Package Registry")

View file

@ -33,7 +33,7 @@ val ownerID = 372703841151614976L
group = "de.limited_dev.botendo" group = "de.limited_dev.botendo"
version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" } version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" }
?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" } ?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" }
?: "6.1.1" ?: "6.2.0"
val kordver = "1.5.6" val kordver = "1.5.6"
val lavaver = "3.8.0" val lavaver = "3.8.0"
@ -44,7 +44,6 @@ project.base.archivesName.set(mavenArtifact)
repositories { repositories {
mavenCentral() mavenCentral()
maven("https://m2.dv8tion.net/releases")
maven { maven {
name = "Gitlab" name = "Gitlab"
val projectId = System.getenv("CI_PROJECT_ID") val projectId = System.getenv("CI_PROJECT_ID")

View file

@ -20,17 +20,24 @@
package de.limited_dev.botendo package de.limited_dev.botendo
import com.kotlindiscord.kord.extensions.ExtensibleBot 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.music.*
import de.limited_dev.botendo.extensions.util.InfoExt 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.CredentialManager
import de.limited_dev.botendo.util.Logger 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 import dev.schlaubi.lavakord.LavaKord
import dev.schlaubi.lavakord.kord.lavakord import dev.schlaubi.lavakord.kord.lavakord
object Bot { object Bot {
//The kord object gets set at app launch //The kord object gets set at app launch
lateinit var lava: LavaKord
private lateinit var bot: ExtensibleBot private lateinit var bot: ExtensibleBot
lateinit var lava: LavaKord
suspend fun start() { suspend fun start() {
Logger.out("Starting Bot...") Logger.out("Starting Bot...")
@ -51,12 +58,17 @@ object Bot {
} }
extensions { extensions {
add(::InfoExt) add(::InfoExtension)
add(::PlayExt) add(::PlayExtension)
add(::StopExt) add(::StopExtension)
add(::SkipExt) add(::SkipExtension)
add(::NowPlayingExt) add(::NowPlayingExtension)
add(::QueueExt) add(::QueueExtension)
add(::PotatoExtension)
}
this.presence {
this.streaming("music", "https://twitch.tv/limited_dev")
} }
} }
@ -66,6 +78,33 @@ object Bot {
//Add the LavaLink node from config //Add the LavaLink node from config
lava.addNode(CredentialManager.linkip, CredentialManager.linkpw) lava.addNode(CredentialManager.linkip, CredentialManager.linkpw)
//Register Button presses
bot.kordRef.on<ButtonInteractionCreateEvent> {
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 //Start the bot
bot.start() bot.start()
} }

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
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
) {
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
package de.limited_dev.botendo.buttons
import de.limited_dev.botendo.buttons.music.*
object ButtonManager {
val buttons = listOf(RepeatButton(), PauseButton(), SkipButton(), QueueButton(), StopButton())
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
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)
}
}
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
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)
}
}
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
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)
}
}
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
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)
}
}
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
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
)
)
}
}
}

View file

@ -21,14 +21,19 @@ package de.limited_dev.botendo.extensions.music
import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand 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.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.MessageUtil
import de.limited_dev.botendo.util.TimeUtil import de.limited_dev.botendo.util.TimeUtil
import de.limited_dev.botendo.util.UrlUtil 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.audio.Link
import dev.schlaubi.lavakord.kord.getLink import dev.schlaubi.lavakord.kord.getLink
class NowPlayingExt : Extension() { class NowPlayingExtension : Extension() {
override val name = "nowplaying" override val name = "nowplaying"
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand { publicSlashCommand {
@ -41,6 +46,7 @@ class NowPlayingExt : Extension() {
if (link.state == Link.State.NOT_CONNECTED) { if (link.state == Link.State.NOT_CONNECTED) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0A81A),
"Not connected", "Not connected",
"I'm not in a VC and therefore, I am not playing anything." "I'm not in a VC and therefore, I am not playing anything."
) )
@ -50,26 +56,38 @@ class NowPlayingExt : Extension() {
if (track == null) { if (track == null) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0A81A),
"Not Playing", "Not Playing",
"I'm not playing anything currently" "I'm not playing anything currently"
) )
return@action return@action
} }
MessageUtil.sendEmbedForPublicSlashCommandWithImage( val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
this,
"Currently playing", this.respond {
"**${track.title}**\n*Now Playing*\nby ${track.author} :${ this.embeds.add(
TimeUtil.getTimeFormatedRaw( MessageUtil.getEmbedWithImage(
track.position.inWholeMilliseconds 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 this.actionRow {
) ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating)
}\n" + }
">>>${track.uri}", }
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg"
)
} }
} }
} }

View file

@ -27,10 +27,12 @@ import com.kotlindiscord.kord.extensions.types.respond
import de.limited_dev.botendo.Bot import de.limited_dev.botendo.Bot
import de.limited_dev.botendo.extensions.music.components.MusicManager import de.limited_dev.botendo.extensions.music.components.MusicManager
import de.limited_dev.botendo.util.MessageUtil import de.limited_dev.botendo.util.MessageUtil
import dev.kord.common.Color
import dev.schlaubi.lavakord.audio.Link import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.kord.getLink import dev.schlaubi.lavakord.kord.getLink
class PlayExt : Extension() {
class PlayExtension : Extension() {
override val name = "play" override val name = "play"
@ -47,6 +49,7 @@ class PlayExt : Extension() {
this.respond { this.respond {
embeds.add( embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A),
"You are not connected to a VC", "You are not connected to a VC",
"Please connect to a VC", "Please connect to a VC",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -64,6 +67,7 @@ class PlayExt : Extension() {
this.respond { this.respond {
embeds.add( embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A),
"You are not in my VC", "You are not in my VC",
"We are not in the same VC and therefore, you cannot play any music", "We are not in the same VC and therefore, you cannot play any music",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -82,6 +86,7 @@ class PlayExt : Extension() {
this.respond { this.respond {
embeds.add( embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0A81A),
"Searching...", "Searching...",
"We are looking for $query", "We are looking for $query",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator

View file

@ -21,13 +21,17 @@ package de.limited_dev.botendo.extensions.music
import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand 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.Bot
import de.limited_dev.botendo.extensions.music.components.MusicManager 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.MessageUtil
import de.limited_dev.botendo.util.TimeUtil 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 import dev.schlaubi.lavakord.audio.Link
class QueueExt : Extension() { class QueueExtension : Extension() {
override val name = "queue" override val name = "queue"
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand { publicSlashCommand {
@ -40,6 +44,7 @@ class QueueExt : Extension() {
if (link.state == Link.State.NOT_CONNECTED) { if (link.state == Link.State.NOT_CONNECTED) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0311A),
"Not connected", "Not connected",
"I'm not in a VC and therefore, I am not playing anything." "I'm not in a VC and therefore, I am not playing anything."
) )
@ -49,6 +54,7 @@ class QueueExt : Extension() {
if (track == null) { if (track == null) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0A81A),
"Queue empty", "Queue empty",
"I'm not playing anything currently" "I'm not playing anything currently"
) )
@ -63,8 +69,20 @@ class QueueExt : Extension() {
continue continue
desc += tr.info.title + " - " + TimeUtil.getTimeFormatedShortend(tr.info.length) + " (" + tr.info.author + ")\n" 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)
}
}
} }
} }
} }

View file

@ -21,14 +21,18 @@ package de.limited_dev.botendo.extensions.music
import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand 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.Bot
import de.limited_dev.botendo.extensions.music.components.MusicManager 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.MessageUtil
import de.limited_dev.botendo.util.TimeUtil import de.limited_dev.botendo.util.TimeUtil
import de.limited_dev.botendo.util.UrlUtil 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.audio.Link
class SkipExt : Extension() { class SkipExtension : Extension() {
override val name = "skip" override val name = "skip"
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand { publicSlashCommand {
@ -43,6 +47,7 @@ class SkipExt : Extension() {
if (voiceState == null) { if (voiceState == null) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0311A),
"You are not connected to a VC", "You are not connected to a VC",
"Please connect to a VC" "Please connect to a VC"
) )
@ -53,6 +58,7 @@ class SkipExt : Extension() {
if (link.state == Link.State.NOT_CONNECTED) { if (link.state == Link.State.NOT_CONNECTED) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0311A),
"Not connected", "Not connected",
"I'm not in a VC and therefore, I am not playing anything." "I'm not in a VC and therefore, I am not playing anything."
) )
@ -60,6 +66,7 @@ class SkipExt : Extension() {
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) { } else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0311A),
"You are not in my VC", "You are not in my VC",
"We are not in the same VC and therefore, you cannot control the music" "We are not in the same VC and therefore, you cannot control the music"
) )
@ -69,26 +76,41 @@ class SkipExt : Extension() {
if (track == null) { if (track == null) {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0xE0311A),
"Not playing", "Not playing",
"I'm not playing anything currently" "I'm not playing anything currently"
) )
return@action return@action
} }
val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player) val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
track = gts.getHead().toTrack() if (!gts.isEmpty()) {
gts.playNext() track = gts.getHead().toTrack()
MessageUtil.sendEmbedForPublicSlashCommandWithImage( gts.playNext()
this, } else {
"Skipped song; now playing", player.stopTrack()
"**${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"
)
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)
}
}
} }
} }
} }

View file

@ -25,10 +25,11 @@ import com.kotlindiscord.kord.extensions.types.respond
import de.limited_dev.botendo.Bot import de.limited_dev.botendo.Bot
import de.limited_dev.botendo.extensions.music.components.MusicManager import de.limited_dev.botendo.extensions.music.components.MusicManager
import de.limited_dev.botendo.util.MessageUtil import de.limited_dev.botendo.util.MessageUtil
import dev.kord.common.Color
import dev.schlaubi.lavakord.audio.Link import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.kord.getLink import dev.schlaubi.lavakord.kord.getLink
class StopExt : Extension() { class StopExtension : Extension() {
override val name = "stop" override val name = "stop"
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand { publicSlashCommand {
@ -44,6 +45,7 @@ class StopExt : Extension() {
this.respond { this.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A),
"You are not connected to a VC", "You are not connected to a VC",
"Please connect to my VC", u.asUser().username + "#" + u.asUser().discriminator "Please connect to my VC", u.asUser().username + "#" + u.asUser().discriminator
) )
@ -56,6 +58,7 @@ class StopExt : Extension() {
this.respond { this.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A),
"Not connected", "Not connected",
"I'm not in a VC and therefore, I am not playing anything.", "I'm not in a VC and therefore, I am not playing anything.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -67,6 +70,7 @@ class StopExt : Extension() {
this.respond { this.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A),
"You are not in my VC", "You are not in my VC",
"We are not in the same VC", u.asUser().username + "#" + u.asUser().discriminator "We are not in the same VC", u.asUser().username + "#" + u.asUser().discriminator
) )
@ -80,6 +84,7 @@ class StopExt : Extension() {
this.respond { this.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0x52E01A),
"I stopped and left", "I stopped and left",
"just like your girlfriend", "just like your girlfriend",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator

View file

@ -109,5 +109,9 @@ class GuildTrackScheduler(val pl: Player) {
fun getHead(): TrackResponse.PartialTrack { fun getHead(): TrackResponse.PartialTrack {
return queue.first() return queue.first()
} }
fun isEmpty(): Boolean {
return queue.isEmpty()
}
} }

View file

@ -22,12 +22,15 @@ package de.limited_dev.botendo.extensions.music.components
import com.kotlindiscord.kord.extensions.commands.application.slash.PublicSlashCommandContext import com.kotlindiscord.kord.extensions.commands.application.slash.PublicSlashCommandContext
import com.kotlindiscord.kord.extensions.components.forms.ModalForm import com.kotlindiscord.kord.extensions.components.forms.ModalForm
import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.types.respond
import de.limited_dev.botendo.extensions.music.PlayExt 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.MessageUtil
import de.limited_dev.botendo.util.TimeUtil import de.limited_dev.botendo.util.TimeUtil
import de.limited_dev.botendo.util.UrlUtil import de.limited_dev.botendo.util.UrlUtil
import dev.kord.common.Color
import dev.kord.common.entity.Snowflake import dev.kord.common.entity.Snowflake
import dev.kord.core.entity.Guild 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.Link
import dev.schlaubi.lavakord.audio.player.Player import dev.schlaubi.lavakord.audio.player.Player
import dev.schlaubi.lavakord.rest.TrackResponse import dev.schlaubi.lavakord.rest.TrackResponse
@ -44,7 +47,7 @@ object MusicManager {
suspend fun addToQueue( suspend fun addToQueue(
ctx: PublicSlashCommandContext<PlayExt.PlayArgs, ModalForm>, ctx: PublicSlashCommandContext<PlayExtension.PlayArgs, ModalForm>,
link: Link, link: Link,
search: String search: String
) { ) {
@ -52,7 +55,7 @@ object MusicManager {
} }
suspend fun addToQueue( suspend fun addToQueue(
ctx: PublicSlashCommandContext<PlayExt.PlayArgs, ModalForm>, ctx: PublicSlashCommandContext<PlayExtension.PlayArgs, ModalForm>,
link: Link, link: Link,
search: String, search: String,
silent: Boolean silent: Boolean
@ -71,6 +74,7 @@ object MusicManager {
ctx.respond { ctx.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbedWithImage( MessageUtil.getEmbedWithImage(
Color(0x52E01A),
"Queuing track from link", "Queuing track from link",
"**${item.track.info.title}**\n*Queue*\nby ${item.track.info.author} :: ${ "**${item.track.info.title}**\n*Queue*\nby ${item.track.info.author} :: ${
TimeUtil.getTimeFormatedRaw( TimeUtil.getTimeFormatedRaw(
@ -81,6 +85,15 @@ object MusicManager {
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.track.info.uri) + "/maxresdefault.jpg" "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 { ctx.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbedWithImage( MessageUtil.getEmbedWithImage(
Color(0x52E01A),
"Queuing playlist from link", "Queuing playlist from link",
"**${item.tracks.first().info.title}**\n*${item.playlistInfo.name}*\nby ${item.tracks.first().info.author} :: ${ "**${item.tracks.first().info.title}**\n*${item.playlistInfo.name}*\nby ${item.tracks.first().info.author} :: ${
TimeUtil.getTimeFormatedRaw( TimeUtil.getTimeFormatedRaw(
@ -103,6 +117,15 @@ object MusicManager {
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.track.info.uri) + "/maxresdefault.jpg" "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 { ctx.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbedWithImage( MessageUtil.getEmbedWithImage(
Color(0x52E01A),
"Queuing track from query", "Queuing track from query",
"**${item.tracks.first().info.title}**\n*Queue*\nby ${item.tracks.first().info.author} :: ${ "**${item.tracks.first().info.title}**\n*Queue*\nby ${item.tracks.first().info.author} :: ${
TimeUtil.getTimeFormatedRaw( TimeUtil.getTimeFormatedRaw(
@ -122,6 +146,15 @@ object MusicManager {
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.tracks.first().info.uri) + "/maxresdefault.jpg" "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 { ctx.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A),
"Not found", "Not found",
"There were no matches.", "There were no matches.",
u.username + "#" + u.discriminator u.username + "#" + u.discriminator
@ -143,6 +177,7 @@ object MusicManager {
ctx.respond { ctx.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A),
"Load failed", "Load failed",
"There was an error while loading.", u.username + "#" + u.discriminator "There was an error while loading.", u.username + "#" + u.discriminator
) )

View file

@ -23,8 +23,9 @@ import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import de.limited_dev.botendo.build.BuildConstants import de.limited_dev.botendo.build.BuildConstants
import de.limited_dev.botendo.util.MessageUtil import de.limited_dev.botendo.util.MessageUtil
import dev.kord.common.Color
class InfoExt : Extension() { class InfoExtension : Extension() {
override val name = "info" override val name = "info"
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand { publicSlashCommand {
@ -32,9 +33,9 @@ class InfoExt : Extension() {
description = "Show infos about the bot" description = "Show infos about the bot"
this.action { this.action {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, "Botendo", this, Color(0x52E01A), "Botendo",
"Botendo ***v." + BuildConstants.version + "***\n" + "Botendo ***v." + BuildConstants.version + "***\n" +
"kord-extensions ***v." + BuildConstants.kordVersion + "***\n" + "Kord-Extensions ***v." + BuildConstants.kordVersion + "***\n" +
"lavalink.kt ***v." + BuildConstants.lavaVersion + "***\n" + "lavalink.kt ***v." + BuildConstants.lavaVersion + "***\n" +
"Coroutines ***v." + BuildConstants.coroutinesVersion + "***" "Coroutines ***v." + BuildConstants.coroutinesVersion + "***"
) )

View file

@ -0,0 +1,42 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*
*/
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"
override suspend fun setup() {
publicSlashCommand {
name = "potato"
description = "Potato"
this.action {
MessageUtil.sendEmbedForPublicSlashCommandWithImage(
this, Color(0xE0311A), "Potato",
"Potato",
"https://static.tumblr.com/c06d8e0928395746a63b9c5d3cb1ce66/sl9iajp/gxFmqk38z/tumblr_static_potato-equality.jpg"
)
}
}
}
}

View file

@ -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 <https://www.gnu.org/licenses/>.
*
*/
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
}
}

View file

@ -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.commands.application.slash.PublicSlashCommandContext
import com.kotlindiscord.kord.extensions.components.forms.ModalForm import com.kotlindiscord.kord.extensions.components.forms.ModalForm
import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.types.respond
import dev.kord.common.Color
import dev.kord.rest.builder.message.EmbedBuilder import dev.kord.rest.builder.message.EmbedBuilder
import java.time.LocalDateTime import java.time.LocalDateTime
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
@ -30,14 +31,17 @@ import java.time.format.DateTimeFormatter
object MessageUtil { object MessageUtil {
private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy @ HH:mm:ss") private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy @ HH:mm:ss")
///Send an embedded message as a reply
suspend fun sendEmbedForPublicSlashCommand( suspend fun sendEmbedForPublicSlashCommand(
ctx: PublicSlashCommandContext<Arguments, ModalForm>, ctx: PublicSlashCommandContext<Arguments, ModalForm>,
color: Color,
title: String, title: String,
description: String description: String
) { ) {
ctx.respond { ctx.respond {
embeds.add( embeds.add(
getEmbed( getEmbed(
color,
title, title,
description, description,
ctx.user.asUser().username + "#" + ctx.user.asUser().discriminator 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( suspend fun sendEmbedForPublicSlashCommandWithImage(
ctx: PublicSlashCommandContext<Arguments, ModalForm>, ctx: PublicSlashCommandContext<Arguments, ModalForm>,
color: Color,
title: String, title: String,
description: String, description: String,
thumbnailUrl: String thumbnailUrl: String
@ -55,6 +61,7 @@ object MessageUtil {
ctx.respond { ctx.respond {
embeds.add( embeds.add(
getEmbedWithImage( getEmbedWithImage(
color,
title, title,
description, description,
ctx.user.asUser().username + "#" + ctx.user.asUser().discriminator, 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 now: LocalDateTime = LocalDateTime.now()
val ebb = EmbedBuilder() val ebb = EmbedBuilder()
ebb.title = title ebb.title = title
ebb.description = description ebb.description = description
ebb.footer = EmbedBuilder.Footer() ebb.footer = EmbedBuilder.Footer()
ebb.footer!!.text = ">" + dtf.format(now) + " - $source" ebb.footer!!.text = ">" + dtf.format(now) + " - $source"
ebb.color = color
return ebb return ebb
} }
///Get an embedded msg with image, title, description and a src
fun getEmbedWithImage( fun getEmbedWithImage(
color: Color,
title: String, title: String,
description: String, description: String,
source: String, source: String,
thumbnailUrl: String thumbnailUrl: String
): EmbedBuilder { ): EmbedBuilder {
val ebb = getEmbed(title, description, source) val ebb = getEmbed(color, title, description, source)
ebb.thumbnail = EmbedBuilder.Thumbnail() ebb.thumbnail = EmbedBuilder.Thumbnail()
ebb.thumbnail!!.url = thumbnailUrl ebb.thumbnail!!.url = thumbnailUrl
return ebb return ebb

View file

@ -22,7 +22,8 @@ package de.limited_dev.botendo.util
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
object TimeUtil { object TimeUtil {
fun getTimeFormatedShortend(time: Long): String? { ///Convert Miliseconds to xdays xhours xmins xsecs
fun getTimeFormatedShortend(time: Long): String {
var time = time var time = time
val days = TimeUnit.MILLISECONDS val days = TimeUnit.MILLISECONDS
.toDays(time) .toDays(time)
@ -54,7 +55,7 @@ object TimeUtil {
return s return s
} }
fun getTimeFormatedRaw(time: Long): String? { fun getTimeFormatedRaw(time: Long): String {
var time = time var time = time
val days = TimeUnit.MILLISECONDS val days = TimeUnit.MILLISECONDS
.toDays(time) .toDays(time)

View file

@ -20,6 +20,7 @@
package de.limited_dev.botendo.util package de.limited_dev.botendo.util
object UrlUtil { object UrlUtil {
///Strip the video ID from a YouTube link
fun getYtThumbnailUrl(uri: String): String { fun getYtThumbnailUrl(uri: String): String {
return uri.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1] return uri.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
} }