Compare commits

...

34 commits

Author SHA1 Message Date
8cc3e70f24
chore: improved readability
Signed-off-by: moonleay <contact@moonleay.net>
2023-12-14 09:05:27 +01:00
1dec02f40f
chore: upgrade gradle to 8.5
Signed-off-by: moonleay <contact@moonleay.net>
2023-12-13 19:11:28 +01:00
e3d107199e
chore: update Copyright
Signed-off-by: moonleay <contact@moonleay.net>
2023-12-13 19:08:08 +01:00
425c9bf1cd
chore: bump version
Signed-off-by: moonleay <contact@moonleay.net>
2023-12-13 19:02:38 +01:00
3d66548a3d
fix: bot now doesn't leave when failing to find a song with no song in queue and one playing
Signed-off-by: moonleay <contact@moonleay.net>
2023-12-13 19:02:12 +01:00
9b51693a75
feat: make the bot leave, if they are the last one in the vc
Signed-off-by: moonleay <contact@moonleay.net>
2023-12-13 18:52:46 +01:00
8b6b7dc5d5
feat: leave vc, if there is no song next up and the current one failed to load 2023-12-13 18:50:38 +01:00
ae507dc4aa
feat: added time delay to allow for lavalink to start in docker container, added debug flag to skip the wait, if in dev env 2023-12-13 18:19:32 +01:00
232a854863
chore: add new command to README 2023-12-13 18:06:14 +01:00
a7bafe5a7e
fix: bumped version to fit docker releases 2023-12-13 18:03:41 +01:00
aa81261dd9
chore: bump version 2023-12-13 16:50:00 +01:00
acefe1b712 Merge pull request 'chore/upgrade-lavakord' (#7) from chore/upgrade-lavakord into master
Reviewed-on: #7
2023-12-13 16:48:39 +01:00
fab645d945
chore: improved build.gradle.kts dependency version naming 2023-12-13 16:47:26 +01:00
6cc91f0cfe
chore: bump slf4j version 2023-12-13 16:43:52 +01:00
6c83ea6b4c
fix: fixed errors caused by upgrading lavalink 2023-12-13 16:41:52 +01:00
e1fdc954ce
WIP: started working on fixing errors 2023-12-13 15:15:29 +01:00
a2ce58010a
chore: bump lavakord version 2023-12-13 15:15:13 +01:00
589997c29e
chore: updated .gitignore, updated README.md 2023-12-13 14:39:19 +01:00
55ccb175e1
chore: upgrade kord-extensions, rewrote all embeds
fix: fixed issues caused due to upgrade
2023-12-13 14:39:01 +01:00
3a9795794c chore: bump version
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-24 00:29:48 +02:00
5a65aad3e2 fix: fixed InfoExtension
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-24 00:29:30 +02:00
1cbf631f27 chore: updated command source system
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-24 00:18:41 +02:00
f94d6c6ae7 feat: added UserUtil
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-24 00:18:18 +02:00
b59b72b3b8 fix: fixed typo in SkipExtension
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-23 23:49:19 +02:00
266da050d2 chore: bump version
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-23 23:48:20 +02:00
cccd602a94 chore: updated InfoExtension output
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-23 23:45:37 +02:00
26137e8806 feat: added SeekExtension to extensions
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-23 23:44:01 +02:00
aabab047f7 feat: added SeekExtension
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-23 23:43:47 +02:00
d8f8231028 feat: added SeekArguments
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-23 23:43:40 +02:00
47f92a0765 feat: added getTimeUnformated function to TimeUtil
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-07-23 23:43:25 +02:00
ee6b31a868 Merge remote-tracking branch 'origin/master' 2023-05-21 15:25:13 +02:00
c087a484a4 chore: update README.md
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-05-21 15:25:00 +02:00
142f60ec71 chore: update README.md
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-05-21 15:24:07 +02:00
2e309dfc52 chore: updated owner tag to 0001
Signed-off-by: limited_dev <loginakkisativ@gmail.com>
2023-05-19 15:46:02 +02:00
39 changed files with 950 additions and 652 deletions

2
.gitignore vendored
View file

@ -1,5 +1,7 @@
### CUSTOM ###
/run/
/data/
data/
/.idea/

View file

@ -4,23 +4,17 @@
A Discord music bot, written in Kotlin using the kord library.
[![Latest Release](https://gitlab.com/moonleay/botendo/-/badges/release.svg)](https://gitlab.com/moonleay/botendo/-/releases)
[![pipeline status](https://gitlab.com/moonleay/botendo/badges/master/pipeline.svg)](https://gitlab.com/moonleay/botendo/-/commits/master)
[![coverage report](https://gitlab.com/moonleay/botendo/badges/master/coverage.svg)](https://gitlab.com/moonleay/botendo/-/commits/master)
## Contributors
<div class="aside">
<img src="https://img.shields.io/badge/moonleay-Head%20Developer-red" alt="moonleay: Head Developer"/>
</div>
[![Developer](https://img.shields.io/badge/moonleay-Developer-red)](https://gitlab.com/moonleay)
## Special Thanks to
- HopeBaron for helping me a lot
## Known issues
## Issues
- None (currently). Report issues to issues@moonleay.net or moonleay#0069
- Report issues to issues@moonleay.net or message @moonleay on Discord
## Commands & Features
@ -32,6 +26,7 @@ A Discord music bot, written in Kotlin using the kord library.
- skip -- Skip to the next song
- queue -- Show what songs are next up
- nowplaying -- Show what is currently playing
- seek -- Seek to a specific time in the song
- Features
- Button Controller -- You can control the currently playing music using buttons.
@ -65,9 +60,3 @@ A Discord music bot, written in Kotlin using the kord library.
Install IntellJ and import the project from git.
Done.
## Docker commands 4 me
- docker run -it -m 2g -v/home/limited_dev/Documents/Code/Botendo/run/data/:/data/:rw limiteddev/botendo:x.x.x
- docker build -t limiteddev/botendo:x.x.x .
- docker push limiteddev/botendo:x.x.x

View file

@ -14,7 +14,6 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
import org.jetbrains.gradle.ext.ProjectSettings
@ -33,11 +32,12 @@ val ownerID = 372703841151614976L
group = "net.moonleay.botendo"
version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" }
?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" }
?: "6.4.0"
?: "6.5.5"
val kordver = "1.5.6"
val lavaver = "4.0.0"
val coroutinesver = "1.1.0"
val kordext_ver = "1.7.1-SNAPSHOT"
val lavakord_ver = "6.0.0"
val coroutines_ver = "1.7.3"
val slf4j_ver = "2.0.9"
val mavenArtifact = "Botendo"
project.base.archivesName.set(mavenArtifact)
@ -70,6 +70,14 @@ repositories {
}
}
}
maven {
name = "sonatype"
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots")
}
maven {
name = "sonatype 2"
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
}
}
val shadow by configurations.getting
@ -78,15 +86,15 @@ implementation.extendsFrom(shadow)
dependencies {
//Discord
shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordver")
shadow("dev.schlaubi.lavakord:kord:$lavaver")
shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordext_ver")
shadow("dev.schlaubi.lavakord:kord:$lavakord_ver")
//Util
shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver")
shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_ver")
//Logging
shadow("org.slf4j:slf4j-api:2.0.3")
shadow("org.slf4j:slf4j-simple:2.0.3")
shadow("org.slf4j:slf4j-api:$slf4j_ver")
shadow("org.slf4j:slf4j-simple:$slf4j_ver")
}
@ -96,9 +104,9 @@ val templateDest = project.buildDir.resolve("generated/templates")
val templateProps = mapOf(
"version" to project.version as String,
"ownerID" to ownerID,
"kordversion" to kordver,
"lavaversion" to lavaver,
"coroutinesversion" to coroutinesver
"kordversion" to kordext_ver,
"lavaversion" to lavakord_ver,
"coroutinesversion" to coroutines_ver
)

View file

@ -15,5 +15,4 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#
kotlin.code.style=official

Binary file not shown.

View file

@ -15,9 +15,11 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

42
gradlew vendored
View file

@ -17,7 +17,6 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#
##############################################################################
#
@ -58,7 +57,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@ -83,13 +82,11 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@ -136,22 +133,29 @@ location of your Java installation."
fi
else
JAVACMD=java
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@ -196,11 +200,15 @@ if "$cygwin" || "$msys" ; then
done
fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
@ -208,6 +216,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.

15
gradlew.bat vendored
View file

@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal

View file

@ -1,20 +1,19 @@
/*
* Botendo
* Copyright (C) 2023 limited_dev
* Botendo
* Copyright (C) 2023 moonleay
*
* 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 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/>.
* 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/>.
*/
rootProject.name = "Botendo"

View file

@ -14,20 +14,28 @@
*
* 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 net.moonleay.botendo
import com.kotlindiscord.kord.extensions.ExtensibleBot
import dev.kord.common.Color
import dev.kord.common.entity.Snowflake
import dev.kord.core.behavior.getChannelOf
import dev.kord.core.behavior.interaction.response.respond
import dev.kord.core.entity.channel.VoiceChannel
import dev.kord.core.event.interaction.ButtonInteractionCreateEvent
import dev.kord.core.event.user.VoiceStateUpdateEvent
import dev.kord.core.on
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.LavaKord
import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.kord.getLink
import dev.schlaubi.lavakord.kord.lavakord
import kotlinx.coroutines.flow.count
import net.moonleay.botendo.data.CredentialManager
import net.moonleay.botendo.extensions.music.*
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.extensions.util.InfoExtension
import net.moonleay.botendo.util.Logger
import net.moonleay.botendo.util.MessageUtil
@ -63,10 +71,11 @@ object Bot {
add(::NowPlayingExtension)
add(::QueueExtension)
add(::UpsertExtension)
add(::SeekExtension)
}
this.presence {
this.streaming("music", "https://twitch.tv/limited_dev")
this.streaming("music", "https://twitch.tv/moonleaytv")
}
}
@ -88,18 +97,47 @@ object Bot {
b.onInteraction(response, g, u)
return@on
}
// Button not found
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Error"
this.description = "Could not find button with id \"${inter.componentId}\".\nPlease report this."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
}
// Allow the bot to leave the VC if there are no users in the VC
bot.kordRef.on<VoiceStateUpdateEvent> {
if (this.state.userId == bot.kordRef.selfId) {
// Ignore self
return@on
}
val g = this.state.getGuild().asGuild()
val link = lava.getLink(g.id)
if (link.state != Link.State.CONNECTED) {
// Ignore if not connected
return@on
}
val myChannel = link.lastChannelId!!
if (g.getChannelOrNull(Snowflake(myChannel)) == null) {
// Ignore if channel cannot be found
return@on
}
val ch = g.getChannelOf<VoiceChannel>(Snowflake(myChannel))
if (ch.voiceStates.count() > 1) {
// Ignore if there are other users in the channel
return@on
}
// Stop playing if there are no users in the channel
val pl = MusicManager.getMusicManager(g)!!.pl
pl.stopTrack()
link.destroy()
}
//Start the bot
bot.start()
}

View file

@ -14,14 +14,15 @@
*
* 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 net.moonleay.botendo
import net.moonleay.botendo.util.Logger
///Show the splash and launch the Bot
suspend fun main() {
suspend fun main(args: Array<String>) {
println(
"M#\"\"\"\"\"\"\"'M dP dP \n" +
"## mmmm. `M 88 88 \n" +
@ -33,5 +34,9 @@ suspend fun main() {
" "
)
println("Bot v.${net.moonleay.botendo.build.BuildConstants.version}, Kord Extensions v.${net.moonleay.botendo.build.BuildConstants.kordVersion}, LavaKord v.${net.moonleay.botendo.build.BuildConstants.lavaVersion}, Coroutines v.${net.moonleay.botendo.build.BuildConstants.coroutinesVersion}")
if(args.isEmpty() || args[0] != "--debug") {
Logger.out("Waiting 10 seconds for Lavalink to start...")
Thread.sleep(10000)
}
Bot.start()
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.buttons

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.buttons

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.buttons.music
@ -24,7 +23,9 @@ import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteract
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.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.ButtonUtil
@ -42,14 +43,14 @@ class PauseButton : net.moonleay.botendo.buttons.Button("btn.music.pause") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
@ -57,26 +58,26 @@ class PauseButton : net.moonleay.botendo.buttons.Button("btn.music.pause") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot control the music"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
@ -85,19 +86,18 @@ class PauseButton : net.moonleay.botendo.buttons.Button("btn.music.pause") {
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)
this.embed {
this.color = Color(0x52E01A)
this.title = if (player.paused) "I paused" else "I'm continuing"
this.description = if (player.paused) "I paused the song" else "I'm continuing to play the song."
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
this.actionRow(fun ActionRowBuilder.() {
components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
})
}
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.buttons.music
@ -24,7 +23,9 @@ import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteract
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.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.ButtonUtil
@ -42,53 +43,54 @@ class QueueButton : net.moonleay.botendo.buttons.Button("btn.music.queue") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
val track = player.playingTrack
if (track == null) {
if (player.playingTrack == null) {
response.respond {
this.embeds = mutableListOf(
MessageUtil.getEmbed(
Color(0xE0311A),
"Not playing",
"I'm not playing anything currently", user.asUser().username + "#" + user.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not playing"
this.description = "I'm not playing anything currently"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
val track = player.playingTrack!!.info
val gts = MusicManager.getGuildTrackScheduler(guild.asGuild(), player)
val q = gts.getQueue()
var desc =
"""${"**" + track.title + " - " + TimeUtil.getTimeFormatedShortend(track.length.inWholeMilliseconds)} (${track.author})**""" + "\n"
"""${"**" + track.title + " - " + TimeUtil.getTimeFormatedShortend(track.length)} (${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)
this.embed {
this.color = Color(0x52E01A)
this.title = "Queue"
this.description = desc
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
this.actionRow(fun ActionRowBuilder.() {
components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
})
}
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.buttons.music
@ -24,7 +23,9 @@ import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteract
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.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.ButtonUtil
@ -42,14 +43,14 @@ class RepeatButton : net.moonleay.botendo.buttons.Button("btn.music.repeat") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
@ -57,26 +58,26 @@ class RepeatButton : net.moonleay.botendo.buttons.Button("btn.music.repeat") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot control the music"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
@ -84,19 +85,19 @@ class RepeatButton : net.moonleay.botendo.buttons.Button("btn.music.repeat") {
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)
this.embed {
this.color = Color(0x52E01A)
this.title = if (gts.repeating) "Now Repeating" else "Now Continuing"
this.description =
if (gts.repeating) "The current track will now loop" else "The next track will play when this song finishes"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
this.actionRow(fun ActionRowBuilder.() {
components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
})
}
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.buttons.music
@ -25,7 +24,9 @@ import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteract
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.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.ButtonUtil
@ -45,14 +46,14 @@ class SkipButton : net.moonleay.botendo.buttons.Button("btn.music.skip") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
@ -60,61 +61,64 @@ class SkipButton : net.moonleay.botendo.buttons.Button("btn.music.skip") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot control the music"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
var track = player.playingTrack
if (track == null) {
if (player.playingTrack == null) {
response.respond {
this.embeds = mutableListOf(
MessageUtil.getEmbed(
Color(0xE0311A),
"Not playing",
"I'm not playing anything currently", user.asUser().username + "#" + user.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not Playing"
this.description = "I'm not playing anything currently"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
var track = player.playingTrack!!.info
val gts = MusicManager.getGuildTrackScheduler(guild.asGuild(), player)
if (!gts.isEmpty()) {
track = gts.getHead().toTrack()
track = gts.getHead().info
gts.playNext(link)
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}",
user.asUser().username + "#" + user.asUser().discriminator,
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg"
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "Skipped song; now playing"
this.description = "**${track.title}**\n*Now Playing*\nby ${track.author} :: ${
TimeUtil.getTimeFormatedRaw(
track.length
)
}\n" +
">>>${track.uri}"
this.footer {
this.text = MessageUtil.getFooter(user)
}
this.thumbnail {
this.url = "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg"
}
}
this.actionRow {
this.components.addAll(
@ -130,17 +134,17 @@ class SkipButton : net.moonleay.botendo.buttons.Button("btn.music.skip") {
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)
this.embed {
this.color = Color(0x52E01A)
this.title = "Skipped song"
this.description = "Nothing"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
this.actionRow(fun ActionRowBuilder.() {
components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
})
}
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.buttons.music
@ -24,6 +23,7 @@ import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteract
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.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.MessageUtil
@ -40,14 +40,14 @@ class StopButton : net.moonleay.botendo.buttons.Button("btn.music.stop") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
@ -55,26 +55,26 @@ class StopButton : net.moonleay.botendo.buttons.Button("btn.music.stop") {
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
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
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot control the music"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
return
}
@ -83,14 +83,14 @@ class StopButton : net.moonleay.botendo.buttons.Button("btn.music.stop") {
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
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "I stopped and left"
this.description = "just like your girlfriend"
this.footer {
this.text = MessageUtil.getFooter(user)
}
}
}
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.data

View file

@ -14,16 +14,16 @@
*
* 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 net.moonleay.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 dev.kord.common.Color
import dev.kord.rest.builder.message.create.actionRow
import dev.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.kord.getLink
import net.moonleay.botendo.extensions.music.components.MusicManager
@ -42,55 +42,68 @@ class NowPlayingExtension : Extension() {
val guildId = this.guild!!.id
val link = net.moonleay.botendo.Bot.lava.getLink(guildId)
val player = link.player
val u = this.user
if (link.state == Link.State.NOT_CONNECTED) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0A81A),
"Not connected",
"I'm not in a VC and therefore, I am not playing anything."
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
val track = player.playingTrack
if (track == null) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0A81A),
"Not Playing",
"I'm not playing anything currently"
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Not Playing"
this.description = "I'm not playing anything currently"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
this.respond {
this.embeds.add(
MessageUtil.getEmbedWithImage(
Color(0x52E01A),
"Currently playing",
"**${track.title}**\n*Now Playing*\nby ${track.author} ; ${
TimeUtil.getTimeFormatedRaw(
player.position
)
}: ${
TimeUtil.getTimeFormatedRaw(
track.length.inWholeMilliseconds
)
}\n" +
">>>${track.uri}",
user.asUser().username + "#" + user.asUser().discriminator,
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri.toString()) + "/maxresdefault.jpg"
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "Currently playing"
this.description = "**${track.info.title}**\n*Now Playing*\nby ${track.info.author} ; ${
TimeUtil.getTimeFormatedRaw(
player.position
)
}: ${
TimeUtil.getTimeFormatedRaw(
track.info.length
)
}\n" +
">>>${track.info.uri}"
this.footer {
this.text = MessageUtil.getFooter(u)
}
if(track.info.uri == null){
this.thumbnail {
this.url = "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.info.uri!!) + "/maxresdefault.jpg"
}
}
}
this.actionRow {
this.components.addAll(
this.actionRow(fun ActionRowBuilder.() {
components.addAll(
ButtonUtil.getMusicControllerButtons(
player.paused,
gts.repeating
).components
)
}
})
}
}
}

View file

@ -14,20 +14,21 @@
*
* 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 net.moonleay.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 dev.kord.common.Color
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.kord.getLink
import net.moonleay.botendo.Bot
import net.moonleay.botendo.extensions.music.components.LinkArguments
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.MessageUtil
import net.moonleay.botendo.util.UserUtil
class PlayExtension : Extension() {
@ -40,19 +41,19 @@ class PlayExtension : Extension() {
description = "Play music"
this.action {
val guildId = this.guild!!.id
val link = net.moonleay.botendo.Bot.lava.getLink(guildId)
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(
Color(0xE0311A),
"You are not connected to a VC",
"Please connect to a VC",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
@ -63,14 +64,14 @@ class PlayExtension : Extension() {
link.connectAudio(channelId!!.value)
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
this.respond {
embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"You are not in my VC",
"We are not in the same VC and therefore, you cannot play any music",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot play any music"
this.author {
this.name = UserUtil.getCommandSrc(u)
}
}
}
return@action
}
@ -82,14 +83,14 @@ class PlayExtension : Extension() {
"ytsearch:$query"
}
this.respond {
embeds.add(
MessageUtil.getEmbed(
Color(0xE0A81A),
"Searching...",
"We are looking for $query",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0A81A)
this.title = "Searching..."
this.description = "We are looking for $query"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
MusicManager.addToQueue(this, link, search)
}

View file

@ -14,16 +14,16 @@
*
* 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 net.moonleay.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 dev.kord.common.Color
import dev.kord.rest.builder.message.create.actionRow
import dev.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.ButtonUtil
@ -40,52 +40,61 @@ class QueueExtension : Extension() {
val guildId = this.guild!!.id
val link = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
val player = link.player
val u = this.user
if (link.state == Link.State.NOT_CONNECTED) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0311A),
"Not connected",
"I'm not in a VC and therefore, I am not playing anything."
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
val track = player.playingTrack
if (track == null) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0A81A),
"Queue empty",
"I'm not playing anything currently"
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Queue empty"
this.description = "I'm not playing anything currently"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
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"
"""${"**" + track.info.title + " - " + TimeUtil.getTimeFormatedShortend(track.info.length)} (${track.info.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"
}
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0x52E01A),
"Queue",
desc,
user.asUser().username + "#" + user.asUser().discriminator
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "Queue"
this.description = desc
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
this.actionRow {
this.components.addAll(
this.actionRow(fun ActionRowBuilder.() {
components.addAll(
ButtonUtil.getMusicControllerButtons(
player.paused,
gts.repeating
).components
)
}
})
}
}
}

View file

@ -0,0 +1,155 @@
/*
* Botendo
* Copyright (C) 2023 moonleay
*
* 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 net.moonleay.botendo.extensions.music
import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import dev.kord.common.Color
import dev.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.extensions.music.components.SeekArguments
import net.moonleay.botendo.util.ButtonUtil
import net.moonleay.botendo.util.MessageUtil
import net.moonleay.botendo.util.TimeUtil
import net.moonleay.botendo.util.UrlUtil
class SeekExtension : Extension() {
override val name = "seek"
override suspend fun setup() {
publicSlashCommand(::SeekArguments) {
name = "seek"
description = "Skip to a certain point in a track"
this.action {
val guildId = this.guild!!.id
val link = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
val player = link.player
val u = this.user
val voiceState = u.asMember(guildId).getVoiceStateOrNull()
if (voiceState == null) {
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
val channelId = voiceState.channelId
if (link.state == Link.State.NOT_CONNECTED) {
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot control the music"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
if (player.playingTrack == null) {
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Not playing"
this.description = "I'm not playing anything currently"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
var track = player.playingTrack!!.info
val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
val targetPos = TimeUtil.getTimeUnformated(this.arguments.position)
if (player.playingTrack!!.info.length > targetPos && targetPos >= 0) {
player.seekTo(targetPos)
} else {
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Invalid position"
this.description = "The position you specified is invalid"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
this.respond {
this.embed {
this.color = Color(0x52E01A)
this.title = "Jumped; now playing"
this.description = "**${track.title}**\n*Now Playing*\nby ${track.author} ; ${
TimeUtil.getTimeFormatedRaw(
player.position
)
}: ${
TimeUtil.getTimeFormatedRaw(
track.length
)
}\n" +
">>>${track.uri}"
this.footer {
this.text = MessageUtil.getFooter(u)
}
this.thumbnail {
this.url = "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg"
}
}
this.actionRow(fun ActionRowBuilder.() {
components.addAll(
ButtonUtil.getMusicControllerButtons(
player.paused,
gts.repeating
).components
)
})
}
}
}
}
}

View file

@ -14,16 +14,16 @@
*
* 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 net.moonleay.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 dev.kord.common.Color
import dev.kord.rest.builder.message.create.actionRow
import dev.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import net.moonleay.botendo.extensions.music.components.MusicManager
import net.moonleay.botendo.util.ButtonUtil
@ -44,46 +44,62 @@ class SkipExtension : Extension() {
val u = this.user
val voiceState = u.asMember(guildId).getVoiceStateOrNull()
if (voiceState == null) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0311A),
"You are not connected to a VC",
"Please connect to a VC"
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
val channelId = voiceState.channelId
if (link.state == Link.State.NOT_CONNECTED) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0311A),
"Not connected",
"I'm not in a VC and therefore, I am not playing anything."
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0311A),
"You are not in my VC",
"We are not in the same VC and therefore, you cannot control the music"
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot control the music"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
var track = player.playingTrack
var track = player.playingTrack!!.info
if (track == null) {
MessageUtil.sendEmbedForPublicSlashCommand(
this,
Color(0xE0311A),
"Not playing",
"I'm not playing anything currently"
)
this.respond {
this.embed {
this.color = Color(0xE0311A)
this.title = "Not playing"
this.description = "I'm not playing anything currently"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
if (!gts.isEmpty()) {
track = gts.getHead().toTrack()
track = gts.getHead().info
gts.playNext(link)
} else {
player.stopTrack()
@ -91,29 +107,31 @@ class SkipExtension : Extension() {
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}",
user.asUser().username + "#" + user.asUser().discriminator,
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg"
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "Skipped song; now playing"
this.description = "**${track.title}**\n*Now Playing*\nby ${track.author} ;: ${
TimeUtil.getTimeFormatedRaw(
track.length
)
}\n" +
">>>${track.uri}"
this.footer {
this.text = MessageUtil.getFooter(u)
}
this.thumbnail {
this.url = "https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg"
}
}
this.actionRow {
this.components.addAll(
this.actionRow(fun ActionRowBuilder.() {
components.addAll(
ButtonUtil.getMusicControllerButtons(
player.paused,
gts.repeating
).components
)
}
})
}
}
}

View file

@ -14,15 +14,14 @@
*
* 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 net.moonleay.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 dev.kord.common.Color
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.kord.getLink
import net.moonleay.botendo.extensions.music.components.MusicManager
@ -42,38 +41,40 @@ class StopExtension : Extension() {
val vcsUser = u.asMember(guildId).getVoiceStateOrNull()
if (vcsUser == null) {
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"You are not connected to a VC",
"Please connect to my VC", u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
val channelId = vcsUser.channelId
if (link.state == Link.State.NOT_CONNECTED) {
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"Not connected",
"I'm not in a VC and therefore, I am not playing anything.",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not connected"
this.description = "I'm not in a VC and therefore, I am not playing anything."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"You are not in my VC",
"We are not in the same VC", u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
@ -81,14 +82,14 @@ class StopExtension : Extension() {
link.destroy()
MusicManager.getGuildTrackScheduler(this.getGuild()!!.asGuild(), player).clear()
this.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0x52E01A),
"I stopped and left",
"just like your girlfriend",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "I stopped and left"
this.description = "just like your girlfriend"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
}
}

View file

@ -14,15 +14,14 @@
*
* 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 net.moonleay.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 dev.kord.common.Color
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.kord.getLink
import net.moonleay.botendo.extensions.music.components.LinkArguments
@ -45,14 +44,14 @@ class UpsertExtension : Extension() {
val vcsUser = u.asMember(guildId).getVoiceStateOrNull()
if (vcsUser == null) {
this.respond {
embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"You are not connected to a VC",
"Please connect to a VC",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not connected to a VC"
this.description = "Please connect to a VC"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
@ -63,14 +62,14 @@ class UpsertExtension : Extension() {
link.connectAudio(channelId!!.value)
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
this.respond {
embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"You are not in my VC",
"We are not in the same VC and therefore, you cannot play any music",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "You are not in my VC"
this.description = "We are not in the same VC and therefore, you cannot play any music"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
return@action
}
@ -82,14 +81,14 @@ class UpsertExtension : Extension() {
"ytsearch:$query"
}
this.respond {
embeds.add(
MessageUtil.getEmbed(
Color(0xE0A81A),
"Searching...",
"We are looking for $query",
u.asUser().username + "#" + u.asUser().discriminator
)
)
this.embed {
this.color = Color(0xE0A81A)
this.title = "Searching..."
this.description = "We are looking for $query"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
MusicManager.upsertIntoQueue(this, link, search)
}

View file

@ -14,26 +14,26 @@
*
* 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 net.moonleay.botendo.extensions.music.components
import dev.arbjerg.lavalink.protocol.v4.Track
import dev.schlaubi.lavakord.audio.*
import dev.schlaubi.lavakord.audio.player.Player
import dev.schlaubi.lavakord.rest.models.PartialTrack
import net.moonleay.botendo.Bot
import net.moonleay.botendo.util.Logger
import java.util.concurrent.BlockingQueue
import java.util.concurrent.LinkedBlockingQueue
class GuildTrackScheduler(val pl: Player) {
private var queue: BlockingQueue<PartialTrack> = LinkedBlockingQueue()
private var queue: BlockingQueue<Track> = LinkedBlockingQueue()
var repeating = false
private var hasRegisteredEvents = false
///Add a track to queue and start playing, if there is no song currently playing
suspend fun queue(track: PartialTrack, type: MusicManager.AddType) {
suspend fun queue(track: Track, type: MusicManager.AddType) {
if (this.pl.playingTrack == null) {
play(track)
return
@ -44,7 +44,7 @@ class GuildTrackScheduler(val pl: Player) {
}
MusicManager.AddType.UPSERT -> {
val nq = LinkedBlockingQueue<PartialTrack>()
val nq = LinkedBlockingQueue<Track>()
nq.offer(track)
for (t in queue.toList()) {
nq.offer(t)
@ -56,7 +56,7 @@ class GuildTrackScheduler(val pl: Player) {
suspend fun playNext(link: Link) {
if (!queue.isEmpty())
this.pl.playTrack(queue.poll())
this.pl.playTrack(track = queue.poll())
else {
this.pl.stopTrack()
link.destroy()
@ -64,8 +64,8 @@ class GuildTrackScheduler(val pl: Player) {
}
}
private suspend fun play(tr: PartialTrack) {
this.pl.playTrack(tr)
private suspend fun play(track: Track) {
this.pl.playTrack(track)
}
fun addEvents() {
@ -92,22 +92,22 @@ class GuildTrackScheduler(val pl: Player) {
if (e.reason.mayStartNext) {
if (repeating) {
Logger.out("Repeating track...")
this.pl.playTrack(e.getTrack().copy())
this.pl.playTrack(e.track.copy())
return
}
Logger.out("Track has ended; Playing next...")
playNext(net.moonleay.botendo.Bot.lava.getLink(e.guildId))
playNext(Bot.lava.getLink(e.guildId))
}
}
private suspend fun onTrackStuck(e: TrackStuckEvent) {
Logger.out("Track is stuck, retrying...")
this.pl.playTrack(e.getTrack().copy())
this.pl.playTrack(e.track.copy())
}
private suspend fun onTrackExc(e: TrackExceptionEvent) {
Logger.out("Track had an exception, retrying...")
this.pl.playTrack(e.getTrack().copy())
this.pl.playTrack(e.track.copy())
}
fun clear() {
@ -116,11 +116,11 @@ class GuildTrackScheduler(val pl: Player) {
queue.clear()
}
fun getQueue(): List<PartialTrack> {
fun getQueue(): List<Track> {
return queue.toList()
}
fun getHead(): PartialTrack {
fun getHead(): Track {
return queue.first()
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.extensions.music.components

View file

@ -14,22 +14,22 @@
*
* 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 net.moonleay.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 dev.arbjerg.lavalink.protocol.v4.LoadResult
import dev.kord.common.Color
import dev.kord.common.entity.Snowflake
import dev.kord.core.entity.Guild
import dev.kord.rest.builder.message.create.actionRow
import dev.kord.rest.builder.component.ActionRowBuilder
import dev.kord.rest.builder.message.actionRow
import dev.kord.rest.builder.message.embed
import dev.schlaubi.lavakord.audio.Link
import dev.schlaubi.lavakord.audio.player.Player
import dev.schlaubi.lavakord.rest.loadItem
import dev.schlaubi.lavakord.rest.models.TrackResponse
import net.moonleay.botendo.util.ButtonUtil
import net.moonleay.botendo.util.MessageUtil
import net.moonleay.botendo.util.TimeUtil
@ -38,6 +38,10 @@ import net.moonleay.botendo.util.UrlUtil
object MusicManager {
private var musicManagerMap: MutableMap<Snowflake, GuildTrackScheduler> = mutableMapOf()
fun getMusicManager(guild: Guild): GuildTrackScheduler? {
return musicManagerMap[guild.id]
}
fun getGuildTrackScheduler(guild: Guild, player: Player): GuildTrackScheduler {
return musicManagerMap.computeIfAbsent(guild.id) {
GuildTrackScheduler(player)
@ -69,61 +73,72 @@ object MusicManager {
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, type)
when (val itm = link.loadItem(search)) {
is LoadResult.TrackLoaded -> {
gts.queue(itm.data, type)
if (!silent)
ctx.respond {
this.embeds.add(
MessageUtil.getEmbedWithImage(
Color(0x52E01A),
"${type.s} 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"
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "${type.s} track from link"
this.description = "**${itm.data.info.title}**\n*Queue*\nby ${itm.data.info.author} ;: ${
TimeUtil.getTimeFormatedRaw(
itm.data.info.length
)
}\n" +
">>>${itm.data.info.uri}"
this.footer {
this.text = MessageUtil.getFooter(u)
}
if (itm.data.info.uri != null) {
this.thumbnail {
this.url =
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(itm.data.info.uri!!) + "/maxresdefault.jpg"
}
}
}
this.actionRow {
this.components.addAll(
this.actionRow(fun ActionRowBuilder.() {
components.addAll(
ButtonUtil.getMusicControllerButtons(
player.paused,
gts.repeating
).components
)
}
})
}
}
TrackResponse.LoadType.PLAYLIST_LOADED -> {
val l = item.tracks.reversed()
is LoadResult.PlaylistLoaded -> {
player.playTrack(track = itm.data.tracks.first())
val l= itm.data.tracks.toList().reversed()
for (partialTrack in l) {
gts.queue(partialTrack, type)
}
if (!silent)
ctx.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0x52E01A),
"${type.s} 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
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "${type.s} playlist from link"
this.description = "**${itm.data.tracks.first().info.title}**\n*${itm.data.info.name}*\nby ${itm.data.tracks.first().info.author} ;: ${
TimeUtil.getTimeFormatedRaw(
itm.data.tracks.first().info.length
)
}\n" +
">>>${itm.data.tracks.first().info.uri}"
this.footer {
this.text = MessageUtil.getFooter(u)
}
if (itm.data.tracks.first().info.uri != null) {
this.thumbnail {
this.url =
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(itm.data.tracks.first().info.uri!!) + "/maxresdefault.jpg"
}
}
}
this.actionRow {
this.components.addAll(
@ -134,25 +149,31 @@ object MusicManager {
)
}
}
}
TrackResponse.LoadType.SEARCH_RESULT -> {
gts.queue(item.tracks.first(), type)
}
is LoadResult.SearchResult -> {
gts.queue(itm.data.tracks.first(), type)
if (!silent)
ctx.respond {
this.embeds.add(
MessageUtil.getEmbedWithImage(
Color(0x52E01A),
"${type.s} 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"
)
)
this.embed {
this.color = Color(0x52E01A)
this.title = "${type.s} track from query"
this.description = "**${itm.data.tracks.first().info.title}**\n*Queue*\nby ${itm.data.tracks.first().info.author} ;: ${
TimeUtil.getTimeFormatedRaw(
itm.data.tracks.first().info.length
)
}\n" +
">>>${itm.data.tracks.first().info.uri}"
this.footer {
this.text = MessageUtil.getFooter(u)
}
if (itm.data.tracks.first().info.uri != null) {
this.thumbnail {
this.url =
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(itm.data.tracks.first().info.uri!!) + "/maxresdefault.jpg"
}
}
}
this.actionRow {
this.components.addAll(
@ -163,39 +184,47 @@ object MusicManager {
)
}
}
}
TrackResponse.LoadType.NO_MATCHES -> {
}
is LoadResult.NoMatches -> {
if (gts.isEmpty() && player.playingTrack == null) {
player.stopTrack()
link.destroy()
}
if (!silent)
ctx.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"Not found",
"There were no matches.",
u.username + "#" + u.discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Not found"
this.description = "There were no matches."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
}
TrackResponse.LoadType.LOAD_FAILED -> {
is LoadResult.LoadFailed -> {
if (gts.isEmpty() && player.playingTrack == null) {
player.stopTrack()
link.destroy()
}
if (!silent)
ctx.respond {
this.embeds.add(
MessageUtil.getEmbed(
Color(0xE0311A),
"Load failed",
"There was an error while loading.", u.username + "#" + u.discriminator
)
)
this.embed {
this.color = Color(0xE0311A)
this.title = "Load failed"
this.description = "There was an error while loading."
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
}
}
}
enum class AddType(val s: String) {
QUEUE("Added"),
UPSERT("Upserted")
}
}

View file

@ -0,0 +1,29 @@
/*
* Botendo
* Copyright (C) 2023 moonleay
*
* 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 net.moonleay.botendo.extensions.music.components
import com.kotlindiscord.kord.extensions.commands.Arguments
import com.kotlindiscord.kord.extensions.commands.converters.impl.string
class SeekArguments : Arguments() {
val position by string {
name = "position"
description = "The target postion to seek to. FORMAT: \"XXh XXm XXs\""
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.extensions.util
@ -22,6 +21,7 @@ package net.moonleay.botendo.extensions.util
import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import dev.kord.common.Color
import dev.kord.rest.builder.message.embed
import net.moonleay.botendo.util.MessageUtil
class InfoExtension : Extension() {
@ -31,15 +31,23 @@ class InfoExtension : Extension() {
name = "info"
description = "Show infos about the bot"
this.action {
MessageUtil.sendEmbedForPublicSlashCommand(
this, Color(0x52E01A), "Botendo",
"Botendo ***v." + net.moonleay.botendo.build.BuildConstants.version + "***\n" +
val u = this.user
this.respond {
this.embed {
this.color = Color(0x52E01A)
this.title = "Botendo"
this.description = "Botendo ***v." + net.moonleay.botendo.build.BuildConstants.version + "***\n" +
"Kord-Extensions ***v." + net.moonleay.botendo.build.BuildConstants.kordVersion + "***\n" +
"lavalink.kt ***v." + net.moonleay.botendo.build.BuildConstants.lavaVersion + "***\n" +
"Coroutines ***v." + net.moonleay.botendo.build.BuildConstants.coroutinesVersion + "***\n\n\n" +
"***Bot made by moonleay#0069***\n" +
"(c) 2023, licensed under GPL-3.0"
)
"***Bot made by moonleay***\n" +
"(c) 2023, licensed under GPL-3.0\n" +
"More infos: https://moonleay.net/projects/botendo\n"
this.footer {
this.text = MessageUtil.getFooter(u)
}
}
}
}
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.util

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.util

View file

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

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.util

View file

@ -14,11 +14,11 @@
*
* 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 net.moonleay.botendo.util
import java.time.Duration
import java.util.concurrent.TimeUnit
object TimeUtil {
@ -87,4 +87,28 @@ object TimeUtil {
return s
}
//This 100000%ly can be improved, I wrote this at 2am
fun getTimeUnformated(timeStr: String): Long {
var days: Long = 0
var hours: Long = 0
var minutes: Long = 0
var seconds: Long = 0
val timeArr = timeStr.split(" ".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()
for (s in timeArr) {
Logger.out(s)
if (s.endsWith("d")) {
days = s.split("d".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].toLong()
} else if (s.endsWith("h")) {
hours = s.split("h".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].toLong()
} else if (s.endsWith("m")) {
minutes = s.split("m".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].toLong()
} else if (s.endsWith("s")) {
seconds = s.split("s".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[0].toLong()
}
}
val value = Duration.ofSeconds(seconds).plus(Duration.ofMinutes(minutes)).plus(Duration.ofHours(hours))
.plus(Duration.ofDays(days)).toMillis()
return value
}
}

View file

@ -14,7 +14,6 @@
*
* 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 net.moonleay.botendo.util

View file

@ -0,0 +1,27 @@
/*
* Botendo
* Copyright (C) 2023 moonleay
*
* 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 net.moonleay.botendo.util
import dev.kord.core.behavior.UserBehavior
object UserUtil {
suspend fun getCommandSrc(u: UserBehavior): String {
return "${u.asUser().username}}"
}
}

View file

@ -15,4 +15,3 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
#