Made LogalBot open source.
This commit is contained in:
163
.gitignore
vendored
Normal file
163
.gitignore
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
# Created by https://www.gitignore.io/api/git,java,redis,linux,gradle,eclipse,visualstudiocode
|
||||
# Edit at https://www.gitignore.io/?templates=git,java,redis,linux,gradle,eclipse,visualstudiocode
|
||||
|
||||
### Eclipse ###
|
||||
.metadata
|
||||
bin/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.settings/
|
||||
.loadpath
|
||||
.recommenders
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# PyDev specific (Python IDE for Eclipse)
|
||||
*.pydevproject
|
||||
|
||||
# CDT-specific (C/C++ Development Tooling)
|
||||
.cproject
|
||||
|
||||
# CDT- autotools
|
||||
.autotools
|
||||
|
||||
# Java annotation processor (APT)
|
||||
.factorypath
|
||||
|
||||
# PDT-specific (PHP Development Tools)
|
||||
.buildpath
|
||||
|
||||
# sbteclipse plugin
|
||||
.target
|
||||
|
||||
# Tern plugin
|
||||
.tern-project
|
||||
|
||||
# TeXlipse plugin
|
||||
.texlipse
|
||||
|
||||
# STS (Spring Tool Suite)
|
||||
.springBeans
|
||||
|
||||
# Code Recommenders
|
||||
.recommenders/
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated/
|
||||
|
||||
# Scala IDE specific (Scala & Java development for Eclipse)
|
||||
.cache-main
|
||||
.scala_dependencies
|
||||
.worksheet
|
||||
|
||||
### Eclipse Patch ###
|
||||
# Eclipse Core
|
||||
.project
|
||||
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Annotation Processing
|
||||
.apt_generated
|
||||
|
||||
.sts4-cache/
|
||||
|
||||
### Git ###
|
||||
# Created by git for backups. To disable backups in Git:
|
||||
# $ git config --global mergetool.keepBackup false
|
||||
*.orig
|
||||
|
||||
# Created by git when using merge tools for conflicts
|
||||
*.BACKUP.*
|
||||
*.BASE.*
|
||||
*.LOCAL.*
|
||||
*.REMOTE.*
|
||||
*_BACKUP_*.txt
|
||||
*_BASE_*.txt
|
||||
*_LOCAL_*.txt
|
||||
*_REMOTE_*.txt
|
||||
|
||||
### Java ###
|
||||
# Compiled class file
|
||||
*.class
|
||||
|
||||
# Log file
|
||||
*.log
|
||||
|
||||
# BlueJ files
|
||||
*.ctxt
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.nar
|
||||
*.ear
|
||||
*.zip
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
### Linux ###
|
||||
*~
|
||||
|
||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
||||
.fuse_hidden*
|
||||
|
||||
# KDE directory preferences
|
||||
.directory
|
||||
|
||||
# Linux trash folder which might appear on any partition or disk
|
||||
.Trash-*
|
||||
|
||||
# .nfs files are created when an open file is removed but is still being accessed
|
||||
.nfs*
|
||||
|
||||
### Redis ###
|
||||
# Ignore redis binary dump (dump.rdb) files
|
||||
|
||||
*.rdb
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
|
||||
### Gradle ###
|
||||
.gradle
|
||||
build/
|
||||
|
||||
# Ignore Gradle GUI config
|
||||
gradle-app.setting
|
||||
|
||||
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
|
||||
!gradle-wrapper.jar
|
||||
|
||||
# Cache of project
|
||||
.gradletasknamecache
|
||||
|
||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
### Gradle Patch ###
|
||||
**/build/
|
||||
|
||||
# End of https://www.gitignore.io/api/git,java,redis,linux,gradle,eclipse,visualstudiocode
|
||||
15
.vscode/launch.json
vendored
Normal file
15
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"type": "java",
|
||||
"name": "Default",
|
||||
"request": "launch",
|
||||
"mainClass": "dev.logal.logalbot.Main",
|
||||
"projectName": "LogalBot",
|
||||
"env": {
|
||||
"TOKEN": "an_invalid_placeholder_token",
|
||||
"REDIS_HOST": "localhost"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
176
LICENSE.txt
Normal file
176
LICENSE.txt
Normal file
@@ -0,0 +1,176 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
31
build.gradle
Normal file
31
build.gradle
Normal file
@@ -0,0 +1,31 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.4'
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.slf4j:slf4j-simple:1.7.26'
|
||||
|
||||
implementation 'net.dv8tion:JDA:3.8.3_463'
|
||||
implementation 'com.sedmelluq:lavaplayer:1.3.17'
|
||||
implementation 'redis.clients:jedis:3.0.1'
|
||||
implementation 'com.vdurmont:emoji-java:4.0.0'
|
||||
}
|
||||
|
||||
jar {
|
||||
manifest {
|
||||
attributes 'Main-Class': 'dev.logal.logalbot.Main'
|
||||
}
|
||||
}
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-bin.zip
|
||||
172
gradlew
vendored
Executable file
172
gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
gradlew.bat
vendored
Normal file
84
gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
1
settings.gradle
Normal file
1
settings.gradle
Normal file
@@ -0,0 +1 @@
|
||||
rootProject.name = 'LogalBot'
|
||||
141
src/main/java/dev/logal/logalbot/Main.java
Normal file
141
src/main/java/dev/logal/logalbot/Main.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package dev.logal.logalbot;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.commands.administration.*;
|
||||
import dev.logal.logalbot.commands.audio.*;
|
||||
import dev.logal.logalbot.commands.fun.*;
|
||||
import dev.logal.logalbot.commands.general.*;
|
||||
import dev.logal.logalbot.events.*;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.CommandManager;
|
||||
import dev.logal.logalbot.utils.DataManager;
|
||||
import net.dv8tion.jda.core.AccountType;
|
||||
import net.dv8tion.jda.core.JDA;
|
||||
import net.dv8tion.jda.core.JDABuilder;
|
||||
|
||||
public final class Main {
|
||||
private static final Logger logger = LoggerFactory.getLogger(Main.class);
|
||||
|
||||
private static final String token = System.getenv("TOKEN");
|
||||
private static JDA jda;
|
||||
|
||||
private Main() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void main(final String[] arguments) {
|
||||
logger.info("Beginning setup of LogalBot...");
|
||||
|
||||
logger.info("Verifying connection to Redis...");
|
||||
try {
|
||||
DataManager.verifyConnection();
|
||||
} catch (final Throwable exception) {
|
||||
logger.error("An error occurred while attempting to verify the connection to Redis!", exception);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
logger.info("Running any needed schema migrations...");
|
||||
try {
|
||||
DataManager.runMigrations();
|
||||
} catch (final Throwable exception) {
|
||||
logger.error("An error occurred while attempting to migrate the database!", exception);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
logger.info("Attempting to log into Discord...");
|
||||
try {
|
||||
final JDABuilder builder = new JDABuilder(AccountType.BOT);
|
||||
builder.setAutoReconnect(true);
|
||||
builder.setAudioEnabled(true);
|
||||
builder.setToken(token);
|
||||
builder.addEventListener(new GuildReady());
|
||||
jda = builder.build().awaitReady();
|
||||
} catch (final LoginException exception) {
|
||||
logger.error("The token specified is not valid.");
|
||||
System.exit(1);
|
||||
} catch (final Throwable exception) {
|
||||
logger.error("An error occurred while attempting to set up JDA!", exception);
|
||||
System.exit(1);
|
||||
}
|
||||
logger.info("Successfully logged into Discord as bot user '" + jda.getSelfUser().getName() + "'.");
|
||||
|
||||
logger.info("Initializing...");
|
||||
AudioUtil.initializePlayerManager();
|
||||
|
||||
jda.addEventListener(new GuildVoiceLeave());
|
||||
jda.addEventListener(new GuildVoiceMove());
|
||||
jda.addEventListener(new GuildMessageReactionAdd());
|
||||
|
||||
// General Commands
|
||||
CommandManager.registerCommand("about", new About(), false);
|
||||
CommandManager.registerCommand("help", new Help(), false);
|
||||
|
||||
// Fun Commands
|
||||
CommandManager.registerCommand("8ball", new EightBall(), false);
|
||||
|
||||
// Audio Commands
|
||||
CommandManager.registerCommand("forceskip", new ForceSkip(), true);
|
||||
CommandManager.registerCommandAlias("fs", "forceskip");
|
||||
CommandManager.registerCommandAlias("fskip", "forceskip");
|
||||
CommandManager.registerCommand("lock", new Lock(), true);
|
||||
CommandManager.registerCommandAlias("l", "lock");
|
||||
CommandManager.registerCommand("nowplaying", new NowPlaying(), false);
|
||||
CommandManager.registerCommandAlias("np", "nowplaying");
|
||||
CommandManager.registerCommand("pause", new Pause(), true);
|
||||
CommandManager.registerCommand("play", new Play(), false);
|
||||
CommandManager.registerCommandAlias("p", "play");
|
||||
CommandManager.registerCommandAlias("pl", "play");
|
||||
CommandManager.registerCommandAlias("add", "play");
|
||||
CommandManager.registerCommandAlias("a", "play");
|
||||
CommandManager.registerCommand("queue", new Queue(), false);
|
||||
CommandManager.registerCommandAlias("q", "queue");
|
||||
CommandManager.registerCommand("remove", new Remove(), true);
|
||||
CommandManager.registerCommandAlias("r", "remove");
|
||||
CommandManager.registerCommandAlias("x", "remove");
|
||||
CommandManager.registerCommandAlias("rem", "remove");
|
||||
CommandManager.registerCommandAlias("rm", "remove");
|
||||
CommandManager.registerCommand("reset", new Reset(), true);
|
||||
CommandManager.registerCommandAlias("rst", "reset");
|
||||
CommandManager.registerCommand("skip", new Skip(), false);
|
||||
CommandManager.registerCommandAlias("s", "skip");
|
||||
CommandManager.registerCommand("volume", new Volume(), true);
|
||||
CommandManager.registerCommandAlias("v", "volume");
|
||||
CommandManager.registerCommandAlias("vol", "volume");
|
||||
CommandManager.registerCommand("shuffle", new Shuffle(), true);
|
||||
CommandManager.registerCommandAlias("shuf", "shuffle");
|
||||
CommandManager.registerCommandAlias("shuff", "shuffle");
|
||||
CommandManager.registerCommandAlias("shfl", "shuffle");
|
||||
|
||||
// Administration Commands
|
||||
CommandManager.registerCommand("whitelist", new Whitelist(), true);
|
||||
CommandManager.registerCommandAlias("wl", "whitelist");
|
||||
CommandManager.registerCommand("settings", new Settings(), true);
|
||||
CommandManager.registerCommandAlias("set", "settings");
|
||||
CommandManager.registerCommandAlias("setting", "settings");
|
||||
CommandManager.registerCommandAlias("configure", "settings");
|
||||
CommandManager.registerCommandAlias("config", "settings");
|
||||
CommandManager.registerCommandAlias("conf", "settings");
|
||||
|
||||
logger.info("Everything seems to be ready! Enabling command listener...");
|
||||
jda.addEventListener(new GuildMessageReceived());
|
||||
logger.info("Initialization complete!");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.logal.logalbot.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
|
||||
|
||||
import net.dv8tion.jda.core.audio.AudioSendHandler;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class AudioPlayerSendHandler implements AudioSendHandler {
|
||||
private final AudioPlayer audioPlayer;
|
||||
private AudioFrame lastFrame;
|
||||
|
||||
public AudioPlayerSendHandler(final AudioPlayer audioPlayer) {
|
||||
Checks.notNull(audioPlayer, "Audio Player");
|
||||
|
||||
this.audioPlayer = audioPlayer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean canProvide() {
|
||||
lastFrame = audioPlayer.provide();
|
||||
return lastFrame != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final byte[] provide20MsAudio() {
|
||||
return lastFrame.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isOpus() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
201
src/main/java/dev/logal/logalbot/audio/TrackLoadHandler.java
Normal file
201
src/main/java/dev/logal/logalbot/audio/TrackLoadHandler.java
Normal file
@@ -0,0 +1,201 @@
|
||||
package dev.logal.logalbot.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.PermissionManager;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class TrackLoadHandler implements AudioLoadResultHandler {
|
||||
private final Logger logger = LoggerFactory.getLogger(TrackLoadHandler.class);
|
||||
|
||||
private final Member requester;
|
||||
private final TextChannel channel;
|
||||
|
||||
public TrackLoadHandler(final Member requester, final TextChannel channel) {
|
||||
Checks.notNull(requester, "Requester");
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
this.requester = requester;
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void trackLoaded(final AudioTrack track) {
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
final CommandResponse response;
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(this.channel.getGuild());
|
||||
|
||||
final AudioTrackInfo info = track.getInfo();
|
||||
if (info.isStream) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but streams cannot be added to the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((info.length >= 60000 && info.length <= 900000) || PermissionManager.isWhitelisted(this.requester)) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but you can only add tracks between 1 and 15 minutes in length.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (scheduler.isQueued(track)) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but that track is already queued.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler.addToQueue(track, requester);
|
||||
response = new CommandResponse("notes",
|
||||
this.requester.getAsMention() + " added the following track to the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(track));
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void playlistLoaded(final AudioPlaylist playlist) {
|
||||
Checks.notNull(playlist, "Playlist");
|
||||
|
||||
CommandResponse response;
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(this.channel.getGuild());
|
||||
|
||||
final AudioTrack selectedTrack = playlist.getSelectedTrack();
|
||||
AudioTrack track = null;
|
||||
if (!playlist.isSearchResult() && selectedTrack != null) {
|
||||
track = selectedTrack;
|
||||
} else if (playlist.isSearchResult()) {
|
||||
track = playlist.getTracks().get(0);
|
||||
}
|
||||
|
||||
if (track != null) {
|
||||
if (scheduler.isQueued(track)) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but that track is already queued.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
final AudioTrackInfo info = track.getInfo();
|
||||
if (info.isStream) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention() + ", but streams cannot be added to the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((info.length >= 60000 && info.length <= 900000) || PermissionManager.isWhitelisted(this.requester)) {
|
||||
scheduler.addToQueue(track, this.requester);
|
||||
response = new CommandResponse("notes",
|
||||
this.requester.getAsMention() + " added the following track to the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(track));
|
||||
response.sendResponse(this.channel);
|
||||
} else {
|
||||
response = new CommandResponse("no_entry_sign", "Sorry " + this.requester.getAsMention()
|
||||
+ ", but you are not allowed to add tracks less than 1 minute or greater than 15 minutes in length.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
} else {
|
||||
if (PermissionManager.isWhitelisted(this.requester)) {
|
||||
final ArrayList<AudioTrack> addedTracks = new ArrayList<>();
|
||||
for (final AudioTrack playlistTrack : playlist.getTracks()) {
|
||||
if (!scheduler.isQueueFull()) {
|
||||
if (!scheduler.isQueued(playlistTrack) && !playlistTrack.getInfo().isStream) {
|
||||
scheduler.addToQueue(playlistTrack, this.requester);
|
||||
addedTracks.add(playlistTrack);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (addedTracks.size() == 0) {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but none of the tracks in that playlist could be added.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
|
||||
response = new CommandResponse("notes",
|
||||
this.requester.getAsMention() + " added the following tracks to the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackListInfoEmbed(addedTracks, false));
|
||||
response.sendResponse(this.channel);
|
||||
} else {
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but you are not allowed to add playlists to the queue.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void noMatches() {
|
||||
final CommandResponse response = new CommandResponse("map",
|
||||
"Sorry " + this.requester.getAsMention() + ", but I was not able to find that track.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void loadFailed(final FriendlyException exception) {
|
||||
Checks.notNull(exception, "Exception");
|
||||
|
||||
final CommandResponse response;
|
||||
if (exception.getMessage().equals("Unknown file format.")) {
|
||||
response = new CommandResponse("question",
|
||||
"Sorry " + this.requester.getAsMention() + ", but I do not recognize the format of that track.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
} else {
|
||||
final Guild guild = this.channel.getGuild();
|
||||
logger.error("An error occurred for " + guild.getName() + " (" + guild.getId()
|
||||
+ ") while trying to load a track!", exception);
|
||||
response = new CommandResponse("sos",
|
||||
"Sorry " + this.requester.getAsMention()
|
||||
+ ", but an error occurred while trying to get that track!").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
response.sendResponse(this.channel);
|
||||
}
|
||||
}
|
||||
176
src/main/java/dev/logal/logalbot/audio/TrackScheduler.java
Normal file
176
src/main/java/dev/logal/logalbot/audio/TrackScheduler.java
Normal file
@@ -0,0 +1,176 @@
|
||||
package dev.logal.logalbot.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.tasks.IdleDisconnectTask;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.DataManager;
|
||||
import dev.logal.logalbot.utils.PermissionManager;
|
||||
import dev.logal.logalbot.utils.Scheduler;
|
||||
import dev.logal.logalbot.utils.SkipTracker;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class TrackScheduler extends AudioEventAdapter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(TrackScheduler.class);
|
||||
|
||||
private final Guild guild;
|
||||
private final ArrayList<AudioTrack> queue = new ArrayList<>(250);
|
||||
private boolean queueLocked = false;
|
||||
private ScheduledFuture<?> idleLogoutTask;
|
||||
|
||||
public TrackScheduler(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
public final void addToQueue(final AudioTrack track, final Member requester) {
|
||||
Checks.notNull(track, "Track");
|
||||
Checks.notNull(requester, "Requester");
|
||||
|
||||
if (this.queueLocked && !PermissionManager.isWhitelisted(requester)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isQueueFull()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final User user = requester.getUser();
|
||||
logger.info(user.getName() + " (" + user.getId() + ") added '" + track.getInfo().title + "' to the queue in "
|
||||
+ this.guild.getName() + " (" + this.guild.getId() + ").");
|
||||
this.queue.add(track);
|
||||
if (!AudioUtil.isTrackLoaded(this.guild)) {
|
||||
AudioUtil.openAudioConnection(VoiceChannelUtil.getVoiceChannelMemberIsConnectedTo(requester));
|
||||
AudioUtil.playTrack(this.guild, this.queue.remove(0));
|
||||
}
|
||||
}
|
||||
|
||||
public final void removeFromQueue(final int index) {
|
||||
Checks.notNull(index, "Index");
|
||||
|
||||
logger.info("Track '" + queue.remove(index).getInfo().title + "' has been removed from the queue in "
|
||||
+ this.guild.getName() + " (" + this.guild.getId() + ").");
|
||||
}
|
||||
|
||||
public final boolean isQueued(final AudioTrack track) {
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
for (final AudioTrack queuedTrack : queue) {
|
||||
if (track.getInfo().identifier.equals(queuedTrack.getInfo().identifier)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final boolean isQueueFull() {
|
||||
return this.queue.size() >= 250;
|
||||
}
|
||||
|
||||
public final boolean isQueueEmpty() {
|
||||
return this.queue.isEmpty();
|
||||
}
|
||||
|
||||
public final boolean isQueueLocked() {
|
||||
return this.queueLocked;
|
||||
}
|
||||
|
||||
public final void setQueueLocked(final boolean locked) {
|
||||
Checks.notNull(locked, "Locked");
|
||||
|
||||
this.queueLocked = locked;
|
||||
}
|
||||
|
||||
public final void clearQueue() {
|
||||
this.queue.clear();
|
||||
}
|
||||
|
||||
public final void shuffleQueue() {
|
||||
Collections.shuffle(this.queue);
|
||||
}
|
||||
|
||||
public final ArrayList<AudioTrack> getQueue() {
|
||||
return this.queue;
|
||||
}
|
||||
|
||||
public final void skipCurrentTrack() {
|
||||
if (AudioUtil.isTrackLoaded(this.guild)) {
|
||||
logger.info("Track '" + AudioUtil.getLoadedTrack(this.guild).getInfo().title + "' in "
|
||||
+ this.guild.getName() + " (" + this.guild.getId() + ") been skipped.");
|
||||
AudioUtil.stopTrack(this.guild);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onTrackStart(final AudioPlayer player, final AudioTrack track) {
|
||||
Checks.notNull(player, "Player");
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
logger.info("Track '" + track.getInfo().title + "' in " + this.guild.getName() + " (" + this.guild.getId()
|
||||
+ ") has started.");
|
||||
if (this.idleLogoutTask != null && !this.idleLogoutTask.isDone()) {
|
||||
logger.info("A track has started in " + this.guild.getName() + " (" + this.guild.getId()
|
||||
+ "). Cancelling scheduled disconnect.");
|
||||
this.idleLogoutTask.cancel(true);
|
||||
}
|
||||
SkipTracker.resetVotes(this.guild);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onTrackEnd(final AudioPlayer player, final AudioTrack track,
|
||||
final AudioTrackEndReason endReason) {
|
||||
Checks.notNull(player, "Player");
|
||||
Checks.notNull(track, "Track");
|
||||
Checks.notNull(endReason, "End reason");
|
||||
|
||||
logger.info("Track '" + track.getInfo().title + "' in " + this.guild.getName() + " (" + this.guild.getId()
|
||||
+ ") has stopped.");
|
||||
if ((endReason.mayStartNext || endReason == AudioTrackEndReason.STOPPED) && this.queue.size() >= 1) {
|
||||
AudioUtil.playTrack(this.guild, this.queue.remove(0));
|
||||
} else {
|
||||
try {
|
||||
AudioUtil.setVolume(this.guild, Integer.parseInt(DataManager.getGuildValue(guild, "defaultVolume")));
|
||||
} catch (final NumberFormatException exception) {
|
||||
AudioUtil.setVolume(this.guild, 10);
|
||||
}
|
||||
this.queueLocked = false;
|
||||
AudioUtil.setPausedState(this.guild, false);
|
||||
final VoiceChannel currentChannel = AudioUtil.getVoiceChannelConnectedTo(this.guild);
|
||||
logger.info("Disconnecting from " + currentChannel.getName() + " (" + currentChannel.getId() + ") in "
|
||||
+ this.guild.getName() + " (" + this.guild.getId() + ") in 1 minute...");
|
||||
this.idleLogoutTask = Scheduler.schedule(new IdleDisconnectTask(this.guild), 1, TimeUnit.MINUTES);
|
||||
}
|
||||
SkipTracker.resetVotes(this.guild);
|
||||
}
|
||||
}
|
||||
22
src/main/java/dev/logal/logalbot/commands/Command.java
Normal file
22
src/main/java/dev/logal/logalbot/commands/Command.java
Normal file
@@ -0,0 +1,22 @@
|
||||
package dev.logal.logalbot.commands;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public interface Command {
|
||||
CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel);
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package dev.logal.logalbot.commands;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.vdurmont.emoji.Emoji;
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.tasks.MessageDeleteTask;
|
||||
import dev.logal.logalbot.utils.ReactionCallbackManager;
|
||||
import dev.logal.logalbot.utils.Scheduler;
|
||||
import net.dv8tion.jda.core.MessageBuilder;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
|
||||
public final class CommandResponse {
|
||||
private final Emoji emoji;
|
||||
private final String response;
|
||||
private final LinkedHashMap<Emoji, ReactionCallback> callbacks = new LinkedHashMap<>();
|
||||
private MessageEmbed responseEmbed;
|
||||
private User callbacksTarget;
|
||||
|
||||
private long deletionDelay = 0;
|
||||
private TimeUnit deletionDelayUnit;
|
||||
|
||||
public CommandResponse(final String emoji, final String response) {
|
||||
this.emoji = EmojiManager.getForAlias(emoji);
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
public final CommandResponse attachEmbed(final MessageEmbed embed) {
|
||||
this.responseEmbed = embed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final CommandResponse setDeletionDelay(final long delay, final TimeUnit unit) {
|
||||
this.deletionDelay = delay;
|
||||
this.deletionDelayUnit = unit;
|
||||
return this;
|
||||
}
|
||||
|
||||
public final CommandResponse addReactionCallback(final Emoji emoji, final ReactionCallback callback) {
|
||||
this.callbacks.put(emoji, callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public final CommandResponse setReactionCallbackTarget(final Member member) {
|
||||
this.callbacksTarget = member.getUser();
|
||||
return this;
|
||||
}
|
||||
|
||||
public final void sendResponse(final TextChannel channel) {
|
||||
final MessageBuilder builder = new MessageBuilder();
|
||||
builder.setContent(this.emoji.getUnicode() + " " + this.response);
|
||||
|
||||
if (this.responseEmbed != null) {
|
||||
builder.setEmbed(this.responseEmbed);
|
||||
}
|
||||
|
||||
channel.sendMessage(builder.build()).queue(this::handleResponseCreation);
|
||||
}
|
||||
|
||||
private final void handleResponseCreation(final Message message) {
|
||||
if ((this.deletionDelay != 0) && (this.deletionDelayUnit != null)) {
|
||||
Scheduler.schedule(new MessageDeleteTask(message), this.deletionDelay, this.deletionDelayUnit);
|
||||
}
|
||||
|
||||
for (final Map.Entry<Emoji, ReactionCallback> callback : callbacks.entrySet()) {
|
||||
ReactionCallbackManager.registerCallback(message, callback.getKey(), callback.getValue());
|
||||
ReactionCallbackManager.setCallbackTarget(this.callbacksTarget, message);
|
||||
message.addReaction(callback.getKey().getUnicode()).queue();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.logal.logalbot.commands;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
|
||||
public interface ReactionCallback {
|
||||
void run(final Member reactor, final long messageID);
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package dev.logal.logalbot.commands.administration;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.DataManager;
|
||||
import dev.logal.logalbot.utils.StringUtil;
|
||||
import net.dv8tion.jda.core.EmbedBuilder;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Settings implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = executor.getGuild();
|
||||
|
||||
if (arguments.length == 0) {
|
||||
final CommandResponse response = new CommandResponse("tools",
|
||||
executor.getAsMention() + ", these are the current settings for this guild:");
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle("**Current Settings for " + StringUtil.sanitize(guild.getName()) + "**");
|
||||
|
||||
final String commandCharacter = DataManager.getGuildValue(guild, "commandCharacter");
|
||||
if (commandCharacter == null) {
|
||||
builder.addField("Command Character", "Not Set", true);
|
||||
} else {
|
||||
builder.addField("Command Character", commandCharacter, true);
|
||||
}
|
||||
|
||||
final String defaultVolume = DataManager.getGuildValue(guild, "defaultVolume");
|
||||
if (defaultVolume == null) {
|
||||
builder.addField("Default Volume", "10%", true);
|
||||
} else {
|
||||
builder.addField("Default Volume", defaultVolume + "%", true);
|
||||
}
|
||||
response.attachEmbed(builder.build());
|
||||
return response;
|
||||
}
|
||||
|
||||
if (arguments[0].equalsIgnoreCase("commandcharacter") || arguments[0].equalsIgnoreCase("cmdchar")) {
|
||||
if (arguments.length == 1) {
|
||||
DataManager.deleteGuildKey(guild, "commandCharacter");
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the command character has been disabled.");
|
||||
} else {
|
||||
final char[] input = arguments[1].replaceAll("\n", "").toCharArray();
|
||||
if (input.length > 1) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but the command character must be a single character.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
} else if (input.length == 0) {
|
||||
DataManager.deleteGuildKey(guild, "commandCharacter");
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the command character has been disabled.");
|
||||
} else {
|
||||
DataManager.setGuildValue(guild, "commandCharacter", "" + input[0]);
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the command character has been set to `" + input[0] + "`.");
|
||||
}
|
||||
}
|
||||
} else if (arguments[0].equalsIgnoreCase("defaultvolume") || arguments[0].equalsIgnoreCase("volume")) {
|
||||
if (arguments.length == 1) {
|
||||
DataManager.deleteGuildKey(guild, "defaultVolume");
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.setVolume(guild, 10);
|
||||
}
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the default volume has been reset to `10%`.");
|
||||
} else {
|
||||
final int volume;
|
||||
try {
|
||||
volume = Integer.parseInt(arguments[1]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the default volume must be an integer.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (volume == 10) {
|
||||
DataManager.deleteGuildKey(guild, "defaultVolume");
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the default volume has been reset to `10%`.");
|
||||
}
|
||||
|
||||
if (volume <= 150 && volume >= 1) {
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.setVolume(guild, volume);
|
||||
}
|
||||
DataManager.setGuildValue(guild, "defaultVolume", "" + volume);
|
||||
return new CommandResponse("white_check_mark",
|
||||
executor.getAsMention() + ", the default volume has been set to `" + volume + "%`.");
|
||||
} else {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but the default volume must be between 1% and 150%.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but I do not know what that setting is.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package dev.logal.logalbot.commands.administration;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.PermissionManager;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Whitelist implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!executor.hasPermission(Permission.ADMINISTRATOR)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you are not allowed to use this command.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but you need to specify a user to add or remove from the whitelist.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final String userID = arguments[0].replaceFirst("<@[!]?([0-9]*)>", "$1");
|
||||
final Member member;
|
||||
try {
|
||||
member = guild.getMemberById(userID);
|
||||
} catch (final Throwable exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but that doesn't appear to be a valid user.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (member == null) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but that doesn't appear to be a valid user.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (member.hasPermission(Permission.ADMINISTRATOR)) {
|
||||
return new CommandResponse("no_entry_sign", "Sorry " + executor.getAsMention()
|
||||
+ ", but you cannot remove that user from the whitelist due to them being a guild administrator.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (member.getUser().isBot()) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you cannot whitelist bots.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (PermissionManager.isWhitelisted(member)) {
|
||||
PermissionManager.removeFromWhitelist(member);
|
||||
return new CommandResponse("heavy_multiplication_x",
|
||||
executor.getAsMention() + " has removed " + member.getAsMention() + " from the whitelist.");
|
||||
} else {
|
||||
PermissionManager.addToWhitelist(member);
|
||||
return new CommandResponse("heavy_check_mark",
|
||||
executor.getAsMention() + " has added " + member.getAsMention() + " to the whitelist.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class ForceSkip implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to force skip it.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to force skip tracks.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final AudioTrack skippedTrack = AudioUtil.getLoadedTrack(guild);
|
||||
|
||||
AudioUtil.getTrackScheduler(guild).skipCurrentTrack();
|
||||
final CommandResponse response = new CommandResponse("gun",
|
||||
executor.getAsMention() + " force skipped the following track:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(skippedTrack));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
55
src/main/java/dev/logal/logalbot/commands/audio/Lock.java
Normal file
55
src/main/java/dev/logal/logalbot/commands/audio/Lock.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Lock implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to lock or unlock the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to lock or unlock the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
|
||||
if (scheduler.isQueueLocked()) {
|
||||
scheduler.setQueueLocked(false);
|
||||
return new CommandResponse("unlock", executor.getAsMention() + " unlocked the queue.");
|
||||
} else {
|
||||
scheduler.setQueueLocked(true);
|
||||
return new CommandResponse("lock", executor.getAsMention() + " locked the queue.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class NowPlaying implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("mute", executor.getAsMention() + ", there is nothing currently playing.");
|
||||
}
|
||||
|
||||
final CommandResponse response = new CommandResponse("dancer",
|
||||
executor.getAsMention() + ", this is the track currently playing:");
|
||||
response.attachEmbed(TrackUtil.generateCurrentTrackInfoEmbed(guild));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
53
src/main/java/dev/logal/logalbot/commands/audio/Pause.java
Normal file
53
src/main/java/dev/logal/logalbot/commands/audio/Pause.java
Normal file
@@ -0,0 +1,53 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Pause implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to pause or resume the track player.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to pause or resume the track player.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (AudioUtil.isPlayerPaused(guild)) {
|
||||
AudioUtil.setPausedState(guild, false);
|
||||
return new CommandResponse("arrow_forward", executor.getAsMention() + " resumed the track player.");
|
||||
} else {
|
||||
AudioUtil.setPausedState(guild, true);
|
||||
return new CommandResponse("pause_button", executor.getAsMention() + " paused the track player.");
|
||||
}
|
||||
}
|
||||
}
|
||||
100
src/main/java/dev/logal/logalbot/commands/audio/Play.java
Normal file
100
src/main/java/dev/logal/logalbot/commands/audio/Play.java
Normal file
@@ -0,0 +1,100 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.PermissionManager;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
|
||||
public final class Play implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to add songs to the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final VoiceChannel targetChannel = VoiceChannelUtil.getVoiceChannelMemberIsConnectedTo(executor);
|
||||
if (targetChannel == null) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but you need to be in a voice channel in order to add songs to the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final Member selfMember = guild.getSelfMember();
|
||||
if (!selfMember.hasPermission(targetChannel, Permission.VOICE_CONNECT)
|
||||
|| !selfMember.hasPermission(targetChannel, Permission.VOICE_SPEAK)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but I do not have the required permissions to use your current voice channel.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but you need to provide a search query or a link to a specific track or playlist.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
|
||||
if (scheduler.isQueueLocked() && !PermissionManager.isWhitelisted(executor)) {
|
||||
return new CommandResponse("lock", "Sorry " + executor.getAsMention() + ", but the queue is locked.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (scheduler.isQueueFull()) {
|
||||
return new CommandResponse("card_box", "Sorry " + executor.getAsMention() + ", but the queue is full.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
boolean isLink;
|
||||
try {
|
||||
new URL(arguments[0]);
|
||||
isLink = true;
|
||||
} catch (final MalformedURLException exception) {
|
||||
isLink = false;
|
||||
}
|
||||
|
||||
final StringBuilder query;
|
||||
if (isLink) {
|
||||
query = new StringBuilder(arguments[0]);
|
||||
} else {
|
||||
query = new StringBuilder("ytsearch:");
|
||||
for (final String part : arguments) {
|
||||
query.append(part).append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
AudioUtil.findTrack(query.toString(), executor, channel);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
55
src/main/java/dev/logal/logalbot/commands/audio/Queue.java
Normal file
55
src/main/java/dev/logal/logalbot/commands/audio/Queue.java
Normal file
@@ -0,0 +1,55 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Queue implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.getTrackScheduler(guild).isQueueEmpty()) {
|
||||
return new CommandResponse("information_source", executor.getAsMention() + ", the queue is empty.");
|
||||
}
|
||||
|
||||
final CommandResponse response = new CommandResponse("bookmark_tabs",
|
||||
executor.getAsMention() + ", the following tracks are in the queue:");
|
||||
|
||||
final int page;
|
||||
if (arguments.length == 0) {
|
||||
page = 1;
|
||||
} else {
|
||||
try {
|
||||
page = Integer.parseInt(arguments[0]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the page number must be an integer.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
response.attachEmbed(
|
||||
TrackUtil.generatePaginatedTrackListInfoEmbed(AudioUtil.getTrackScheduler(guild).getQueue(), page));
|
||||
return response;
|
||||
}
|
||||
}
|
||||
114
src/main/java/dev/logal/logalbot/commands/audio/Remove.java
Normal file
114
src/main/java/dev/logal/logalbot/commands/audio/Remove.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.commands.ReactionCallback;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.CommandManager;
|
||||
import dev.logal.logalbot.utils.ReactionCallbackManager;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Remove implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(channel.getGuild());
|
||||
if (scheduler.isQueueEmpty()) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but there are no tracks in the queue.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to remove tracks from the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
if (!guild.getSelfMember().hasPermission(channel, Permission.MESSAGE_ADD_REACTION)) {
|
||||
return new CommandResponse("no_entry_sign", "Sorry " + executor.getAsMention()
|
||||
+ ", but I do not have the required permissions to create a reaction selection dialog in this text channel.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final CommandResponse response = new CommandResponse("question",
|
||||
executor.getAsMention() + ", which track would you like to remove from the top of the queue?");
|
||||
response.attachEmbed(TrackUtil.generateTrackListInfoEmbed(scheduler.getQueue(), true));
|
||||
|
||||
for (int i = 0; i < scheduler.getQueue().size(); i++) {
|
||||
final int trackNumber = i + 1;
|
||||
if (trackNumber == 11) {
|
||||
break;
|
||||
}
|
||||
|
||||
response.addReactionCallback(EmojiManager.getForAlias("" + trackNumber), new ReactionCallback() {
|
||||
@Override
|
||||
public final void run(final Member reactor, final long messageID) {
|
||||
ReactionCallbackManager.unregisterMessage(messageID);
|
||||
channel.getMessageById(messageID).queue(this::deleteMessage);
|
||||
CommandManager.executeCommand(("remove " + trackNumber).split(" "), reactor, channel);
|
||||
}
|
||||
|
||||
private void deleteMessage(final Message message) {
|
||||
message.delete().queue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
response.setReactionCallbackTarget(executor);
|
||||
response.setDeletionDelay(30, TimeUnit.SECONDS);
|
||||
return response;
|
||||
}
|
||||
|
||||
final int index;
|
||||
try {
|
||||
index = Integer.parseInt(arguments[0]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the index must be an integer.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
try {
|
||||
final AudioTrack removedTrack = scheduler.getQueue().get(index - 1);
|
||||
|
||||
scheduler.removeFromQueue(index - 1);
|
||||
final CommandResponse response = new CommandResponse("scissors",
|
||||
executor.getAsMention() + " removed the following track from the queue:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(removedTrack));
|
||||
return response;
|
||||
} catch (final IndexOutOfBoundsException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but that index is outside the bounds of the queue.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
46
src/main/java/dev/logal/logalbot/commands/audio/Reset.java
Normal file
46
src/main/java/dev/logal/logalbot/commands/audio/Reset.java
Normal file
@@ -0,0 +1,46 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Reset implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to reset the audio player.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
AudioUtil.getTrackScheduler(guild).clearQueue();
|
||||
if (AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.stopTrack(guild);
|
||||
}
|
||||
|
||||
return new CommandResponse("recycle",
|
||||
executor.getAsMention() + " has stopped the current track and reset the queue.");
|
||||
}
|
||||
}
|
||||
49
src/main/java/dev/logal/logalbot/commands/audio/Shuffle.java
Normal file
49
src/main/java/dev/logal/logalbot/commands/audio/Shuffle.java
Normal file
@@ -0,0 +1,49 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Shuffle implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
final TrackScheduler scheduler = AudioUtil.getTrackScheduler(guild);
|
||||
if (scheduler.isQueueEmpty()) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but there are no tracks in the queue.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (AudioUtil.isTrackLoaded(guild) && !VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you need to be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to shuffle the queue.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
scheduler.shuffleQueue();
|
||||
return new CommandResponse("salad", executor.getAsMention() + " shuffled the queue.");
|
||||
}
|
||||
}
|
||||
73
src/main/java/dev/logal/logalbot/commands/audio/Skip.java
Normal file
73
src/main/java/dev/logal/logalbot/commands/audio/Skip.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.SkipTracker;
|
||||
import dev.logal.logalbot.utils.TrackUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Skip implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to vote to skip it.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(channel.getGuild()).getName()
|
||||
+ "` in order to vote to skip the current track.").setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (SkipTracker.hasVoted(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"You have already voted to skip the current track " + executor.getAsMention() + ".")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
SkipTracker.registerVote(executor);
|
||||
if (SkipTracker.shouldSkip(guild)) {
|
||||
final AudioTrack skippedTrack = AudioUtil.getLoadedTrack(guild);
|
||||
AudioUtil.getTrackScheduler(guild).skipCurrentTrack();
|
||||
final CommandResponse response = new CommandResponse("gun",
|
||||
executor.getAsMention() + " was the last required vote. The following track has been skipped:");
|
||||
response.attachEmbed(TrackUtil.generateTrackInfoEmbed(skippedTrack));
|
||||
return response;
|
||||
} else {
|
||||
if (SkipTracker.getRemainingRequired(guild) == 1) {
|
||||
return new CommandResponse("x", executor.getAsMention() + " has voted to skip the current track. "
|
||||
+ SkipTracker.getRemainingRequired(guild) + " more vote is needed.");
|
||||
} else {
|
||||
return new CommandResponse("x", executor.getAsMention() + " has voted to skip the current track. "
|
||||
+ SkipTracker.getRemainingRequired(guild) + " more votes are needed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/main/java/dev/logal/logalbot/commands/audio/Volume.java
Normal file
81
src/main/java/dev/logal/logalbot/commands/audio/Volume.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package dev.logal.logalbot.commands.audio;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import dev.logal.logalbot.utils.VoiceChannelUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Volume implements Command {
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final Guild guild = channel.getGuild();
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention()
|
||||
+ ", but there must be a track playing in order to change the volume of the track player.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (!VoiceChannelUtil.isInCurrentVoiceChannel(executor)) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you must be in voice channel `"
|
||||
+ AudioUtil.getVoiceChannelConnectedTo(guild).getName()
|
||||
+ "` in order to change the volume of the track player.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (arguments.length == 0) {
|
||||
if (AudioUtil.getVolume(guild) >= 75) {
|
||||
return new CommandResponse("loud_sound", executor.getAsMention() + ", the volume is currently set to `"
|
||||
+ AudioUtil.getVolume(guild) + "%`.");
|
||||
} else {
|
||||
return new CommandResponse("sound", executor.getAsMention() + ", the volume is currently set to `"
|
||||
+ AudioUtil.getVolume(guild) + "%`.");
|
||||
}
|
||||
}
|
||||
|
||||
final int volume;
|
||||
try {
|
||||
volume = Integer.parseInt(arguments[0]);
|
||||
} catch (final NumberFormatException exception) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the volume must be an integer.").setDeletionDelay(10,
|
||||
TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
if (volume <= 150 && volume >= 1) {
|
||||
final int oldVolume = AudioUtil.getVolume(guild);
|
||||
AudioUtil.setVolume(guild, volume);
|
||||
if (volume >= 75) {
|
||||
return new CommandResponse("loud_sound",
|
||||
executor.getAsMention() + " set the volume from `" + oldVolume + "%` to `" + volume + "%`.");
|
||||
} else {
|
||||
return new CommandResponse("sound",
|
||||
executor.getAsMention() + " set the volume from `" + oldVolume + "%` to `" + volume + "%`.");
|
||||
}
|
||||
} else {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but the volume must be between 1% and 150%.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
73
src/main/java/dev/logal/logalbot/commands/fun/EightBall.java
Normal file
73
src/main/java/dev/logal/logalbot/commands/fun/EightBall.java
Normal file
@@ -0,0 +1,73 @@
|
||||
package dev.logal.logalbot.commands.fun;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import dev.logal.logalbot.utils.StringUtil;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class EightBall implements Command {
|
||||
private final ArrayList<String> responses = new ArrayList<>(20);
|
||||
private final Random rng = new Random();
|
||||
|
||||
public EightBall() {
|
||||
responses.add("It is certain");
|
||||
responses.add("It is decidedly so");
|
||||
responses.add("Without a doubt");
|
||||
responses.add("Yes - definitely");
|
||||
responses.add("You may rely on it");
|
||||
responses.add("As I see it, yes");
|
||||
responses.add("Most likely");
|
||||
responses.add("Outlook good");
|
||||
responses.add("Yes");
|
||||
responses.add("Signs point to yes");
|
||||
|
||||
responses.add("Reply hazy, try again");
|
||||
responses.add("Ask again later");
|
||||
responses.add("Better not tell you now");
|
||||
responses.add("Cannot predict now");
|
||||
responses.add("Concentrate and ask again");
|
||||
|
||||
responses.add("Don't count on it");
|
||||
responses.add("My reply is no");
|
||||
responses.add("My sources say no");
|
||||
responses.add("Outlook not so good");
|
||||
responses.add("Very doubtful");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
if (arguments.length == 0) {
|
||||
return new CommandResponse("no_entry_sign",
|
||||
"Sorry, " + executor.getAsMention() + ", but you need to supply a question for the Magic 8 Ball.")
|
||||
.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
final String question = StringUtil.sanitizeCodeBlock(String.join(" ", arguments));
|
||||
|
||||
return new CommandResponse("question",
|
||||
executor.getAsMention() + " asked the Magic 8 Ball: `" + question + "`\n"
|
||||
+ EmojiManager.getForAlias("8ball").getUnicode() + " The Magic 8 Ball responds: *"
|
||||
+ responses.get(rng.nextInt(responses.size())) + "*.");
|
||||
}
|
||||
}
|
||||
28
src/main/java/dev/logal/logalbot/commands/general/About.java
Normal file
28
src/main/java/dev/logal/logalbot/commands/general/About.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package dev.logal.logalbot.commands.general;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class About implements Command {
|
||||
@Override
|
||||
public CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
return new CommandResponse("wave", "Hello " + executor.getAsMention()
|
||||
+ "! I'm LogalBot, a bot created by LogalDeveloper. https://logal.dev/");
|
||||
}
|
||||
}
|
||||
34
src/main/java/dev/logal/logalbot/commands/general/Help.java
Normal file
34
src/main/java/dev/logal/logalbot/commands/general/Help.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package dev.logal.logalbot.commands.general;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import net.dv8tion.jda.core.EmbedBuilder;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
|
||||
public final class Help implements Command {
|
||||
@Override
|
||||
public CommandResponse execute(final String[] arguments, final Member executor, final TextChannel channel) {
|
||||
final CommandResponse response = new CommandResponse("directory",
|
||||
executor.getAsMention() + ", here are some helpful links:");
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.addField("Command Reference", "https://logal.dev/projects/logalbot/command-reference/", false);
|
||||
builder.addField("Git Repository", "https://git.logal.dev/LogalDeveloper/LogalBot", false);
|
||||
response.attachEmbed(builder.build());
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import dev.logal.logalbot.utils.ReactionCallbackManager;
|
||||
import net.dv8tion.jda.core.events.message.guild.react.GuildMessageReactionAddEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildMessageReactionAdd extends ListenerAdapter {
|
||||
@Override
|
||||
public final void onGuildMessageReactionAdd(final GuildMessageReactionAddEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
if (!event.getUser().equals(event.getJDA().getSelfUser())) {
|
||||
ReactionCallbackManager.executeCallback(event.getMessageIdLong(), event.getMember(),
|
||||
event.getReactionEmote().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import dev.logal.logalbot.utils.CommandManager;
|
||||
import dev.logal.logalbot.utils.DataManager;
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.SelfUser;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildMessageReceived extends ListenerAdapter {
|
||||
@Override
|
||||
public final void onGuildMessageReceived(final GuildMessageReceivedEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
final Guild guild = event.getGuild();
|
||||
final Member self = guild.getSelfMember();
|
||||
final TextChannel channel = event.getChannel();
|
||||
final Message message = event.getMessage();
|
||||
if (event.getAuthor().isBot() || message.isTTS() || !self.hasPermission(channel, Permission.MESSAGE_WRITE)
|
||||
|| !self.hasPermission(channel, Permission.MESSAGE_EMBED_LINKS)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String content = message.getContentRaw();
|
||||
final SelfUser selfUser = event.getJDA().getSelfUser();
|
||||
final List<Member> mentionedMembers = message.getMentionedMembers();
|
||||
final Member author = event.getMember();
|
||||
if (mentionedMembers.size() >= 1 && mentionedMembers.get(0).getUser().getIdLong() == selfUser.getIdLong()
|
||||
&& (content.startsWith(self.getAsMention()) || content.startsWith(selfUser.getAsMention()))) {
|
||||
final String[] rawCommand = content.split(" ");
|
||||
final String[] command = Arrays.copyOfRange(rawCommand, 1, rawCommand.length);
|
||||
if (command.length >= 1) {
|
||||
if (self.hasPermission(channel, Permission.MESSAGE_MANAGE)) {
|
||||
message.delete().reason("LogalBot Command Execution").queue();
|
||||
}
|
||||
CommandManager.executeCommand(command, author, channel);
|
||||
}
|
||||
} else {
|
||||
final String commandCharacter = DataManager.getGuildValue(guild, "commandCharacter");
|
||||
if (commandCharacter == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final char commandChar = commandCharacter.toCharArray()[0];
|
||||
|
||||
if (content.length() > 1 && content.charAt(0) == commandChar) {
|
||||
final String[] command = content.substring(1).split(" ");
|
||||
if (self.hasPermission(channel, Permission.MESSAGE_MANAGE)) {
|
||||
message.delete().reason("LogalBot Command Execution").queue();
|
||||
}
|
||||
CommandManager.executeCommand(command, author, channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
29
src/main/java/dev/logal/logalbot/events/GuildReady.java
Normal file
29
src/main/java/dev/logal/logalbot/events/GuildReady.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import net.dv8tion.jda.core.events.guild.GuildReadyEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildReady extends ListenerAdapter {
|
||||
@Override
|
||||
public final void onGuildReady(final GuildReadyEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
AudioUtil.initialize(event.getGuild());
|
||||
}
|
||||
}
|
||||
65
src/main/java/dev/logal/logalbot/events/GuildVoiceLeave.java
Normal file
65
src/main/java/dev/logal/logalbot/events/GuildVoiceLeave.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.events.guild.voice.GuildVoiceLeaveEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildVoiceLeave extends ListenerAdapter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GuildVoiceLeave.class);
|
||||
|
||||
@Override
|
||||
public final void onGuildVoiceLeave(final GuildVoiceLeaveEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
final Guild guild = event.getGuild();
|
||||
if (!AudioUtil.isAudioConnectionOpen(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Member member = event.getMember();
|
||||
|
||||
if (member.getUser().equals(event.getJDA().getSelfUser())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final VoiceChannel leftChannel = event.getChannelLeft();
|
||||
if (leftChannel.equals(AudioUtil.getVoiceChannelConnectedTo(guild))) {
|
||||
final List<Member> members = leftChannel.getMembers();
|
||||
if (members.size() == 1 && members.get(0).getUser().equals(event.getJDA().getSelfUser())) {
|
||||
logger.info("All listeners left " + leftChannel.getName() + " (" + leftChannel.getId() + ") in "
|
||||
+ guild.getName() + " (" + guild.getId() + ").");
|
||||
AudioUtil.getTrackScheduler(guild).clearQueue();
|
||||
if (AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.stopTrack(guild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
src/main/java/dev/logal/logalbot/events/GuildVoiceMove.java
Normal file
65
src/main/java/dev/logal/logalbot/events/GuildVoiceMove.java
Normal file
@@ -0,0 +1,65 @@
|
||||
package dev.logal.logalbot.events;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.events.guild.voice.GuildVoiceMoveEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class GuildVoiceMove extends ListenerAdapter {
|
||||
private static final Logger logger = LoggerFactory.getLogger(GuildVoiceMove.class);
|
||||
|
||||
@Override
|
||||
public final void onGuildVoiceMove(final GuildVoiceMoveEvent event) {
|
||||
Checks.notNull(event, "Event");
|
||||
|
||||
final Guild guild = event.getGuild();
|
||||
if (!AudioUtil.isAudioConnectionOpen(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AudioUtil.isTrackLoaded(guild)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Member member = event.getMember();
|
||||
|
||||
if (member.getUser().equals(event.getJDA().getSelfUser())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final VoiceChannel leftChannel = event.getChannelLeft();
|
||||
if (leftChannel.equals(AudioUtil.getVoiceChannelConnectedTo(guild))) {
|
||||
final List<Member> members = leftChannel.getMembers();
|
||||
if (members.size() == 1 && members.get(0).getUser().equals(event.getJDA().getSelfUser())) {
|
||||
logger.info("All listeners left " + leftChannel.getName() + " (" + leftChannel.getId() + ") in "
|
||||
+ guild.getName() + " (" + guild.getId() + ").");
|
||||
AudioUtil.getTrackScheduler(guild).clearQueue();
|
||||
if (AudioUtil.isTrackLoaded(guild)) {
|
||||
AudioUtil.stopTrack(guild);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.logal.logalbot.tasks;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import dev.logal.logalbot.utils.AudioUtil;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class IdleDisconnectTask implements Runnable {
|
||||
private final Guild guild;
|
||||
|
||||
public IdleDisconnectTask(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
AudioUtil.closeAudioConnection(guild);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package dev.logal.logalbot.tasks;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import dev.logal.logalbot.utils.ReactionCallbackManager;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class MessageDeleteTask implements Runnable {
|
||||
private final Message messageToDelete;
|
||||
|
||||
public MessageDeleteTask(final Message message) {
|
||||
Checks.notNull(message, "Message");
|
||||
|
||||
this.messageToDelete = message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
ReactionCallbackManager.unregisterMessage(messageToDelete.getIdLong());
|
||||
messageToDelete.delete().queue();
|
||||
}
|
||||
}
|
||||
173
src/main/java/dev/logal/logalbot/utils/AudioUtil.java
Normal file
173
src/main/java/dev/logal/logalbot/utils/AudioUtil.java
Normal file
@@ -0,0 +1,173 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.audio.AudioPlayerSendHandler;
|
||||
import dev.logal.logalbot.audio.TrackLoadHandler;
|
||||
import dev.logal.logalbot.audio.TrackScheduler;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.managers.AudioManager;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class AudioUtil {
|
||||
private static final Logger logger = LoggerFactory.getLogger(AudioUtil.class);
|
||||
|
||||
private static final AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
|
||||
private static final HashMap<String, AudioPlayer> players = new HashMap<>();
|
||||
private static final HashMap<String, TrackScheduler> schedulers = new HashMap<>();
|
||||
|
||||
private AudioUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void initializePlayerManager() {
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
}
|
||||
|
||||
public static final void initialize(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
players.put(guild.getId(), playerManager.createPlayer());
|
||||
schedulers.put(guild.getId(), new TrackScheduler(guild));
|
||||
players.get(guild.getId()).addListener(schedulers.get(guild.getId()));
|
||||
|
||||
try {
|
||||
setVolume(guild, Integer.parseInt(DataManager.getGuildValue(guild, "defaultVolume")));
|
||||
} catch (final NumberFormatException exception) {
|
||||
setVolume(guild, 10);
|
||||
}
|
||||
|
||||
getTrackScheduler(guild).setQueueLocked(false);
|
||||
setPausedState(guild, false);
|
||||
|
||||
logger.info("Audio environment initialized for " + guild.getName() + " (" + guild.getId() + ").");
|
||||
}
|
||||
|
||||
public static final void openAudioConnection(final VoiceChannel channel) {
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
final Guild guild = channel.getGuild();
|
||||
final AudioManager audioManager = guild.getAudioManager();
|
||||
|
||||
audioManager.setSendingHandler(new AudioPlayerSendHandler(players.get(guild.getId())));
|
||||
audioManager.openAudioConnection(channel);
|
||||
}
|
||||
|
||||
public static final void closeAudioConnection(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
guild.getAudioManager().closeAudioConnection();
|
||||
}
|
||||
|
||||
public static final VoiceChannel getVoiceChannelConnectedTo(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return guild.getAudioManager().getConnectedChannel();
|
||||
}
|
||||
|
||||
public static final boolean isAudioConnectionOpen(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return guild.getAudioManager().isConnected();
|
||||
}
|
||||
|
||||
public static final void playTrack(final Guild guild, final AudioTrack track) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
players.get(guild.getId()).playTrack(track);
|
||||
}
|
||||
|
||||
public static final void stopTrack(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
players.get(guild.getId()).stopTrack();
|
||||
}
|
||||
|
||||
public static final boolean isTrackLoaded(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return !(getLoadedTrack(guild) == null);
|
||||
}
|
||||
|
||||
public static final AudioTrack getLoadedTrack(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return players.get(guild.getId()).getPlayingTrack();
|
||||
}
|
||||
|
||||
public static final void setPausedState(final Guild guild, final boolean pausedState) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notNull(pausedState, "Paused state");
|
||||
|
||||
guild.getAudioManager().setSelfMuted(pausedState);
|
||||
players.get(guild.getId()).setPaused(pausedState);
|
||||
|
||||
if (pausedState) {
|
||||
logger.info("The audio player was paused in " + guild.getName() + " (" + guild.getId() + ").");
|
||||
} else {
|
||||
logger.info("The audio player was resumed in " + guild.getName() + " (" + guild.getId() + ").");
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean isPlayerPaused(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return players.get(guild.getId()).isPaused();
|
||||
}
|
||||
|
||||
public static final void setVolume(final Guild guild, final int volume) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.positive(volume, "Volume");
|
||||
|
||||
players.get(guild.getId()).setVolume(volume);
|
||||
logger.info("The audio player's volume was set to " + getVolume(guild) + "% in " + guild.getName() + " ("
|
||||
+ guild.getId() + ").");
|
||||
}
|
||||
|
||||
public static final int getVolume(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return players.get(guild.getId()).getVolume();
|
||||
}
|
||||
|
||||
public static final void findTrack(final String query, final Member requester, final TextChannel channel) {
|
||||
Checks.notNull(query, "Query");
|
||||
Checks.notNull(requester, "Requester");
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
playerManager.loadItem(query, new TrackLoadHandler(requester, channel));
|
||||
}
|
||||
|
||||
public static final TrackScheduler getTrackScheduler(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return schedulers.get(guild.getId());
|
||||
}
|
||||
}
|
||||
127
src/main/java/dev/logal/logalbot/utils/CommandManager.java
Normal file
127
src/main/java/dev/logal/logalbot/utils/CommandManager.java
Normal file
@@ -0,0 +1,127 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dev.logal.logalbot.commands.Command;
|
||||
import dev.logal.logalbot.commands.CommandResponse;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.TextChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class CommandManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(CommandManager.class);
|
||||
|
||||
private static final HashMap<String, Command> commandMap = new HashMap<>();
|
||||
private static final HashMap<String, Boolean> permissionMap = new HashMap<>();
|
||||
private static final HashMap<String, String> aliasMap = new HashMap<>();
|
||||
|
||||
private CommandManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void executeCommand(final String[] command, final Member executor, final TextChannel channel) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
Checks.notNull(executor, "Executor");
|
||||
Checks.notNull(channel, "Channel");
|
||||
|
||||
String commandName = command[0].toLowerCase();
|
||||
final String[] arguments = Arrays.copyOfRange(command, 1, command.length);
|
||||
final Guild guild = channel.getGuild();
|
||||
CommandResponse response;
|
||||
|
||||
if (aliasMap.containsKey(commandName)) {
|
||||
commandName = aliasMap.get(commandName);
|
||||
}
|
||||
|
||||
logger.info(executor.getEffectiveName() + " (" + executor.getUser().getId() + ") executed command '"
|
||||
+ commandName + "' with arguments '" + String.join(" ", arguments) + "' in " + guild.getName() + " ("
|
||||
+ guild.getId() + ").");
|
||||
if (!commandMap.containsKey(commandName)) {
|
||||
response = new CommandResponse("question",
|
||||
"Sorry " + executor.getAsMention() + ", but I do not know what that command is.");
|
||||
response.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (permissionMap.get(commandName) && !PermissionManager.isWhitelisted(executor)) {
|
||||
logger.info(executor.getEffectiveName() + " (" + executor.getUser().getId()
|
||||
+ ") was denied access to a command due to not being whitelisted in " + guild.getName() + " ("
|
||||
+ guild.getId() + ").");
|
||||
response = new CommandResponse("no_entry_sign",
|
||||
"Sorry " + executor.getAsMention() + ", but you are not allowed to use this command.");
|
||||
response.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
response = commandMap.get(commandName).execute(arguments, executor, channel);
|
||||
} catch (final Throwable exception) {
|
||||
logger.error(
|
||||
"An error occurred while executing a command for " + executor.getEffectiveName() + " ("
|
||||
+ executor.getUser().getId() + ") in " + guild.getName() + " (" + guild.getId() + ").",
|
||||
exception);
|
||||
response = new CommandResponse("sos",
|
||||
"Sorry " + executor.getAsMention() + ", but an error occurred while executing your command!!");
|
||||
response.setDeletionDelay(10, TimeUnit.SECONDS);
|
||||
response.sendResponse(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (response != null) {
|
||||
response.sendResponse(channel);
|
||||
}
|
||||
}
|
||||
|
||||
public static final void registerCommand(final String command, final Command commandObject,
|
||||
final boolean mustBeWhitelisted) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
Checks.notNull(commandObject, "Command object");
|
||||
Checks.notNull(mustBeWhitelisted, "Whitelist requirement");
|
||||
|
||||
commandMap.put(command, commandObject);
|
||||
permissionMap.put(command, mustBeWhitelisted);
|
||||
}
|
||||
|
||||
public static final void registerCommandAlias(final String alias, final String command) {
|
||||
Checks.notEmpty(alias, "Alias");
|
||||
Checks.notEmpty(command, "Command");
|
||||
|
||||
aliasMap.put(alias, command);
|
||||
}
|
||||
|
||||
public static final void unregisterCommand(final String command) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
|
||||
commandMap.remove(command);
|
||||
permissionMap.remove(command);
|
||||
}
|
||||
|
||||
public static final void unregisterCommandAlias(final String command) {
|
||||
Checks.notEmpty(command, "Command");
|
||||
|
||||
aliasMap.remove(command);
|
||||
}
|
||||
}
|
||||
126
src/main/java/dev/logal/logalbot/utils/DataManager.java
Normal file
126
src/main/java/dev/logal/logalbot/utils/DataManager.java
Normal file
@@ -0,0 +1,126 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
import redis.clients.jedis.Jedis;
|
||||
|
||||
public final class DataManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DataManager.class);
|
||||
|
||||
private static final String host = System.getenv("REDIS_HOST");
|
||||
private static final String password = System.getenv("REDIS_PASSWORD");
|
||||
private static final String databaseNumber = System.getenv("REDIS_DATABASE");
|
||||
private static Jedis jedis = new Jedis();
|
||||
|
||||
private DataManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void verifyConnection() {
|
||||
if (!jedis.isConnected()) {
|
||||
jedis = new Jedis(host);
|
||||
|
||||
if (password != null) {
|
||||
jedis.auth(password);
|
||||
}
|
||||
|
||||
if (databaseNumber != null) {
|
||||
final int num = Integer.parseInt(databaseNumber);
|
||||
jedis.select(num);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final void runMigrations() {
|
||||
if (jedis.get("schemaVersion") == null) {
|
||||
logger.info("Migrating schema to version 1...");
|
||||
jedis.set("schemaVersion", "1");
|
||||
logger.info("Migration to schema version 1 complete.");
|
||||
}
|
||||
}
|
||||
|
||||
public static final String getUserValue(final Member member, final String key) {
|
||||
Checks.notNull(member, "Member");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
return jedis.get("g" + member.getGuild().getId() + ":u" + member.getUser().getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final void setUserValue(final Member member, final String key, final String value) {
|
||||
Checks.notNull(member, "Member");
|
||||
Checks.notEmpty(key, "Key");
|
||||
Checks.notEmpty(value, "Value");
|
||||
|
||||
jedis.set("g" + member.getGuild().getId() + ":u" + member.getUser().getId() + ":" + key, value);
|
||||
}
|
||||
|
||||
public static final void deleteUserKey(final Member member, final String key) {
|
||||
Checks.notNull(member, "Member");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
jedis.del("g" + member.getGuild().getId() + ":u" + member.getUser().getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final String getGlobalUserValue(final User user, final String key) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
return jedis.get("u" + user.getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final void setGlobalUserValue(final User user, final String key, final String value) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notEmpty(key, "Key");
|
||||
Checks.notEmpty(value, "Value");
|
||||
|
||||
jedis.set("u" + user.getId() + ":" + key, value);
|
||||
}
|
||||
|
||||
public static final void deleteGlobalUserKey(final User user, final String key) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
jedis.del("u" + user.getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final String getGuildValue(final Guild guild, final String key) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
return jedis.get("g" + guild.getId() + ":" + key);
|
||||
}
|
||||
|
||||
public static final void setGuildValue(final Guild guild, final String key, final String value) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notEmpty(key, "Key");
|
||||
Checks.notEmpty(value, "Value");
|
||||
|
||||
jedis.set("g" + guild.getId() + ":" + key, value);
|
||||
}
|
||||
|
||||
public static final void deleteGuildKey(final Guild guild, final String key) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
Checks.notEmpty(key, "Key");
|
||||
|
||||
jedis.del("g" + guild.getId() + ":" + key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import net.dv8tion.jda.core.Permission;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class PermissionManager {
|
||||
private static final Logger logger = LoggerFactory.getLogger(PermissionManager.class);
|
||||
|
||||
private PermissionManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final boolean isWhitelisted(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
if (member.hasPermission(Permission.ADMINISTRATOR)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (DataManager.getUserValue(member, "whitelisted") == null) {
|
||||
DataManager.setUserValue(member, "whitelisted", "false");
|
||||
}
|
||||
|
||||
return DataManager.getUserValue(member, "whitelisted").equals("true");
|
||||
}
|
||||
|
||||
public static final void addToWhitelist(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
DataManager.setUserValue(member, "whitelisted", "true");
|
||||
logger.info(member.getEffectiveName() + " (" + member.getUser().getId() + ") was added to the whitelist in "
|
||||
+ member.getGuild().getName() + " (" + member.getGuild().getId() + ").");
|
||||
}
|
||||
|
||||
public static final void removeFromWhitelist(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
DataManager.setUserValue(member, "whitelisted", "false");
|
||||
logger.info(member.getEffectiveName() + " (" + member.getUser().getId() + ") was removed from the whitelist in "
|
||||
+ member.getGuild().getName() + " (" + member.getGuild().getId() + ").");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.vdurmont.emoji.Emoji;
|
||||
import com.vdurmont.emoji.EmojiManager;
|
||||
|
||||
import dev.logal.logalbot.commands.ReactionCallback;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.Message;
|
||||
import net.dv8tion.jda.core.entities.User;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class ReactionCallbackManager {
|
||||
private static final HashMap<Long, HashMap<Emoji, ReactionCallback>> callbackDictionary = new HashMap<>();
|
||||
private static final HashMap<Long, Long> targetDictionary = new HashMap<>();
|
||||
|
||||
private ReactionCallbackManager() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void registerCallback(final Message message, final Emoji emoji,
|
||||
final ReactionCallback callback) {
|
||||
Checks.notNull(message, "Message");
|
||||
Checks.notNull(emoji, "Emoji");
|
||||
Checks.notNull(callback, "Callback");
|
||||
|
||||
if (!callbackDictionary.containsKey(message.getIdLong())) {
|
||||
callbackDictionary.put(message.getIdLong(), new HashMap<>());
|
||||
}
|
||||
|
||||
callbackDictionary.get(message.getIdLong()).put(emoji, callback);
|
||||
}
|
||||
|
||||
public static final void setCallbackTarget(final User user, final Message message) {
|
||||
Checks.notNull(user, "User");
|
||||
Checks.notNull(message, "Messsage");
|
||||
|
||||
targetDictionary.put(message.getIdLong(), user.getIdLong());
|
||||
}
|
||||
|
||||
public static final void unregisterMessage(final long messageID) {
|
||||
Checks.notNull(messageID, "Message ID");
|
||||
|
||||
callbackDictionary.remove(messageID);
|
||||
targetDictionary.remove(messageID);
|
||||
}
|
||||
|
||||
public static final void executeCallback(final long messageID, final Member reactor, final String emoji) {
|
||||
Checks.notNull(messageID, "Message ID");
|
||||
Checks.notNull(reactor, "Reactor");
|
||||
Checks.notEmpty(emoji, "Emoji");
|
||||
|
||||
if (callbackDictionary.containsKey(messageID)) {
|
||||
if (targetDictionary.containsKey(messageID)
|
||||
&& !targetDictionary.get(messageID).equals(reactor.getUser().getIdLong())) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Emoji parsedEmoji = EmojiManager.getByUnicode(emoji);
|
||||
if (callbackDictionary.get(messageID).containsKey(parsedEmoji)) {
|
||||
callbackDictionary.get(messageID).get(parsedEmoji).run(reactor, messageID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/main/java/dev/logal/logalbot/utils/Scheduler.java
Normal file
48
src/main/java/dev/logal/logalbot/utils/Scheduler.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class Scheduler {
|
||||
private static final ScheduledExecutorService pool = Executors.newScheduledThreadPool(1);
|
||||
|
||||
private Scheduler() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final ScheduledFuture<?> schedule(final Runnable runnable, final long delay, final TimeUnit unit) {
|
||||
Checks.notNull(runnable, "Runnable");
|
||||
Checks.notNull(delay, "Delay");
|
||||
Checks.notNull(unit, "Unit");
|
||||
|
||||
return pool.schedule(runnable, delay, unit);
|
||||
}
|
||||
|
||||
public static final ScheduledFuture<?> scheduleRepeating(final Runnable runnable, final long initialDelay,
|
||||
final long period, final TimeUnit unit) {
|
||||
Checks.notNull(runnable, "Runnable");
|
||||
Checks.notNull(initialDelay, "Initial delay");
|
||||
Checks.notNull(period, "Period");
|
||||
Checks.notNull(unit, "Unit");
|
||||
|
||||
return pool.scheduleAtFixedRate(runnable, initialDelay, period, unit);
|
||||
}
|
||||
}
|
||||
77
src/main/java/dev/logal/logalbot/utils/SkipTracker.java
Normal file
77
src/main/java/dev/logal/logalbot/utils/SkipTracker.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class SkipTracker {
|
||||
private static final HashMap<Long, ArrayList<Long>> skipVotesDictionary = new HashMap<>();
|
||||
|
||||
private SkipTracker() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final void registerVote(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
final Guild guild = member.getGuild();
|
||||
if (!skipVotesDictionary.containsKey(guild.getIdLong())) {
|
||||
resetVotes(guild);
|
||||
}
|
||||
|
||||
final ArrayList<Long> registeredVotes = skipVotesDictionary.get(guild.getIdLong());
|
||||
if (!registeredVotes.contains(member.getUser().getIdLong())) {
|
||||
registeredVotes.add(member.getUser().getIdLong());
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean hasVoted(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
return skipVotesDictionary.get(member.getGuild().getIdLong()).contains(member.getUser().getIdLong());
|
||||
}
|
||||
|
||||
public static final void resetVotes(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
final long guildID = guild.getIdLong();
|
||||
if (skipVotesDictionary.containsKey(guildID)) {
|
||||
skipVotesDictionary.get(guildID).clear();
|
||||
} else {
|
||||
skipVotesDictionary.put(guildID, new ArrayList<>());
|
||||
}
|
||||
}
|
||||
|
||||
public static final int getRemainingRequired(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
final int listeners = (int) AudioUtil.getVoiceChannelConnectedTo(guild).getMembers().stream()
|
||||
.filter(member -> !member.getUser().isBot()).count();
|
||||
final int required = (int) Math.ceil(listeners * .55);
|
||||
|
||||
return (required - skipVotesDictionary.get(guild.getIdLong()).size());
|
||||
}
|
||||
|
||||
public static final boolean shouldSkip(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
return getRemainingRequired(guild) <= 0;
|
||||
}
|
||||
}
|
||||
45
src/main/java/dev/logal/logalbot/utils/StringUtil.java
Normal file
45
src/main/java/dev/logal/logalbot/utils/StringUtil.java
Normal file
@@ -0,0 +1,45 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class StringUtil {
|
||||
private StringUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final String sanitize(final String string) {
|
||||
Checks.notNull(string, "String");
|
||||
|
||||
return string.replaceAll("([_*`<@>~|])", "\\\\$1").replaceAll("[\r\n]", "");
|
||||
}
|
||||
|
||||
public static final String sanitizeCodeBlock(final String string) {
|
||||
Checks.notNull(string, "String");
|
||||
|
||||
return string.replaceAll("[`]", "'").replaceAll("[\r\n]", "");
|
||||
}
|
||||
|
||||
public static final String formatTime(final long milliseconds) {
|
||||
Checks.notNull(milliseconds, "Milliseconds");
|
||||
|
||||
final long second = (milliseconds / 1000) % 60;
|
||||
final long minute = (milliseconds / (1000 * 60)) % 60;
|
||||
final long hour = (milliseconds / (1000 * 60 * 60)) % 24;
|
||||
|
||||
return String.format("%02d:%02d:%02d", hour, minute, second);
|
||||
}
|
||||
}
|
||||
110
src/main/java/dev/logal/logalbot/utils/TrackUtil.java
Normal file
110
src/main/java/dev/logal/logalbot/utils/TrackUtil.java
Normal file
@@ -0,0 +1,110 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||
|
||||
import net.dv8tion.jda.core.EmbedBuilder;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class TrackUtil {
|
||||
private TrackUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final MessageEmbed generateTrackInfoEmbed(final AudioTrack track) {
|
||||
Checks.notNull(track, "Track");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.addField(StringUtil.sanitize(track.getInfo().title),
|
||||
StringUtil.sanitize(track.getInfo().author) + " - " + StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static final MessageEmbed generateCurrentTrackInfoEmbed(final Guild guild) {
|
||||
Checks.notNull(guild, "Guild");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
final AudioTrack track = AudioUtil.getLoadedTrack(guild);
|
||||
builder.addField(
|
||||
StringUtil.sanitize(track.getInfo().title), StringUtil.sanitize(track.getInfo().author) + " - "
|
||||
+ StringUtil.formatTime(track.getPosition()) + "/" + StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static final MessageEmbed generateTrackListInfoEmbed(final List<AudioTrack> tracks, final boolean numbered) {
|
||||
Checks.notNull(tracks, "Tracks");
|
||||
Checks.notNull(numbered, "Numbered");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
for (int i = 0; i < tracks.size(); i++) {
|
||||
if (i == 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
final AudioTrack track = tracks.get(i);
|
||||
if (numbered) {
|
||||
builder.addField("**" + (i + 1) + ":** " + StringUtil.sanitize(track.getInfo().title),
|
||||
StringUtil.sanitize(track.getInfo().author) + " - "
|
||||
+ StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
} else {
|
||||
builder.addField(StringUtil.sanitize(track.getInfo().title), StringUtil.sanitize(track.getInfo().author)
|
||||
+ " - " + StringUtil.formatTime(track.getDuration()), false);
|
||||
}
|
||||
}
|
||||
|
||||
if (tracks.size() > 10) {
|
||||
builder.setTitle("**Top 10 Tracks - " + (tracks.size() - 10) + " Not Shown**");
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static final MessageEmbed generatePaginatedTrackListInfoEmbed(final List<AudioTrack> tracks, int page) {
|
||||
Checks.notNull(tracks, "Tracks");
|
||||
Checks.notNull(page, "Page");
|
||||
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
if (page < 1) {
|
||||
page = 1;
|
||||
}
|
||||
|
||||
final int pages = (int) Math.ceil(tracks.size() / 10d);
|
||||
|
||||
if (page > pages) {
|
||||
page = pages;
|
||||
}
|
||||
|
||||
page = page - 1;
|
||||
final int start = page * 10;
|
||||
final int end = start + 10;
|
||||
|
||||
for (int i = start; i < end && i < tracks.size(); i++) {
|
||||
final AudioTrack track = tracks.get(i);
|
||||
builder.addField("**" + (i + 1) + ":** " + StringUtil.sanitize(track.getInfo().title),
|
||||
StringUtil.sanitize(track.getInfo().author) + " - " + StringUtil.formatTime(track.getDuration()),
|
||||
false);
|
||||
}
|
||||
|
||||
builder.setTitle("**" + tracks.size() + " Total Tracks - Page " + (page + 1) + "/" + pages + "**");
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
42
src/main/java/dev/logal/logalbot/utils/VoiceChannelUtil.java
Normal file
42
src/main/java/dev/logal/logalbot/utils/VoiceChannelUtil.java
Normal file
@@ -0,0 +1,42 @@
|
||||
package dev.logal.logalbot.utils;
|
||||
|
||||
// Copyright 2019 Logan Fick
|
||||
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import net.dv8tion.jda.core.entities.Member;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.utils.Checks;
|
||||
|
||||
public final class VoiceChannelUtil {
|
||||
private VoiceChannelUtil() {
|
||||
// Static access only.
|
||||
}
|
||||
|
||||
public static final VoiceChannel getVoiceChannelMemberIsConnectedTo(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
for (final VoiceChannel channel : member.getGuild().getVoiceChannels()) {
|
||||
if (channel.getMembers().contains(member)) {
|
||||
return channel;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final boolean isInCurrentVoiceChannel(final Member member) {
|
||||
Checks.notNull(member, "Member");
|
||||
|
||||
return AudioUtil.getVoiceChannelConnectedTo(member.getGuild()).getMembers().contains(member);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user