Compare commits
56 commits
Author | SHA1 | Date | |
---|---|---|---|
8cc3e70f24 | |||
1dec02f40f | |||
e3d107199e | |||
425c9bf1cd | |||
3d66548a3d | |||
9b51693a75 | |||
8b6b7dc5d5 | |||
ae507dc4aa | |||
232a854863 | |||
a7bafe5a7e | |||
aa81261dd9 | |||
acefe1b712 | |||
fab645d945 | |||
6cc91f0cfe | |||
6c83ea6b4c | |||
e1fdc954ce | |||
a2ce58010a | |||
589997c29e | |||
55ccb175e1 | |||
3a9795794c | |||
5a65aad3e2 | |||
1cbf631f27 | |||
f94d6c6ae7 | |||
b59b72b3b8 | |||
266da050d2 | |||
cccd602a94 | |||
26137e8806 | |||
aabab047f7 | |||
d8f8231028 | |||
47f92a0765 | |||
ee6b31a868 | |||
c087a484a4 | |||
142f60ec71 | |||
2e309dfc52 | |||
9e42893123 | |||
612d7b58cc | |||
1c00f856ab | |||
861cd4b697 | |||
fe4e47744c | |||
e7001f9946 | |||
1654d24378 | |||
23e5abbca9 | |||
8737d3921b | |||
ef130a1510 | |||
f1454af395 | |||
7237095636 | |||
27aee06681 | |||
47b3674b6e | |||
098634ee3f | |||
0d8001b951 | |||
997b25e659 | |||
7a20ad8088 | |||
5abfad091d | |||
e5af032be8 | |||
4713921279 | |||
2e35bbd0c7 |
64 changed files with 2551 additions and 2144 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,5 +1,7 @@
|
||||||
### CUSTOM ###
|
### CUSTOM ###
|
||||||
/run/
|
/run/
|
||||||
|
/data/
|
||||||
|
data/
|
||||||
/.idea/
|
/.idea/
|
||||||
|
|
||||||
|
|
||||||
|
|
34
README.md
34
README.md
|
@ -3,32 +3,32 @@
|
||||||
"6th times the charm" ~ me
|
"6th times the charm" ~ me
|
||||||
|
|
||||||
A Discord music bot, written in Kotlin using the kord library.
|
A Discord music bot, written in Kotlin using the kord library.
|
||||||
<div class="aside">
|
|
||||||
<img src="https://img.shields.io/badge/100%25-Selfmade-success" alt="100% Selfmade"/>
|
|
||||||
<img src="https://img.shields.io/badge/0%25-optimized-orange" alt="0% optimized"/>
|
|
||||||
<img src="https://img.shields.io/badge/fuck%20it-ship%20it-orange" alt="fuck it, ship it"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Contributors
|
## Contributors
|
||||||
|
|
||||||
<div class="aside">
|
[](https://gitlab.com/moonleay)
|
||||||
<img src="https://img.shields.io/badge/limited__dev-Owner%20%26%20Developer-blue" alt="limited_dev: Owner & Developer"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Special Thanks to
|
## Special Thanks to
|
||||||
|
|
||||||
- HopeBaron for helping me a whole lot
|
- HopeBaron for helping me a lot
|
||||||
|
|
||||||
## Known issues
|
## Issues
|
||||||
|
|
||||||
- The Repeat feature does not function
|
- Report issues to issues@moonleay.net or message @moonleay on Discord
|
||||||
- Not all comments are listed below
|
|
||||||
|
|
||||||
## Commands
|
## Commands & Features
|
||||||
|
|
||||||
|
- Commands
|
||||||
- info -- Show basic infos about the bot
|
- info -- Show basic infos about the bot
|
||||||
- play -- Play a song
|
- play -- Play a song and or add it to queue
|
||||||
|
- upsert -- Play a song next up
|
||||||
- stop -- Stop playing a song and leave the vc
|
- stop -- Stop playing a song and leave the vc
|
||||||
|
- 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.
|
||||||
|
|
||||||
## How to self-host (using the Docker container)
|
## How to self-host (using the Docker container)
|
||||||
|
|
||||||
|
@ -60,9 +60,3 @@ A Discord music bot, written in Kotlin using the kord library.
|
||||||
|
|
||||||
Install IntellJ and import the project from git.
|
Install IntellJ and import the project from git.
|
||||||
Done.
|
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
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Botendo
|
* Botendo
|
||||||
* Copyright (C) 2023 limited_dev
|
* Copyright (C) 2023 moonleay
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -14,7 +14,6 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import org.jetbrains.gradle.ext.ProjectSettings
|
import org.jetbrains.gradle.ext.ProjectSettings
|
||||||
|
@ -30,15 +29,15 @@ plugins {
|
||||||
|
|
||||||
//Botendo version 6
|
//Botendo version 6
|
||||||
val ownerID = 372703841151614976L
|
val ownerID = 372703841151614976L
|
||||||
group = "de.limited_dev.botendo"
|
group = "net.moonleay.botendo"
|
||||||
version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" }
|
version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" }
|
||||||
?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" }
|
?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" }
|
||||||
?: "6.3.0"
|
?: "6.5.5"
|
||||||
|
|
||||||
val kordver = "1.5.6"
|
val kordext_ver = "1.7.1-SNAPSHOT"
|
||||||
val lavaver = "4.0.0"
|
val lavakord_ver = "6.0.0"
|
||||||
val coroutinesver = "1.1.0"
|
val coroutines_ver = "1.7.3"
|
||||||
//val ffmpegver = "5.1.2-1.5.8"
|
val slf4j_ver = "2.0.9"
|
||||||
|
|
||||||
val mavenArtifact = "Botendo"
|
val mavenArtifact = "Botendo"
|
||||||
project.base.archivesName.set(mavenArtifact)
|
project.base.archivesName.set(mavenArtifact)
|
||||||
|
@ -71,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
|
val shadow by configurations.getting
|
||||||
|
@ -79,18 +86,15 @@ implementation.extendsFrom(shadow)
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
//Discord
|
//Discord
|
||||||
shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordver")
|
shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordext_ver")
|
||||||
shadow("dev.schlaubi.lavakord:kord:$lavaver")
|
shadow("dev.schlaubi.lavakord:kord:$lavakord_ver")
|
||||||
|
|
||||||
//Util
|
//Util
|
||||||
shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver")
|
shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_ver")
|
||||||
|
|
||||||
//Logging
|
//Logging
|
||||||
shadow("org.slf4j:slf4j-api:2.0.3")
|
shadow("org.slf4j:slf4j-api:$slf4j_ver")
|
||||||
shadow("org.slf4j:slf4j-simple:2.0.3")
|
shadow("org.slf4j:slf4j-simple:$slf4j_ver")
|
||||||
|
|
||||||
//ffmpeg
|
|
||||||
//shadow("org.bytedeco:ffmpeg:$ffmpegver")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -100,9 +104,9 @@ val templateDest = project.buildDir.resolve("generated/templates")
|
||||||
val templateProps = mapOf(
|
val templateProps = mapOf(
|
||||||
"version" to project.version as String,
|
"version" to project.version as String,
|
||||||
"ownerID" to ownerID,
|
"ownerID" to ownerID,
|
||||||
"kordversion" to kordver,
|
"kordversion" to kordext_ver,
|
||||||
"lavaversion" to lavaver,
|
"lavaversion" to lavakord_ver,
|
||||||
"coroutinesversion" to coroutinesver
|
"coroutinesversion" to coroutines_ver
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -119,7 +123,7 @@ tasks {
|
||||||
|
|
||||||
withType<Jar> {
|
withType<Jar> {
|
||||||
manifest {
|
manifest {
|
||||||
attributes["Main-Class"] = "de.limited_dev.botendo.MainKt"
|
attributes["Main-Class"] = "net.moonleay.botendo.MainKt"
|
||||||
}
|
}
|
||||||
// To add all of the dependencies
|
// To add all of the dependencies
|
||||||
from(sourceSets.main.get().output)
|
from(sourceSets.main.get().output)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#
|
#
|
||||||
# Botendo
|
# Botendo
|
||||||
# Copyright (C) 2023 limited_dev
|
# Copyright (C) 2023 moonleay
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,5 +15,4 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#
|
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
8
gradle/wrapper/gradle-wrapper.properties
vendored
8
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
#
|
#
|
||||||
# Botendo
|
# Botendo
|
||||||
# Copyright (C) 2023 limited_dev
|
# Copyright (C) 2023 moonleay
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,9 +15,11 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
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
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
44
gradlew
vendored
44
gradlew
vendored
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#
|
#
|
||||||
# Botendo
|
# Botendo
|
||||||
# Copyright (C) 2023 limited_dev
|
# Copyright (C) 2023 moonleay
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,7 +17,6 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#
|
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
#
|
#
|
||||||
|
@ -58,7 +57,7 @@
|
||||||
# Darwin, MinGW, and NonStop.
|
# Darwin, MinGW, and NonStop.
|
||||||
#
|
#
|
||||||
# (3) This script is generated from the Groovy template
|
# (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.
|
# within the Gradle project.
|
||||||
#
|
#
|
||||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
@ -83,13 +82,11 @@ do
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=${0##*/}
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
|
||||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
MAX_FD=maximum
|
MAX_FD=maximum
|
||||||
|
@ -136,22 +133,29 @@ location of your Java installation."
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
JAVACMD=java
|
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
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
location of your Java installation."
|
location of your Java installation."
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# Increase the maximum file descriptors if we can.
|
||||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
max*)
|
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 ) ||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
warn "Could not query maximum file descriptor limit"
|
warn "Could not query maximum file descriptor limit"
|
||||||
esac
|
esac
|
||||||
case $MAX_FD in #(
|
case $MAX_FD in #(
|
||||||
'' | soft) :;; #(
|
'' | 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" ||
|
ulimit -n "$MAX_FD" ||
|
||||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
esac
|
esac
|
||||||
|
@ -196,11 +200,15 @@ if "$cygwin" || "$msys" ; then
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Collect all arguments for the java command;
|
|
||||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
# shell script including quotes and variable substitutions, so put them in
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
# double quotes to make sure that they get re-expanded; and
|
|
||||||
# * put everything else in single quotes, so that it's not re-expanded.
|
# 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 -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
@ -208,6 +216,12 @@ set -- \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
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.
|
# Use "xargs" to parse quoted args.
|
||||||
#
|
#
|
||||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
|
11
gradlew.bat
vendored
11
gradlew.bat
vendored
|
@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
set DIRNAME=%~dp0
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%"=="" set DIRNAME=.
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
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
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
:fail
|
:fail
|
||||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
rem the _cmd.exe /c_ return code!
|
rem the _cmd.exe /c_ return code!
|
||||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
exit /b 1
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
:mainEnd
|
:mainEnd
|
||||||
if "%OS%"=="Windows_NT" endlocal
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Botendo
|
* Botendo
|
||||||
* Copyright (C) 2023 limited_dev
|
* Copyright (C) 2023 moonleay
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -14,7 +14,6 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rootProject.name = "Botendo"
|
rootProject.name = "Botendo"
|
||||||
|
|
|
@ -1,108 +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
|
|
||||||
|
|
||||||
import com.kotlindiscord.kord.extensions.ExtensibleBot
|
|
||||||
import de.limited_dev.botendo.buttons.ButtonManager
|
|
||||||
import de.limited_dev.botendo.data.CredentialManager
|
|
||||||
import de.limited_dev.botendo.extensions.music.*
|
|
||||||
import de.limited_dev.botendo.extensions.util.InfoExtension
|
|
||||||
import de.limited_dev.botendo.extensions.util.PotatoExtension
|
|
||||||
import de.limited_dev.botendo.util.Logger
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.core.behavior.interaction.response.respond
|
|
||||||
import dev.kord.core.event.interaction.ButtonInteractionCreateEvent
|
|
||||||
import dev.kord.core.on
|
|
||||||
import dev.schlaubi.lavakord.LavaKord
|
|
||||||
import dev.schlaubi.lavakord.kord.lavakord
|
|
||||||
|
|
||||||
object Bot {
|
|
||||||
//The kord object gets set at app launch
|
|
||||||
private lateinit var bot: ExtensibleBot
|
|
||||||
lateinit var lava: LavaKord
|
|
||||||
suspend fun start() {
|
|
||||||
Logger.out("Starting Bot...")
|
|
||||||
|
|
||||||
//Load config
|
|
||||||
CredentialManager.load()
|
|
||||||
|
|
||||||
//Don't run the bot when there is no bot token in config
|
|
||||||
if (CredentialManager.token == "empty") {
|
|
||||||
Logger.out("The config does not contain a bot token")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//Add Bot token to kord
|
|
||||||
//kord = Kord(CredentialManager.token)
|
|
||||||
bot = ExtensibleBot(CredentialManager.token) {
|
|
||||||
applicationCommands {
|
|
||||||
enabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
extensions {
|
|
||||||
add(::InfoExtension)
|
|
||||||
add(::PlayExtension)
|
|
||||||
add(::StopExtension)
|
|
||||||
add(::SkipExtension)
|
|
||||||
add(::NowPlayingExtension)
|
|
||||||
add(::QueueExtension)
|
|
||||||
add(::PotatoExtension)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.presence {
|
|
||||||
this.streaming("music", "https://twitch.tv/limited_dev")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Add LavaLink
|
|
||||||
lava = bot.kordRef.lavakord()
|
|
||||||
|
|
||||||
//Add the LavaLink node from config
|
|
||||||
lava.addNode(CredentialManager.linkip, CredentialManager.linkpw)
|
|
||||||
|
|
||||||
//Register Button presses
|
|
||||||
bot.kordRef.on<ButtonInteractionCreateEvent> {
|
|
||||||
val inter = this.interaction
|
|
||||||
val response = inter.deferPublicResponse()
|
|
||||||
val u = inter.user
|
|
||||||
val g = this.interaction.getOriginalInteractionResponse().getGuild()
|
|
||||||
for (b in ButtonManager.buttons) {
|
|
||||||
if (b.id != inter.componentId)
|
|
||||||
continue
|
|
||||||
b.onInteraction(response, g, u)
|
|
||||||
return@on
|
|
||||||
}
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Error",
|
|
||||||
"Could not find button with id \"${inter.componentId}\".\nPlease report this.",
|
|
||||||
u.asUser().username + "#" + u.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Start the bot
|
|
||||||
bot.start()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,39 +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
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.build.BuildConstants
|
|
||||||
|
|
||||||
|
|
||||||
///Show the splash and launch the Bot
|
|
||||||
suspend fun main() {
|
|
||||||
println(
|
|
||||||
"M#\"\"\"\"\"\"\"'M dP dP \n" +
|
|
||||||
"## mmmm. `M 88 88 \n" +
|
|
||||||
"#' .M .d8888b. d8888P .d8888b. 88d888b. .d888b88 .d8888b. \n" +
|
|
||||||
"M# MMMb.'YM 88' `88 88 88ooood8 88' `88 88' `88 88' `88 \n" +
|
|
||||||
"M# MMMM' M 88. .88 88 88. ... 88 88 88. .88 88. .88 \n" +
|
|
||||||
"M# .;M `88888P' dP `88888P' dP dP `88888P8 `88888P' \n" +
|
|
||||||
"M#########M \n" +
|
|
||||||
" "
|
|
||||||
)
|
|
||||||
println("Bot v.${BuildConstants.version}, Kord Extensions v.${BuildConstants.kordVersion}, LavaKord v.${BuildConstants.lavaVersion}, Coroutines v.${BuildConstants.coroutinesVersion}, Ktor v.${BuildConstants.ktorVersion}, Exposed v.${BuildConstants.exposedVersion}, Postgres v.${BuildConstants.postgresVersion}")
|
|
||||||
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.buttons
|
|
||||||
|
|
||||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
|
||||||
import dev.kord.core.entity.Guild
|
|
||||||
import dev.kord.core.entity.User
|
|
||||||
|
|
||||||
open class Button(val id: String) {
|
|
||||||
|
|
||||||
open suspend fun onInteraction(
|
|
||||||
response: DeferredPublicMessageInteractionResponseBehavior,
|
|
||||||
guild: Guild,
|
|
||||||
user: User
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.buttons
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.buttons.music.*
|
|
||||||
|
|
||||||
object ButtonManager {
|
|
||||||
val buttons = listOf(RepeatButton(), PauseButton(), SkipButton(), QueueButton(), StopButton())
|
|
||||||
}
|
|
|
@ -1,105 +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.buttons.music
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.buttons.Button
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
|
||||||
import dev.kord.core.behavior.interaction.response.respond
|
|
||||||
import dev.kord.core.entity.Guild
|
|
||||||
import dev.kord.core.entity.User
|
|
||||||
import dev.kord.rest.builder.message.modify.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
|
|
||||||
class PauseButton : Button("btn.music.pause") {
|
|
||||||
override suspend fun onInteraction(
|
|
||||||
response: DeferredPublicMessageInteractionResponseBehavior,
|
|
||||||
guild: Guild,
|
|
||||||
user: User
|
|
||||||
) {
|
|
||||||
val guildId = guild.id
|
|
||||||
val link = Bot.lava.getLink(guildId.toString())
|
|
||||||
val player = link.player
|
|
||||||
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
|
||||||
if (voiceState == null) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not connected to a VC",
|
|
||||||
"Please connect to a VC",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val channelId = voiceState.channelId
|
|
||||||
if (link.state == Link.State.NOT_CONNECTED) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not connected",
|
|
||||||
"I'm not in a VC and therefore, I am not playing anything.",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not in my VC",
|
|
||||||
"We are not in the same VC and therefore, you cannot control the music",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
player.pause(!player.paused)
|
|
||||||
|
|
||||||
val gts = MusicManager.getGuildTrackScheduler(guild, player)
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0x52E01A),
|
|
||||||
if (player.paused) "I paused" else "I'm continuing",
|
|
||||||
if (player.paused) "I paused the song" else "I'm continuing to play the song.",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,96 +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.buttons.music
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.buttons.Button
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import de.limited_dev.botendo.util.TimeUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
|
||||||
import dev.kord.core.behavior.interaction.response.respond
|
|
||||||
import dev.kord.core.entity.Guild
|
|
||||||
import dev.kord.core.entity.User
|
|
||||||
import dev.kord.rest.builder.message.modify.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
|
|
||||||
class QueueButton : Button("btn.music.queue") {
|
|
||||||
override suspend fun onInteraction(
|
|
||||||
response: DeferredPublicMessageInteractionResponseBehavior,
|
|
||||||
guild: Guild,
|
|
||||||
user: User
|
|
||||||
) {
|
|
||||||
val guildId = guild.id
|
|
||||||
val link = Bot.lava.getLink(guildId.toString())
|
|
||||||
val player = link.player
|
|
||||||
if (link.state == Link.State.NOT_CONNECTED) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not connected",
|
|
||||||
"I'm not in a VC and therefore, I am not playing anything.",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val track = player.playingTrack
|
|
||||||
if (track == null) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not playing",
|
|
||||||
"I'm not playing anything currently", user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val gts = MusicManager.getGuildTrackScheduler(guild.asGuild(), player)
|
|
||||||
val q = gts.getQueue()
|
|
||||||
var desc =
|
|
||||||
"""${"**" + track.title + " - " + TimeUtil.getTimeFormatedShortend(track.length.inWholeMilliseconds)} (${track.author})**""" + "\n"
|
|
||||||
for ((i, tr) in q.withIndex()) {
|
|
||||||
if (i >= 14)
|
|
||||||
continue
|
|
||||||
desc += tr.info.title + " - " + TimeUtil.getTimeFormatedShortend(tr.info.length) + " (" + tr.info.author + ")\n"
|
|
||||||
}
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"Queue",
|
|
||||||
desc,
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,104 +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.buttons.music
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.buttons.Button
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
|
||||||
import dev.kord.core.behavior.interaction.response.respond
|
|
||||||
import dev.kord.core.entity.Guild
|
|
||||||
import dev.kord.core.entity.User
|
|
||||||
import dev.kord.rest.builder.message.modify.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
|
|
||||||
class RepeatButton : Button("btn.music.repeat") {
|
|
||||||
override suspend fun onInteraction(
|
|
||||||
response: DeferredPublicMessageInteractionResponseBehavior,
|
|
||||||
guild: Guild,
|
|
||||||
user: User
|
|
||||||
) {
|
|
||||||
val guildId = guild.id
|
|
||||||
val link = Bot.lava.getLink(guildId.toString())
|
|
||||||
val player = link.player
|
|
||||||
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
|
||||||
if (voiceState == null) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not connected to a VC",
|
|
||||||
"Please connect to a VC",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val channelId = voiceState.channelId
|
|
||||||
if (link.state == Link.State.NOT_CONNECTED) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not connected",
|
|
||||||
"I'm not in a VC and therefore, I am not playing anything.",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not in my VC",
|
|
||||||
"We are not in the same VC and therefore, you cannot control the music",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val gts = MusicManager.getGuildTrackScheduler(guild, player)
|
|
||||||
gts.repeating = !gts.repeating
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0x52E01A),
|
|
||||||
if (gts.repeating) "Now Repeating" else "Now Continuing",
|
|
||||||
if (gts.repeating) "The current track will now loop" else "The next track will play when this song finishes",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,147 +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.buttons.music
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.buttons.Button
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import de.limited_dev.botendo.util.TimeUtil
|
|
||||||
import de.limited_dev.botendo.util.UrlUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
|
||||||
import dev.kord.core.behavior.interaction.response.respond
|
|
||||||
import dev.kord.core.entity.Guild
|
|
||||||
import dev.kord.core.entity.User
|
|
||||||
import dev.kord.rest.builder.message.modify.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
|
|
||||||
class SkipButton : Button("btn.music.skip") {
|
|
||||||
override suspend fun onInteraction(
|
|
||||||
response: DeferredPublicMessageInteractionResponseBehavior,
|
|
||||||
guild: Guild,
|
|
||||||
user: User
|
|
||||||
) {
|
|
||||||
val guildId = guild.id
|
|
||||||
val link = Bot.lava.getLink(guildId.toString())
|
|
||||||
val player = link.player
|
|
||||||
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
|
||||||
if (voiceState == null) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not connected to a VC",
|
|
||||||
"Please connect to a VC",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val channelId = voiceState.channelId
|
|
||||||
if (link.state == Link.State.NOT_CONNECTED) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not connected",
|
|
||||||
"I'm not in a VC and therefore, I am not playing anything.",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not in my VC",
|
|
||||||
"We are not in the same VC and therefore, you cannot control the music",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var track = player.playingTrack
|
|
||||||
if (track == null) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not playing",
|
|
||||||
"I'm not playing anything currently", user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val gts = MusicManager.getGuildTrackScheduler(guild.asGuild(), player)
|
|
||||||
if (!gts.isEmpty()) {
|
|
||||||
track = gts.getHead().toTrack()
|
|
||||||
gts.playNext()
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbedWithImage(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"Skipped song; now playing",
|
|
||||||
"**${track.title}**\n*Now Playing*\nby ${track.author} :: ${
|
|
||||||
TimeUtil.getTimeFormatedRaw(
|
|
||||||
track.length.inWholeMilliseconds
|
|
||||||
)
|
|
||||||
}\n" +
|
|
||||||
">>>${track.uri}",
|
|
||||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
this.components.addAll(
|
|
||||||
ButtonUtil.getMusicControllerButtons(
|
|
||||||
player.paused,
|
|
||||||
gts.repeating
|
|
||||||
).components
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
player.stopTrack()
|
|
||||||
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"Skipped song; now playing",
|
|
||||||
"Nothing",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
this.actionRow {
|
|
||||||
this.components.addAll(ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating).components)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,98 +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.buttons.music
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.buttons.Button
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
|
||||||
import dev.kord.core.behavior.interaction.response.respond
|
|
||||||
import dev.kord.core.entity.Guild
|
|
||||||
import dev.kord.core.entity.User
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
|
|
||||||
class StopButton : Button("btn.music.stop") {
|
|
||||||
override suspend fun onInteraction(
|
|
||||||
response: DeferredPublicMessageInteractionResponseBehavior,
|
|
||||||
guild: Guild,
|
|
||||||
user: User
|
|
||||||
) {
|
|
||||||
val guildId = guild.id
|
|
||||||
val link = Bot.lava.getLink(guildId.toString())
|
|
||||||
val player = link.player
|
|
||||||
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
|
||||||
if (voiceState == null) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not connected to a VC",
|
|
||||||
"Please connect to a VC",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val channelId = voiceState.channelId
|
|
||||||
if (link.state == Link.State.NOT_CONNECTED) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not connected",
|
|
||||||
"I'm not in a VC and therefore, I am not playing anything.",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not in my VC",
|
|
||||||
"We are not in the same VC and therefore, you cannot control the music",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
player.stopTrack()
|
|
||||||
link.destroy()
|
|
||||||
MusicManager.getGuildTrackScheduler(guild.asGuild(), player).clear()
|
|
||||||
response.respond {
|
|
||||||
this.embeds = mutableListOf(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"I stopped and left",
|
|
||||||
"just like your girlfriend",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,94 +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.extensions.music
|
|
||||||
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.Extension
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
|
|
||||||
import com.kotlindiscord.kord.extensions.types.respond
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import de.limited_dev.botendo.util.TimeUtil
|
|
||||||
import de.limited_dev.botendo.util.UrlUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.rest.builder.message.create.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
import dev.schlaubi.lavakord.kord.getLink
|
|
||||||
|
|
||||||
class NowPlayingExtension : 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.NOT_CONNECTED) {
|
|
||||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
|
||||||
this,
|
|
||||||
Color(0xE0A81A),
|
|
||||||
"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,
|
|
||||||
Color(0xE0A81A),
|
|
||||||
"Not Playing",
|
|
||||||
"I'm not playing anything currently"
|
|
||||||
)
|
|
||||||
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(
|
|
||||||
track.position.inWholeMilliseconds
|
|
||||||
)
|
|
||||||
}: ${
|
|
||||||
TimeUtil.getTimeFormatedRaw(
|
|
||||||
track.length.inWholeMilliseconds
|
|
||||||
)
|
|
||||||
}\n" +
|
|
||||||
">>>${track.uri}",
|
|
||||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,109 +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.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.kord.common.Color
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
import dev.schlaubi.lavakord.kord.getLink
|
|
||||||
|
|
||||||
|
|
||||||
class PlayExtension : 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(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"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(
|
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return@action
|
|
||||||
}
|
|
||||||
|
|
||||||
val query = arguments.linkquery
|
|
||||||
val search = if (query.startsWith("http")) {
|
|
||||||
query
|
|
||||||
} else {
|
|
||||||
"ytsearch:$query"
|
|
||||||
}
|
|
||||||
this.respond {
|
|
||||||
embeds.add(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0A81A),
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,89 +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.extensions.music
|
|
||||||
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.Extension
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
|
|
||||||
import com.kotlindiscord.kord.extensions.types.respond
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import de.limited_dev.botendo.util.TimeUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.rest.builder.message.create.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
|
|
||||||
class QueueExtension : Extension() {
|
|
||||||
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.NOT_CONNECTED) {
|
|
||||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
|
||||||
this,
|
|
||||||
Color(0xE0311A),
|
|
||||||
"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,
|
|
||||||
Color(0xE0A81A),
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
this.respond {
|
|
||||||
this.embeds.add(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"Queue",
|
|
||||||
desc,
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,117 +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.extensions.music
|
|
||||||
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.Extension
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
|
|
||||||
import com.kotlindiscord.kord.extensions.types.respond
|
|
||||||
import de.limited_dev.botendo.Bot
|
|
||||||
import de.limited_dev.botendo.extensions.music.components.MusicManager
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import de.limited_dev.botendo.util.TimeUtil
|
|
||||||
import de.limited_dev.botendo.util.UrlUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.rest.builder.message.create.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
|
|
||||||
class SkipExtension : Extension() {
|
|
||||||
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,
|
|
||||||
Color(0xE0311A),
|
|
||||||
"You are not connected to a VC",
|
|
||||||
"Please connect to a VC"
|
|
||||||
)
|
|
||||||
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."
|
|
||||||
)
|
|
||||||
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"
|
|
||||||
)
|
|
||||||
return@action
|
|
||||||
}
|
|
||||||
var track = player.playingTrack
|
|
||||||
if (track == null) {
|
|
||||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
|
||||||
this,
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not playing",
|
|
||||||
"I'm not playing anything currently"
|
|
||||||
)
|
|
||||||
return@action
|
|
||||||
}
|
|
||||||
val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
|
|
||||||
if (!gts.isEmpty()) {
|
|
||||||
track = gts.getHead().toTrack()
|
|
||||||
gts.playNext()
|
|
||||||
} else {
|
|
||||||
player.stopTrack()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.respond {
|
|
||||||
this.embeds.add(
|
|
||||||
MessageUtil.getEmbedWithImage(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"Skipped song; now playing",
|
|
||||||
"**${track.title}**\n*Now Playing*\nby ${track.author} :: ${
|
|
||||||
TimeUtil.getTimeFormatedRaw(
|
|
||||||
track.length.inWholeMilliseconds
|
|
||||||
)
|
|
||||||
}\n" +
|
|
||||||
">>>${track.uri}",
|
|
||||||
"https://img.youtube.com/vi/" + UrlUtil.getYtThumbnailUrl(track.uri!!) + "/maxresdefault.jpg",
|
|
||||||
user.asUser().username + "#" + user.asUser().discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
ButtonUtil.getMusicControllerButtons(player.paused, gts.repeating)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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.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.kord.common.Color
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
import dev.schlaubi.lavakord.kord.getLink
|
|
||||||
|
|
||||||
class StopExtension : 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(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"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.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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return@action
|
|
||||||
}
|
|
||||||
player.stopTrack()
|
|
||||||
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
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,114 +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.extensions.music.components
|
|
||||||
|
|
||||||
import de.limited_dev.botendo.util.Logger
|
|
||||||
import dev.schlaubi.lavakord.audio.*
|
|
||||||
import dev.schlaubi.lavakord.audio.player.Player
|
|
||||||
import dev.schlaubi.lavakord.rest.models.PartialTrack
|
|
||||||
import java.util.concurrent.BlockingQueue
|
|
||||||
import java.util.concurrent.LinkedBlockingQueue
|
|
||||||
|
|
||||||
class GuildTrackScheduler(val pl: Player) {
|
|
||||||
|
|
||||||
private var queue: BlockingQueue<PartialTrack> = 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) {
|
|
||||||
if (this.pl.playingTrack == null) {
|
|
||||||
play(track)
|
|
||||||
} else {
|
|
||||||
queue.offer(track)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun playNext() {
|
|
||||||
if (!queue.isEmpty())
|
|
||||||
this.pl.playTrack(queue.poll())
|
|
||||||
else
|
|
||||||
this.pl.stopTrack()
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun play(tr: PartialTrack) {
|
|
||||||
this.pl.playTrack(tr)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addEvents() {
|
|
||||||
if (hasRegisteredEvents)
|
|
||||||
return
|
|
||||||
hasRegisteredEvents = true
|
|
||||||
|
|
||||||
Logger.out("Adding track events to GuildTrackScheduler...")
|
|
||||||
|
|
||||||
pl.on<Event, TrackEndEvent> {
|
|
||||||
onTrackEnd(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
pl.on<Event, TrackStuckEvent> {
|
|
||||||
onTrackStuck(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
pl.on<Event, TrackExceptionEvent> {
|
|
||||||
onTrackExc(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun onTrackEnd(e: TrackEndEvent) {
|
|
||||||
if (e.reason.mayStartNext) {
|
|
||||||
if (repeating) {
|
|
||||||
this.pl.playTrack(e.getTrack().copy())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
Logger.out("Track has ended; Playing next...")
|
|
||||||
playNext()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun onTrackStuck(e: TrackStuckEvent) {
|
|
||||||
Logger.out("Track is stuck, retrying...")
|
|
||||||
this.pl.playTrack(e.getTrack().copy())
|
|
||||||
}
|
|
||||||
|
|
||||||
private suspend fun onTrackExc(e: TrackExceptionEvent) {
|
|
||||||
Logger.out("Track had an exception, retrying...")
|
|
||||||
this.pl.playTrack(e.getTrack().copy())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clear() {
|
|
||||||
Logger.out("Clearing queue...")
|
|
||||||
repeating = false
|
|
||||||
queue.clear()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getQueue(): List<PartialTrack> {
|
|
||||||
return queue.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getHead(): PartialTrack {
|
|
||||||
return queue.first()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isEmpty(): Boolean {
|
|
||||||
return queue.isEmpty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,189 +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.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.PlayExtension
|
|
||||||
import de.limited_dev.botendo.util.ButtonUtil
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import de.limited_dev.botendo.util.TimeUtil
|
|
||||||
import de.limited_dev.botendo.util.UrlUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
import dev.kord.common.entity.Snowflake
|
|
||||||
import dev.kord.core.entity.Guild
|
|
||||||
import dev.kord.rest.builder.message.create.actionRow
|
|
||||||
import dev.schlaubi.lavakord.audio.Link
|
|
||||||
import dev.schlaubi.lavakord.audio.player.Player
|
|
||||||
import dev.schlaubi.lavakord.rest.loadItem
|
|
||||||
import dev.schlaubi.lavakord.rest.models.TrackResponse
|
|
||||||
|
|
||||||
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<PlayExtension.PlayArgs, ModalForm>,
|
|
||||||
link: Link,
|
|
||||||
search: String
|
|
||||||
) {
|
|
||||||
addToQueue(ctx, link, search, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun addToQueue(
|
|
||||||
ctx: PublicSlashCommandContext<PlayExtension.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(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"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"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
this.components.addAll(
|
|
||||||
ButtonUtil.getMusicControllerButtons(
|
|
||||||
player.paused,
|
|
||||||
gts.repeating
|
|
||||||
).components
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"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"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
this.actionRow {
|
|
||||||
this.components.addAll(
|
|
||||||
ButtonUtil.getMusicControllerButtons(
|
|
||||||
player.paused,
|
|
||||||
gts.repeating
|
|
||||||
).components
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackResponse.LoadType.SEARCH_RESULT -> {
|
|
||||||
gts.queue(item.tracks.first())
|
|
||||||
if (!silent)
|
|
||||||
ctx.respond {
|
|
||||||
this.embeds.add(
|
|
||||||
MessageUtil.getEmbedWithImage(
|
|
||||||
Color(0x52E01A),
|
|
||||||
"Queuing track from query",
|
|
||||||
"**${item.tracks.first().info.title}**\n*Queue*\nby ${item.tracks.first().info.author} :: ${
|
|
||||||
TimeUtil.getTimeFormatedRaw(
|
|
||||||
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.actionRow {
|
|
||||||
this.components.addAll(
|
|
||||||
ButtonUtil.getMusicControllerButtons(
|
|
||||||
player.paused,
|
|
||||||
gts.repeating
|
|
||||||
).components
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackResponse.LoadType.NO_MATCHES -> {
|
|
||||||
if (!silent)
|
|
||||||
ctx.respond {
|
|
||||||
this.embeds.add(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Not found",
|
|
||||||
"There were no matches.",
|
|
||||||
u.username + "#" + u.discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackResponse.LoadType.LOAD_FAILED -> {
|
|
||||||
if (!silent)
|
|
||||||
ctx.respond {
|
|
||||||
this.embeds.add(
|
|
||||||
MessageUtil.getEmbed(
|
|
||||||
Color(0xE0311A),
|
|
||||||
"Load failed",
|
|
||||||
"There was an error while loading.", u.username + "#" + u.discriminator
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,48 +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.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
|
|
||||||
import dev.kord.common.Color
|
|
||||||
|
|
||||||
class InfoExtension : Extension() {
|
|
||||||
override val name = "info"
|
|
||||||
override suspend fun setup() {
|
|
||||||
publicSlashCommand {
|
|
||||||
name = "info"
|
|
||||||
description = "Show infos about the bot"
|
|
||||||
this.action {
|
|
||||||
MessageUtil.sendEmbedForPublicSlashCommand(
|
|
||||||
this, Color(0x52E01A), "Botendo",
|
|
||||||
"Botendo ***v." + BuildConstants.version + "***\n" +
|
|
||||||
"Kord-Extensions ***v." + BuildConstants.kordVersion + "***\n" +
|
|
||||||
"lavalink.kt ***v." + BuildConstants.lavaVersion + "***\n" +
|
|
||||||
"Coroutines ***v." + BuildConstants.coroutinesVersion + "***\n" +
|
|
||||||
"Ktor ***v." + BuildConstants.ktorVersion + "***\n" +
|
|
||||||
"Exposed ***v." + BuildConstants.exposedVersion + "***\n" +
|
|
||||||
"PostgreSQL ***v." + BuildConstants.postgresVersion + "***"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +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.extensions.util
|
|
||||||
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.Extension
|
|
||||||
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
|
|
||||||
import de.limited_dev.botendo.util.MessageUtil
|
|
||||||
import dev.kord.common.Color
|
|
||||||
|
|
||||||
class PotatoExtension : Extension() {
|
|
||||||
override val name = "potato"
|
|
||||||
override suspend fun setup() {
|
|
||||||
publicSlashCommand {
|
|
||||||
name = "potato"
|
|
||||||
description = "Potato"
|
|
||||||
this.action {
|
|
||||||
MessageUtil.sendEmbedForPublicSlashCommandWithImage(
|
|
||||||
this, Color(0xE0311A), "Potato",
|
|
||||||
"Potato",
|
|
||||||
"https://static.tumblr.com/c06d8e0928395746a63b9c5d3cb1ce66/sl9iajp/gxFmqk38z/tumblr_static_potato-equality.jpg"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,42 +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.util
|
|
||||||
|
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
|
|
||||||
object Logger {
|
|
||||||
private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("yy/MM/dd HH:mm:ss")
|
|
||||||
|
|
||||||
fun out(msg: String) {
|
|
||||||
val caller = Thread.currentThread().stackTrace[2]
|
|
||||||
val now: LocalDateTime = LocalDateTime.now()
|
|
||||||
try {
|
|
||||||
println(
|
|
||||||
("[" + Class.forName(caller.className).simpleName + "." +
|
|
||||||
caller.methodName + ":" + caller.lineNumber + "] [" + dtf.format(now)).toString() + "] <" + msg + ">"
|
|
||||||
)
|
|
||||||
} catch (e: ClassNotFoundException) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
// Ich kann nicht mehr
|
|
||||||
// [Klasse.Funktion] [T/M HH:MM] <NACHRICHT>
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,104 +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.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 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 {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,30 +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.util
|
|
||||||
|
|
||||||
object Status {
|
|
||||||
//TODO: impl.
|
|
||||||
suspend fun updateStatus() {
|
|
||||||
/* Bot.kord.editPresence {
|
|
||||||
this.playing("")
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,90 +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.util
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
object TimeUtil {
|
|
||||||
///Convert Miliseconds to xdays xhours xmins xsecs
|
|
||||||
fun getTimeFormatedShortend(time: Long): String {
|
|
||||||
var time = time
|
|
||||||
val days = TimeUnit.MILLISECONDS
|
|
||||||
.toDays(time)
|
|
||||||
time -= TimeUnit.DAYS.toMillis(days)
|
|
||||||
val hours = TimeUnit.MILLISECONDS
|
|
||||||
.toHours(time)
|
|
||||||
time -= TimeUnit.HOURS.toMillis(hours)
|
|
||||||
val minutes = TimeUnit.MILLISECONDS
|
|
||||||
.toMinutes(time)
|
|
||||||
time -= TimeUnit.MINUTES.toMillis(minutes)
|
|
||||||
val seconds = TimeUnit.MILLISECONDS
|
|
||||||
.toSeconds(time)
|
|
||||||
var s = ""
|
|
||||||
if (days >= 1) {
|
|
||||||
s += days.toString() + "d "
|
|
||||||
}
|
|
||||||
if (hours >= 1) {
|
|
||||||
s += hours.toString() + "h "
|
|
||||||
}
|
|
||||||
if (minutes >= 1) {
|
|
||||||
s += minutes.toString() + "m "
|
|
||||||
}
|
|
||||||
if (seconds >= 1 && hours < 1) {
|
|
||||||
s += seconds.toString() + "s"
|
|
||||||
}
|
|
||||||
if (s.isEmpty() || s.isBlank()) {
|
|
||||||
s = "0s"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getTimeFormatedRaw(time: Long): String {
|
|
||||||
var time = time
|
|
||||||
val days = TimeUnit.MILLISECONDS
|
|
||||||
.toDays(time)
|
|
||||||
time -= TimeUnit.DAYS.toMillis(days)
|
|
||||||
val hours = TimeUnit.MILLISECONDS
|
|
||||||
.toHours(time)
|
|
||||||
time -= TimeUnit.HOURS.toMillis(hours)
|
|
||||||
val minutes = TimeUnit.MILLISECONDS
|
|
||||||
.toMinutes(time)
|
|
||||||
time -= TimeUnit.MINUTES.toMillis(minutes)
|
|
||||||
val seconds = TimeUnit.MILLISECONDS
|
|
||||||
.toSeconds(time)
|
|
||||||
var s = ""
|
|
||||||
if (days >= 1) {
|
|
||||||
s += days.toString() + "d "
|
|
||||||
}
|
|
||||||
if (hours >= 1) {
|
|
||||||
s += hours.toString() + "h "
|
|
||||||
}
|
|
||||||
if (minutes >= 1) {
|
|
||||||
s += minutes.toString() + "m "
|
|
||||||
}
|
|
||||||
if (seconds >= 1) {
|
|
||||||
s += seconds.toString() + "s"
|
|
||||||
}
|
|
||||||
if (s.isEmpty() || s.isBlank()) {
|
|
||||||
s = "0s"
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,27 +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.util
|
|
||||||
|
|
||||||
object UrlUtil {
|
|
||||||
///Strip the video ID from a YouTube link
|
|
||||||
fun getYtThumbnailUrl(uri: String): String {
|
|
||||||
return uri.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
|
|
||||||
}
|
|
||||||
}
|
|
144
src/main/kotlin/net/moonleay/botendo/Bot.kt
Normal file
144
src/main/kotlin/net/moonleay/botendo/Bot.kt
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
object Bot {
|
||||||
|
//The kord object gets set at app launch
|
||||||
|
private lateinit var bot: ExtensibleBot
|
||||||
|
lateinit var lava: LavaKord
|
||||||
|
suspend fun start() {
|
||||||
|
Logger.out("Starting Bot...")
|
||||||
|
|
||||||
|
//Load config
|
||||||
|
CredentialManager.load()
|
||||||
|
|
||||||
|
//Don't run the bot when there is no bot token in config
|
||||||
|
if (CredentialManager.token == "empty") {
|
||||||
|
Logger.out("The config does not contain a bot token")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add Bot token to kord
|
||||||
|
//kord = Kord(CredentialManager.token)
|
||||||
|
bot = ExtensibleBot(CredentialManager.token) {
|
||||||
|
applicationCommands {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
extensions {
|
||||||
|
add(::InfoExtension)
|
||||||
|
add(::PlayExtension)
|
||||||
|
add(::StopExtension)
|
||||||
|
add(::SkipExtension)
|
||||||
|
add(::NowPlayingExtension)
|
||||||
|
add(::QueueExtension)
|
||||||
|
add(::UpsertExtension)
|
||||||
|
add(::SeekExtension)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.presence {
|
||||||
|
this.streaming("music", "https://twitch.tv/moonleaytv")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add LavaLink
|
||||||
|
lava = bot.kordRef.lavakord()
|
||||||
|
|
||||||
|
//Add the LavaLink node from config
|
||||||
|
lava.addNode(CredentialManager.linkip, CredentialManager.linkpw)
|
||||||
|
|
||||||
|
//Register Button presses
|
||||||
|
bot.kordRef.on<ButtonInteractionCreateEvent> {
|
||||||
|
val inter = this.interaction
|
||||||
|
val response = inter.deferPublicResponse()
|
||||||
|
val u = inter.user
|
||||||
|
val g = this.interaction.getOriginalInteractionResponse().getGuild()
|
||||||
|
for (b in net.moonleay.botendo.buttons.ButtonManager.buttons) {
|
||||||
|
if (b.id != inter.componentId)
|
||||||
|
continue
|
||||||
|
b.onInteraction(response, g, u)
|
||||||
|
return@on
|
||||||
|
}
|
||||||
|
// Button not found
|
||||||
|
response.respond {
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
42
src/main/kotlin/net/moonleay/botendo/Main.kt
Normal file
42
src/main/kotlin/net/moonleay/botendo/Main.kt
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
import net.moonleay.botendo.util.Logger
|
||||||
|
|
||||||
|
|
||||||
|
///Show the splash and launch the Bot
|
||||||
|
suspend fun main(args: Array<String>) {
|
||||||
|
println(
|
||||||
|
"M#\"\"\"\"\"\"\"'M dP dP \n" +
|
||||||
|
"## mmmm. `M 88 88 \n" +
|
||||||
|
"#' .M .d8888b. d8888P .d8888b. 88d888b. .d888b88 .d8888b. \n" +
|
||||||
|
"M# MMMb.'YM 88' `88 88 88ooood8 88' `88 88' `88 88' `88 \n" +
|
||||||
|
"M# MMMM' M 88. .88 88 88. ... 88 88 88. .88 88. .88 \n" +
|
||||||
|
"M# .;M `88888P' dP `88888P' dP dP `88888P8 `88888P' \n" +
|
||||||
|
"M#########M \n" +
|
||||||
|
" "
|
||||||
|
)
|
||||||
|
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()
|
||||||
|
}
|
34
src/main/kotlin/net/moonleay/botendo/buttons/Button.kt
Normal file
34
src/main/kotlin/net/moonleay/botendo/buttons/Button.kt
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* 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.buttons
|
||||||
|
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.entity.Guild
|
||||||
|
import dev.kord.core.entity.User
|
||||||
|
|
||||||
|
open class Button(val id: String) {
|
||||||
|
|
||||||
|
open suspend fun onInteraction(
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
guild: Guild,
|
||||||
|
user: User
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* 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.buttons
|
||||||
|
|
||||||
|
import net.moonleay.botendo.buttons.music.*
|
||||||
|
|
||||||
|
object ButtonManager {
|
||||||
|
val buttons = listOf(
|
||||||
|
RepeatButton(),
|
||||||
|
PauseButton(),
|
||||||
|
SkipButton(),
|
||||||
|
QueueButton(),
|
||||||
|
StopButton()
|
||||||
|
)
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* 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.buttons.music
|
||||||
|
|
||||||
|
import dev.kord.common.Color
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.behavior.interaction.response.respond
|
||||||
|
import dev.kord.core.entity.Guild
|
||||||
|
import dev.kord.core.entity.User
|
||||||
|
import dev.kord.rest.builder.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
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
|
||||||
|
class PauseButton : net.moonleay.botendo.buttons.Button("btn.music.pause") {
|
||||||
|
override suspend fun onInteraction(
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
guild: Guild,
|
||||||
|
user: User
|
||||||
|
) {
|
||||||
|
val guildId = guild.id
|
||||||
|
val link = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
|
||||||
|
val player = link.player
|
||||||
|
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
||||||
|
if (voiceState == null) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val channelId = voiceState.channelId
|
||||||
|
if (link.state == Link.State.NOT_CONNECTED) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
player.pause(!player.paused)
|
||||||
|
|
||||||
|
val gts = MusicManager.getGuildTrackScheduler(guild, player)
|
||||||
|
response.respond {
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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.buttons.music
|
||||||
|
|
||||||
|
import dev.kord.common.Color
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.behavior.interaction.response.respond
|
||||||
|
import dev.kord.core.entity.Guild
|
||||||
|
import dev.kord.core.entity.User
|
||||||
|
import dev.kord.rest.builder.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
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
import net.moonleay.botendo.util.TimeUtil
|
||||||
|
|
||||||
|
class QueueButton : net.moonleay.botendo.buttons.Button("btn.music.queue") {
|
||||||
|
override suspend fun onInteraction(
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
guild: Guild,
|
||||||
|
user: User
|
||||||
|
) {
|
||||||
|
val guildId = guild.id
|
||||||
|
val link = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
|
||||||
|
val player = link.player
|
||||||
|
if (link.state == Link.State.NOT_CONNECTED) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player.playingTrack == null) {
|
||||||
|
response.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(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)} (${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.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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* 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.buttons.music
|
||||||
|
|
||||||
|
import dev.kord.common.Color
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.behavior.interaction.response.respond
|
||||||
|
import dev.kord.core.entity.Guild
|
||||||
|
import dev.kord.core.entity.User
|
||||||
|
import dev.kord.rest.builder.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
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
|
||||||
|
class RepeatButton : net.moonleay.botendo.buttons.Button("btn.music.repeat") {
|
||||||
|
override suspend fun onInteraction(
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
guild: Guild,
|
||||||
|
user: User
|
||||||
|
) {
|
||||||
|
val guildId = guild.id
|
||||||
|
val link = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
|
||||||
|
val player = link.player
|
||||||
|
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
||||||
|
if (voiceState == null) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val channelId = voiceState.channelId
|
||||||
|
if (link.state == Link.State.NOT_CONNECTED) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val gts = MusicManager.getGuildTrackScheduler(guild, player)
|
||||||
|
gts.repeating = !gts.repeating
|
||||||
|
response.respond {
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
150
src/main/kotlin/net/moonleay/botendo/buttons/music/SkipButton.kt
Normal file
150
src/main/kotlin/net/moonleay/botendo/buttons/music/SkipButton.kt
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
/*
|
||||||
|
* 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.buttons.music
|
||||||
|
|
||||||
|
|
||||||
|
import dev.kord.common.Color
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.behavior.interaction.response.respond
|
||||||
|
import dev.kord.core.entity.Guild
|
||||||
|
import dev.kord.core.entity.User
|
||||||
|
import dev.kord.rest.builder.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
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
import net.moonleay.botendo.util.TimeUtil
|
||||||
|
import net.moonleay.botendo.util.UrlUtil
|
||||||
|
|
||||||
|
class SkipButton : net.moonleay.botendo.buttons.Button("btn.music.skip") {
|
||||||
|
override suspend fun onInteraction(
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
guild: Guild,
|
||||||
|
user: User
|
||||||
|
) {
|
||||||
|
val guildId = guild.id
|
||||||
|
val link = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
|
||||||
|
val player = link.player
|
||||||
|
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
||||||
|
if (voiceState == null) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val channelId = voiceState.channelId
|
||||||
|
if (link.state == Link.State.NOT_CONNECTED) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (player.playingTrack == null) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var track = player.playingTrack!!.info
|
||||||
|
val gts = MusicManager.getGuildTrackScheduler(guild.asGuild(), player)
|
||||||
|
if (!gts.isEmpty()) {
|
||||||
|
track = gts.getHead().info
|
||||||
|
gts.playNext(link)
|
||||||
|
response.respond {
|
||||||
|
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(
|
||||||
|
ButtonUtil.getMusicControllerButtons(
|
||||||
|
player.paused,
|
||||||
|
gts.repeating
|
||||||
|
).components
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
player.stopTrack()
|
||||||
|
|
||||||
|
response.respond {
|
||||||
|
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)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* 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.buttons.music
|
||||||
|
|
||||||
|
import dev.kord.common.Color
|
||||||
|
import dev.kord.core.behavior.interaction.response.DeferredPublicMessageInteractionResponseBehavior
|
||||||
|
import dev.kord.core.behavior.interaction.response.respond
|
||||||
|
import dev.kord.core.entity.Guild
|
||||||
|
import dev.kord.core.entity.User
|
||||||
|
import dev.kord.rest.builder.message.embed
|
||||||
|
import dev.schlaubi.lavakord.audio.Link
|
||||||
|
import net.moonleay.botendo.extensions.music.components.MusicManager
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
|
||||||
|
class StopButton : net.moonleay.botendo.buttons.Button("btn.music.stop") {
|
||||||
|
override suspend fun onInteraction(
|
||||||
|
response: DeferredPublicMessageInteractionResponseBehavior,
|
||||||
|
guild: Guild,
|
||||||
|
user: User
|
||||||
|
) {
|
||||||
|
val guildId = guild.id
|
||||||
|
val link = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
|
||||||
|
val player = link.player
|
||||||
|
val voiceState = user.asMember(guildId).getVoiceStateOrNull()
|
||||||
|
if (voiceState == null) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val channelId = voiceState.channelId
|
||||||
|
if (link.state == Link.State.NOT_CONNECTED) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
} else if (link.state == Link.State.CONNECTED && link.lastChannelId != channelId!!.value) {
|
||||||
|
response.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(user)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
player.stopTrack()
|
||||||
|
link.destroy()
|
||||||
|
MusicManager.getGuildTrackScheduler(guild.asGuild(), player).clear()
|
||||||
|
response.respond {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Botendo
|
* Botendo
|
||||||
* Copyright (C) 2023 limited_dev
|
* Copyright (C) 2023 moonleay
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -14,10 +14,9 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.limited_dev.botendo.data
|
package net.moonleay.botendo.data
|
||||||
|
|
||||||
import java.io.*
|
import java.io.*
|
||||||
import java.util.*
|
import java.util.*
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* 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 dev.schlaubi.lavakord.kord.getLink
|
||||||
|
import net.moonleay.botendo.extensions.music.components.MusicManager
|
||||||
|
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 NowPlayingExtension : 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 = net.moonleay.botendo.Bot.lava.getLink(guildId)
|
||||||
|
val player = link.player
|
||||||
|
val u = this.user
|
||||||
|
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
|
||||||
|
}
|
||||||
|
val track = player.playingTrack
|
||||||
|
if (track == 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
|
||||||
|
}
|
||||||
|
val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
|
||||||
|
|
||||||
|
this.respond {
|
||||||
|
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(fun ActionRowBuilder.() {
|
||||||
|
components.addAll(
|
||||||
|
ButtonUtil.getMusicControllerButtons(
|
||||||
|
player.paused,
|
||||||
|
gts.repeating
|
||||||
|
).components
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
/*
|
||||||
|
* 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.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() {
|
||||||
|
|
||||||
|
override val name = "play"
|
||||||
|
|
||||||
|
override suspend fun setup() {
|
||||||
|
publicSlashCommand(::LinkArguments) {
|
||||||
|
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 {
|
||||||
|
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.CONNECTED) {
|
||||||
|
link.connectAudio(channelId!!.value)
|
||||||
|
} 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 play any music"
|
||||||
|
this.author {
|
||||||
|
this.name = UserUtil.getCommandSrc(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return@action
|
||||||
|
}
|
||||||
|
|
||||||
|
val query = arguments.linkquery
|
||||||
|
val search = if (query.startsWith("http")) {
|
||||||
|
query
|
||||||
|
} else {
|
||||||
|
"ytsearch:$query"
|
||||||
|
}
|
||||||
|
this.respond {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* 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.util.ButtonUtil
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
import net.moonleay.botendo.util.TimeUtil
|
||||||
|
|
||||||
|
class QueueExtension : 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 = net.moonleay.botendo.Bot.lava.getLink(guildId.toString())
|
||||||
|
val player = link.player
|
||||||
|
val u = this.user
|
||||||
|
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
|
||||||
|
}
|
||||||
|
val track = player.playingTrack
|
||||||
|
if (track == null) {
|
||||||
|
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.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.embed {
|
||||||
|
this.color = Color(0x52E01A)
|
||||||
|
this.title = "Queue"
|
||||||
|
this.description = desc
|
||||||
|
this.footer {
|
||||||
|
this.text = MessageUtil.getFooter(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.actionRow(fun ActionRowBuilder.() {
|
||||||
|
components.addAll(
|
||||||
|
ButtonUtil.getMusicControllerButtons(
|
||||||
|
player.paused,
|
||||||
|
gts.repeating
|
||||||
|
).components
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* 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.util.ButtonUtil
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
import net.moonleay.botendo.util.TimeUtil
|
||||||
|
import net.moonleay.botendo.util.UrlUtil
|
||||||
|
|
||||||
|
class SkipExtension : 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 = 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
|
||||||
|
}
|
||||||
|
var track = player.playingTrack!!.info
|
||||||
|
if (track == 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
|
||||||
|
}
|
||||||
|
val gts = MusicManager.getGuildTrackScheduler(this.guild!!.asGuild(), player)
|
||||||
|
if (!gts.isEmpty()) {
|
||||||
|
track = gts.getHead().info
|
||||||
|
gts.playNext(link)
|
||||||
|
} else {
|
||||||
|
player.stopTrack()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.respond {
|
||||||
|
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(fun ActionRowBuilder.() {
|
||||||
|
components.addAll(
|
||||||
|
ButtonUtil.getMusicControllerButtons(
|
||||||
|
player.paused,
|
||||||
|
gts.repeating
|
||||||
|
).components
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* 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.message.embed
|
||||||
|
import dev.schlaubi.lavakord.audio.Link
|
||||||
|
import dev.schlaubi.lavakord.kord.getLink
|
||||||
|
import net.moonleay.botendo.extensions.music.components.MusicManager
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
|
||||||
|
class StopExtension : 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 = net.moonleay.botendo.Bot.lava.getLink(guildId)
|
||||||
|
val player = link.player
|
||||||
|
val u = this.user
|
||||||
|
val vcsUser = u.asMember(guildId).getVoiceStateOrNull()
|
||||||
|
if (vcsUser == 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 = vcsUser.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"
|
||||||
|
this.footer {
|
||||||
|
this.text = MessageUtil.getFooter(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return@action
|
||||||
|
}
|
||||||
|
player.stopTrack()
|
||||||
|
link.destroy()
|
||||||
|
MusicManager.getGuildTrackScheduler(this.getGuild()!!.asGuild(), player).clear()
|
||||||
|
this.respond {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* 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.message.embed
|
||||||
|
import dev.schlaubi.lavakord.audio.Link
|
||||||
|
import dev.schlaubi.lavakord.kord.getLink
|
||||||
|
import net.moonleay.botendo.extensions.music.components.LinkArguments
|
||||||
|
import net.moonleay.botendo.extensions.music.components.MusicManager
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
|
||||||
|
|
||||||
|
class UpsertExtension : Extension() {
|
||||||
|
|
||||||
|
override val name = "upsert"
|
||||||
|
|
||||||
|
override suspend fun setup() {
|
||||||
|
publicSlashCommand(::LinkArguments) {
|
||||||
|
name = "upsert"
|
||||||
|
description = "Upsert music"
|
||||||
|
this.action {
|
||||||
|
val guildId = this.guild!!.id
|
||||||
|
val link = net.moonleay.botendo.Bot.lava.getLink(guildId)
|
||||||
|
val u = this.user
|
||||||
|
val vcsUser = u.asMember(guildId).getVoiceStateOrNull()
|
||||||
|
if (vcsUser == 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 = 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 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
val query = arguments.linkquery
|
||||||
|
val search = if (query.startsWith("http")) {
|
||||||
|
query
|
||||||
|
} else {
|
||||||
|
"ytsearch:$query"
|
||||||
|
}
|
||||||
|
this.respond {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
* 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 dev.arbjerg.lavalink.protocol.v4.Track
|
||||||
|
import dev.schlaubi.lavakord.audio.*
|
||||||
|
import dev.schlaubi.lavakord.audio.player.Player
|
||||||
|
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<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: Track, type: MusicManager.AddType) {
|
||||||
|
if (this.pl.playingTrack == null) {
|
||||||
|
play(track)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
when (type) {
|
||||||
|
MusicManager.AddType.QUEUE -> {
|
||||||
|
queue.offer(track)
|
||||||
|
}
|
||||||
|
|
||||||
|
MusicManager.AddType.UPSERT -> {
|
||||||
|
val nq = LinkedBlockingQueue<Track>()
|
||||||
|
nq.offer(track)
|
||||||
|
for (t in queue.toList()) {
|
||||||
|
nq.offer(t)
|
||||||
|
}
|
||||||
|
queue = nq
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun playNext(link: Link) {
|
||||||
|
if (!queue.isEmpty())
|
||||||
|
this.pl.playTrack(track = queue.poll())
|
||||||
|
else {
|
||||||
|
this.pl.stopTrack()
|
||||||
|
link.destroy()
|
||||||
|
clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun play(track: Track) {
|
||||||
|
this.pl.playTrack(track)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addEvents() {
|
||||||
|
if (hasRegisteredEvents)
|
||||||
|
return
|
||||||
|
hasRegisteredEvents = true
|
||||||
|
|
||||||
|
Logger.out("Adding track events to GuildTrackScheduler...")
|
||||||
|
|
||||||
|
pl.on<Event, TrackEndEvent> {
|
||||||
|
onTrackEnd(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
pl.on<Event, TrackStuckEvent> {
|
||||||
|
onTrackStuck(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
pl.on<Event, TrackExceptionEvent> {
|
||||||
|
onTrackExc(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onTrackEnd(e: TrackEndEvent) {
|
||||||
|
if (e.reason.mayStartNext) {
|
||||||
|
if (repeating) {
|
||||||
|
Logger.out("Repeating track...")
|
||||||
|
this.pl.playTrack(e.track.copy())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Logger.out("Track has ended; Playing next...")
|
||||||
|
playNext(Bot.lava.getLink(e.guildId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onTrackStuck(e: TrackStuckEvent) {
|
||||||
|
Logger.out("Track is stuck, retrying...")
|
||||||
|
this.pl.playTrack(e.track.copy())
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun onTrackExc(e: TrackExceptionEvent) {
|
||||||
|
Logger.out("Track had an exception, retrying...")
|
||||||
|
this.pl.playTrack(e.track.copy())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clear() {
|
||||||
|
Logger.out("Clearing queue...")
|
||||||
|
repeating = false
|
||||||
|
queue.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getQueue(): List<Track> {
|
||||||
|
return queue.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHead(): Track {
|
||||||
|
return queue.first()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isEmpty(): Boolean {
|
||||||
|
return queue.isEmpty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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 LinkArguments : Arguments() {
|
||||||
|
val linkquery by string {
|
||||||
|
name = "linkqery"
|
||||||
|
description = "Song link or search query"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,230 @@
|
||||||
|
/*
|
||||||
|
* 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.application.slash.PublicSlashCommandContext
|
||||||
|
import com.kotlindiscord.kord.extensions.components.forms.ModalForm
|
||||||
|
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.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 net.moonleay.botendo.util.ButtonUtil
|
||||||
|
import net.moonleay.botendo.util.MessageUtil
|
||||||
|
import net.moonleay.botendo.util.TimeUtil
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suspend fun addToQueue(
|
||||||
|
ctx: PublicSlashCommandContext<LinkArguments, ModalForm>,
|
||||||
|
link: Link,
|
||||||
|
search: String
|
||||||
|
) {
|
||||||
|
addToQueue(ctx, link, search, AddType.QUEUE, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun upsertIntoQueue(
|
||||||
|
ctx: PublicSlashCommandContext<LinkArguments, ModalForm>,
|
||||||
|
link: Link,
|
||||||
|
search: String
|
||||||
|
) {
|
||||||
|
addToQueue(ctx, link, search, AddType.UPSERT, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun addToQueue(
|
||||||
|
ctx: PublicSlashCommandContext<LinkArguments, ModalForm>,
|
||||||
|
link: Link,
|
||||||
|
search: String,
|
||||||
|
type: AddType,
|
||||||
|
silent: Boolean
|
||||||
|
) {
|
||||||
|
val player = link.player
|
||||||
|
val gts = getGuildTrackScheduler(ctx.guild!!.asGuild(), player)
|
||||||
|
val u = ctx.user.asUser()
|
||||||
|
gts.addEvents()
|
||||||
|
|
||||||
|
when (val itm = link.loadItem(search)) {
|
||||||
|
is LoadResult.TrackLoaded -> {
|
||||||
|
gts.queue(itm.data, type)
|
||||||
|
if (!silent)
|
||||||
|
ctx.respond {
|
||||||
|
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(fun ActionRowBuilder.() {
|
||||||
|
components.addAll(
|
||||||
|
ButtonUtil.getMusicControllerButtons(
|
||||||
|
player.paused,
|
||||||
|
gts.repeating
|
||||||
|
).components
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.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(
|
||||||
|
ButtonUtil.getMusicControllerButtons(
|
||||||
|
player.paused,
|
||||||
|
gts.repeating
|
||||||
|
).components
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
is LoadResult.SearchResult -> {
|
||||||
|
gts.queue(itm.data.tracks.first(), type)
|
||||||
|
if (!silent)
|
||||||
|
ctx.respond {
|
||||||
|
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(
|
||||||
|
ButtonUtil.getMusicControllerButtons(
|
||||||
|
player.paused,
|
||||||
|
gts.repeating
|
||||||
|
).components
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
is LoadResult.NoMatches -> {
|
||||||
|
if (gts.isEmpty() && player.playingTrack == null) {
|
||||||
|
player.stopTrack()
|
||||||
|
link.destroy()
|
||||||
|
}
|
||||||
|
if (!silent)
|
||||||
|
ctx.respond {
|
||||||
|
this.embed {
|
||||||
|
this.color = Color(0xE0311A)
|
||||||
|
this.title = "Not found"
|
||||||
|
this.description = "There were no matches."
|
||||||
|
this.footer {
|
||||||
|
this.text = MessageUtil.getFooter(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is LoadResult.LoadFailed -> {
|
||||||
|
if (gts.isEmpty() && player.playingTrack == null) {
|
||||||
|
player.stopTrack()
|
||||||
|
link.destroy()
|
||||||
|
}
|
||||||
|
if (!silent)
|
||||||
|
ctx.respond {
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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\""
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.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() {
|
||||||
|
override val name = "info"
|
||||||
|
override suspend fun setup() {
|
||||||
|
publicSlashCommand {
|
||||||
|
name = "info"
|
||||||
|
description = "Show infos about the bot"
|
||||||
|
this.action {
|
||||||
|
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***\n" +
|
||||||
|
"(c) 2023, licensed under GPL-3.0\n" +
|
||||||
|
"More infos: https://moonleay.net/projects/botendo\n"
|
||||||
|
this.footer {
|
||||||
|
this.text = MessageUtil.getFooter(u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Botendo
|
* Botendo
|
||||||
* Copyright (C) 2023 limited_dev
|
* Copyright (C) 2023 moonleay
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -14,10 +14,9 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package de.limited_dev.botendo.util
|
package net.moonleay.botendo.util
|
||||||
|
|
||||||
import dev.kord.common.entity.ButtonStyle
|
import dev.kord.common.entity.ButtonStyle
|
||||||
import dev.kord.rest.builder.component.ActionRowBuilder
|
import dev.kord.rest.builder.component.ActionRowBuilder
|
41
src/main/kotlin/net/moonleay/botendo/util/Logger.kt
Normal file
41
src/main/kotlin/net/moonleay/botendo/util/Logger.kt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
* 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 java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
object Logger {
|
||||||
|
private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("yy/MM/dd HH:mm:ss")
|
||||||
|
|
||||||
|
fun out(msg: String) {
|
||||||
|
val caller = Thread.currentThread().stackTrace[2]
|
||||||
|
val now: LocalDateTime = LocalDateTime.now()
|
||||||
|
try {
|
||||||
|
println(
|
||||||
|
("[" + Class.forName(caller.className).simpleName + "." +
|
||||||
|
caller.methodName + ":" + caller.lineNumber + "] [" + dtf.format(now)) + "] <" + msg + ">"
|
||||||
|
)
|
||||||
|
} catch (e: ClassNotFoundException) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
// Ich kann nicht mehr
|
||||||
|
// [Class.function] [T/M HH:MM] <MESSAGE>
|
||||||
|
}
|
||||||
|
}
|
32
src/main/kotlin/net/moonleay/botendo/util/MessageUtil.kt
Normal file
32
src/main/kotlin/net/moonleay/botendo/util/MessageUtil.kt
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
|
object MessageUtil {
|
||||||
|
private val dtf: DateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy @ HH:mm:ss")
|
||||||
|
|
||||||
|
suspend fun getFooter(u: UserBehavior? = null): String{
|
||||||
|
val now: LocalDateTime = LocalDateTime.now()
|
||||||
|
return ">" + dtf.format(now) + " - ${u?.asUser()?.username?:"Automatic Message"}"
|
||||||
|
}
|
||||||
|
}
|
29
src/main/kotlin/net/moonleay/botendo/util/Status.kt
Normal file
29
src/main/kotlin/net/moonleay/botendo/util/Status.kt
Normal 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.util
|
||||||
|
|
||||||
|
object Status {
|
||||||
|
//TODO: impl.
|
||||||
|
suspend fun updateStatus() {
|
||||||
|
/* Bot.kord.editPresence {
|
||||||
|
this.playing("")
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
114
src/main/kotlin/net/moonleay/botendo/util/TimeUtil.kt
Normal file
114
src/main/kotlin/net/moonleay/botendo/util/TimeUtil.kt
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
* 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 java.time.Duration
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
object TimeUtil {
|
||||||
|
///Convert Miliseconds to xdays xhours xmins xsecs
|
||||||
|
fun getTimeFormatedShortend(timeIn: Long): String {
|
||||||
|
var time = timeIn
|
||||||
|
val days = TimeUnit.MILLISECONDS
|
||||||
|
.toDays(time)
|
||||||
|
time -= TimeUnit.DAYS.toMillis(days)
|
||||||
|
val hours = TimeUnit.MILLISECONDS
|
||||||
|
.toHours(time)
|
||||||
|
time -= TimeUnit.HOURS.toMillis(hours)
|
||||||
|
val minutes = TimeUnit.MILLISECONDS
|
||||||
|
.toMinutes(time)
|
||||||
|
time -= TimeUnit.MINUTES.toMillis(minutes)
|
||||||
|
val seconds = TimeUnit.MILLISECONDS
|
||||||
|
.toSeconds(time)
|
||||||
|
var s = ""
|
||||||
|
if (days >= 1) {
|
||||||
|
s += days.toString() + "d "
|
||||||
|
}
|
||||||
|
if (hours >= 1) {
|
||||||
|
s += hours.toString() + "h "
|
||||||
|
}
|
||||||
|
if (minutes >= 1) {
|
||||||
|
s += minutes.toString() + "m "
|
||||||
|
}
|
||||||
|
if (seconds >= 1 && hours < 1) {
|
||||||
|
s += seconds.toString() + "s"
|
||||||
|
}
|
||||||
|
if (s.isEmpty() || s.isBlank()) {
|
||||||
|
s = "0s"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTimeFormatedRaw(timeIn: Long): String {
|
||||||
|
var time = timeIn
|
||||||
|
val days = TimeUnit.MILLISECONDS
|
||||||
|
.toDays(time)
|
||||||
|
time -= TimeUnit.DAYS.toMillis(days)
|
||||||
|
val hours = TimeUnit.MILLISECONDS
|
||||||
|
.toHours(time)
|
||||||
|
time -= TimeUnit.HOURS.toMillis(hours)
|
||||||
|
val minutes = TimeUnit.MILLISECONDS
|
||||||
|
.toMinutes(time)
|
||||||
|
time -= TimeUnit.MINUTES.toMillis(minutes)
|
||||||
|
val seconds = TimeUnit.MILLISECONDS
|
||||||
|
.toSeconds(time)
|
||||||
|
var s = ""
|
||||||
|
if (days >= 1) {
|
||||||
|
s += days.toString() + "d "
|
||||||
|
}
|
||||||
|
if (hours >= 1) {
|
||||||
|
s += hours.toString() + "h "
|
||||||
|
}
|
||||||
|
if (minutes >= 1) {
|
||||||
|
s += minutes.toString() + "m "
|
||||||
|
}
|
||||||
|
if (seconds >= 1) {
|
||||||
|
s += seconds.toString() + "s"
|
||||||
|
}
|
||||||
|
if (s.isEmpty() || s.isBlank()) {
|
||||||
|
s = "0s"
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
26
src/main/kotlin/net/moonleay/botendo/util/UrlUtil.kt
Normal file
26
src/main/kotlin/net/moonleay/botendo/util/UrlUtil.kt
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
|
||||||
|
object UrlUtil {
|
||||||
|
///Strip the video ID from a YouTube link
|
||||||
|
fun getYtThumbnailUrl(uri: String): String {
|
||||||
|
return uri.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
|
||||||
|
}
|
||||||
|
}
|
27
src/main/kotlin/net/moonleay/botendo/util/UserUtil.kt
Normal file
27
src/main/kotlin/net/moonleay/botendo/util/UserUtil.kt
Normal 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}}"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#
|
#
|
||||||
# Botendo
|
# Botendo
|
||||||
# Copyright (C) 2023 limited_dev
|
# Copyright (C) 2023 moonleay
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -15,4 +15,3 @@
|
||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
# along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
#
|
|
||||||
|
|
|
@ -1,28 +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.build
|
|
||||||
|
|
||||||
internal object BuildConstants {
|
|
||||||
const val version = "${version}"
|
|
||||||
const val ownerID = "${ownerID}"
|
|
||||||
const val kordVersion = "${kordversion}"
|
|
||||||
const val lavaVersion = "${lavaversion}"
|
|
||||||
const val coroutinesVersion = "${coroutinesversion}"
|
|
||||||
}
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
* 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.build
|
||||||
|
|
||||||
|
internal object BuildConstants {
|
||||||
|
const val version = "${version}"
|
||||||
|
const val ownerID = "${ownerID}"
|
||||||
|
const val kordVersion = "${kordversion}"
|
||||||
|
const val lavaVersion = "${lavaversion}"
|
||||||
|
const val coroutinesVersion = "${coroutinesversion}"
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue