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