Initial commit
This commit is contained in:
commit
423e9269ee
9
.dockerignore
Normal file
9
.dockerignore
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
.idea/
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
test.db
|
||||||
|
gradle/
|
||||||
|
gradlew
|
||||||
|
gradlew.bat
|
||||||
|
.gitignore
|
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
.idea/
|
||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
out/
|
||||||
|
test.db
|
||||||
|
dump/
|
||||||
|
local.properties
|
27
.gitlab-ci.yml
Normal file
27
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
image: docker:latest
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
|
||||||
|
variables:
|
||||||
|
IMAGE_TAG: $CI_REGISTRY_IMAGE:latest
|
||||||
|
NAME: $CI_PROJECT_NAME
|
||||||
|
DOCKER_BUILDKIT: 1
|
||||||
|
|
||||||
|
build_and_push:
|
||||||
|
stage: build
|
||||||
|
only:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN registry.voidcorp.nl
|
||||||
|
- docker build -t $IMAGE_TAG .
|
||||||
|
- docker push $IMAGE_TAG
|
||||||
|
|
||||||
|
only_build:
|
||||||
|
stage: build
|
||||||
|
except:
|
||||||
|
- master
|
||||||
|
script:
|
||||||
|
- docker build -t $IMAGE_TAG .
|
12
Dockerfile
Normal file
12
Dockerfile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
FROM gradle:6.6-jdk14 AS builder
|
||||||
|
|
||||||
|
COPY --chown=gradle:gradle . /home/gradle/src
|
||||||
|
WORKDIR /home/gradle/src
|
||||||
|
RUN gradle distTar
|
||||||
|
|
||||||
|
FROM adoptopenjdk:14-jre-hotspot
|
||||||
|
COPY --from=builder /home/gradle/src/build/distributions/ottobot.tar /app/ottobot.tar
|
||||||
|
WORKDIR /app
|
||||||
|
RUN tar -xvf ottobot.tar
|
||||||
|
WORKDIR /app/ottobot
|
||||||
|
CMD bin/ottobot
|
46
build.gradle.kts
Normal file
46
build.gradle.kts
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
application
|
||||||
|
kotlin("jvm") version "1.4.0"
|
||||||
|
}
|
||||||
|
group = "nl.voidcorp.ottobot"
|
||||||
|
version = "1.0-SNAPSHOT"
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun DependencyHandlerScope.exposed(part: String) = implementation("org.jetbrains.exposed", part, "0.27.1")
|
||||||
|
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("net.dv8tion:JDA:4.2.0_200") {
|
||||||
|
exclude(module = "opus-java")
|
||||||
|
}
|
||||||
|
implementation("io.ktor:ktor-client-apache:1.4.0")
|
||||||
|
implementation("io.ktor:ktor-client-jackson:1.4.0")
|
||||||
|
|
||||||
|
implementation("ch.qos.logback:logback-classic:1.2.3")
|
||||||
|
exposed("exposed-core")
|
||||||
|
exposed("exposed-dao")
|
||||||
|
exposed("exposed-jdbc")
|
||||||
|
implementation("org.xerial:sqlite-jdbc:3.30.1")
|
||||||
|
implementation("com.impossibl.pgjdbc-ng:pgjdbc-ng:0.8.3")
|
||||||
|
implementation(kotlin("reflect"))
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<KotlinCompile>() {
|
||||||
|
kotlinOptions.jvmTarget = "13"
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
distTar {
|
||||||
|
archiveFileName.set("ottobot.tar")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
applicationName = "ottobot"
|
||||||
|
mainClassName = "nl.voidcorp.ottobot.MainKt"
|
||||||
|
}
|
1
gradle.properties
Normal file
1
gradle.properties
Normal file
|
@ -0,0 +1 @@
|
||||||
|
kotlin.code.style=official
|
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
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
183
gradlew
vendored
Normal file
183
gradlew
vendored
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2015 the original author or authors.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## 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='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# 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 or MSYS, switch paths to Windows format before running java
|
||||||
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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=`expr $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"
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
103
gradlew.bat
vendored
Normal file
103
gradlew.bat
vendored
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@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 Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@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="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@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
|
3
settings.gradle.kts
Normal file
3
settings.gradle.kts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
rootProject.name = "ottobot-v3"
|
||||||
|
|
55
src/main/kotlin/nl/voidcorp/ottobot/Main.kt
Normal file
55
src/main/kotlin/nl/voidcorp/ottobot/Main.kt
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package nl.voidcorp.ottobot
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Activity
|
||||||
|
import net.dv8tion.jda.api.sharding.DefaultShardManagerBuilder
|
||||||
|
import net.dv8tion.jda.api.sharding.ShardManager
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.database.*
|
||||||
|
import nl.voidcorp.ottobot.events.CommandListener
|
||||||
|
import nl.voidcorp.ottobot.events.DisconnectListenerAdapter
|
||||||
|
import nl.voidcorp.ottobot.events.OttoListener
|
||||||
|
import org.jetbrains.exposed.sql.Database
|
||||||
|
import org.jetbrains.exposed.sql.SchemaUtils
|
||||||
|
import org.jetbrains.exposed.sql.selectAll
|
||||||
|
import org.jetbrains.exposed.sql.transactions.TransactionManager
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import org.slf4j.LoggerFactory
|
||||||
|
import java.sql.Connection
|
||||||
|
|
||||||
|
val logger: Logger = LoggerFactory.getLogger("OttoBot")
|
||||||
|
const val creator = 168743656738521088
|
||||||
|
lateinit var jda: ShardManager
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val token: String = System.getenv("DISCORD_TOKEN") ?: throw RuntimeException("Missing DISCORD_TOKEN in env!")
|
||||||
|
Database.connect(
|
||||||
|
System.getenv("JDBC_URL") ?: "jdbc:sqlite:test.db",
|
||||||
|
System.getenv("JDBC_DRIVER") ?: "org.sqlite.JDBC",
|
||||||
|
System.getenv("JDBC_USER") ?: "",
|
||||||
|
System.getenv("JDBC_PASSWORD") ?: ""
|
||||||
|
)
|
||||||
|
TransactionManager.manager.defaultIsolationLevel = Connection.TRANSACTION_SERIALIZABLE
|
||||||
|
transaction {
|
||||||
|
SchemaUtils.createMissingTablesAndColumns(GuildStores)
|
||||||
|
SchemaUtils.createMissingTablesAndColumns(
|
||||||
|
GuildStoreAdminRoles,
|
||||||
|
GuildStoreBotChannels,
|
||||||
|
GuildStoreModeratorRoles,
|
||||||
|
GuildStoreRoleMap
|
||||||
|
)
|
||||||
|
}
|
||||||
|
startBot(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startBot(token: String) {
|
||||||
|
|
||||||
|
val builder = DefaultShardManagerBuilder.createDefault(token)
|
||||||
|
|
||||||
|
builder.addEventListeners(CommandListener(Command.allCommands), DisconnectListenerAdapter, OttoListener)
|
||||||
|
jda = builder.build()
|
||||||
|
jda.setActivityProvider {
|
||||||
|
Activity.playing("v3.0 ($it)")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
220
src/main/kotlin/nl/voidcorp/ottobot/command/Command.kt
Normal file
220
src/main/kotlin/nl/voidcorp/ottobot/command/Command.kt
Normal file
|
@ -0,0 +1,220 @@
|
||||||
|
package nl.voidcorp.ottobot.command
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.Permission
|
||||||
|
import net.dv8tion.jda.api.entities.ChannelType
|
||||||
|
import net.dv8tion.jda.api.entities.Member
|
||||||
|
import net.dv8tion.jda.api.entities.TextChannel
|
||||||
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
|
||||||
|
import nl.voidcorp.ottobot.commands.HelpCommand
|
||||||
|
import nl.voidcorp.ottobot.commands.`fun`.*
|
||||||
|
import nl.voidcorp.ottobot.commands.debug.DebugCommand
|
||||||
|
import nl.voidcorp.ottobot.commands.debug.Flex
|
||||||
|
import nl.voidcorp.ottobot.commands.debug.PermissionLevelCommand
|
||||||
|
import nl.voidcorp.ottobot.commands.general.ATQCommand
|
||||||
|
import nl.voidcorp.ottobot.commands.general.SpillKerrieCommand
|
||||||
|
import nl.voidcorp.ottobot.commands.general.XYProblemCommand
|
||||||
|
import nl.voidcorp.ottobot.commands.management.*
|
||||||
|
import nl.voidcorp.ottobot.commands.roles.*
|
||||||
|
import nl.voidcorp.ottobot.creator
|
||||||
|
import nl.voidcorp.ottobot.database.GuildStore
|
||||||
|
import nl.voidcorp.ottobot.database.GuildStores
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
|
abstract class Command(
|
||||||
|
val name: String,
|
||||||
|
val helpMesage: String = "",
|
||||||
|
val usage: String = "",
|
||||||
|
val commandLevel: CommandLevel = CommandLevel.VERIFIED,
|
||||||
|
val aliases: List<String> = emptyList(),
|
||||||
|
val location: CommandSource = CommandSource.BOTH,
|
||||||
|
val group: CommandGroup = CommandGroup.GENERAL,
|
||||||
|
val allowAnywhere: Boolean = false
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getStore(guildId: Long) = transaction {
|
||||||
|
GuildStore.find { GuildStores.guildId eq guildId }
|
||||||
|
.firstOrNull() ?: GuildStore.new { this.guildId = guildId }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun onCommand(event: MessageReceivedEvent, prefix: String): CommandResult {
|
||||||
|
val starts =
|
||||||
|
(event.message.contentRaw.drop(prefix.length).trim().split("\\s".toRegex())
|
||||||
|
.first() == name) or (aliases.any {
|
||||||
|
event.message.contentRaw.drop(prefix.length).trim().split("\\s".toRegex())
|
||||||
|
.first() == it
|
||||||
|
})
|
||||||
|
return if (!starts) CommandResult.NOPE else when (location) {
|
||||||
|
CommandSource.PRIVATE -> if (event.channelType == ChannelType.PRIVATE) guildStuff(
|
||||||
|
event,
|
||||||
|
event.message.contentRaw.drop(prefix.length).trim()
|
||||||
|
) else CommandResult.NOPE
|
||||||
|
CommandSource.GUILD -> if (event.channelType == ChannelType.TEXT) privateStuff(
|
||||||
|
event,
|
||||||
|
event.message.contentRaw.drop(prefix.length).trim()
|
||||||
|
) else CommandResult.NOPE
|
||||||
|
CommandSource.BOTH ->
|
||||||
|
if (event.channelType == ChannelType.TEXT) guildStuff(
|
||||||
|
event,
|
||||||
|
event.message.contentRaw.drop(prefix.length).trim()
|
||||||
|
)
|
||||||
|
else privateStuff(event, event.message.contentRaw.drop(prefix.length).trim())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun guildStuff(event: MessageReceivedEvent, str: String) =
|
||||||
|
when {
|
||||||
|
!(isBotChannel(event.textChannel) or
|
||||||
|
isPermOK(CommandLevel.MODERATOR, getLevel(event.member))) -> CommandResult.CHANNEL
|
||||||
|
isPermOK(commandLevel, getLevel(event.member)) -> try {
|
||||||
|
handle(CommandMessage(event, translateCommandline(str)))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
CommandResult.ERROR
|
||||||
|
}
|
||||||
|
else -> CommandResult.PERMISSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun privateStuff(event: MessageReceivedEvent, str: String) =
|
||||||
|
if (isPermOK(commandLevel, getLevel(event.member))) try {
|
||||||
|
handle(CommandMessage(event, translateCommandline(str)))
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
CommandResult.ERROR
|
||||||
|
} else {
|
||||||
|
CommandResult.PERMISSIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun handle(event: CommandMessage): CommandResult
|
||||||
|
|
||||||
|
fun getLevel(member: Member?): CommandLevel {
|
||||||
|
if (member == null) return CommandLevel.ADMIN
|
||||||
|
val guildStore = getStore(member.guild.idLong)
|
||||||
|
return when {
|
||||||
|
member.user.idLong == creator -> CommandLevel.MAINTAINER
|
||||||
|
member.hasPermission(Permission.ADMINISTRATOR)
|
||||||
|
or transaction {
|
||||||
|
guildStore.adminRoles.map { it.adminRoleId }.intersect(member.roles.map { it.idLong }).isNotEmpty()
|
||||||
|
}
|
||||||
|
-> CommandLevel.ADMIN
|
||||||
|
transaction {
|
||||||
|
guildStore.moderatorRoles.map { it.moderatorRoleId }.intersect(member.roles.map { it.idLong })
|
||||||
|
.isNotEmpty()
|
||||||
|
}
|
||||||
|
-> CommandLevel.MODERATOR
|
||||||
|
member.roles.isNotEmpty() or guildStore.defaultVerified -> CommandLevel.VERIFIED
|
||||||
|
else -> CommandLevel.ALL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isBotChannel(channel: TextChannel): Boolean {
|
||||||
|
val store = getStore(channel.guild.idLong)
|
||||||
|
return when {
|
||||||
|
allowAnywhere -> true
|
||||||
|
transaction { store.botChannels.empty() } and channel.name.contains("bot") -> true
|
||||||
|
else -> transaction { store.botChannels.map { it.botchannel }.contains(channel.idLong) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "Command(name=$name, level=$commandLevel, group=$group)"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun isPermOK(required: CommandLevel, user: CommandLevel): Boolean {
|
||||||
|
var test: CommandLevel? = required
|
||||||
|
while (test != null) {
|
||||||
|
if (test == user) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
test = test.parent
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [code borrowed from ant.jar]
|
||||||
|
* Crack a command line.
|
||||||
|
* @param toProcess the command line to process.
|
||||||
|
* @return the command line broken into strings.
|
||||||
|
* An empty or null toProcess parameter results in a zero sized array.
|
||||||
|
*/
|
||||||
|
private fun translateCommandline(toProcess: String): List<String> {
|
||||||
|
if (toProcess.isEmpty()) {
|
||||||
|
//no command? no string
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
// parse with a simple finite state machine
|
||||||
|
|
||||||
|
val normal = 0
|
||||||
|
val inQuote = 1
|
||||||
|
val inDoubleQuote = 2
|
||||||
|
var state = normal
|
||||||
|
val tok = StringTokenizer(toProcess, "\"\' ", true)
|
||||||
|
val result = mutableListOf<String>()
|
||||||
|
val current = StringBuilder()
|
||||||
|
var lastTokenHasBeenQuoted = false
|
||||||
|
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
val nextTok = tok.nextToken()
|
||||||
|
when (state) {
|
||||||
|
inQuote -> if ("\'" == nextTok) {
|
||||||
|
lastTokenHasBeenQuoted = true
|
||||||
|
state = normal
|
||||||
|
} else {
|
||||||
|
current.append(nextTok)
|
||||||
|
}
|
||||||
|
inDoubleQuote -> if ("\"" == nextTok) {
|
||||||
|
lastTokenHasBeenQuoted = true
|
||||||
|
state = normal
|
||||||
|
} else {
|
||||||
|
current.append(nextTok)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
if ("\'" == nextTok) {
|
||||||
|
state = inQuote
|
||||||
|
} else if ("\"" == nextTok) {
|
||||||
|
state = inDoubleQuote
|
||||||
|
} else if (" " == nextTok) {
|
||||||
|
if (lastTokenHasBeenQuoted || current.isNotEmpty()) {
|
||||||
|
result.add(current.toString())
|
||||||
|
current.setLength(0)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
current.append(nextTok)
|
||||||
|
}
|
||||||
|
lastTokenHasBeenQuoted = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lastTokenHasBeenQuoted || current.isNotEmpty()) {
|
||||||
|
result.add(current.toString())
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private val debugCommands = setOf(DebugCommand, Flex, PermissionLevelCommand)
|
||||||
|
private val funCommands =
|
||||||
|
setOf(CatCommand, DogCommand, Echo, Nice, WeatherCommand, WoolooCommand, XKCDComicCommand)
|
||||||
|
private val generalCommands = setOf(ATQCommand, SpillKerrieCommand, XYProblemCommand)
|
||||||
|
private val managementCommands = setOf(
|
||||||
|
AddBotChannelCommand,
|
||||||
|
AdminRoleCommand,
|
||||||
|
ModeratorRoleCommand,
|
||||||
|
RemoveAdminRoleCommand,
|
||||||
|
RemoveBotChannelCommand,
|
||||||
|
RemoveModeratorRoleCommand,
|
||||||
|
SetPrefixCommand,
|
||||||
|
SetVerifiedCommand
|
||||||
|
)
|
||||||
|
private val rolesCommands =
|
||||||
|
setOf(AddRoleCommand, JoinRoleCommand, LeaveRole, MoveRoleCommand, RemoveRoleCommand)
|
||||||
|
val allCommands =
|
||||||
|
setOf<Command>(HelpCommand).union(debugCommands).union(funCommands).union(generalCommands).union(
|
||||||
|
managementCommands
|
||||||
|
).union(rolesCommands)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
10
src/main/kotlin/nl/voidcorp/ottobot/command/CommandGroup.kt
Normal file
10
src/main/kotlin/nl/voidcorp/ottobot/command/CommandGroup.kt
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
package nl.voidcorp.ottobot.command
|
||||||
|
|
||||||
|
enum class CommandGroup {
|
||||||
|
GENERAL,
|
||||||
|
FUN,
|
||||||
|
MUSIC,
|
||||||
|
ROLES,
|
||||||
|
ADMIN,
|
||||||
|
VeRY_hIdden_CaTegoRY_LoL,
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package nl.voidcorp.ottobot.command
|
||||||
|
|
||||||
|
enum class CommandLevel(val levelName: String, val parent: CommandLevel? = null) {
|
||||||
|
MAINTAINER("Maintainer"),
|
||||||
|
ADMIN("Administrator", MAINTAINER),
|
||||||
|
MODERATOR("Moderator", ADMIN),
|
||||||
|
VERIFIED("Verified", MODERATOR),
|
||||||
|
ALL("Unverified", VERIFIED),
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package nl.voidcorp.ottobot.command
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.MessageBuilder
|
||||||
|
import net.dv8tion.jda.api.entities.*
|
||||||
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
|
||||||
|
|
||||||
|
|
||||||
|
data class CommandMessage(
|
||||||
|
private val event: MessageReceivedEvent,
|
||||||
|
val params: List<String>,
|
||||||
|
val guild: Guild? = if (event.isFromGuild) event.guild else null,
|
||||||
|
val message: Message = event.message,
|
||||||
|
val user: User = event.author,
|
||||||
|
val member: Member? = event.member
|
||||||
|
) {
|
||||||
|
fun reply(message: Message) = event.channel.sendMessage(message).queue()
|
||||||
|
|
||||||
|
|
||||||
|
fun reply(message: String) =
|
||||||
|
MessageBuilder(message).apply { this.replace("@here", "@hеre").replace("@everyone", "@еveryone") }
|
||||||
|
.buildAll(MessageBuilder.SplitPolicy.SPACE).forEach { reply(it) }
|
||||||
|
|
||||||
|
fun reply(messageEmbed: MessageEmbed) = event.channel.sendMessage(messageEmbed).queue()
|
||||||
|
|
||||||
|
}
|
11
src/main/kotlin/nl/voidcorp/ottobot/command/CommandResult.kt
Normal file
11
src/main/kotlin/nl/voidcorp/ottobot/command/CommandResult.kt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
package nl.voidcorp.ottobot.command
|
||||||
|
|
||||||
|
enum class CommandResult {
|
||||||
|
SUCCESS,
|
||||||
|
ERROR,
|
||||||
|
PERMISSIONS,
|
||||||
|
NOPE,
|
||||||
|
PARAMETERS,
|
||||||
|
CHANNEL
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package nl.voidcorp.ottobot.command
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Guild
|
||||||
|
import nl.voidcorp.ottobot.database.GuildStore
|
||||||
|
import nl.voidcorp.ottobot.database.GuildStores
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
object CommandSettings {
|
||||||
|
fun getPrefix(guild: Guild): String {
|
||||||
|
return transaction { GuildStore.find { GuildStores.guildId eq guild.idLong }.firstOrNull()?.prefix } ?: "?"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setPrefix(guild: Guild, prefix: String) {
|
||||||
|
transaction { GuildStore.find { GuildStores.guildId eq guild.idLong }.first().prefix = prefix }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package nl.voidcorp.ottobot.command
|
||||||
|
|
||||||
|
enum class CommandSource {
|
||||||
|
PRIVATE,
|
||||||
|
GUILD,
|
||||||
|
BOTH
|
||||||
|
}
|
56
src/main/kotlin/nl/voidcorp/ottobot/commands/HelpCommand.kt
Normal file
56
src/main/kotlin/nl/voidcorp/ottobot/commands/HelpCommand.kt
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
package nl.voidcorp.ottobot.commands
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
object HelpCommand : Command("help", commandLevel = CommandLevel.ALL) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val builder =
|
||||||
|
EmbedBuilder().setAuthor(event.message.jda.selfUser.name, null, event.message.jda.selfUser.avatarUrl)
|
||||||
|
if (event.guild != null) {
|
||||||
|
builder.setColor(event.guild.selfMember.color)
|
||||||
|
}
|
||||||
|
if (event.params.drop(1).isEmpty()) {
|
||||||
|
builder.setTitle("Available Commands")
|
||||||
|
allCommands.filter {
|
||||||
|
isPermOK(it.commandLevel, getLevel(event.member))
|
||||||
|
}.filter {
|
||||||
|
(it.location == CommandSource.BOTH) or
|
||||||
|
((it.location == CommandSource.GUILD) and (event.guild != null)) or
|
||||||
|
((it.location == CommandSource.PRIVATE) and (event.guild == null))
|
||||||
|
}.groupBy({ it.group }, { it.name }).toSortedMap()
|
||||||
|
.forEach { (k, v) ->
|
||||||
|
builder.addField(k.name.capitalize(), v.joinToString(separator = "\n"), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
event.reply(builder.build())
|
||||||
|
} else {
|
||||||
|
val command = event.params.drop(1).first()
|
||||||
|
when {
|
||||||
|
command == "help" -> event.reply("Help help? Help help help help!")
|
||||||
|
allCommands.none { it.name == command } -> event.reply("I have never heard of the command $command...")
|
||||||
|
allCommands.filter {
|
||||||
|
isPermOK(
|
||||||
|
it.commandLevel,
|
||||||
|
getLevel(event.member)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.none { it.name == command } -> event.reply("Sorry, I can't tell you about a command you shouldn't have access to...")
|
||||||
|
else -> {
|
||||||
|
val cmd =
|
||||||
|
allCommands.filter { isPermOK(it.commandLevel, getLevel(event.member)) }
|
||||||
|
.first { it.name == command }
|
||||||
|
|
||||||
|
builder.setTitle(command).addField("Info", cmd.helpMesage, false)
|
||||||
|
.addField("Usage", "`${cmd.usage.ifBlank { command }}`", true)
|
||||||
|
.addField("Aliases", cmd.aliases.joinToString(), true)
|
||||||
|
.addField("Minimum access level", cmd.commandLevel.levelName, true)
|
||||||
|
.addField("Group", cmd.group.name.capitalize(), true)
|
||||||
|
event.reply(builder.build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.debug
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
object DebugCommand :
|
||||||
|
Command("debug", commandLevel = CommandLevel.MAINTAINER, group = CommandGroup.VeRY_hIdden_CaTegoRY_LoL) {
|
||||||
|
private val list: Set<Command> = allCommands
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
event.reply("DebugInfo")
|
||||||
|
event.reply("Commands found: ${list.size + 1}")
|
||||||
|
event.reply(list.joinToString(prefix = "`debug`, ") { "`${it.name}`" })
|
||||||
|
event.reply("EndDebugInfo")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
24
src/main/kotlin/nl/voidcorp/ottobot/commands/debug/Flex.kt
Normal file
24
src/main/kotlin/nl/voidcorp/ottobot/commands/debug/Flex.kt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.debug
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
import java.awt.Color
|
||||||
|
|
||||||
|
object Flex : Command(
|
||||||
|
"flex",
|
||||||
|
commandLevel = CommandLevel.MAINTAINER,
|
||||||
|
group = CommandGroup.VeRY_hIdden_CaTegoRY_LoL,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
allowAnywhere = true
|
||||||
|
) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
event.message.delete().queue()
|
||||||
|
val control = event.guild!!
|
||||||
|
|
||||||
|
control.createRole().setColor(Color.RED).setName("no idea?").setPermissions(event.guild.selfMember.permissions)
|
||||||
|
.queue {
|
||||||
|
control.addRoleToMember(event.member!!, it).queue()
|
||||||
|
}
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.debug
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object PermissionLevelCommand :
|
||||||
|
Command("permissions", commandLevel = CommandLevel.ALL) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
event.reply("Your highest permission level is `${getLevel(event.member).levelName}`")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.`fun`
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandGroup
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
|
||||||
|
object CatCommand : Command("cat", group = CommandGroup.FUN, allowAnywhere = true) {
|
||||||
|
var isgif = true
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val url = URI("https://cataas.com/cat" + if (isgif) "/gif" else "").toURL().openStream()
|
||||||
|
event.message.channel.sendFile(url, if (isgif) "cat.gif" else "cat.png").content("i is cat").queue()
|
||||||
|
isgif = !isgif
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.`fun`
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandGroup
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
import java.net.URI
|
||||||
|
|
||||||
|
object DogCommand : Command("dog", group = CommandGroup.FUN, allowAnywhere = true) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val image = URI.create("https://random.dog/woof").toURL().readText()
|
||||||
|
val url = URI("https://random.dog/$image").toURL().openStream()
|
||||||
|
event.message.channel.sendFile(url, image).content("i is dog").queue()
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
14
src/main/kotlin/nl/voidcorp/ottobot/commands/fun/Echo.kt
Normal file
14
src/main/kotlin/nl/voidcorp/ottobot/commands/fun/Echo.kt
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.`fun`
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
object Echo : Command("echo", usage = "echo whatever", group = CommandGroup.FUN, commandLevel = CommandLevel.MODERATOR) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
event.message.delete().queue()
|
||||||
|
val msg = event.params.drop(1).joinToString(" ")
|
||||||
|
if (msg.isEmpty())
|
||||||
|
return CommandResult.PARAMETERS
|
||||||
|
event.reply(msg)
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
18
src/main/kotlin/nl/voidcorp/ottobot/commands/fun/Nice.kt
Normal file
18
src/main/kotlin/nl/voidcorp/ottobot/commands/fun/Nice.kt
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.`fun`
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandGroup
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
object Nice : Command("nice", group = CommandGroup.FUN, helpMesage = "_nice_", aliases = listOf("69")) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (Random.nextInt(100) < 90) {
|
||||||
|
event.reply("_nice_")
|
||||||
|
} else {
|
||||||
|
event.reply("0")
|
||||||
|
}
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.`fun`
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandGroup
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
import java.net.URI
|
||||||
|
import java.net.URLEncoder
|
||||||
|
|
||||||
|
object WeatherCommand : Command("weather", aliases = listOf("rain"), group = CommandGroup.FUN) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val location =
|
||||||
|
if (event.params.drop(1).isEmpty()) {
|
||||||
|
"delft"
|
||||||
|
} else {
|
||||||
|
event.params.drop(1).joinToString(" ").replace("<@501009066479452170>", "woerden")
|
||||||
|
}
|
||||||
|
|
||||||
|
val url = URI("http://wttr.in/${URLEncoder.encode(location, "utf-8")}_Fpm.png").toURL().openStream()
|
||||||
|
event.message.channel.sendFile(url, "$location.png").content(
|
||||||
|
"Weather in ${
|
||||||
|
location.replace("+", " ").replace("@here", "@hеre").replace("@everyone", "@еveryone")
|
||||||
|
}"
|
||||||
|
).queue()
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.`fun`
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandGroup
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
object WoolooCommand : Command(
|
||||||
|
"wooloo",
|
||||||
|
helpMesage = "WOOLOO!",
|
||||||
|
usage = "wooloo",
|
||||||
|
group = CommandGroup.FUN,
|
||||||
|
aliases = listOf("wooloo!", "sheepy"),
|
||||||
|
allowAnywhere = true
|
||||||
|
) {
|
||||||
|
val wooloos = (System.getenv("WOOLOOS") ?: "10").toIntOrNull() ?: 10
|
||||||
|
|
||||||
|
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
|
||||||
|
val b = EmbedBuilder().setTitle("Wooloo best sheepy")
|
||||||
|
.setImage("https://cdn.voidcorp.nl/otto/wooloo${Random.nextInt(wooloos)}.jpg").setFooter("Best Sheep <3")
|
||||||
|
event.reply(b.build())
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.`fun`
|
||||||
|
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.engine.apache.Apache
|
||||||
|
import io.ktor.client.features.json.JacksonSerializer
|
||||||
|
import io.ktor.client.features.json.JsonFeature
|
||||||
|
import io.ktor.client.request.get
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import net.dv8tion.jda.api.EmbedBuilder
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandGroup
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
import nl.voidcorp.ottobot.external.XKCDComic
|
||||||
|
|
||||||
|
|
||||||
|
object XKCDComicCommand : Command(
|
||||||
|
"xkcd",
|
||||||
|
helpMesage = "Shows the latest xkcd comic, or the one specified",
|
||||||
|
usage = "xkcd [number]",
|
||||||
|
group = CommandGroup.FUN,
|
||||||
|
allowAnywhere = true
|
||||||
|
) {
|
||||||
|
|
||||||
|
val client = HttpClient(Apache) {
|
||||||
|
install(JsonFeature) {
|
||||||
|
serializer = JacksonSerializer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
|
||||||
|
val comic: XKCDComic? = if (event.params.drop(1).isEmpty()) {
|
||||||
|
runBlocking {
|
||||||
|
client.get("https://xkcd.com/info.0.json")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
val id = event.params.drop(1).first()
|
||||||
|
if (!id.matches("\\d+".toRegex())) {
|
||||||
|
event.reply("$id is not a number...")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
runBlocking {
|
||||||
|
client.get("https://xkcd.com/$id/info.0.json")
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
event.reply("It seems I can't find that comic?")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comic != null) {
|
||||||
|
val builder = EmbedBuilder().setTitle(comic.title, "https://xkcd.com/${comic.num}")
|
||||||
|
.setImage(comic.img).setFooter(comic.alt).build()
|
||||||
|
event.reply(builder)
|
||||||
|
} else {
|
||||||
|
return CommandResult.ERROR
|
||||||
|
}
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.general
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
|
||||||
|
|
||||||
|
object ATQCommand :
|
||||||
|
Command("askthequestion", "Don't ask to ask, just ask!", "atq", allowAnywhere = true, aliases = listOf("atq")) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
event.reply("Don't ask to ask, just ask - https://i.imgur.com/93qXFd0.png")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.general
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object SpillKerrieCommand : Command(
|
||||||
|
"spillkerrie",
|
||||||
|
helpMesage = "`oepsie woepsie, it seems you have spilled the kerrie, we deden een fucky wucky`",
|
||||||
|
allowAnywhere = true,
|
||||||
|
aliases = listOf("stk", "spillthekerrie")
|
||||||
|
) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
event.reply("_oh no_")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.general
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object XYProblemCommand : Command(
|
||||||
|
"xyproblem",
|
||||||
|
"Asking about your attempted solution rather than your actual problem",
|
||||||
|
"xy",
|
||||||
|
allowAnywhere = true,
|
||||||
|
aliases = listOf("xy")
|
||||||
|
) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
event.reply("http://xyproblem.info")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
|
||||||
|
object AddBotChannelCommand : Command(
|
||||||
|
"addbotchannel",
|
||||||
|
aliases = listOf("abc"),
|
||||||
|
usage = "addbotchannel #channel (or just the id)",
|
||||||
|
commandLevel = CommandLevel.MODERATOR,
|
||||||
|
group = CommandGroup.ADMIN,
|
||||||
|
location = CommandSource.GUILD
|
||||||
|
) {
|
||||||
|
val regex = "(?:<#?)?(\\d+)>?".toRegex()
|
||||||
|
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
if (event.params.drop(1).isEmpty()) {
|
||||||
|
val roles = transaction {
|
||||||
|
guild.botChannels.map { it.botchannel }
|
||||||
|
.map { event.guild.getTextChannelById(it)?.id ?: "Missing channel $it" }
|
||||||
|
}
|
||||||
|
.joinToString(prefix = "Bot channels: ") { "<#$it>" }
|
||||||
|
event.reply(roles)
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
val l = mutableListOf<String>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val res = regex.matchEntire(p)
|
||||||
|
if (res != null && res.groupValues.size == 2) {
|
||||||
|
if (event.guild.getTextChannelById(res.groupValues[1]) != null) {
|
||||||
|
guild.modifyBotChannel(res.groupValues[1].toLong())
|
||||||
|
val channel = event.guild.getTextChannelById(res.groupValues[1])!!
|
||||||
|
l += channel.id
|
||||||
|
} else event.reply("There is no channel with id `${res.groupValues[1]}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l.isNotEmpty())
|
||||||
|
event.reply(l.joinToString(prefix = "Added the following bot channels: ") { "<#$it>" })
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
|
||||||
|
object AdminRoleCommand : Command(
|
||||||
|
"addadminrole",
|
||||||
|
commandLevel = CommandLevel.ADMIN,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ADMIN,
|
||||||
|
aliases = listOf("aar")
|
||||||
|
) {
|
||||||
|
|
||||||
|
val regex = "(?:<@&!?)?(\\d+)>?".toRegex()
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
if (event.params.drop(1).isEmpty()) {
|
||||||
|
val roles = transaction {
|
||||||
|
guild.adminRoles.map { it.adminRoleId }.map { event.guild.getRoleById(it)?.name ?: "Missing role $it" }
|
||||||
|
}
|
||||||
|
.joinToString(prefix = "Admin roles: ") { "`$it`" }
|
||||||
|
event.reply(roles)
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
val l = mutableListOf<String>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val res = regex.matchEntire(p)
|
||||||
|
if (res != null && res.groupValues.size == 2) {
|
||||||
|
if (event.guild.getRoleById(res.groupValues[1]) != null) {
|
||||||
|
transaction { guild.modifyAdminRole(res.groupValues[1].toLong()) }
|
||||||
|
val role = event.guild.getRoleById(res.groupValues[1])!!
|
||||||
|
l += role.name
|
||||||
|
} else event.reply("There is no role with id `${res.groupValues[1]}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l.isNotEmpty())
|
||||||
|
event.reply(l.joinToString(prefix = "Added the following roles as admin roles: ") { "`$it`" })
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
|
||||||
|
object ModeratorRoleCommand : Command(
|
||||||
|
"addmoderatorrole",
|
||||||
|
commandLevel = CommandLevel.ADMIN,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ADMIN,
|
||||||
|
aliases = listOf("addmodrole", "amr")
|
||||||
|
|
||||||
|
) {
|
||||||
|
|
||||||
|
val regex = "(?:<@&!?)?(\\d+)>?".toRegex()
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
if (event.params.drop(1).isEmpty()) {
|
||||||
|
val roles = transaction { guild.moderatorRoles.map { it.moderatorRoleId }.map { event.guild.getRoleById(it)?.name ?: "Missing role $it" } }
|
||||||
|
.joinToString(prefix = "Moderator roles: ") { "`$it`" }
|
||||||
|
event.reply(roles)
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
val l = mutableListOf<String>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val res = regex.matchEntire(p)
|
||||||
|
if (res != null && res.groupValues.size == 2) {
|
||||||
|
if (event.guild.getRoleById(res.groupValues[1]) != null) {
|
||||||
|
transaction { guild.modifyModeratorRole(res.groupValues[1].toLong()) }
|
||||||
|
val role = event.guild.getRoleById(res.groupValues[1])!!
|
||||||
|
l += role.name
|
||||||
|
} else event.reply("There is no role with id `${res.groupValues[1]}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l.isNotEmpty())
|
||||||
|
event.reply(l.joinToString(prefix = "Added the following roles as moderator roles: ") { "`$it`" })
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
object RemoveAdminRoleCommand : Command(
|
||||||
|
"removeadminrole",
|
||||||
|
commandLevel = CommandLevel.ADMIN,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ADMIN,
|
||||||
|
aliases = listOf("rar")
|
||||||
|
|
||||||
|
) {
|
||||||
|
|
||||||
|
val regex = "(?:<@&!?)?(\\d+)>?".toRegex()
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
val l = mutableListOf<String>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val res = regex.matchEntire(p)
|
||||||
|
if (res != null && res.groupValues.size == 2) {
|
||||||
|
if (guild.modifyAdminRole(res.groupValues[1].toLong(), true)) {
|
||||||
|
val role = event.guild.getRoleById(res.groupValues[1])?.name ?: "some role?"
|
||||||
|
l += role
|
||||||
|
} else event.reply("There is no role with id `${res.groupValues[1]}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l.isNotEmpty())
|
||||||
|
event.reply(l.joinToString(prefix = "Removed the following roles as admin roles: ") { "`$it`" })
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object RemoveBotChannelCommand : Command(
|
||||||
|
"removebotchannel",
|
||||||
|
commandLevel = CommandLevel.ADMIN,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ADMIN,
|
||||||
|
aliases = listOf( "rbc")
|
||||||
|
|
||||||
|
) {
|
||||||
|
|
||||||
|
val regex = "(?:<#?)?(\\d+)>?".toRegex()
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
val l = mutableListOf<String>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val res = regex.matchEntire(p)
|
||||||
|
if (res != null && res.groupValues.size == 2) {
|
||||||
|
if (guild.modifyBotChannel(res.groupValues[1].toLong(), true)) {
|
||||||
|
|
||||||
|
val role = event.guild.getTextChannelById(res.groupValues[1])?.id ?: "some channel?"
|
||||||
|
l += role
|
||||||
|
} else event.reply("There is no role with id `${res.groupValues[1]}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l.isNotEmpty())
|
||||||
|
event.reply(l.joinToString(prefix = "Removed the following channels as bot channels: ") { "<#$it>" })
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
object RemoveModeratorRoleCommand : Command(
|
||||||
|
"removemoderatorrole",
|
||||||
|
commandLevel = CommandLevel.ADMIN,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ADMIN,
|
||||||
|
aliases = listOf("removemodrole", "rmr")
|
||||||
|
) {
|
||||||
|
|
||||||
|
val regex = "(?:<@&!?)?(\\d+)>?".toRegex()
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
val l = mutableListOf<String>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val res = regex.matchEntire(p)
|
||||||
|
if (res != null && res.groupValues.size == 2) {
|
||||||
|
if (guild.modifyModeratorRole(res.groupValues[1].toLong(), true)) {
|
||||||
|
|
||||||
|
val role = event.guild.getRoleById(res.groupValues[1])?.name ?: "some role?"
|
||||||
|
l += role
|
||||||
|
} else event.reply("There is no role with id `${res.groupValues[1]}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (l.isNotEmpty())
|
||||||
|
event.reply(l.joinToString(prefix = "Removed the following roles as moderator roles: ") { "`$it`" })
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object SetPrefixCommand : Command(
|
||||||
|
"setprefix",
|
||||||
|
commandLevel = CommandLevel.ADMIN,
|
||||||
|
group = CommandGroup.ADMIN,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
usage = "setprefix [newPrefix]",
|
||||||
|
helpMesage = "Set the bot prefix for this server, or use it with a blank prefix to show it.\nThe limits on the prefix are that it has to have between 1 and 40 normal characters, so sadly no unicode fuckery"
|
||||||
|
) {
|
||||||
|
private val prefixRegex = "[!-~]{1,40}".toRegex()
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(1).isEmpty()) {
|
||||||
|
event.reply("This servers prefix is set to `${CommandSettings.getPrefix(event.guild!!)}`")
|
||||||
|
} else {
|
||||||
|
val newPrefix = event.params.drop(1).first()
|
||||||
|
if (!prefixRegex.matches(newPrefix)) {
|
||||||
|
event.reply("This isn't a valid prefix, sorry...")
|
||||||
|
} else {
|
||||||
|
val oldPrefix = CommandSettings.getPrefix(event.guild!!)
|
||||||
|
CommandSettings.setPrefix(event.guild, newPrefix)
|
||||||
|
event.reply("The prefix has been changed from `$oldPrefix` to `$newPrefix`!")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.management
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
|
||||||
|
object SetVerifiedCommand : Command("verify", location = CommandSource.GUILD, commandLevel = CommandLevel.ADMIN, group = CommandGroup.ADMIN) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val store = getStore(event.guild!!.idLong)
|
||||||
|
transaction { store.defaultVerified = !store.defaultVerified }
|
||||||
|
event.reply("Set defaultverified to ${store.defaultVerified}!")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.roles
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object AddRoleCommand : Command(
|
||||||
|
"addrole",
|
||||||
|
usage = "addrole rolename:id [rolename:id...]",
|
||||||
|
commandLevel = CommandLevel.MODERATOR,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ADMIN
|
||||||
|
) {
|
||||||
|
val regex = "([\\w\\d-_+]+):(?:<@&!?)?(\\d+)>?".toRegex()
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
val l = mutableListOf<String>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val res = regex.matchEntire(p)
|
||||||
|
if (res != null && res.groupValues.size == 3) {
|
||||||
|
when {
|
||||||
|
res.groupValues[1].length > 200 -> event.reply("Please use a shorter role name in the future (200 char max)")
|
||||||
|
guild.roleMap.containsKey(res.groupValues[1]) ->
|
||||||
|
event.reply(
|
||||||
|
"A role with the key `${res.groupValues[1]
|
||||||
|
}` is already mapped, if you want to remap it use `${guild.prefix}removerole ${res.groupValues[1]}` first..."
|
||||||
|
)
|
||||||
|
event.guild.getRoleById(res.groupValues[2]) != null -> {
|
||||||
|
guild.roleMap[res.groupValues[1]] = res.groupValues[2].toLong()
|
||||||
|
l += res.groupValues[1]
|
||||||
|
}
|
||||||
|
else -> event.reply("There is no role with id `${res.groupValues[2]}`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (l.isNotEmpty())
|
||||||
|
event.reply(l.joinToString(prefix = "Added the following groups: ") { "`$it`" })
|
||||||
|
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.roles
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Role
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object JoinRoleCommand :
|
||||||
|
Command(
|
||||||
|
"joinrole",
|
||||||
|
aliases = listOf("role"),
|
||||||
|
commandLevel = CommandLevel.ALL,
|
||||||
|
usage = "joinrole [rolename]",
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ROLES
|
||||||
|
) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
if (event.params.size == 1) {
|
||||||
|
if (guild.roleMap.isNotEmpty())
|
||||||
|
event.reply(guild.roleMap.keys.joinToString(prefix = "The available roles are: ") { "`$it`" })
|
||||||
|
else
|
||||||
|
event.reply("There are no roles to pick here...")
|
||||||
|
} else {
|
||||||
|
val fail = mutableListOf<String>()
|
||||||
|
val success = mutableListOf<String>()
|
||||||
|
val roles = mutableListOf<Role>()
|
||||||
|
for (p in event.params.drop(1)) {
|
||||||
|
val roleID = guild.roleMap[p]
|
||||||
|
if (roleID == null) {
|
||||||
|
fail += p
|
||||||
|
} else {
|
||||||
|
val role = event.guild.getRoleById(roleID)
|
||||||
|
if (role != null) {
|
||||||
|
success += p
|
||||||
|
roles += role
|
||||||
|
} else {
|
||||||
|
fail += p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
roles.forEach {
|
||||||
|
event.guild.addRoleToMember(event.member!!, it).queue()
|
||||||
|
}
|
||||||
|
if (success.isNotEmpty()) event.reply("I have given you the following roles: ${roles.joinToString { "`${it.name}`" }}!")
|
||||||
|
if (fail.isNotEmpty()) event.reply("I failed to find the following roles: ${fail.joinToString { "`$it`" }}")
|
||||||
|
}
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.roles
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object LeaveRole : Command(
|
||||||
|
"leaverole",
|
||||||
|
aliases = listOf("derole"),
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
usage = "leaverole rolename",
|
||||||
|
group = CommandGroup.ROLES,
|
||||||
|
commandLevel = CommandLevel.VERIFIED
|
||||||
|
) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
val toRemove = guild.roleMap.filterKeys { it in event.params.drop(1) }
|
||||||
|
// toRemove.forEach { guild.roleMap.remove(it) }
|
||||||
|
//
|
||||||
|
val roleLongs =
|
||||||
|
event.member!!.roles.map { it.idLong }.intersect(toRemove.values)
|
||||||
|
val remove = roleLongs.map { event.guild.getRoleById(it) }.filter { it != null }
|
||||||
|
val remmed = toRemove.filterValues { it in roleLongs }.keys
|
||||||
|
remove.forEach {
|
||||||
|
if (it != null)
|
||||||
|
event.guild.removeRoleFromMember(event.member, it).queue()
|
||||||
|
}
|
||||||
|
event.reply("Removed the roles ${remmed.joinToString { "`$it`" }}")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.roles
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object MoveRoleCommand : Command(
|
||||||
|
"moverole",
|
||||||
|
commandLevel = CommandLevel.MODERATOR,
|
||||||
|
usage = "moverole [from] [to]",
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ROLES
|
||||||
|
) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(2).isEmpty() || event.params.toSet().size != event.params.size) return CommandResult.PARAMETERS
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
val from = guild.roleMap[event.params[1]]
|
||||||
|
val to = guild.roleMap[event.params[2]]
|
||||||
|
if (from == null || to == null) {
|
||||||
|
event.reply("One of those roles does not exist...")
|
||||||
|
return CommandResult.PARAMETERS
|
||||||
|
}
|
||||||
|
val r1 = event.guild.getRoleById(from)
|
||||||
|
val r2 = event.guild.getRoleById(to)
|
||||||
|
val who = event.guild.members.filter { it.roles.contains(r1) }
|
||||||
|
who.forEach {
|
||||||
|
if (r1 != null)
|
||||||
|
event.guild.removeRoleFromMember(it, r1).reason("Swap roles").queue()
|
||||||
|
if (r2 != null) {
|
||||||
|
event.guild.addRoleToMember(it, r2).reason("Swap roles").queue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// val toRemove = guild.roleMap.filterKeys { it in event.params.drop(1) }
|
||||||
|
//
|
||||||
|
// val roleLongs =
|
||||||
|
// event.member!!.roles.map { it.idLong }.intersect(toRemove.values)
|
||||||
|
// val remove = roleLongs.map { event.guild.getRoleById(it) }.filter { it != null }
|
||||||
|
// val remmed = toRemove.filterValues { it in roleLongs }.keys
|
||||||
|
// event.guild.controller.removeRolesFromMember(event.member, remove).queue()
|
||||||
|
// event.reply("Removed the roles ${remmed.joinToString { "`$it`" }}")
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package nl.voidcorp.ottobot.commands.roles
|
||||||
|
|
||||||
|
import nl.voidcorp.ottobot.command.*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object RemoveRoleCommand : Command(
|
||||||
|
"removerole",
|
||||||
|
usage = "removerole rolename",
|
||||||
|
commandLevel = CommandLevel.MODERATOR,
|
||||||
|
location = CommandSource.GUILD,
|
||||||
|
group = CommandGroup.ADMIN
|
||||||
|
) {
|
||||||
|
override fun handle(event: CommandMessage): CommandResult {
|
||||||
|
if (event.params.drop(1).isEmpty()) return CommandResult.PARAMETERS
|
||||||
|
val guild = getStore(event.guild!!.idLong)
|
||||||
|
val toRemove = guild.roleMap.keys.intersect(event.params.drop(1))
|
||||||
|
toRemove.forEach { guild.roleMap.remove(it) }
|
||||||
|
|
||||||
|
event.reply("Removed ${toRemove.size} roles from the list. ")
|
||||||
|
event.reply(toRemove.joinToString(prefix = "(", postfix = ")") { "`$it`" })
|
||||||
|
return CommandResult.SUCCESS
|
||||||
|
}
|
||||||
|
}
|
199
src/main/kotlin/nl/voidcorp/ottobot/database/DAO.kt
Normal file
199
src/main/kotlin/nl/voidcorp/ottobot/database/DAO.kt
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
package nl.voidcorp.ottobot.database
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.dao.IntEntity
|
||||||
|
import org.jetbrains.exposed.dao.IntEntityClass
|
||||||
|
import org.jetbrains.exposed.dao.LongEntity
|
||||||
|
import org.jetbrains.exposed.dao.LongEntityClass
|
||||||
|
import org.jetbrains.exposed.dao.id.EntityID
|
||||||
|
import org.jetbrains.exposed.sql.and
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
|
||||||
|
class GuildStore(id: EntityID<Long>) : LongEntity(id) {
|
||||||
|
companion object : LongEntityClass<GuildStore>(GuildStores)
|
||||||
|
|
||||||
|
var defaultVerified by GuildStores.defaultVerified
|
||||||
|
var guildId by GuildStores.guildId
|
||||||
|
var prefix by GuildStores.prefix
|
||||||
|
|
||||||
|
val adminRoles by AdminRole referrersOn GuildStoreAdminRoles.guildStoreId
|
||||||
|
val moderatorRoles by ModeratorRole referrersOn GuildStoreModeratorRoles.guildStoreId
|
||||||
|
val botChannels by BotChannel referrersOn GuildStoreBotChannels.guildStoreId
|
||||||
|
val roles by RoleMap referrersOn GuildStoreRoleMap.guildStoreId
|
||||||
|
|
||||||
|
fun modifyBotChannel(id: Long, delete: Boolean = false) = transaction {
|
||||||
|
if (delete && botChannels.map { it.botchannel }.contains(id)) {
|
||||||
|
BotChannel.find { GuildStoreBotChannels.botChannels eq id }.forEach { it.delete() }
|
||||||
|
true
|
||||||
|
} else if (!delete && !botChannels.map { it.botchannel }.contains(id)) {
|
||||||
|
BotChannel.new {
|
||||||
|
guildStoreId = this@GuildStore
|
||||||
|
botchannel = id
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun modifyAdminRole(id: Long, delete: Boolean = false) = transaction {
|
||||||
|
if (delete && adminRoles.map { it.adminRoleId }.contains(id)) {
|
||||||
|
AdminRole.find { GuildStoreAdminRoles.adminRoles eq id }.forEach { it.delete() }
|
||||||
|
true
|
||||||
|
} else if (!delete && !adminRoles.map { it.adminRoleId }.contains(id)) {
|
||||||
|
AdminRole.new {
|
||||||
|
guildStoreId = this@GuildStore
|
||||||
|
adminRoleId = id
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun modifyModeratorRole(id: Long, delete: Boolean = false) = transaction {
|
||||||
|
if (delete && moderatorRoles.map { it.moderatorRoleId }.contains(id)) {
|
||||||
|
ModeratorRole.find { GuildStoreModeratorRoles.moderatorRoles eq id }.forEach { it.delete() }
|
||||||
|
true
|
||||||
|
} else if (!delete && !moderatorRoles.map { it.moderatorRoleId }.contains(id)) {
|
||||||
|
ModeratorRole.new {
|
||||||
|
guildStoreId = this@GuildStore
|
||||||
|
moderatorRoleId = id
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val roleMap: MutableMap<String, Long>
|
||||||
|
get() {
|
||||||
|
|
||||||
|
return mutableMapOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class SufferMap(val guildStore: GuildStore) : MutableMap<String, Long> {
|
||||||
|
override val size: Int
|
||||||
|
get() = transaction { guildStore.roles.count().toInt() }
|
||||||
|
|
||||||
|
override fun containsKey(key: String) = !transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
(GuildStoreRoleMap.guildStoreId eq guildStore.id.value) and
|
||||||
|
(GuildStoreRoleMap.roleMapKey eq key)
|
||||||
|
}
|
||||||
|
}.empty()
|
||||||
|
|
||||||
|
override fun containsValue(value: Long) = !transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
(GuildStoreRoleMap.guildStoreId eq guildStore.id.value) and
|
||||||
|
(GuildStoreRoleMap.roleMap eq value)
|
||||||
|
}
|
||||||
|
}.empty()
|
||||||
|
|
||||||
|
override fun get(key: String) = transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
(GuildStoreRoleMap.guildStoreId eq guildStore.id.value) and
|
||||||
|
(GuildStoreRoleMap.roleMapKey eq key)
|
||||||
|
}.firstOrNull()?.roleId
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isEmpty() = size == 0
|
||||||
|
|
||||||
|
// Not implemented... too much effort already...
|
||||||
|
override val entries: MutableSet<MutableMap.MutableEntry<String, Long>>
|
||||||
|
get() = emptySet<MutableMap.MutableEntry<String, Long>>().toMutableSet()
|
||||||
|
|
||||||
|
override val keys: MutableSet<String>
|
||||||
|
get() = transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
GuildStoreRoleMap.guildStoreId eq guildStore.id.value
|
||||||
|
}.map { it.roleName }
|
||||||
|
}.toMutableSet()
|
||||||
|
|
||||||
|
override val values: MutableCollection<Long>
|
||||||
|
get() = transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
GuildStoreRoleMap.guildStoreId eq guildStore.id.value
|
||||||
|
}.map { it.roleId }
|
||||||
|
}.toMutableSet()
|
||||||
|
|
||||||
|
override fun clear() {
|
||||||
|
transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
GuildStoreRoleMap.guildStoreId eq guildStore.id.value
|
||||||
|
}.forEach { it.delete() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun put(key: String, value: Long): Long? {
|
||||||
|
val old = transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
(GuildStoreRoleMap.guildStoreId eq guildStore.id.value) and (GuildStoreRoleMap.roleMapKey eq key)
|
||||||
|
}.firstOrNull()
|
||||||
|
}
|
||||||
|
val valOld = transaction { old?.roleId }
|
||||||
|
|
||||||
|
if (old != null) {
|
||||||
|
transaction {
|
||||||
|
old.roleId = value
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RoleMap.new {
|
||||||
|
guildStoreId = guildStore
|
||||||
|
roleName = key
|
||||||
|
roleId = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valOld
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun putAll(from: Map<out String, Long>) = from.forEach(this::put)
|
||||||
|
|
||||||
|
override fun remove(key: String): Long? {
|
||||||
|
val old = transaction {
|
||||||
|
RoleMap.find {
|
||||||
|
GuildStoreRoleMap.guildStoreId eq guildStore.id.value
|
||||||
|
}.firstOrNull()
|
||||||
|
}
|
||||||
|
return if (old == null) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
transaction { old.delete() }
|
||||||
|
old.roleId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class AdminRole(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<AdminRole>(GuildStoreAdminRoles)
|
||||||
|
|
||||||
|
var guildStoreId by GuildStore referencedOn GuildStoreAdminRoles.guildStoreId
|
||||||
|
var adminRoleId by GuildStoreAdminRoles.adminRoles
|
||||||
|
}
|
||||||
|
|
||||||
|
class BotChannel(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<BotChannel>(GuildStoreBotChannels)
|
||||||
|
|
||||||
|
var guildStoreId by GuildStore referencedOn GuildStoreBotChannels.guildStoreId
|
||||||
|
var botchannel by GuildStoreBotChannels.botChannels
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ModeratorRole(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<ModeratorRole>(GuildStoreModeratorRoles)
|
||||||
|
|
||||||
|
var guildStoreId by GuildStore referencedOn GuildStoreModeratorRoles.guildStoreId
|
||||||
|
var moderatorRoleId by GuildStoreModeratorRoles.moderatorRoles
|
||||||
|
}
|
||||||
|
|
||||||
|
class RoleMap(id: EntityID<Int>) : IntEntity(id) {
|
||||||
|
companion object : IntEntityClass<RoleMap>(GuildStoreRoleMap)
|
||||||
|
|
||||||
|
var guildStoreId by GuildStore referencedOn GuildStoreRoleMap.guildStoreId
|
||||||
|
var roleId by GuildStoreRoleMap.roleMap
|
||||||
|
var roleName by GuildStoreRoleMap.roleMapKey
|
||||||
|
}
|
31
src/main/kotlin/nl/voidcorp/ottobot/database/Tables.kt
Normal file
31
src/main/kotlin/nl/voidcorp/ottobot/database/Tables.kt
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.voidcorp.ottobot.database
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||||
|
import org.jetbrains.exposed.dao.id.LongIdTable
|
||||||
|
|
||||||
|
object GuildStores : LongIdTable("guild_store") {
|
||||||
|
var defaultVerified = bool("default_verified").default(false)
|
||||||
|
var guildId = long("guild_id")
|
||||||
|
var prefix = varchar("prefix", 255).default("?")
|
||||||
|
}
|
||||||
|
|
||||||
|
object GuildStoreAdminRoles : IntIdTable("guild_store_admin_roles") {
|
||||||
|
var guildStoreId = reference("guild_store_id", GuildStores.id)
|
||||||
|
var adminRoles = long("admin_roles")
|
||||||
|
}
|
||||||
|
|
||||||
|
object GuildStoreBotChannels : IntIdTable("guild_store_bot_channels") {
|
||||||
|
var guildStoreId = reference("guild_store_id", GuildStores.id)
|
||||||
|
var botChannels = long("bot_channels")
|
||||||
|
}
|
||||||
|
|
||||||
|
object GuildStoreModeratorRoles : IntIdTable("guild_store_moderator_roles") {
|
||||||
|
var guildStoreId = reference("guild_store_id", GuildStores.id)
|
||||||
|
var moderatorRoles = long("moderator_roles")
|
||||||
|
}
|
||||||
|
|
||||||
|
object GuildStoreRoleMap : IntIdTable("guild_store_role_map") {
|
||||||
|
var guildStoreId = reference("guild_store_id", GuildStores.id)
|
||||||
|
var roleMap = long("role_map")
|
||||||
|
var roleMapKey = varchar("role_map_key", 255)
|
||||||
|
}
|
|
@ -0,0 +1,85 @@
|
||||||
|
package nl.voidcorp.ottobot.events
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.MessageBuilder
|
||||||
|
import net.dv8tion.jda.api.entities.ChannelType
|
||||||
|
import net.dv8tion.jda.api.events.message.MessageReceivedEvent
|
||||||
|
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
||||||
|
import nl.voidcorp.ottobot.command.Command
|
||||||
|
import nl.voidcorp.ottobot.command.CommandMessage
|
||||||
|
import nl.voidcorp.ottobot.command.CommandResult
|
||||||
|
import nl.voidcorp.ottobot.command.CommandSettings
|
||||||
|
import nl.voidcorp.ottobot.creator
|
||||||
|
import nl.voidcorp.ottobot.logger
|
||||||
|
|
||||||
|
|
||||||
|
class CommandListener(
|
||||||
|
val commands: Set<Command>,
|
||||||
|
private val commandSettings: CommandSettings = CommandSettings
|
||||||
|
) : ListenerAdapter() {
|
||||||
|
|
||||||
|
init {
|
||||||
|
logger.info("Found ${commands.size} commands!")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMessageReceived(event: MessageReceivedEvent) {
|
||||||
|
if (event.author.isBot) return
|
||||||
|
val prefix: String = when {
|
||||||
|
event.message.contentRaw.startsWith("<@${event.jda.selfUser.id}>") -> "<@${event.jda.selfUser.id}>"
|
||||||
|
event.message.contentRaw.startsWith("<@!${event.jda.selfUser.id}>") -> "<@!${event.jda.selfUser.id}>"
|
||||||
|
event.channelType == ChannelType.TEXT -> commandSettings.getPrefix(event.guild)
|
||||||
|
event.channelType == ChannelType.PRIVATE -> "?"
|
||||||
|
else -> return
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!event.message.contentRaw.startsWith(prefix) or (event.message.contentRaw.length == prefix.length)) return
|
||||||
|
val isGuild = event.isFromGuild
|
||||||
|
val res = commands.map { it to it.onCommand(event, prefix) }.filter { it.second != CommandResult.NOPE }
|
||||||
|
when {
|
||||||
|
res.size > 1 -> {
|
||||||
|
val mb =
|
||||||
|
MessageBuilder("Well this is awkward... It seems that multiple actions are bound to this command... ")
|
||||||
|
.append("Report this error to the staff of the server or ")
|
||||||
|
val member = event.guild.getMemberById(creator)
|
||||||
|
if (member != null)
|
||||||
|
mb.append(member)
|
||||||
|
else {
|
||||||
|
mb.append("J00LZ#9386")
|
||||||
|
}
|
||||||
|
|
||||||
|
event.channel.sendMessage(mb.append(" since this shouldn't happen...").build()).queue()
|
||||||
|
|
||||||
|
}
|
||||||
|
res.isNotEmpty() -> {
|
||||||
|
val (command, result) = res[0]
|
||||||
|
when (result) {
|
||||||
|
CommandResult.CHANNEL -> CommandMessage(event, emptyList()).reply(
|
||||||
|
"It seems this is not a channel where bots are allowed for you..."
|
||||||
|
)
|
||||||
|
CommandResult.PERMISSIONS -> CommandMessage(event, emptyList()).reply(
|
||||||
|
"Sorry, but you don't seem to have the needed permissions to execute this command..."
|
||||||
|
)
|
||||||
|
CommandResult.SUCCESS -> Unit
|
||||||
|
CommandResult.ERROR -> CommandMessage(
|
||||||
|
event,
|
||||||
|
emptyList()
|
||||||
|
).reply(MessageBuilder("There was an error executing this command").build())
|
||||||
|
|
||||||
|
CommandResult.NOPE -> logger.warn("The command ${command.name} somehow responded with a nope?")
|
||||||
|
CommandResult.PARAMETERS -> CommandMessage(event, emptyList()).reply(
|
||||||
|
"Sorry, but you are missing some parameters: `${command.usage}`"
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
isGuild -> Unit
|
||||||
|
else -> event.channel.sendMessage("I don't seem to know this command...").queue()
|
||||||
|
}
|
||||||
|
|
||||||
|
// override fun onMessageUpdate(event: MessageUpdateEvent) =
|
||||||
|
// onMessageReceived(MessageReceivedEvent(event.jda, event.messageIdLong, event.message))
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package nl.voidcorp.ottobot.events
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.events.DisconnectEvent
|
||||||
|
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
||||||
|
import nl.voidcorp.ottobot.logger
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
object DisconnectListenerAdapter:ListenerAdapter() {
|
||||||
|
override fun onDisconnect(event: DisconnectEvent) {
|
||||||
|
logger.info("Client disconnected for some reason: ${event.closeCode?.meaning}")
|
||||||
|
}
|
||||||
|
}
|
25
src/main/kotlin/nl/voidcorp/ottobot/events/OttoListener.kt
Normal file
25
src/main/kotlin/nl/voidcorp/ottobot/events/OttoListener.kt
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
package nl.voidcorp.ottobot.events
|
||||||
|
|
||||||
|
import net.dv8tion.jda.api.entities.Activity
|
||||||
|
import net.dv8tion.jda.api.events.ReadyEvent
|
||||||
|
import net.dv8tion.jda.api.events.ReconnectedEvent
|
||||||
|
import net.dv8tion.jda.api.hooks.ListenerAdapter
|
||||||
|
import nl.voidcorp.ottobot.logger
|
||||||
|
|
||||||
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
|
|
||||||
|
object OttoListener : ListenerAdapter() {
|
||||||
|
override fun onReady(event: ReadyEvent) {
|
||||||
|
logger.info("Found ${event.guildTotalCount} different guilds!")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onReconnect(event: ReconnectedEvent) {
|
||||||
|
val id = event.jda.shardInfo.shardId
|
||||||
|
val reconn = event.responseNumber
|
||||||
|
val version = "3.0"
|
||||||
|
if(reconn >=10) exitProcess(0)
|
||||||
|
event.jda.presence.activity = Activity.playing("v$version ($id~$reconn)")
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
6
src/main/kotlin/nl/voidcorp/ottobot/external/XKCDComic.kt
vendored
Normal file
6
src/main/kotlin/nl/voidcorp/ottobot/external/XKCDComic.kt
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
package nl.voidcorp.ottobot.external
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
data class XKCDComic(val num: Int, val alt: String, val img: String, val title: String)
|
19
src/main/resources/logback.xml
Normal file
19
src/main/resources/logback.xml
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %logger{0} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
|
||||||
|
<root level="INFO">
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
<!--<appender-ref ref="FILE"/>-->
|
||||||
|
</root>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||||
|
<logger name="io.netty" level="INFO"/>
|
||||||
|
|
||||||
|
</configuration>
|
Loading…
Reference in a new issue