feat: rebuild system on kord-extensions, marking the 3rd rewirte
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
This commit is contained in:
parent
9d34385fb1
commit
be96fae5eb
25 changed files with 683 additions and 818 deletions
|
@ -35,7 +35,7 @@ version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_
|
|||
?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" }
|
||||
?: "DevelopmentBuild"
|
||||
|
||||
val kordver = "0.8.3"
|
||||
val kordver = "1.5.6"
|
||||
val lavaver = "3.8.0"
|
||||
val coroutinesver = "1.1.0"
|
||||
|
||||
|
@ -68,12 +68,16 @@ repositories {
|
|||
}
|
||||
}
|
||||
|
||||
val shadow by configurations.getting
|
||||
val implementation by configurations.getting
|
||||
implementation.extendsFrom(shadow)
|
||||
|
||||
dependencies {
|
||||
implementation("dev.kord:kord-core:$kordver")
|
||||
implementation("dev.schlaubi.lavakord:kord:$lavaver")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver")
|
||||
implementation("org.slf4j:slf4j-api:2.0.3")
|
||||
implementation("org.slf4j:slf4j-simple:2.0.3")
|
||||
shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordver")
|
||||
shadow("dev.schlaubi.lavakord:kord:$lavaver")
|
||||
shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver")
|
||||
shadow("org.slf4j:slf4j-api:2.0.3")
|
||||
shadow("org.slf4j:slf4j-simple:2.0.3")
|
||||
}
|
||||
|
||||
|
||||
|
@ -117,13 +121,7 @@ tasks {
|
|||
|
||||
|
||||
withType<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar> {
|
||||
dependencies {
|
||||
include(dependency("dev.schlaubi.lavakord:kord:$lavaver"))
|
||||
include(dependency("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver"))
|
||||
include(dependency("dev.kord:kord-core:$kordver"))
|
||||
include(dependency("org.slf4j:slf4j-api:2.0.3"))
|
||||
include(dependency("org.slf4j:slf4j-simple:2.0.3"))
|
||||
}
|
||||
configurations = listOf(shadow)
|
||||
dependsOn("generateTemplates", "processResources")
|
||||
}
|
||||
|
||||
|
|
|
@ -19,24 +19,18 @@
|
|||
|
||||
package de.limited_dev.botendo
|
||||
|
||||
import de.limited_dev.botendo.commands.slash.component.SlashCommandManager
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import de.limited_dev.botendo.commands.slash.component.options.OptionType
|
||||
import com.kotlindiscord.kord.extensions.ExtensibleBot
|
||||
import de.limited_dev.botendo.extensions.music.*
|
||||
import de.limited_dev.botendo.extensions.util.InfoExt
|
||||
import de.limited_dev.botendo.util.CredentialManager
|
||||
import de.limited_dev.botendo.util.Logger
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import dev.kord.core.Kord
|
||||
import dev.kord.core.event.interaction.GuildChatInputCommandInteractionCreateEvent
|
||||
import dev.kord.core.on
|
||||
import dev.kord.gateway.Intent
|
||||
import dev.kord.gateway.PrivilegedIntent
|
||||
import dev.schlaubi.lavakord.LavaKord
|
||||
import dev.schlaubi.lavakord.kord.lavakord
|
||||
|
||||
object Bot {
|
||||
//The kord object gets set at app launch
|
||||
lateinit var kord: Kord
|
||||
lateinit var lava: LavaKord
|
||||
private lateinit var bot: ExtensibleBot
|
||||
suspend fun start() {
|
||||
Logger.out("Starting Bot...")
|
||||
|
||||
|
@ -49,97 +43,30 @@ object Bot {
|
|||
return
|
||||
}
|
||||
|
||||
//Register slash commands to bot
|
||||
SlashCommandManager.register()
|
||||
|
||||
//Add Bot token to kord
|
||||
kord = Kord(CredentialManager.token)
|
||||
|
||||
//Register Command Listener
|
||||
kord.on<GuildChatInputCommandInteractionCreateEvent> {
|
||||
val deferred = interaction.deferPublicResponse()
|
||||
//val deferred = async { interaction.deferPublicResponse() }
|
||||
val command = interaction.command
|
||||
Logger.out("Command /${command.rootName} with ${command.options.size} Option${if (command.options.size == 1) "" else "s"}")
|
||||
for (c in SlashCommandManager.commands) {
|
||||
if (c.name != command.rootName)
|
||||
continue
|
||||
val opt = mutableMapOf<CommandOption, String>()
|
||||
if (c.options != null) {
|
||||
for (o in c.options) {
|
||||
when (o.type) {
|
||||
OptionType.INT ->
|
||||
if (command.integers[o.name] != null)
|
||||
opt[o] = command.integers[o.name].toString()
|
||||
|
||||
OptionType.STRING ->
|
||||
if (command.strings[o.name] != null)
|
||||
opt[o] = command.strings[o.name].toString()
|
||||
|
||||
OptionType.BOOLEAN ->
|
||||
if (command.booleans[o.name] != null)
|
||||
opt[o] = command.booleans[o.name].toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
c.onSlashCommand(interaction, deferred, opt)
|
||||
return@on
|
||||
}
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction, deferred, "Command not found", "Could not find the command, which you just ran.\n" +
|
||||
"This is 110%ly an error. Please report it to limited_dev#7441."
|
||||
)
|
||||
//kord = Kord(CredentialManager.token)
|
||||
bot = ExtensibleBot(CredentialManager.token) {
|
||||
applicationCommands {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
//Register Slash Commands at Discord
|
||||
/*
|
||||
kord.createGlobalApplicationCommands {
|
||||
for (sc in SlashCommandManager.commands) {
|
||||
this.input(sc.name, sc.description, builder = {
|
||||
if (sc.options != null) {
|
||||
for (o in sc.options) {
|
||||
when (o.type) {
|
||||
|
||||
OptionType.INT -> {
|
||||
integer(o.name, o.description) {
|
||||
this.required = o.required
|
||||
extensions {
|
||||
add(::InfoExt)
|
||||
add(::PlayExt)
|
||||
add(::StopExt)
|
||||
add(::SkipExt)
|
||||
add(::NowPlayingExt)
|
||||
add(::QueueExt)
|
||||
}
|
||||
}
|
||||
|
||||
OptionType.STRING -> {
|
||||
string(o.name, o.description) {
|
||||
this.required = o.required
|
||||
}
|
||||
}
|
||||
|
||||
OptionType.BOOLEAN -> {
|
||||
boolean(o.name, o.description) {
|
||||
this.required = o.required
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
} */
|
||||
|
||||
//Add LavaLink
|
||||
lava = kord.lavakord()
|
||||
lava = bot.kordRef.lavakord()
|
||||
|
||||
//Add the LavaLink node from config
|
||||
lava.addNode(CredentialManager.linkip, CredentialManager.linkpw)
|
||||
|
||||
Logger.out("Logging in")
|
||||
|
||||
//Start the bot
|
||||
kord.login {
|
||||
// Load gateway privileges
|
||||
@OptIn(PrivilegedIntent::class)
|
||||
intents += Intent.GuildMembers
|
||||
|
||||
@OptIn(PrivilegedIntent::class)
|
||||
intents += Intent.MessageContent
|
||||
}
|
||||
bot.start()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,6 @@ suspend fun main() {
|
|||
"M#########M \n" +
|
||||
" "
|
||||
)
|
||||
println("Bot ver.${BuildConstants.version}")
|
||||
println("Bot v.${BuildConstants.version}, Kord Extensions v.${BuildConstants.kordVersion}, LavaKord v.${BuildConstants.lavaVersion}, Coroutines v.${BuildConstants.coroutinesVersion}")
|
||||
Bot.start()
|
||||
}
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.component
|
||||
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
|
||||
abstract class SlashCommand(val name: String, val description: String, val options: List<CommandOption>? = null) {
|
||||
|
||||
open suspend fun onSlashCommand(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
args: Map<CommandOption, String>
|
||||
) {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.component
|
||||
|
||||
import de.limited_dev.botendo.commands.slash.music.*
|
||||
import de.limited_dev.botendo.commands.slash.util.InfoCommand
|
||||
|
||||
object SlashCommandManager {
|
||||
|
||||
val commands = mutableListOf<SlashCommand>()
|
||||
|
||||
fun register() {
|
||||
commands.add(InfoCommand())
|
||||
commands.add(PlayCommand())
|
||||
commands.add(StopCommand())
|
||||
commands.add(NowPlayingCommand())
|
||||
commands.add(QueueCommand())
|
||||
commands.add(SkipCommand())
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.component.options
|
||||
|
||||
data class CommandOption(val name: String, val description: String, val required: Boolean, val type: OptionType)
|
|
@ -1,26 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.component.options
|
||||
|
||||
enum class OptionType {
|
||||
INT,
|
||||
STRING,
|
||||
BOOLEAN
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.music
|
||||
|
||||
import de.limited_dev.botendo.Bot
|
||||
import de.limited_dev.botendo.commands.slash.component.SlashCommand
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import de.limited_dev.botendo.util.TimeUtil
|
||||
import de.limited_dev.botendo.util.UrlUtil
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
|
||||
class NowPlayingCommand : SlashCommand("nowplaying", "Show what's currently playing", null) {
|
||||
override suspend fun onSlashCommand(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
args: Map<CommandOption, String>
|
||||
) {
|
||||
val guildId = interaction.guildId
|
||||
val link = Bot.lava.getLink(guildId.toString())
|
||||
val player = link.player
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything."
|
||||
)
|
||||
return
|
||||
}
|
||||
val track = player.playingTrack
|
||||
if (track == null) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Not Playing",
|
||||
"I'm not playing anything currently"
|
||||
)
|
||||
return
|
||||
}
|
||||
MessageUtil.sendEmbedForInteractionWithImage(
|
||||
interaction,
|
||||
deferred,
|
||||
"Currently 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"
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.music
|
||||
|
||||
import de.limited_dev.botendo.Bot.lava
|
||||
import de.limited_dev.botendo.commands.slash.component.SlashCommand
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import de.limited_dev.botendo.commands.slash.component.options.OptionType
|
||||
import de.limited_dev.botendo.commands.slash.music.component.MusicManager
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
|
||||
class PlayCommand : SlashCommand(
|
||||
"play",
|
||||
"Play music",
|
||||
listOf(CommandOption("linkquery", "Either a search query or a Link", true, OptionType.STRING))
|
||||
) {
|
||||
override suspend fun onSlashCommand(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
args: Map<CommandOption, String>
|
||||
) {
|
||||
val guildId = interaction.guildId
|
||||
val link = lava.getLink(guildId.toString())
|
||||
|
||||
val voiceState = interaction.user.getVoiceStateOrNull()
|
||||
if (voiceState == null) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"You are not connected to a VC",
|
||||
"Please connect to a VC"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val channelId = voiceState.channelId
|
||||
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
link.connectAudio(channelId!!.value)
|
||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"You are not in my VC",
|
||||
"We are not in the same VC and therefore, you cannot play any music"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val query = args[this.options!![0]]
|
||||
val search = if (query!!.startsWith("http")) {
|
||||
query
|
||||
} else {
|
||||
"ytsearch:$query"
|
||||
}
|
||||
MessageUtil.sendEmbedForInteraction(interaction, deferred, "Searching...", "We are looking for $query")
|
||||
MusicManager.addToQueue(interaction, deferred, link, search)
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.music
|
||||
|
||||
import de.limited_dev.botendo.Bot
|
||||
import de.limited_dev.botendo.commands.slash.component.SlashCommand
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import de.limited_dev.botendo.commands.slash.music.component.MusicManager
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import de.limited_dev.botendo.util.TimeUtil
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
|
||||
class QueueCommand : SlashCommand("queue", "Show whats up next", null) {
|
||||
override suspend fun onSlashCommand(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
args: Map<CommandOption, String>
|
||||
) {
|
||||
val guildId = interaction.guildId
|
||||
val link = Bot.lava.getLink(guildId.toString())
|
||||
val player = link.player
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything."
|
||||
)
|
||||
return
|
||||
}
|
||||
val track = player.playingTrack
|
||||
if (track == null) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Queue empty",
|
||||
"I'm not playing anything currently"
|
||||
)
|
||||
return
|
||||
}
|
||||
val gts = MusicManager.getGuildTrackScheduler(interaction.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"
|
||||
}
|
||||
MessageUtil.sendEmbedForInteraction(interaction, deferred, "Queue", desc)
|
||||
}
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.music
|
||||
|
||||
import de.limited_dev.botendo.Bot
|
||||
import de.limited_dev.botendo.commands.slash.component.SlashCommand
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import de.limited_dev.botendo.commands.slash.music.component.MusicManager
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import de.limited_dev.botendo.util.TimeUtil
|
||||
import de.limited_dev.botendo.util.UrlUtil
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
|
||||
class SkipCommand : SlashCommand("skip", "Skip to the next song in queue", null) {
|
||||
override suspend fun onSlashCommand(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
args: Map<CommandOption, String>
|
||||
) {
|
||||
val guildId = interaction.guildId
|
||||
val link = Bot.lava.getLink(guildId.toString())
|
||||
val player = link.player
|
||||
val voiceState = interaction.user.getVoiceStateOrNull()
|
||||
if (voiceState == null) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"You are not connected to a VC",
|
||||
"Please connect to a VC"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val channelId = voiceState.channelId
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything."
|
||||
)
|
||||
return
|
||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"You are not in my VC",
|
||||
"We are not in the same VC and therefore, you cannot control the music"
|
||||
)
|
||||
return
|
||||
}
|
||||
var track = player.playingTrack
|
||||
if (track == null) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Not playing",
|
||||
"I'm not playing anything currently"
|
||||
)
|
||||
return
|
||||
}
|
||||
val gts = MusicManager.getGuildTrackScheduler(interaction.guild.asGuild(), player)
|
||||
track = gts.getHead().toTrack()
|
||||
gts.playNext()
|
||||
MessageUtil.sendEmbedForInteractionWithImage(
|
||||
interaction,
|
||||
deferred,
|
||||
"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"
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.music
|
||||
|
||||
import de.limited_dev.botendo.Bot
|
||||
import de.limited_dev.botendo.commands.slash.component.SlashCommand
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import de.limited_dev.botendo.commands.slash.music.component.MusicManager
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
|
||||
class StopCommand : SlashCommand("stop", "Stop playing and start leavin'", null) {
|
||||
override suspend fun onSlashCommand(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
args: Map<CommandOption, String>
|
||||
) {
|
||||
val guildId = interaction.guildId
|
||||
val link = Bot.lava.getLink(guildId.toString())
|
||||
val player = link.player
|
||||
|
||||
val voiceState = interaction.user.getVoiceStateOrNull()
|
||||
if (voiceState == null) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"You are not connected to a VC",
|
||||
"Please connect to my VC"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val channelId = voiceState.channelId
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything."
|
||||
)
|
||||
return
|
||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"You are not in my VC",
|
||||
"We are not in the same VC"
|
||||
)
|
||||
return
|
||||
}
|
||||
player.stopTrack()
|
||||
link.destroy()
|
||||
MusicManager.getGuildTrackScheduler(interaction.getGuild(), player).clear()
|
||||
MessageUtil.sendEmbedForInteraction(interaction, deferred, "I stopped and left", "just like your girlfriend")
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.music.component
|
||||
|
||||
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.entity.Snowflake
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.Guild
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
import dev.schlaubi.lavakord.audio.player.Player
|
||||
import dev.schlaubi.lavakord.rest.TrackResponse
|
||||
import dev.schlaubi.lavakord.rest.loadItem
|
||||
|
||||
object MusicManager {
|
||||
private var musicManagerMap: MutableMap<Snowflake, GuildTrackScheduler> = mutableMapOf()
|
||||
|
||||
fun getGuildTrackScheduler(guild: Guild, player: Player): GuildTrackScheduler {
|
||||
return musicManagerMap.computeIfAbsent(guild.id) {
|
||||
GuildTrackScheduler(player)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
suspend fun addToQueue(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
link: Link,
|
||||
search: String
|
||||
) {
|
||||
addToQueue(interaction, deferred, link, search, false)
|
||||
}
|
||||
|
||||
suspend fun addToQueue(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
link: Link,
|
||||
search: String,
|
||||
silent: Boolean
|
||||
) {
|
||||
val player = link.player
|
||||
val item = link.loadItem(search)
|
||||
val gts = getGuildTrackScheduler(interaction.getGuild(), player)
|
||||
|
||||
gts.addEvents()
|
||||
|
||||
when (item.loadType) {
|
||||
TrackResponse.LoadType.TRACK_LOADED -> {
|
||||
gts.queue(item.track)
|
||||
if (!silent)
|
||||
MessageUtil.sendEmbedForInteractionWithImage(
|
||||
interaction,
|
||||
deferred,
|
||||
"Queuing track from link",
|
||||
"**${item.track.info.title}**\n*Queue*\nby ${item.track.info.author} :: ${
|
||||
TimeUtil.getTimeFormatedRaw(
|
||||
item.track.info.length
|
||||
)
|
||||
}\n" +
|
||||
">>>${item.track.info.uri}",
|
||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.track.info.uri) + "/maxresdefault.jpg"
|
||||
)
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.PLAYLIST_LOADED -> {
|
||||
val l = item.tracks.reversed()
|
||||
for (partialTrack in l) {
|
||||
gts.queue(partialTrack)
|
||||
}
|
||||
if (!silent)
|
||||
MessageUtil.sendEmbedForInteractionWithImage(
|
||||
interaction,
|
||||
deferred,
|
||||
"Queuing playlist from link",
|
||||
"**${item.tracks.first().info.title}**\n*${item.playlistInfo.name}*\nby ${item.tracks.first().info.author} :: ${
|
||||
TimeUtil.getTimeFormatedRaw(
|
||||
item.tracks.first().info.length
|
||||
)
|
||||
}\n" +
|
||||
">>>${item.tracks.first().info.uri}",
|
||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.tracks.first().info.uri) + "/maxresdefault.jpg"
|
||||
)
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.SEARCH_RESULT -> {
|
||||
gts.queue(item.tracks.first())
|
||||
if (!silent)
|
||||
MessageUtil.sendEmbedForInteractionWithImage(
|
||||
interaction,
|
||||
deferred,
|
||||
"Queuing track from query",
|
||||
"**${item.tracks.first().info.title}**\n*Queue*\nby ${item.tracks.first().info.author} :: ${
|
||||
TimeUtil.getTimeFormatedRaw(
|
||||
item.tracks.first().info.length
|
||||
)
|
||||
}\n" +
|
||||
">>>${item.tracks.first().info.uri}",
|
||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.tracks.first().info.uri) + "/maxresdefault.jpg"
|
||||
)
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.NO_MATCHES -> {
|
||||
if (!silent)
|
||||
MessageUtil.sendEmbedForInteraction(interaction, deferred, "Not found", "There were no matches.")
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.LOAD_FAILED -> {
|
||||
if (!silent)
|
||||
MessageUtil.sendEmbedForInteraction(
|
||||
interaction,
|
||||
deferred,
|
||||
"Load failed",
|
||||
"There was an error while loading."
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* 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.commands.slash.util
|
||||
|
||||
import de.limited_dev.botendo.build.BuildConstants
|
||||
import de.limited_dev.botendo.commands.slash.component.SlashCommand
|
||||
import de.limited_dev.botendo.commands.slash.component.options.CommandOption
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
|
||||
class InfoCommand : SlashCommand("info", "Shows infos about the bot", null) {
|
||||
override suspend fun onSlashCommand(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
args: Map<CommandOption, String>
|
||||
) {
|
||||
MessageUtil.sendEmbedForInteraction(interaction, deferred, "Botendo v5", "ver." + BuildConstants.version)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.music
|
||||
|
||||
import com.kotlindiscord.kord.extensions.extensions.Extension
|
||||
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
|
||||
import de.limited_dev.botendo.Bot
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import de.limited_dev.botendo.util.TimeUtil
|
||||
import de.limited_dev.botendo.util.UrlUtil
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
import dev.schlaubi.lavakord.kord.getLink
|
||||
|
||||
class NowPlayingExt : Extension() {
|
||||
override val name = "nowplaying"
|
||||
override suspend fun setup() {
|
||||
publicSlashCommand {
|
||||
name = "nowplaying"
|
||||
description = "Show what's currently playing"
|
||||
this.action {
|
||||
val guildId = this.guild!!.id
|
||||
val link = Bot.lava.getLink(guildId)
|
||||
val player = link.player
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything."
|
||||
)
|
||||
return@action
|
||||
}
|
||||
val track = player.playingTrack
|
||||
if (track == null) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"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.length.inWholeMilliseconds
|
||||
)
|
||||
}\n" +
|
||||
">>>${track.uri}",
|
||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.extensions.music
|
||||
|
||||
import com.kotlindiscord.kord.extensions.commands.Arguments
|
||||
import com.kotlindiscord.kord.extensions.commands.converters.impl.string
|
||||
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.MessageUtil
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
import dev.schlaubi.lavakord.kord.getLink
|
||||
|
||||
class PlayExt : Extension() {
|
||||
|
||||
override val name = "play"
|
||||
|
||||
override suspend fun setup() {
|
||||
publicSlashCommand(::PlayArgs) {
|
||||
name = "play"
|
||||
description = "Play music"
|
||||
this.action {
|
||||
val guildId = this.guild!!.id
|
||||
val link = Bot.lava.getLink(guildId)
|
||||
val u = this.user
|
||||
val vcsUser = u.asMember(guildId).getVoiceStateOrNull()
|
||||
if (vcsUser == null) {
|
||||
this.respond {
|
||||
embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"You are not connected to a VC",
|
||||
"Please connect to a VC",
|
||||
u.asUser().username + "#" + u.asUser().discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
return@action
|
||||
}
|
||||
|
||||
val channelId = vcsUser.channelId
|
||||
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
link.connectAudio(channelId!!.value)
|
||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||
this.respond {
|
||||
embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"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
|
||||
)
|
||||
)
|
||||
}
|
||||
return@action
|
||||
}
|
||||
|
||||
val query = arguments.linkquery
|
||||
val search = if (query.startsWith("http")) {
|
||||
query
|
||||
} else {
|
||||
"ytsearch:$query"
|
||||
}
|
||||
this.respond {
|
||||
embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"Searching...",
|
||||
"We are looking for $query",
|
||||
u.asUser().username + "#" + u.asUser().discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
MusicManager.addToQueue(this, link, search)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inner class PlayArgs : Arguments() {
|
||||
val linkquery by string {
|
||||
name = "linkqery"
|
||||
description = "Song link or search query"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* 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.music
|
||||
|
||||
import com.kotlindiscord.kord.extensions.extensions.Extension
|
||||
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
|
||||
import de.limited_dev.botendo.Bot
|
||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import de.limited_dev.botendo.util.TimeUtil
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
|
||||
class QueueExt : Extension() {
|
||||
override val name = "queue"
|
||||
override suspend fun setup() {
|
||||
publicSlashCommand {
|
||||
name = "queue"
|
||||
description = "Show whats up next"
|
||||
this.action {
|
||||
val guildId = this.guild!!.id
|
||||
val link = Bot.lava.getLink(guildId.toString())
|
||||
val player = link.player
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything."
|
||||
)
|
||||
return@action
|
||||
}
|
||||
val track = player.playingTrack
|
||||
if (track == null) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"Queue empty",
|
||||
"I'm not playing anything currently"
|
||||
)
|
||||
return@action
|
||||
}
|
||||
val gts = MusicManager.getGuildTrackScheduler(this.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"
|
||||
}
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(this, "Queue", desc)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.music
|
||||
|
||||
import com.kotlindiscord.kord.extensions.extensions.Extension
|
||||
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
|
||||
import de.limited_dev.botendo.Bot
|
||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
import de.limited_dev.botendo.util.TimeUtil
|
||||
import de.limited_dev.botendo.util.UrlUtil
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
|
||||
class SkipExt : Extension() {
|
||||
override val name = "skip"
|
||||
override suspend fun setup() {
|
||||
publicSlashCommand {
|
||||
name = "skip"
|
||||
description = "Skip to the next song in queue"
|
||||
this.action {
|
||||
val guildId = this.guild!!.id
|
||||
val link = Bot.lava.getLink(guildId.toString())
|
||||
val player = link.player
|
||||
val u = this.user
|
||||
val voiceState = u.asMember(guildId).getVoiceStateOrNull()
|
||||
if (voiceState == null) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"You are not connected to a VC",
|
||||
"Please connect to a VC"
|
||||
)
|
||||
return@action
|
||||
}
|
||||
|
||||
val channelId = voiceState.channelId
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything."
|
||||
)
|
||||
return@action
|
||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"You are not in my VC",
|
||||
"We are not in the same VC and therefore, you cannot control the music"
|
||||
)
|
||||
return@action
|
||||
}
|
||||
var track = player.playingTrack
|
||||
if (track == null) {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this,
|
||||
"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"
|
||||
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* 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.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.MessageUtil
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
import dev.schlaubi.lavakord.kord.getLink
|
||||
|
||||
class StopExt : Extension() {
|
||||
override val name = "stop"
|
||||
override suspend fun setup() {
|
||||
publicSlashCommand {
|
||||
name = "stop"
|
||||
description = "Stop playing and start leavin'"
|
||||
this.action {
|
||||
val guildId = this.guild!!.id
|
||||
val link = Bot.lava.getLink(guildId)
|
||||
val player = link.player
|
||||
val u = this.user
|
||||
val vcsUser = u.asMember(guildId).getVoiceStateOrNull()
|
||||
if (vcsUser == null) {
|
||||
this.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"You are not connected to a VC",
|
||||
"Please connect to my VC", u.asUser().username + "#" + u.asUser().discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
return@action
|
||||
}
|
||||
val channelId = vcsUser.channelId
|
||||
if (link.state != Link.State.CONNECTED) {
|
||||
this.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"Not connected",
|
||||
"I'm not in a VC and therefore, I am not playing anything.",
|
||||
u.asUser().username + "#" + u.asUser().discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
return@action
|
||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||
this.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"You are not in my VC",
|
||||
"We are not in the same VC", u.asUser().username + "#" + u.asUser().discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
return@action
|
||||
}
|
||||
player.stopTrack()
|
||||
link.destroy()
|
||||
MusicManager.getGuildTrackScheduler(this.getGuild()!!.asGuild(), player).clear()
|
||||
this.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"I stopped and left",
|
||||
"just like your girlfriend",
|
||||
u.asUser().username + "#" + u.asUser().discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@
|
|||
*
|
||||
*/
|
||||
|
||||
package de.limited_dev.botendo.commands.slash.music.component
|
||||
package de.limited_dev.botendo.extensions.music.components
|
||||
|
||||
import de.limited_dev.botendo.util.Logger
|
||||
import dev.schlaubi.lavakord.audio.TrackEndEvent
|
||||
|
@ -110,3 +110,4 @@ class GuildTrackScheduler(val pl: Player) {
|
|||
return queue.first()
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* 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.music.components
|
||||
|
||||
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 de.limited_dev.botendo.extensions.music.PlayExt
|
||||
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.entity.Snowflake
|
||||
import dev.kord.core.entity.Guild
|
||||
import dev.schlaubi.lavakord.audio.Link
|
||||
import dev.schlaubi.lavakord.audio.player.Player
|
||||
import dev.schlaubi.lavakord.rest.TrackResponse
|
||||
import dev.schlaubi.lavakord.rest.loadItem
|
||||
|
||||
object MusicManager {
|
||||
private var musicManagerMap: MutableMap<Snowflake, GuildTrackScheduler> = mutableMapOf()
|
||||
|
||||
fun getGuildTrackScheduler(guild: Guild, player: Player): GuildTrackScheduler {
|
||||
return musicManagerMap.computeIfAbsent(guild.id) {
|
||||
GuildTrackScheduler(player)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
suspend fun addToQueue(
|
||||
ctx: PublicSlashCommandContext<PlayExt.PlayArgs, ModalForm>,
|
||||
link: Link,
|
||||
search: String
|
||||
) {
|
||||
addToQueue(ctx, link, search, false)
|
||||
}
|
||||
|
||||
suspend fun addToQueue(
|
||||
ctx: PublicSlashCommandContext<PlayExt.PlayArgs, ModalForm>,
|
||||
link: Link,
|
||||
search: String,
|
||||
silent: Boolean
|
||||
) {
|
||||
val player = link.player
|
||||
val item = link.loadItem(search)
|
||||
val gts = getGuildTrackScheduler(ctx.guild!!.asGuild(), player)
|
||||
val u = ctx.user.asUser()
|
||||
|
||||
gts.addEvents()
|
||||
|
||||
when (item.loadType) {
|
||||
TrackResponse.LoadType.TRACK_LOADED -> {
|
||||
gts.queue(item.track)
|
||||
if (!silent)
|
||||
ctx.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbedWithImage(
|
||||
"Queuing track from link",
|
||||
"**${item.track.info.title}**\n*Queue*\nby ${item.track.info.author} :: ${
|
||||
TimeUtil.getTimeFormatedRaw(
|
||||
item.track.info.length
|
||||
)
|
||||
}\n" +
|
||||
">>>${item.track.info.uri}", u.username + "#" + u.discriminator,
|
||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.track.info.uri) + "/maxresdefault.jpg"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.PLAYLIST_LOADED -> {
|
||||
val l = item.tracks.reversed()
|
||||
for (partialTrack in l) {
|
||||
gts.queue(partialTrack)
|
||||
}
|
||||
if (!silent)
|
||||
ctx.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbedWithImage(
|
||||
"Queuing playlist from link",
|
||||
"**${item.tracks.first().info.title}**\n*${item.playlistInfo.name}*\nby ${item.tracks.first().info.author} :: ${
|
||||
TimeUtil.getTimeFormatedRaw(
|
||||
item.tracks.first().info.length
|
||||
)
|
||||
}\n" +
|
||||
">>>${item.tracks.first().info.uri}", u.username + "#" + u.discriminator,
|
||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.track.info.uri) + "/maxresdefault.jpg"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.SEARCH_RESULT -> {
|
||||
gts.queue(item.tracks.first())
|
||||
if (!silent)
|
||||
ctx.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbedWithImage(
|
||||
"Queuing track from query",
|
||||
"**${item.tracks.first().info.title}**\n*Queue*\nby ${item.tracks.first().info.author} :: ${
|
||||
TimeUtil.getTimeFormatedRaw(
|
||||
item.tracks.first().info.length
|
||||
)
|
||||
}\n" +
|
||||
">>>${item.tracks.first().info.uri}", u.username + "#" + u.discriminator,
|
||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(item.tracks.first().info.uri) + "/maxresdefault.jpg"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.NO_MATCHES -> {
|
||||
if (!silent)
|
||||
ctx.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"Not found",
|
||||
"There were no matches.",
|
||||
u.username + "#" + u.discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
TrackResponse.LoadType.LOAD_FAILED -> {
|
||||
if (!silent)
|
||||
ctx.respond {
|
||||
this.embeds.add(
|
||||
MessageUtil.getEmbed(
|
||||
"Load failed",
|
||||
"There was an error while loading.", u.username + "#" + u.discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* 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.build.BuildConstants
|
||||
import de.limited_dev.botendo.util.MessageUtil
|
||||
|
||||
class InfoExt : Extension() {
|
||||
override val name = "info"
|
||||
override suspend fun setup() {
|
||||
publicSlashCommand {
|
||||
name = "info"
|
||||
description = "Show infos about the bot"
|
||||
this.action {
|
||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
||||
this, "Botendo",
|
||||
"Botendo ***v." + BuildConstants.version + "***\n" +
|
||||
"kord-extensions ***v." + BuildConstants.kordVersion + "***\n" +
|
||||
"lavalink.kt ***v." + BuildConstants.lavaVersion + "***\n" +
|
||||
"Coroutines ***v." + BuildConstants.coroutinesVersion + "***"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -19,9 +19,10 @@
|
|||
|
||||
package de.limited_dev.botendo.util
|
||||
|
||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||
import dev.kord.core.behavior.interaction.response.respond
|
||||
import dev.kord.core.entity.interaction.GuildChatInputCommandInteraction
|
||||
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.rest.builder.message.EmbedBuilder
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
|
@ -29,43 +30,41 @@ import java.time.format.DateTimeFormatter
|
|||
object MessageUtil {
|
||||
private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy @ HH:mm:ss")
|
||||
|
||||
suspend fun sendEmbedForInteraction(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
suspend fun sendEmbedForPublicSlashCommand(
|
||||
ctx: PublicSlashCommandContext<Arguments, ModalForm>,
|
||||
title: String,
|
||||
description: String
|
||||
) {
|
||||
deferred.respond {
|
||||
embeds = mutableListOf(
|
||||
ctx.respond {
|
||||
embeds.add(
|
||||
getEmbed(
|
||||
title,
|
||||
description,
|
||||
interaction.user.username + "#" + interaction.user.discriminator
|
||||
ctx.user.asUser().username + "#" + ctx.user.asUser().discriminator
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun sendEmbedForInteractionWithImage(
|
||||
interaction: GuildChatInputCommandInteraction,
|
||||
deferred: DeferredPublicMessageInteractionResponseBehavior,
|
||||
suspend fun sendEmbedForPublicSlashCommandWithImage(
|
||||
ctx: PublicSlashCommandContext<Arguments, ModalForm>,
|
||||
title: String,
|
||||
description: String,
|
||||
thumbnailUrl: String
|
||||
) {
|
||||
deferred.respond {
|
||||
embeds = mutableListOf(
|
||||
ctx.respond {
|
||||
embeds.add(
|
||||
getEmbedWithImage(
|
||||
title,
|
||||
description,
|
||||
interaction.user.username + "#" + interaction.user.discriminator,
|
||||
ctx.user.asUser().username + "#" + ctx.user.asUser().discriminator,
|
||||
thumbnailUrl
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getEmbed(title: String, description: String, source: String): EmbedBuilder {
|
||||
fun getEmbed(title: String, description: String, source: String): EmbedBuilder {
|
||||
val now: LocalDateTime = LocalDateTime.now()
|
||||
val ebb = EmbedBuilder()
|
||||
ebb.title = title
|
||||
|
@ -75,7 +74,7 @@ object MessageUtil {
|
|||
return ebb
|
||||
}
|
||||
|
||||
private fun getEmbedWithImage(
|
||||
fun getEmbedWithImage(
|
||||
title: String,
|
||||
description: String,
|
||||
source: String,
|
||||
|
|
|
@ -19,13 +19,12 @@
|
|||
|
||||
package de.limited_dev.botendo.util
|
||||
|
||||
import de.limited_dev.botendo.Bot
|
||||
|
||||
object Status {
|
||||
//TODO: impl.
|
||||
suspend fun updateStatus() {
|
||||
Bot.kord.editPresence {
|
||||
/* Bot.kord.editPresence {
|
||||
this.playing("")
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,5 +16,3 @@
|
|||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
#
|
||||
org.slf4j.simpleLogger.defaultLogLevel=trace
|
||||
org.slf4j.simpleLogger.showDateTime=true
|
||||
|
|
Loading…
Reference in a new issue