+ First release
0.1.0 released on 15. Oct. 2024
+
+ Repo created in 2024 This is the kotlin refactored version
+
+ Licenced under MIT since made public
+
diff --git a/build.gradle.kts b/build.gradle.kts
index 7bec2c99..7184aab1 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,29 +1,86 @@
plugins {
application
- id("com.gradleup.shadow") version("8.3.0")
- id("java")
+ kotlin("jvm") version "2.2.0"
+ kotlin("plugin.serialization") version "2.2.0"
+ id("com.gradleup.shadow") version("8.3.3")
+ id("io.gitlab.arturbosch.detekt").version("1.23.7")
}
-application.mainClass = "dev.vxrp.bot.ScpTools" //
+
+application.mainClass = "dev.vxrp.MainKt"
group = "dev.vxrp"
-version = "1.0-SNAPSHOT"
+version= "1.1.1"
-val jdaVersion = "5.0.0-beta.24" //
+kotlin {
+ jvmToolchain(22)
+}
repositories {
mavenCentral()
}
+val ktorVersion = "3.2.3"
+val kotlinxCoroutinesVersion = "1.10.2"
+
+val exposedVersion = "0.61.0"
+val sqliteVersion = "3.50.3.0"
+val mySqlVersion = "9.4.0"
+val postgresSqlVersion = "42.7.7"
+val mariaDBVersion = "3.5.6"
+
+val kotlinxSerializationVersion = "1.9.0"
+val kamlVersion = "0.85.0"
+val jdaVersion = "5.6.1"
+val jdaKtxVersion = "0.12.0"
+val secretLabKotlinVersion = "0.4.3"
+val logbackVersion = "1.5.18"
+val gsonVersion = "2.13.1"
+
dependencies {
- implementation("net.dv8tion:JDA:$jdaVersion")
- implementation("ch.qos.logback:logback-classic:1.5.6")
- testImplementation(platform("org.junit:junit-bom:5.10.0"))
- testImplementation("org.junit.jupiter:junit-jupiter")
- implementation("org.bspfsystems:yamlconfiguration:2.0.2")
- implementation("org.apache.commons:commons-lang3:3.4")
- implementation("com.google.code.gson:gson:2.11.0")
+ // Default
+ implementation("io.ktor:ktor-server-netty:$ktorVersion")
+ implementation("io.ktor:ktor-client-core:$ktorVersion")
+ implementation("io.ktor:ktor-client-cio:$ktorVersion")
+ implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
+ implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxCoroutinesVersion")
+
+ // Database tools and drivers
+ implementation("org.jetbrains.exposed:exposed-core:$exposedVersion")
+ implementation("org.jetbrains.exposed:exposed-jdbc:$exposedVersion")
+ implementation("org.xerial:sqlite-jdbc:$sqliteVersion")
+ implementation("com.mysql:mysql-connector-j:$mySqlVersion")
+ implementation("org.postgresql:postgresql:$postgresSqlVersion")
+ implementation("org.mariadb.jdbc:mariadb-java-client:$mariaDBVersion")
+
+ // Config and Serialization
+ implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
+ implementation("com.charleskorn.kaml:kaml:$kamlVersion")
+
+ // Discord api implementation + Logback
+ implementation("net.dv8tion:JDA:$jdaVersion") {
+ exclude(module = "opus-java")
+ }
+ implementation("ch.qos.logback:logback-classic:$logbackVersion")
+ implementation("club.minnced:jda-ktx:$jdaKtxVersion")
+
+ // Api Wrapper
+ implementation("io.github.vxrpenter:secretlab-kotlin:$secretLabKotlinVersion")
+
+ // String and JSON tooling
+ implementation("com.google.code.gson:gson:$gsonVersion")
+}
+
+val createVersionProperties by tasks.registering(WriteProperties::class) {
+ val filePath = sourceSets.main.map {
+ it.output.resourcesDir!!.resolve("dev/vxrp/version.properties")
+ }
+ destinationFile = filePath
+
+ property("version", project.version.toString())
+}
+
+tasks.classes {
+ dependsOn(createVersionProperties)
}
-tasks.test {
- useJUnitPlatform()
-}
\ No newline at end of file
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 00000000..b4b6e601
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,7 @@
+services:
+ bot:
+ image: vxrpenter/scptoolsbot:latest
+ ports:
+ - "8080:8080"
+ volumes:
+ - ${CONFIG_PATH}/SCPToolsBot/:/bot/SCPToolsBot/
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c0f80adb..a8f7a692 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
#Fri Aug 16 15:20:05 CEST 2024
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+exposedVersion=0.56.0
\ No newline at end of file
diff --git a/gradlew b/gradlew
old mode 100644
new mode 100755
diff --git a/installer.sh b/installer.sh
new file mode 100755
index 00000000..4063ddc2
--- /dev/null
+++ b/installer.sh
@@ -0,0 +1,516 @@
+#!/bin/bash
+
+#
+# Copyright (c) 2024 Vxrpenter and the SCPToolsBot Contributors
+#
+# Licenced under the MIT License, any non-license compliant usage of this file(s) content
+# is prohibited. If you did not receive a copy of the license with this file, you
+# may obtain the license at
+#
+# https://mit-license.org/
+#
+# This software may be used commercially if the usage is license compliant. The software
+# is provided without any sort of WARRANTY, and the authors cannot be held liable for
+# any form of claim, damages or other liabilities.
+#
+# Note: This is no legal advice, please read the license conditions
+#
+
+#
+# Everything with comment has to be worked on
+#
+
+# Installation Values
+export filename="NULL"
+export installType=""
+export repo="https://github.com/Vxrpenter/SCPToolsBot"
+export version="1.1.1"
+export configPath=""
+
+# Jar Installation
+export versionLink="${repo}/releases/download/v${version}/SCP_Tools-${version}.jar"
+export filename="SCP_Tools-${version}.jar"
+
+# Base Configuration Values
+export botToken=""
+export botSecret=""
+export botGuildId=""
+export botLanguage="en_US"
+
+# Webserver Configuration Values
+export webServerActive=false
+export webServerPort=80
+export webServerRedirectUri="/auth/discord/redirect"
+export webServerUri=""
+
+# Cedmod Configuration Values
+export cedmodActive=false
+export cedmodInstanceUrl=""
+export cedmodApiKey=""
+
+echo "
+ ______ ______ ______ ______ ______ ______ __ ______
+ /\ ___\ /\ ___\ /\ == \ /\__ _\ /\ __ \ /\ __ \ /\ \ /\ ___\\
+ \ \___ \ \ \ \____ \ \ _-/ \/_/\ \/ \ \ \/\ \ \ \ \/\ \ \ \ \____ \ \___ \\
+ \/\_____\ \ \_____\ \ \_\ \ \_\ \ \_____\ \ \_____\ \ \_____\ \/\_____\\
+ \/_____/ \/_____/ \/_/ \/_/ \/_____/ \/_____/ \/_____/ \/_____/
+
+Copyright (c) 2024 Vxrpenter
+"
+
+
+# Basic Functions
+function confirm() {
+ read -rp ":: Do you wish to proceed? [Y/n]: " response
+ case $response in
+ [Nn]* )
+ echo "Stopping installation, exiting..."
+ exit
+ esac
+}
+
+# Root Check
+if [ "$UID" -ne "0" ]; then
+ echo "This script needs to be run as root"
+ exit 9
+fi
+
+# Java Checker
+#
+# This part of the script is based of on this post on stackoverflow https://stackoverflow.com/questions/7334754/correct-way-to-check-java-version-from-bash-script/7335524#7335524
+if type -p java > /dev/null 2>&1; then
+ echo "Found java in executable PATH"
+ _java=java
+elif [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
+ echo "Found java executable in JAVA_HOME"
+ _java="$JAVA_HOME/bin/java"
+else
+ echo "No java installation found, please install java 22 or higher using your distributions package manager"
+fi
+
+if [[ "$_java" ]]; then
+ jarVersion=$("$_java" -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1)
+ if [[ "$jarVersion" -lt 22 ]]; then
+ echo "Java version lower than 22, please upgrade your java installation"
+ exit
+ fi
+fi
+echo "Correct java version for bot is installed, proceeding with installation..."
+echo ""
+
+function jarInstall() {
+ curl -LO $versionLink
+
+ echo ""
+ echo "Executing jar-file to generate configuration files..."
+
+ sudo java -jar $filename > /dev/null 2>&1
+ configPath=$(pwd)
+}
+
+function dockerInstall() {
+ echo ""
+ read -rp ":: Please enter the config bind path? Default [/var/lib/ScpTools/]: " response
+ case $response in
+ "" )
+ echo "Using default config bind path: /var/lib/ScpTools/"
+ configPath="/var/lib/ScpTools/"
+ ;;
+ * )
+ echo "Using config bind path: $response"
+ configPath=$response
+ esac
+
+ echo ""
+ echo "Cloning repository branch $version"
+ git clone --depth 1 --branch $version $repo > /dev/null 2>&1
+ cd SCPToolsBot/ || exit > /dev/null 2>&1
+
+ echo ""
+ echo "Setting config bind path in .env file"
+ env="CONFIG_PATH = ${configPath}"
+ echo "$env" > ".env"
+
+ systemctl start docker > /dev/null 2>&1
+
+ sudo docker compose up > /dev/null 2>&1 & pid=$!
+
+ # This spinner code has been mostly taken from stackoverflow - https://stackoverflow.com/a/12498305
+ spin[0]="⠁"
+ spin[1]="⠂"
+ spin[2]="⠄"
+ spin[3]="⡀"
+ spin[4]="⢀"
+ spin[5]="⠠"
+ spin[6]="⠐"
+ spin[7]="⠈"
+
+ echo ""
+ echo -en "Running docker compose up, this can take a few minutes, don't stop your machine: ${spin[0]}"
+
+ tput civis
+ while kill -0 $pid 2> /dev/null; do
+ for i in "${spin[@]}"; do
+ echo -ne "\b$i"
+
+
+ sleep 0.1
+ done
+ done
+ tput cnorm
+
+ echo "Concluded compose, shutting down..."
+ sudo docker compose down > /dev/null 2>&1
+}
+
+function chooseInstall() {
+ echo ""
+ echo "What install do you want to pursue?"
+ PS3=":: Choose install method: "
+ select installOption in Jar Docker
+ do
+ installType=$installOption
+ break
+ done
+
+ case $installType in
+ Jar )
+ jarInstall
+ ;;
+ Docker )
+ dockerInstall
+ ;;
+ * )
+ echo "This is no install method, please repeat..."
+ chooseInstall
+ esac
+}
+
+echo "Do you want to proceed with the installation?"
+confirm
+
+chooseInstall
+
+echo ""
+echo "Bot process has concluded, do you want to do a complete installation with configuration or end it here?"
+confirm
+
+# Token Configuration
+echo ""
+echo "The bot token can be obtained from the discord developer portal!"
+function token() {
+ read -rp ":: What is your bot token?: " tokenResponse
+
+ read -rp ":: Please repeat token for confirmation: " response
+ if [ "$tokenResponse" == "$response" ]; then
+ botToken=$tokenResponse
+ else
+ echo "Tokens don't match, please try entering it again"
+ token
+ fi
+}
+token
+
+# Secret Configuration
+echo ""
+echo "The bot secret can be obtained from the discord developer portal under the OAuth section!"
+function secret() {
+ read -rp ":: What is your bot secret?: " secretResponse
+
+ read -rp ":: Please repeat secret for confirmation: " response
+ if [ "$secretResponse" == "$response" ]; then
+ botSecret=$secretResponse
+ else
+ echo "Secrets don't match, please try entering it again"
+ token
+ fi
+}
+secret
+
+# Guild Configuration
+echo ""
+echo "The guild id can be obtained by activating developer mode and right clicking the server!"
+function guild() {
+ read -rp ":: What is your bot guildId?: " guildResponse
+
+ read -rp ":: Please repeat id for confirmation: " response
+ if [ "$guildResponse" == "$response" ]; then
+ botGuildId=$guildResponse
+ else
+ echo "Id's don't match, please try entering it again"
+ token
+ fi
+}
+guild
+
+# Language Configuration
+echo ""
+echo "What language preset do you want to use?"
+PS3=":: Enter number of the language option: "
+select option in English German
+do
+ language=$option
+ break
+done
+
+case $language in
+ English )
+ botLanguage="en_US"
+ ;;
+ German )
+ botLanguage="de_DE"
+ ;;
+ * )
+ echo "This is no language, exiting..."
+ exit
+esac
+
+# Webserver Configuration
+function webserver() {
+ # Port Configuration
+ echo ""
+ echo "What port do you want the webserver to run under?"
+ read -rp ":: Enter port here: " port
+
+ webServerPort=$port
+
+ echo ""
+ echo "What firewall do you want to add the port to?"
+ PS3=":: Add to firewall with: "
+ select portOption in UFW SKIP
+ do
+ firewallType=$portOption
+ break
+ done
+
+ case $firewallType in
+ UFW )
+ ufw allow "$webServerPort"
+ ;;
+ SKIP )
+ echo "Skipping firewall setup, make sure to setup yourself to make webserver work"
+ ;;
+ * )
+ echo "This is no firewall, exiting..."
+ exit
+ esac
+
+ # Redirect Uri Configuration
+ echo ""
+ echo "Enter in a URI that you want the OAuth redirect to be at: "
+ read -rp ":: Enter redirect here: [leave empty to go with default]: " redirect
+ case $redirect in
+ "" )
+ echo "Using default $webServerRedirectUri"
+ ;;
+ * )
+ webServerRedirectUri=$redirect
+ esac
+
+ # Uri Configuration
+ echo ""
+ echo "Enter Url of your server, ip or domain with 'http://' or 'https://'!"
+ read -rp ":: Enter url: " uri
+
+ webServerUri=$uri
+
+ echo ""
+ echo "Finished up webserver setup, proceeding with further configuration"
+}
+
+echo ""
+echo "Do you want to set up webserver? This is used for OAuth requests and needed for some features."
+function confirmWebserver() {
+ read -rp ":: Do you wish to proceed? [y/N]: " response
+ case $response in
+ [Yy]* )
+ webServerActive=true
+ webserver
+ ;;
+ * )
+ echo "Skipping webserver setup"
+ esac
+}
+confirmWebserver
+
+# CedMod Configuration
+function cedmod() {
+ # Instance Url Configuration
+ echo ""
+ echo "Enter in the url of your CedMod instance, including 'https'!"
+ read -rp ":: Enter Url: " url
+ cedmodInstanceÚrl=$url
+
+ # Api Key Configuration
+ echo ""
+ echo "Enter in the api key of your CedMod instance"
+ read -rp ":: Enter api key: " api
+ cedmodApiKey=$api
+
+ echo ""
+ echo "Finished up CedMod setup, proceeding with further configuration"
+}
+
+echo ""
+echo "Do you want to set up cedmod api integration? This is used for some features to request data from the server."
+function confirmCedMod() {
+ read -rp ":: Do you wish to proceed [y/N]: " response
+ case $response in
+ [Yy]* )
+ cedmodActive=true
+ cedmod
+ ;;
+ * )
+ echo "Skipping CedMod setup"
+ esac
+}
+confirmCedMod
+
+# End of configuration States
+echo ""
+echo "Do you want to write the configured values to the config?"
+confirm
+
+#
+# Here comes the YAML Parser and the configuration writer stuff
+#
+config="# ______ ______ ______ ______ ______ ______ __ ______
+# /\ ___\ /\ ___\ /\ == \ /\__ _\ /\ __ \ /\ __ \ /\ \ /\ ___\\
+# \ \___ \ \ \ \____ \ \ _-/ \/_/\ \/ \ \ \/\ \ \ \ \/\ \ \ \ \____ \ \___ \\
+# \/\_____\ \ \_____\ \ \_\ \ \_\ \ \_____\ \ \_____\ \ \_____\ \/\_____\\
+# \/_____/ \/_____/ \/_/ \/_/ \/_____/ \/_____/ \/_____/ \/_____/
+#Copyright (c) 2024 Vxrpenter
+
+# The token of your bot application, create one here https://discord.com/developers/
+token: \"$botToken\"
+# The client secret of your bot, get it from here https://discord.com/developers/ under OAuth section
+client_secret: \"$botSecret\"
+# Your server ID, you can get it by activating discord developer mode and right-clicking your server
+guild_id: \"$botGuildId\"
+
+# Which language should the bot use?
+#Choose from these supported languages or duplicate one of the translation files and change it yourself
+# available translations: [\"en_US\", \"de_DE\"]
+load_translation: \"$botLanguage\"
+
+# Activates debug logging, which gives you much more information on what the bot is doing.
+debug: false
+# ** Warning ** This feature is not recommended
+#Displays all available information
+advanced_debug: false
+
+# Settings for the update checker
+updates:
+ # Activate to ignore all versions that contain the beta tag
+ ignore_beta: false
+ # Activate to ignore all versions that contain the alpha tag
+ ignore_alpha: true
+
+# The activity type of the bot, choose from the available list: [COMPETING, CUSTOM_STATUS, LISTENING, PLAYING, WATCHING]
+activity_type: \"PLAYING\"
+# The text that is being displayed in the activity
+activity_content: \"/help\"
+
+database:
+ # Defines which datatype should be used, choose between [NONE, SQLITE]
+ # ** WARNING ** if you set this to none, and no other database option is given, the process will crash on startup
+ use_predefined_database_sets: \"SQLITE\"
+ # ** WARNING ** When using custom, you may experience issues. This is a work in progress feature, so it is unstable, report problems on the GitHub page
+ # Which type of custom db should be used: [SQLITE, MYSQL, POSTGRESQL, MARIADB]
+ custom_type: \"\"
+ # Here you can input a custom database url to connect to. Make sure to not include https:// or http://, just use the plain url for
+ # database connection, e.g., < localhost:3306/test >
+ custom_url: \"\"
+ # Here you've input the custom db password
+ custom_username: \"\"
+ # Here you have to enter the password of your db session
+ custom_password: \"\"
+
+webserver:
+ # Should the webserver be launched? This feature is only used for regulars
+ active: $webServerActive
+ # The port under which the webserver will be launched
+ port: $webServerPort
+ # What uri to start the webserver under
+ redirect_uri: \"$webServerRedirectUri\"
+ # Where should the redirect be?
+ uri: \"$webServerUri\"
+
+cedmod:
+ # This activates the CedMod Api integration. This feature is only used for the following functions, only activated if you have these features in use: Regulars
+ # CedMod Api is only available to users who request access from the CedMod team, ask on their discord for more information - https://discord.gg/p69SGfwxxm
+ active: false
+ # Include https://
+ instance_url: \"\"
+ # Put the plain API key here
+ api_key: \"\"
+
+# ** NOTICE ** Custom level functions are currently not supported because of technical complexity
+# This is a work-in-progress compatibility implementation of the XP plugin by RowspannSCP https://github.com/RowpannSCP/XP. It is intended to be used with the
+# regulars feature for providing additional goals for playtime roles. This feature is highly WIP and will probably take a bit longer to implement, as I have to
+# inspect their code to find some necessary information. The current config options are subject to change.
+XP:
+ # This activates the XP integration. This feature is only used for the following functions, only activated if you have these features in use: Regulars
+ active: false
+ # ** WARNING ** LiteDB will not be supported in any coming version as it would be really challenging to implement, in the end, bringing no real advantage
+ # The address of the database which the plugin uses. If the plugin and bot are running on the same DB, the bot will identify it and not connect to the database
+ # a second time and just pull data from the existing connection. Make sure you give the bot's user enough rights to do so.
+ # Example database address: < localhost:3306/test >
+ database_address: \"\"
+ # The username of the database user you want the bot to use
+ database_user: \"\"
+ # The password of the user you want the bot to use
+ database_password: \"\"
+ # ** WARNING ** To keep this feature as simple as possible, there will only be one auth type supported. Also, Northwood authtype is currently not supported
+ # Which type of authorization table do you want to query from?
+ # Available auth types are [STEAM, DISCORD]
+ auth_type: \"\"
+ # This affects the 'a' parameter in the standard level function. This is the standard function used by the XP plugin: -50 + sqrt((4 * xp / a) + 9800) / 2
+ additional_parameter: 1
+
+# ** WARNING ** For this setting to work, you need to activate the webserver.
+# The webserver is generally just a redirect to receive data from the discord OAuth Api, so it
+# should not interrupt any other web stuff running on your server.
+verify:
+ # Activates the verify feature, make sure you have configured webserver accordingly
+ active: false
+ # This link can be obtained from the oauth section on the discord developer portal. First, enter the redirect you entered in the webserver section exactly
+ # as described here: