1
0

Initial commit

This commit is contained in:
Jannik Reimers 2024-10-01 12:57:44 +02:00 committed by GitHub
commit 5307298dae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
41 changed files with 2485 additions and 0 deletions

12
.editorconfig Normal file

@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
insert_final_newline = true
indent_style = tab
trim_trailing_whitespace = true
max_line_length = 120
[*.yml]
indent_style = space
indent_size = 2

7
.env.example Normal file

@ -0,0 +1,7 @@
# THIS IS A TEMPLATE FILE. MAKE A COPY AND RENAME TO `.env` TO USE.
# https://discord.com/developers
TOKEN=BOT_TOKEN
# ID of the server to use for testing
TEST_SERVER=123

6
.gitattributes vendored Normal file

@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

2
.github/boring-cyborg.yml vendored Normal file

@ -0,0 +1,2 @@
# Boring Cyborg: https://probot.github.io/apps/boring-cyborg/
_extends: ".github"

2
.github/config.yml vendored Normal file

@ -0,0 +1,2 @@
# to-do: https://probot.github.io/apps/todo/
_extends: ".github"

15
.github/dependabot.yml vendored Normal file

@ -0,0 +1,15 @@
version: 2
enable-beta-ecosystems: true
updates:
- package-ecosystem: "gradle"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

2
.github/settings.yml vendored Normal file

@ -0,0 +1,2 @@
# Settings: https://probot.github.io/apps/settings/
_extends: ".github"

43
.github/workflows/ci.yml vendored Normal file

@ -0,0 +1,43 @@
name: Build (CI)
on:
push:
branches-ignore:
- root
- develop
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- name: Gradle (Setup)
uses: gradle/actions/setup-gradle@v4
- name: Gradle (Build)
run: "./gradlew build"
- name: Upload artifacts (Main JAR)
uses: actions/upload-artifact@v4
with:
name: Main JAR
path: build/libs/*-all.jar
- name: Upload artifacts (JARs)
uses: actions/upload-artifact@v4
with:
name: JARs
path: build/libs/*.jar

40
.github/workflows/develop.yml vendored Normal file

@ -0,0 +1,40 @@
name: Build & Publish
on:
push:
branches:
- develop
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- name: Gradle (Setup)
uses: gradle/actions/setup-gradle@v4
- name: Gradle (Build)
run: "./gradlew build"
- name: Upload artifacts (Main JAR)
uses: actions/upload-artifact@v4
with:
name: Main JAR
path: build/libs/*-all.jar
- name: Upload artifacts (JARs)
uses: actions/upload-artifact@v4
with:
name: JARs
path: build/libs/*.jar

43
.github/workflows/root.yml vendored Normal file

@ -0,0 +1,43 @@
name: Build & Publish
on:
push:
branches:
- root
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: 17
distribution: temurin
- name: Gradle (Setup)
uses: gradle/actions/setup-gradle@v4
with:
dependency-graph: generate-and-submit
- name: Gradle (Build)
run: "./gradlew build"
- name: Upload artifacts (Main JAR)
uses: actions/upload-artifact@v4
with:
name: Main JAR
path: build/libs/*-all.jar
- name: Upload artifacts (JARs)
uses: actions/upload-artifact@v4
with:
name: JARs
path: build/libs/*.jar

116
.gitignore vendored Normal file

@ -0,0 +1,116 @@
# Created by .ignore support plugin (hsz.mobi)
### Kotlin template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### Custom rules
# Don't ignore Gradle wrapper
!gradle/**/*
# Local Gradle cache
.gradle
# Gradle build output folder
build/
.kotlin/
# Data files generated by the bot in testing
data/
# Env vars - don't commit this!
.env

8
.idea/.gitignore generated vendored Normal file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/../../../../../../../:\Users\coles\IdeaProjects\kordex\template\.idea/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

13
.idea/compiler.xml generated Normal file

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="13">
<module name="ext-common" target="1.8" />
<module name="ext-common.main" target="1.8" />
<module name="ext-common.test" target="1.8" />
<module name="template.buildSrc" target="17" />
<module name="template.buildSrc.main" target="17" />
<module name="template.buildSrc.test" target="17" />
</bytecodeTargetLevel>
</component>
</project>

6
.idea/discord.xml generated Normal file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
</component>
</project>

8
.idea/file.template.settings.xml generated Normal file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExportableFileTemplateSettings">
<default_templates>
<template name="KordEx Extension.kt" file-name="${DIR_PATH}/${NAME}Extension" reformat="true" live-template-enabled="false" />
</default_templates>
</component>
</project>

14
.idea/fileTemplates/KordEx Extension.kt generated Normal file

@ -0,0 +1,14 @@
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}
#end
import com.kotlindiscord.kord.extensions.extensions.Extension
#set($extName = $NAME.toLowerCase())
#parse("File Header.java")
class ${NAME}Extension : Extension() {
override val name = "$extName"
override suspend fun setup() {
TODO("Not yet implemented")
}
}

6
.idea/git_toolbox_blame.xml generated Normal file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxBlameSettings">
<option name="version" value="2" />
</component>
</project>

20
.idea/git_toolbox_prj.xml generated Normal file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationConfigOverride">
<CommitMessageValidationOverride>
<option name="enabled" value="true" />
</CommitMessageValidationOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

80
.idea/jarRepositories.xml generated Normal file

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="KotDis" />
<option name="name" value="KotDis" />
<option name="url" value="https://maven.kotlindiscord.com/repository/maven-public/" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenLocal" />
<option name="name" value="MavenLocal" />
<option name="url" value="file:/$MAVEN_REPOSITORY$/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="Kotlin Discord" />
<option name="name" value="Kotlin Discord" />
<option name="url" value="https://maven-beta.kotlindiscord.com/snapshots/" />
</remote-repository>
<remote-repository>
<option name="id" value="SonaType" />
<option name="name" value="SonaType" />
<option name="url" value="https://oss.sonatype.org/content/repositories/snapshots" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="Sonatype Snapshots" />
<option name="name" value="Sonatype Snapshots" />
<option name="url" value="https://s01.oss.sonatype.org/content/repositories/snapshots" />
</remote-repository>
<remote-repository>
<option name="id" value="Gradle Central Plugin Repository" />
<option name="name" value="Gradle Central Plugin Repository" />
<option name="url" value="https://plugins.gradle.org/m2" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://repo.kordex.dev/snapshots" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://repo.kordex.dev/releases" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://snapshots-repo.kordex.dev" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://releases-repo.kordex.dev" />
</remote-repository>
</component>
</project>

6
.idea/kotlinc.xml generated Normal file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="KotlinJpsPluginSettings">
<option name="version" value="2.0.20" />
</component>
</project>

@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="libraries-with-intellij-classes">
<option name="intellijApiContainingLibraries">
<list>
<LibraryCoordinatesState>
<option name="artifactId" value="ideaIU" />
<option name="groupId" value="com.jetbrains.intellij.idea" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="ideaIU" />
<option name="groupId" value="com.jetbrains" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="ideaIC" />
<option name="groupId" value="com.jetbrains.intellij.idea" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="ideaIC" />
<option name="groupId" value="com.jetbrains" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="pycharmPY" />
<option name="groupId" value="com.jetbrains.intellij.pycharm" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="pycharmPY" />
<option name="groupId" value="com.jetbrains" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="pycharmPC" />
<option name="groupId" value="com.jetbrains.intellij.pycharm" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="pycharmPC" />
<option name="groupId" value="com.jetbrains" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="clion" />
<option name="groupId" value="com.jetbrains.intellij.clion" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="clion" />
<option name="groupId" value="com.jetbrains" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="riderRD" />
<option name="groupId" value="com.jetbrains.intellij.rider" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="riderRD" />
<option name="groupId" value="com.jetbrains" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="goland" />
<option name="groupId" value="com.jetbrains.intellij.goland" />
</LibraryCoordinatesState>
<LibraryCoordinatesState>
<option name="artifactId" value="goland" />
<option name="groupId" value="com.jetbrains" />
</LibraryCoordinatesState>
</list>
</option>
</component>
</project>

9
.idea/markdown.xml generated Normal file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MarkdownSettings">
<enabledExtensions>
<entry key="MermaidLanguageExtension" value="false" />
<entry key="PlantUMLLanguageExtension" value="false" />
</enabledExtensions>
</component>
</project>

11
.idea/misc.xml generated Normal file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$/../ext-common" />
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_13" project-jdk-name="temurin-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

23
.idea/runConfigurations/Build.xml generated Normal file

@ -0,0 +1,23 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Build" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

28
.idea/runConfigurations/Run.xml generated Normal file

@ -0,0 +1,28 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run" type="GradleRunConfiguration" factoryName="Gradle">
<ExternalSystemSettings>
<option name="env">
<map>
<entry key="ENVIRONMENT" value="dev" />
</map>
</option>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="run" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<method v="2" />
</configuration>
</component>

6
.idea/vcs.xml generated Normal file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

24
LICENSE Normal file

@ -0,0 +1,24 @@
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org>

62
README.md Normal file

@ -0,0 +1,62 @@
# KordEx Bot Template
This repository contains a basic KordEx example bot for you to use as a template for your own KordEx bots. This
includes the following:
- A basic extension that allows you to slap other people, using both chat commands and slash commands.
- A basic bot configuration that enables slash commands and shows you how to conditionally provide a different
chat command prefix for different guilds.
- A Gradle Kotlin build script that uses the KordEx Gradle plugin and Detekt for linting (with a
fairly strict configuration) this uses Gradle 7's new version catalogue feature, for easy configuration of
dependencies.
- GitHub CI scripts that build the bot and publish its artefacts.
- A reasonable `.gitignore` file, including one in the `.idea` folder that ignores files that you shouldn't commit
if you're using IDEA yourself, you should install the Ignore plugin to handle changes to this for you.
- A Groovy-based Logback config, so you have reasonable logging out of the box.
- Automatic generation of a Dockerfile via a `createDockerFile` task, also run at build time.
**Note:** This template includes a `.editorconfig` file that defaults to using tabs for indentation in almost all file
types. This is because tabs are more accessible for the blind, or those with impaired vision. We won't accept
feedback or PRs targeting this approach, though you can always change it in your projects.
## Potential Changes
- The `.yml` files in `.github/` are used to configure GitHub apps. If you're not using them, you can remove them.
- The provided `LICENSE` file contains The Unlicense, which makes this repository public domain. You will probably want
to change this—we suggest looking at [Choose a License](https://choosealicense.com/) if you're not sure where to
start.
- In the `build.gradle.kts`:
- Set the `group` and `version` properties as appropriate.
- In the `kordEx` and `tasks.jar` block, update the main class path/name as appropriate.
- In the `kordEx` block, update the KordEx version if needed.
- In the `settings.gradle.kts`, update the name of the root project as appropriate.
- The bundled Detekt config is pretty strict—you can check over `detekt.yml` if you want to change it, but you need to
follow the to-dos in that file regardless.
- The Logback configuration is in `src/main/resources/logback.groovy`. If the logging setup doesn't suit, you can change
it there.
## Bundled Bot
- `App.kt` includes a basic bot, which uses environment variables (or variables in a `.env` file) for the testing guild
ID (`TEST_SERVER`) and the bot's token (`TOKEN`). You can specify these either directly as environment variables, or
as `KEY=value` pairs in a file named `.env`. Some example code is also included that shows one potential way of
providing different command prefixes for different servers.
- `TestExtension.kt` includes an example extension that creates a `slap` command - this command works as both a
message command and slash command, and allows you to slap other users with whatever you wish, defaulting to a
`large, smelly trout`.
To test the bot, we recommend using a `.env` file that looks like the following:
```dotenv
TOKEN=abc...
TEST_SERVER=123...
```
Create this file, fill it out, and run the `run` gradle task for testing in development.
## Further Reading
To learn more about KordEx and how to work with it, [please browse the documentation](https://docs.kordex.dev).
For more information on the KordEx Gradle plugin and what you can do with it,
[please read this README](https://github.com/Kord-Extensions/gradle-plugins#kordex-plugin).

87
build.gradle.kts Normal file

@ -0,0 +1,87 @@
import dev.kordex.gradle.plugins.docker.file.*
import dev.kordex.gradle.plugins.kordex.DataCollection
plugins {
kotlin("jvm")
kotlin("plugin.serialization")
id("com.github.johnrengelman.shadow")
id("io.gitlab.arturbosch.detekt")
id("dev.kordex.gradle.docker")
id("dev.kordex.gradle.kordex")
}
group = "template"
version = "1.0-SNAPSHOT"
dependencies {
detektPlugins(libs.detekt)
implementation(libs.kotlin.stdlib)
implementation(libs.kx.ser)
// Logging dependencies
implementation(libs.groovy)
implementation(libs.jansi)
implementation(libs.logback)
implementation(libs.logback.groovy)
implementation(libs.logging)
}
kordEx {
kordExVersion = "2.2.1-SNAPSHOT"
bot {
// See https://docs.kordex.dev/data-collection.html
dataCollection(DataCollection.Standard)
mainClass = "template.AppKt"
}
}
detekt {
buildUponDefaultConfig = true
config.from(rootProject.files("detekt.yml"))
}
// Automatically generate a Dockerfile. Set `generateOnBuild` to `false` if you'd prefer to manually run the
// `createDockerfile` task instead of having it run whenever you build.
docker {
// Create the Dockerfile in the root folder.
file(rootProject.file("Dockerfile"))
commands {
// Each function (aside from comment/emptyLine) corresponds to a Dockerfile instruction.
// See: https://docs.docker.com/reference/dockerfile/
from("openjdk:21-jdk-slim")
emptyLine()
runShell("mkdir -p /bot/plugins")
runShell("mkdir -p /bot/data")
emptyLine()
copy("build/libs/$name-*-all.jar", "/bot/bot.jar")
emptyLine()
// Add volumes for locations that you need to persist. This is important!
volume("/bot/data") // Storage for data files
volume("/bot/plugins") // Plugin ZIP/JAR location
emptyLine()
workdir("/bot")
emptyLine()
entryPointExec(
"java", "-Xms2G", "-Xmx2G",
"-jar", "/bot/bot.jar"
)
}
}

679
detekt.yml Normal file

@ -0,0 +1,679 @@
# TODO: Update `rootPackage` in naming -> InvalidPackageDeclaration
build:
maxIssues: 0
excludeCorrectable: false
weights:
# complexity: 2
# LongParameterList: 1
# style: 1
# comments: 1
config:
validation: true
# when writing own rules with new properties, exclude the property path e.g.: 'my_rule_set,.*>.*>[my_property]'
excludes: ''
processors:
active: true
exclude:
- 'DetektProgressListener'
- 'FunctionCountProcessor'
- 'PropertyCountProcessor'
- 'ClassCountProcessor'
- 'PackageCountProcessor'
- 'KtFileCountProcessor'
console-reports:
active: true
exclude:
- 'ProjectStatisticsReport'
- 'NotificationReport'
- 'FileBasedFindingsReport'
output-reports:
active: true
exclude:
# - 'HtmlOutputReport'
- 'TxtOutputReport'
# - 'XmlOutputReport'
comments:
active: true
AbsentOrWrongFileLicense:
active: false
licenseTemplateFile: 'license.template'
CommentOverPrivateFunction:
active: false
CommentOverPrivateProperty:
active: false
EndOfSentenceFormat:
active: true
endOfSentenceFormat: '([.?!][ \t\n\r\f<])|([.?!:]$)'
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
UndocumentedPublicClass:
active: false
searchInNestedClass: true
searchInInnerClass: true
searchInInnerObject: true
searchInInnerInterface: true
UndocumentedPublicFunction:
active: false
UndocumentedPublicProperty:
active: false
complexity:
active: true
ComplexCondition:
active: true
threshold: 10
ComplexInterface:
active: false
threshold: 10
includeStaticDeclarations: false
includePrivateDeclarations: false
ComplexMethod:
active: false
threshold: 15
ignoreSingleWhenExpression: false
ignoreSimpleWhenEntries: false
ignoreNestingFunctions: false
nestingFunctions: [ run, let, apply, with, also, use, forEach, isNotNull, ifNull ]
LabeledExpression:
active: false
ignoredLabels: [ ]
LargeClass:
active: false
threshold: 600
LongMethod:
active: false
threshold: 60
LongParameterList:
active: false
functionThreshold: 6
constructorThreshold: 7
ignoreDefaultParameters: false
ignoreDataClasses: true
ignoreAnnotated: [ ]
MethodOverloading:
active: false
threshold: 6
NestedBlockDepth:
active: false
threshold: 4
ReplaceSafeCallChainWithRun:
active: true
StringLiteralDuplication:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
threshold: 3
ignoreAnnotation: true
excludeStringsWithLessThan5Characters: true
ignoreStringsRegex: '$^'
TooManyFunctions:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
thresholdInFiles: 11
thresholdInClasses: 11
thresholdInInterfaces: 11
thresholdInObjects: 11
thresholdInEnums: 11
ignoreDeprecated: false
ignorePrivate: false
ignoreOverridden: false
coroutines:
active: true
GlobalCoroutineUsage:
active: true
RedundantSuspendModifier:
active: true
SuspendFunWithFlowReturnType:
active: true
empty-blocks:
active: true
EmptyCatchBlock:
active: true
allowedExceptionNameRegex: '^(_|(ignore|expected).*)'
EmptyClassBlock:
active: true
EmptyDefaultConstructor:
active: true
EmptyDoWhileBlock:
active: true
EmptyElseBlock:
active: true
EmptyFinallyBlock:
active: true
EmptyForBlock:
active: true
EmptyFunctionBlock:
active: true
ignoreOverridden: false
EmptyIfBlock:
active: true
EmptyInitBlock:
active: true
EmptyKtFile:
active: true
EmptySecondaryConstructor:
active: true
EmptyTryBlock:
active: true
EmptyWhenBlock:
active: true
EmptyWhileBlock:
active: true
exceptions:
active: true
ExceptionRaisedInUnexpectedLocation:
active: true
methodNames: [ toString, hashCode, equals, finalize ]
InstanceOfCheckForException:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
NotImplementedDeclaration:
active: false
PrintStackTrace:
active: true
RethrowCaughtException:
active: true
ReturnFromFinally:
active: true
ignoreLabeled: false
SwallowedException:
active: false
ignoredExceptionTypes:
- InterruptedException
- NumberFormatException
- ParseException
- MalformedURLException
allowedExceptionNameRegex: '^(_|(ignore|expected).*)'
ThrowingExceptionFromFinally:
active: true
ThrowingExceptionInMain:
active: true
ThrowingExceptionsWithoutMessageOrCause:
active: true
exceptions:
- IllegalArgumentException
- IllegalStateException
- IOException
ThrowingNewInstanceOfSameException:
active: true
TooGenericExceptionCaught:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
exceptionNames:
- ArrayIndexOutOfBoundsException
- Error
- Exception
- IllegalMonitorStateException
- NullPointerException
- IndexOutOfBoundsException
- RuntimeException
- Throwable
allowedExceptionNameRegex: '^(_|(ignore|expected).*)'
TooGenericExceptionThrown:
active: true
exceptionNames:
- Error
- Exception
- Throwable
- RuntimeException
formatting:
active: true
android: false
autoCorrect: true
AnnotationOnSeparateLine:
active: true
autoCorrect: true
AnnotationSpacing:
active: true
autoCorrect: true
ArgumentListWrapping:
active: false # It's wrong!
autoCorrect: true
ChainWrapping:
active: true
autoCorrect: true
CommentSpacing:
active: true
autoCorrect: true
EnumEntryNameCase:
active: true
autoCorrect: true
Filename:
active: true
FinalNewline:
active: true
autoCorrect: true
insertFinalNewLine: true
ImportOrdering:
active: true
autoCorrect: true
layout: "*,java.**,javax.**,kotlin.**,^"
Indentation:
active: false
autoCorrect: false
indentSize: 4
continuationIndentSize: 4
MaximumLineLength:
active: true
maxLineLength: 120
ModifierOrdering:
active: true
autoCorrect: true
MultiLineIfElse:
active: true
autoCorrect: true
NoBlankLineBeforeRbrace:
active: true
autoCorrect: true
NoConsecutiveBlankLines:
active: true
autoCorrect: true
NoEmptyClassBody:
active: true
autoCorrect: true
NoEmptyFirstLineInMethodBlock:
active: true
autoCorrect: true
NoLineBreakAfterElse:
active: true
autoCorrect: true
NoLineBreakBeforeAssignment:
active: true
autoCorrect: true
NoMultipleSpaces:
active: false
autoCorrect: false
NoSemicolons:
active: true
autoCorrect: true
NoTrailingSpaces:
active: true
autoCorrect: true
NoUnitReturn:
active: true
autoCorrect: true
NoUnusedImports:
active: true
autoCorrect: true
NoWildcardImports:
active: false
PackageName:
active: true
autoCorrect: true
ParameterListWrapping:
active: true
autoCorrect: true
indentSize: 4
SpacingAroundColon:
active: true
autoCorrect: true
SpacingAroundComma:
active: true
autoCorrect: true
SpacingAroundCurly:
active: true
autoCorrect: true
SpacingAroundDot:
active: true
autoCorrect: true
SpacingAroundDoubleColon:
active: true
autoCorrect: true
SpacingAroundKeyword:
active: true
autoCorrect: true
SpacingAroundOperators:
active: true
autoCorrect: true
SpacingAroundParens:
active: true
autoCorrect: true
SpacingAroundRangeOperator:
active: true
autoCorrect: true
SpacingBetweenDeclarationsWithAnnotations:
active: true
autoCorrect: true
SpacingBetweenDeclarationsWithComments:
active: true
autoCorrect: true
StringTemplate:
active: true
autoCorrect: true
naming:
active: true
ClassNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
classPattern: '[A-Z$][a-zA-Z0-9$]*'
ConstructorParameterNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
parameterPattern: '[a-z][A-Za-z0-9]*'
privateParameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
EnumNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
enumEntryPattern: '^[A-Z][_a-zA-Z0-9]*'
ForbiddenClassName:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
forbiddenName: [ ]
FunctionMaxLength:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
maximumFunctionNameLength: 30
FunctionMinLength:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
minimumFunctionNameLength: 3
FunctionNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
functionPattern: '^([a-z$][a-zA-Z$0-9]*)|(`.*`)$'
excludeClassPattern: '$^'
ignoreOverridden: true
FunctionParameterNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
parameterPattern: '[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
InvalidPackageDeclaration:
active: true
# TODO: Update this with your project's base package
rootPackage: 'template'
MatchingDeclarationName:
active: true
mustBeFirst: true
MemberNameEqualsClassName:
active: true
ignoreOverridden: true
NonBooleanPropertyPrefixedWithIs:
active: true
ObjectPropertyNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
constantPattern: '[A-Za-z][_A-Za-z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '(_)?[A-Za-z][_A-Za-z0-9]*'
PackageNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
packagePattern: '^[a-z]+(\.[a-z][A-Za-z0-9]*)*$'
TopLevelPropertyNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
constantPattern: '[A-Z][_A-Z0-9]*'
propertyPattern: '[A-Za-z][_A-Za-z0-9]*'
privatePropertyPattern: '_?[A-Za-z][_A-Za-z0-9]*'
VariableMaxLength:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
maximumVariableNameLength: 64
VariableMinLength:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
minimumVariableNameLength: 1
VariableNaming:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
variablePattern: '[a-z][A-Za-z0-9]*'
privateVariablePattern: '(_)?[a-z][A-Za-z0-9]*'
excludeClassPattern: '$^'
ignoreOverridden: true
performance:
active: true
ArrayPrimitive:
active: true
ForEachOnRange:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
SpreadOperator:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
UnnecessaryTemporaryInstantiation:
active: true
potential-bugs:
active: true
Deprecation:
active: true
DuplicateCaseInWhenExpression:
active: true
EqualsAlwaysReturnsTrueOrFalse:
active: true
EqualsWithHashCodeExist:
active: true
ExplicitGarbageCollectionCall:
active: true
HasPlatformType:
active: true
IgnoredReturnValue:
active: true
ImplicitDefaultLocale:
active: false
ImplicitUnitReturnType:
active: true
allowExplicitReturnType: true
InvalidRange:
active: true
IteratorHasNextCallsNextMethod:
active: true
IteratorNotThrowingNoSuchElementException:
active: true
LateinitUsage:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
excludeAnnotatedProperties: [ ]
ignoreOnClassesPattern: ''
MapGetWithNotNullAssertionOperator:
active: true
MissingWhenCase:
active: true
NullableToStringCall:
active: true
RedundantElseInWhen:
active: true
UnconditionalJumpStatementInLoop:
active: true
UnnecessaryNotNullOperator:
active: true
UnnecessarySafeCall:
active: true
UnreachableCode:
active: true
UnsafeCallOnNullableType:
active: true
UnsafeCast:
active: true
UselessPostfixExpression:
active: true
WrongEqualsTypeParameter:
active: true
style:
active: true
ClassOrdering:
active: true
CollapsibleIfStatements:
active: true
DataClassContainsFunctions:
active: true
conversionFunctionPrefix: 'to'
DataClassShouldBeImmutable:
active: true
EqualsNullCall:
active: true
EqualsOnSignatureLine:
active: true
ExplicitCollectionElementAccessMethod:
active: true
ExplicitItLambdaParameter:
active: true
ExpressionBodySyntax:
active: true
includeLineWrapping: false
ForbiddenComment:
active: false
values: [ 'TODO:', 'FIXME:', 'STOPSHIP:' ]
allowedPatterns: ''
ForbiddenImport:
active: false
imports: [ ]
forbiddenPatterns: ''
ForbiddenMethodCall:
active: false
methods: [ ]
ForbiddenPublicDataClass:
active: false
ignorePackages: [ '*.internal', '*.internal.*' ]
ForbiddenVoid:
active: true
ignoreOverridden: true
ignoreUsageInGenerics: false
FunctionOnlyReturningConstant:
active: true
ignoreOverridableFunction: true
excludedFunctions: 'describeContents'
excludeAnnotatedFunction: [ 'dagger.Provides' ]
LibraryCodeMustSpecifyReturnType:
active: true
LibraryEntitiesShouldNotBePublic:
active: true
LoopWithTooManyJumpStatements:
active: true
maxJumpCount: 3
MagicNumber:
active: true
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
ignoreNumbers: [ '-1', '0', '1', '2' ]
ignoreHashCodeFunction: true
ignorePropertyDeclaration: false
ignoreLocalVariableDeclaration: false
ignoreConstantDeclaration: true
ignoreCompanionObjectPropertyDeclaration: true
ignoreAnnotation: true
ignoreNamedArgument: true
ignoreEnums: true
ignoreRanges: false
MandatoryBracesIfStatements:
active: true
MandatoryBracesLoops:
active: true
MaxLineLength:
active: true
maxLineLength: 120
excludePackageStatements: true
excludeImportStatements: true
excludeCommentStatements: false
MayBeConst:
active: true
ModifierOrder:
active: true
NestedClassesVisibility:
active: true
NewLineAtEndOfFile:
active: true
NoTabs:
active: false
OptionalAbstractKeyword:
active: true
OptionalUnit:
active: false
OptionalWhenBraces:
active: true
PreferToOverPairSyntax:
active: true
ProtectedMemberInFinalClass:
active: true
RedundantExplicitType:
active: true
RedundantVisibilityModifierRule:
active: false
ReturnCount:
active: false
max: 2
excludedFunctions: 'equals'
excludeLabeled: false
excludeReturnFromLambda: true
excludeGuardClauses: false
SafeCast:
active: true
SerialVersionUIDInSerializableClass:
active: true
SpacingBetweenPackageAndImports:
active: true
ThrowsCount:
active: false
max: 2
TrailingWhitespace:
active: true
UnderscoresInNumericLiterals:
active: true
acceptableDecimalLength: 5
UnnecessaryAbstractClass:
active: true
excludeAnnotatedClasses: [ 'dagger.Module' ]
UnnecessaryAnnotationUseSiteTarget:
active: true
UnnecessaryApply:
active: true
UnnecessaryInheritance:
active: true
UnnecessaryLet:
active: true
UnnecessaryParentheses:
active: true
UntilInsteadOfRangeTo:
active: true
UnusedImports:
active: true
UnusedPrivateClass:
active: true
UnusedPrivateMember:
active: true
allowedNames: '(_|ignored|expected|serialVersionUID)'
UseArrayLiteralsInAnnotations:
active: true
UseCheckNotNull:
active: true
UseCheckOrError:
active: true
UseDataClass:
active: true
excludeAnnotatedClasses: [ ]
allowVars: false
UseEmptyCounterpart:
active: true
UseIfInsteadOfWhen:
active: true
UseRequire:
active: true
UseRequireNotNull:
active: true
UselessCallOnNotNull:
active: true
UtilityClassWithPublicConstructor:
active: true
VarCouldBeVal:
active: true
WildcardImport:
active: false
excludes: [ '**/test/**', '**/androidTest/**', '**/*.Test.kt', '**/*.Spec.kt', '**/*.Spek.kt' ]
excludeImports: [ 'java.util.*', 'kotlinx.android.synthetic.*' ]

7
gradle.properties Normal file

@ -0,0 +1,7 @@
# Gradle props
org.gradle.jvmargs=-XX:MaxMetaspaceSize=1024m
org.gradle.parallel=true
kotlin.incremental=true
ksp.incremental=false
ksp.useKSP2=true

20
gradle/libs.versions.toml Normal file

@ -0,0 +1,20 @@
[versions]
detekt = "1.23.6" # Note: Plugin versions must be updated in the settings.gradle.kts too
kotlin = "2.0.20" # Note: Plugin versions must be updated in the settings.gradle.kts too
groovy = "3.0.22"
jansi = "2.4.1"
kx-ser = "1.7.2"
logback = "1.5.7"
logback-groovy = "1.14.5"
logging = "7.0.0"
[libraries]
detekt = { module = "io.gitlab.arturbosch.detekt:detekt-formatting", version.ref = "detekt" }
groovy = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
jansi = { module = "org.fusesource.jansi:jansi", version.ref = "jansi" }
kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8" }
kx-ser = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kx-ser" }
logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
logback-groovy = { module = "io.github.virtualdogbert:logback-groovy-config", version.ref = "logback-groovy" }
logging = { module = "io.github.oshai:kotlin-logging", version.ref = "logging" }

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

@ -0,0 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

249
gradlew vendored Executable file

@ -0,0 +1,249 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original 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 POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
warn () {
echo "$*"
} >&2
die () {
echo
echo "$*"
echo
exit 1
} >&2
# 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 ;; #(
MSYS* | 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
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# 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"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

92
gradlew.bat vendored Normal file

@ -0,0 +1,92 @@
@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=.
@rem This is normally unused
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% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
: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 %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 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!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

18
settings.gradle.kts Normal file

@ -0,0 +1,18 @@
pluginManagement {
plugins {
// Update this in libs.version.toml when you change it here.
kotlin("jvm") version "2.0.20"
kotlin("plugin.serialization") version "2.0.20"
// Update this in libs.version.toml when you change it here.
id("io.gitlab.arturbosch.detekt") version "1.23.6"
id("com.github.jakemarsden.git-hooks") version "0.0.2"
id("com.github.johnrengelman.shadow") version "8.1.1"
id("dev.kordex.gradle.docker") version "1.4.2"
id("dev.kordex.gradle.kordex") version "1.4.2"
}
}
rootProject.name = "template"

@ -0,0 +1,40 @@
/*
* This Kotlin source file was generated by the Gradle 'init' task.
*/
package template
import dev.kord.common.entity.Snowflake
import dev.kordex.core.ExtensibleBot
import dev.kordex.core.utils.env
import template.extensions.TestExtension
val TEST_SERVER_ID = Snowflake(
env("TEST_SERVER").toLong() // Get the test server ID from the env vars or a .env file
)
private val TOKEN = env("TOKEN") // Get the bot' token from the env vars or a .env file
suspend fun main() {
val bot = ExtensibleBot(TOKEN) {
chatCommands {
defaultPrefix = "?"
enabled = true
prefix { default ->
if (guildId == TEST_SERVER_ID) {
// For the test server, we use ! as the command prefix
"!"
} else {
// For other servers, we use the configured default prefix
default
}
}
}
extensions {
add(::TestExtension)
}
}
bot.start()
}

@ -0,0 +1,130 @@
package template.extensions
import dev.kordex.core.commands.Arguments
import dev.kordex.core.commands.converters.impl.coalescingDefaultingString
import dev.kordex.core.commands.converters.impl.defaultingString
import dev.kordex.core.commands.converters.impl.user
import dev.kordex.core.components.components
import dev.kordex.core.components.publicButton
import dev.kordex.core.extensions.Extension
import dev.kordex.core.extensions.chatCommand
import dev.kordex.core.extensions.publicSlashCommand
import dev.kordex.core.utils.respond
import template.TEST_SERVER_ID
class TestExtension : Extension() {
override val name = "test"
override suspend fun setup() {
chatCommand(::SlapArgs) {
name = "slap"
description = "Ask the bot to slap another user"
check { failIf(event.message.author == null) }
action {
// Don't slap ourselves on request, slap the requester!
val realTarget = if (arguments.target.id == event.kord.selfId) {
message.author!!
} else {
arguments.target
}
message.respond("*slaps ${realTarget.mention} with their ${arguments.weapon}*")
}
}
chatCommand {
name = "button"
description = "A simple example command that sends a button."
check { failIf(event.message.author == null) }
action {
message.respond {
components {
publicButton {
label = "Button!"
action {
respond {
content = "You pushed the button!"
}
}
}
}
}
}
}
publicSlashCommand(::SlapSlashArgs) {
name = "slap"
description = "Ask the bot to slap another user"
guild(TEST_SERVER_ID) // Otherwise it will take up to an hour to update
action {
// Don't slap ourselves on request, slap the requester!
val realTarget = if (arguments.target.id == event.kord.selfId) {
member
} else {
arguments.target
}
respond {
content = "*slaps ${realTarget?.mention} with their ${arguments.weapon}*"
}
}
}
publicSlashCommand {
name = "button"
description = "A simple example command that sends a button."
action {
respond {
components {
publicButton {
label = "Button!"
action {
respond {
content = "You pushed the button!"
}
}
}
}
}
}
}
}
inner class SlapArgs : Arguments() {
val target by user {
name = "target"
description = "Person you want to slap"
}
val weapon by coalescingDefaultingString {
name = "weapon"
defaultValue = "large, smelly trout"
description = "What you want to slap with"
}
}
inner class SlapSlashArgs : Arguments() {
val target by user {
name = "target"
description = "Person you want to slap"
}
// Slash commands don't support coalescing strings
val weapon by defaultingString {
name = "weapon"
defaultValue = "large, smelly trout"
description = "What you want to slap with"
}
}
}

@ -0,0 +1,27 @@
import ch.qos.logback.core.joran.spi.ConsoleTarget
import ch.qos.logback.core.ConsoleAppender
def environment = System.getenv("ENVIRONMENT") ?: "production"
def defaultLevel = INFO
def defaultTarget = ConsoleTarget.SystemErr
if (environment == "dev") {
defaultLevel = DEBUG
defaultTarget = ConsoleTarget.SystemOut
// Silence warning about missing native PRNG
logger("io.ktor.util.random", ERROR)
}
appender("CONSOLE", ConsoleAppender) {
encoder(PatternLayoutEncoder) {
pattern = "%boldGreen(%d{yyyy-MM-dd}) %boldYellow(%d{HH:mm:ss}) %gray(|) %highlight(%5level) %gray(|) %boldMagenta(%40.40logger{40}) %gray(|) %msg%n"
withJansi = true
}
target = defaultTarget
}
root(defaultLevel, ["CONSOLE"])

@ -0,0 +1,452 @@
importsAcceptList = [
'ch.qos.logback.core.testUtil.SampleConverter',
'ch.qos.logback.core.testUtil.StringListAppender',
'java.lang.Object',
'org.springframework.beans.factory.annotation.Autowired',
'java.nio.charset.Charset.forName',
'com.logentries.logback.LogentriesAppender',
'grails.util.BuildSettings',
'grails.util.Environment',
'io.micronaut.context.env.Environment',
'org.slf4j.MDC',
'org.springframework.boot.logging.logback.ColorConverter',
'org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter',
'java.nio.charset.Charset',
'java.nio.charset.StandardCharsets',
'ch.qos.logback.core.BasicStatusManager',
'ch.qos.logback.core.ConsoleAppender',
'ch.qos.logback.core.hook.ShutdownHook',
'ch.qos.logback.core.hook.ShutdownHookBase',
'ch.qos.logback.core.hook.DelayingShutdownHook',
'ch.qos.logback.core.spi.PropertyContainer',
'ch.qos.logback.core.spi.ContextAwareBase',
'ch.qos.logback.core.spi.LogbackLock',
'ch.qos.logback.core.spi.FilterAttachableImpl',
'ch.qos.logback.core.spi.ContextAwareImpl',
'ch.qos.logback.core.spi.ScanException',
'ch.qos.logback.core.spi.DeferredProcessingAware',
'ch.qos.logback.core.spi.ContextAware',
'ch.qos.logback.core.spi.LifeCycle',
'ch.qos.logback.core.spi.FilterReply',
'ch.qos.logback.core.spi.PreSerializationTransformer',
'ch.qos.logback.core.spi.AppenderAttachable',
'ch.qos.logback.core.spi.CyclicBufferTracker',
'ch.qos.logback.core.spi.FilterAttachable',
'ch.qos.logback.core.spi.ComponentTracker',
'ch.qos.logback.core.spi.AppenderAttachableImpl',
'ch.qos.logback.core.spi.PropertyDefiner',
'ch.qos.logback.core.spi.AbstractComponentTracker',
'ch.qos.logback.core.property.FileExistsPropertyDefiner',
'ch.qos.logback.core.property.ResourceExistsPropertyDefiner',
'ch.qos.logback.core.CoreConstants',
'ch.qos.logback.core.layout.EchoLayout',
'ch.qos.logback.core.Appender',
'ch.qos.logback.core.joran.JoranConfiguratorBase',
'ch.qos.logback.core.joran.spi.ActionException',
'ch.qos.logback.core.joran.spi.HostClassAndPropertyDouble',
'ch.qos.logback.core.joran.spi.JoranException',
'ch.qos.logback.core.joran.spi.NoAutoStart',
'ch.qos.logback.core.joran.spi.EventPlayer',
'ch.qos.logback.core.joran.spi.XMLUtil',
'ch.qos.logback.core.joran.spi.ConsoleTarget',
'ch.qos.logback.core.joran.spi.Interpreter',
'ch.qos.logback.core.joran.spi.SimpleRuleStore',
'ch.qos.logback.core.joran.spi.InterpretationContext',
'ch.qos.logback.core.joran.spi.RuleStore',
'ch.qos.logback.core.joran.spi.NoAutoStartUtil',
'ch.qos.logback.core.joran.spi.ElementSelector',
'ch.qos.logback.core.joran.spi.ConfigurationWatchList',
'ch.qos.logback.core.joran.spi.DefaultNestedComponentRegistry',
'ch.qos.logback.core.joran.spi.DefaultClass',
'ch.qos.logback.core.joran.spi.ElementPath',
'ch.qos.logback.core.joran.conditional.ThenOrElseActionBase',
'ch.qos.logback.core.joran.conditional.Condition',
'ch.qos.logback.core.joran.conditional.PropertyWrapperForScripts',
'ch.qos.logback.core.joran.conditional.ThenAction',
'ch.qos.logback.core.joran.conditional.PropertyEvalScriptBuilder',
'ch.qos.logback.core.joran.conditional.ElseAction',
'ch.qos.logback.core.joran.conditional.IfAction',
'ch.qos.logback.core.joran.util.beans.BeanDescriptionCache',
'ch.qos.logback.core.joran.util.beans.BeanDescriptionFactory',
'ch.qos.logback.core.joran.util.beans.BeanDescription',
'ch.qos.logback.core.joran.util.beans.BeanUtil',
'ch.qos.logback.core.joran.util.PropertySetter',
'ch.qos.logback.core.joran.util.ConfigurationWatchListUtil',
'ch.qos.logback.core.joran.util.StringToObjectConverter',
'ch.qos.logback.core.joran.GenericConfigurator',
'ch.qos.logback.core.joran.action.ImplicitAction',
'ch.qos.logback.core.joran.action.IncludeAction',
'ch.qos.logback.core.joran.action.NOPAction',
'ch.qos.logback.core.joran.action.IADataForBasicProperty',
'ch.qos.logback.core.joran.action.TimestampAction',
'ch.qos.logback.core.joran.action.AbstractEventEvaluatorAction',
'ch.qos.logback.core.joran.action.ParamAction',
'ch.qos.logback.core.joran.action.AppenderAction',
'ch.qos.logback.core.joran.action.DefinePropertyAction',
'ch.qos.logback.core.joran.action.StatusListenerAction',
'ch.qos.logback.core.joran.action.ContextPropertyAction',
'ch.qos.logback.core.joran.action.NestedComplexPropertyIA',
'ch.qos.logback.core.joran.action.NestedBasicPropertyIA',
'ch.qos.logback.core.joran.action.Action',
'ch.qos.logback.core.joran.action.AppenderRefAction',
'ch.qos.logback.core.joran.action.ActionUtil',
'ch.qos.logback.core.joran.action.ShutdownHookAction',
'ch.qos.logback.core.joran.action.IADataForComplexProperty',
'ch.qos.logback.core.joran.action.ConversionRuleAction',
'ch.qos.logback.core.joran.action.ActionConst',
'ch.qos.logback.core.joran.action.PropertyAction',
'ch.qos.logback.core.joran.action.NewRuleAction',
'ch.qos.logback.core.joran.node.ComponentNode',
'ch.qos.logback.core.joran.event.EndEvent',
'ch.qos.logback.core.joran.event.SaxEventRecorder',
'ch.qos.logback.core.joran.event.SaxEvent',
'ch.qos.logback.core.joran.event.BodyEvent',
'ch.qos.logback.core.joran.event.StartEvent',
'ch.qos.logback.core.joran.event.InPlayListener',
'ch.qos.logback.core.joran.event.stax.EndEvent',
'ch.qos.logback.core.joran.event.stax.StaxEventRecorder',
'ch.qos.logback.core.joran.event.stax.BodyEvent',
'ch.qos.logback.core.joran.event.stax.StartEvent',
'ch.qos.logback.core.joran.event.stax.StaxEvent',
'ch.qos.logback.core.LogbackException',
'ch.qos.logback.core.PropertyDefinerBase',
'ch.qos.logback.core.helpers.CyclicBuffer',
'ch.qos.logback.core.helpers.ThrowableToStringArray',
'ch.qos.logback.core.helpers.Transform',
'ch.qos.logback.core.helpers.NOPAppender',
'ch.qos.logback.core.net.LoginAuthenticator',
'ch.qos.logback.core.net.DefaultSocketConnector',
'ch.qos.logback.core.net.ssl.KeyStoreFactoryBean',
'ch.qos.logback.core.net.ssl.SSLParametersConfiguration',
'ch.qos.logback.core.net.ssl.SSLComponent',
'ch.qos.logback.core.net.ssl.SSLNestedComponentRegistryRules',
'ch.qos.logback.core.net.ssl.SSLConfigurableSocket',
'ch.qos.logback.core.net.ssl.SSLConfigurableServerSocket',
'ch.qos.logback.core.net.ssl.SSLConfiguration',
'ch.qos.logback.core.net.ssl.ConfigurableSSLSocketFactory',
'ch.qos.logback.core.net.ssl.ConfigurableSSLServerSocketFactory',
'ch.qos.logback.core.net.ssl.SecureRandomFactoryBean',
'ch.qos.logback.core.net.ssl.SSLContextFactoryBean',
'ch.qos.logback.core.net.ssl.SSL',
'ch.qos.logback.core.net.ssl.SSLConfigurable',
'ch.qos.logback.core.net.ssl.TrustManagerFactoryFactoryBean',
'ch.qos.logback.core.net.ssl.KeyManagerFactoryFactoryBean',
'ch.qos.logback.core.net.SMTPAppenderBase',
'ch.qos.logback.core.net.SyslogAppenderBase',
'ch.qos.logback.core.net.SocketConnector',
'ch.qos.logback.core.net.SyslogOutputStream',
'ch.qos.logback.core.net.QueueFactory',
'ch.qos.logback.core.net.HardenedObjectInputStream',
'ch.qos.logback.core.net.AbstractSocketAppender',
'ch.qos.logback.core.net.AbstractSSLSocketAppender',
'ch.qos.logback.core.net.ObjectWriterFactory',
'ch.qos.logback.core.net.ObjectWriter',
'ch.qos.logback.core.net.AutoFlushingObjectWriter',
'ch.qos.logback.core.net.SyslogConstants',
'ch.qos.logback.core.net.server.ServerRunner',
'ch.qos.logback.core.net.server.Client',
'ch.qos.logback.core.net.server.ServerListener',
'ch.qos.logback.core.net.server.RemoteReceiverStreamClient',
'ch.qos.logback.core.net.server.AbstractServerSocketAppender',
'ch.qos.logback.core.net.server.ClientVisitor',
'ch.qos.logback.core.net.server.RemoteReceiverClient',
'ch.qos.logback.core.net.server.RemoteReceiverServerRunner',
'ch.qos.logback.core.net.server.SSLServerSocketAppenderBase',
'ch.qos.logback.core.net.server.ConcurrentServerRunner',
'ch.qos.logback.core.net.server.ServerSocketListener',
'ch.qos.logback.core.net.server.RemoteReceiverServerListener',
'ch.qos.logback.core.UnsynchronizedAppenderBase',
'ch.qos.logback.core.AsyncAppenderBase',
'ch.qos.logback.core.util.CloseUtil',
'ch.qos.logback.core.util.DatePatternToRegexUtil',
'ch.qos.logback.core.util.StatusListenerConfigHelper',
'ch.qos.logback.core.util.SystemInfo',
'ch.qos.logback.core.util.DefaultInvocationGate',
'ch.qos.logback.core.util.CachingDateFormatter',
'ch.qos.logback.core.util.InterruptUtil',
'ch.qos.logback.core.util.LocationUtil',
'ch.qos.logback.core.util.TimeUtil',
'ch.qos.logback.core.util.COWArrayList',
'ch.qos.logback.core.util.Loader',
'ch.qos.logback.core.util.CharSequenceState',
'ch.qos.logback.core.util.StatusPrinter',
'ch.qos.logback.core.util.Duration',
'ch.qos.logback.core.util.ContentTypeUtil',
'ch.qos.logback.core.util.FileUtil',
'ch.qos.logback.core.util.DynamicClassLoadingException',
'ch.qos.logback.core.util.InvocationGate',
'ch.qos.logback.core.util.OptionHelper',
'ch.qos.logback.core.util.IncompatibleClassException',
'ch.qos.logback.core.util.ExecutorServiceUtil',
'ch.qos.logback.core.util.StringCollectionUtil',
'ch.qos.logback.core.util.CharSequenceToRegexMapper',
'ch.qos.logback.core.util.FixedDelay',
'ch.qos.logback.core.util.FileSize',
'ch.qos.logback.core.util.DelayStrategy',
'ch.qos.logback.core.util.EnvUtil',
'ch.qos.logback.core.util.ContextUtil',
'ch.qos.logback.core.util.AggregationType',
'ch.qos.logback.core.util.PropertySetterException',
'ch.qos.logback.core.LifeCycleManager',
'ch.qos.logback.core.LayoutBase',
'ch.qos.logback.core.encoder.NonClosableInputStream',
'ch.qos.logback.core.encoder.Encoder',
'ch.qos.logback.core.encoder.ByteArrayUtil',
'ch.qos.logback.core.encoder.EncoderBase',
'ch.qos.logback.core.encoder.EchoEncoder',
'ch.qos.logback.core.encoder.LayoutWrappingEncoder',
'ch.qos.logback.core.recovery.RecoveryCoordinator',
'ch.qos.logback.core.recovery.ResilientOutputStreamBase',
'ch.qos.logback.core.recovery.ResilientSyslogOutputStream',
'ch.qos.logback.core.recovery.ResilientFileOutputStream',
'ch.qos.logback.core.AppenderBase',
'ch.qos.logback.core.subst.Node',
'ch.qos.logback.core.subst.Parser',
'ch.qos.logback.core.subst.Token',
'ch.qos.logback.core.subst.NodeToStringTransformer',
'ch.qos.logback.core.subst.Tokenizer',
'ch.qos.logback.core.FileAppender',
'ch.qos.logback.core.sift.AppenderFactory',
'ch.qos.logback.core.sift.SiftingAppenderBase',
'ch.qos.logback.core.sift.SiftingJoranConfiguratorBase',
'ch.qos.logback.core.sift.AbstractDiscriminator',
'ch.qos.logback.core.sift.Discriminator',
'ch.qos.logback.core.sift.AbstractAppenderFactoryUsingJoran',
'ch.qos.logback.core.sift.AppenderTracker',
'ch.qos.logback.core.sift.DefaultDiscriminator',
'ch.qos.logback.core.html.CssBuilder',
'ch.qos.logback.core.html.NOPThrowableRenderer',
'ch.qos.logback.core.html.HTMLLayoutBase',
'ch.qos.logback.core.html.IThrowableRenderer',
'ch.qos.logback.core.rolling.TriggeringPolicyBase',
'ch.qos.logback.core.rolling.helper.Compressor',
'ch.qos.logback.core.rolling.helper.PeriodicityType',
'ch.qos.logback.core.rolling.helper.TokenConverter',
'ch.qos.logback.core.rolling.helper.IntegerTokenConverter',
'ch.qos.logback.core.rolling.helper.CompressionMode',
'ch.qos.logback.core.rolling.helper.ArchiveRemover',
'ch.qos.logback.core.rolling.helper.FileFilterUtil',
'ch.qos.logback.core.rolling.helper.RenameUtil',
'ch.qos.logback.core.rolling.helper.DateTokenConverter',
'ch.qos.logback.core.rolling.helper.FileNamePattern',
'ch.qos.logback.core.rolling.helper.RollingCalendar',
'ch.qos.logback.core.rolling.helper.FileStoreUtil',
'ch.qos.logback.core.rolling.helper.SizeAndTimeBasedArchiveRemover',
'ch.qos.logback.core.rolling.helper.TimeBasedArchiveRemover',
'ch.qos.logback.core.rolling.helper.MonoTypedConverter',
'ch.qos.logback.core.rolling.RollingPolicyBase',
'ch.qos.logback.core.rolling.RollingFileAppender',
'ch.qos.logback.core.rolling.FixedWindowRollingPolicy',
'ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicyBase',
'ch.qos.logback.core.rolling.TimeBasedFileNamingAndTriggeringPolicy',
'ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy',
'ch.qos.logback.core.rolling.RollingPolicy',
'ch.qos.logback.core.rolling.TimeBasedRollingPolicy',
'ch.qos.logback.core.rolling.DefaultTimeBasedFileNamingAndTriggeringPolicy',
'ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy',
'ch.qos.logback.core.rolling.RolloverFailure',
'ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP',
'ch.qos.logback.core.rolling.TriggeringPolicy',
'ch.qos.logback.core.pattern.ReplacingCompositeConverter',
'ch.qos.logback.core.pattern.ConverterUtil',
'ch.qos.logback.core.pattern.parser.Compiler',
'ch.qos.logback.core.pattern.parser.Node',
'ch.qos.logback.core.pattern.parser.Parser',
'ch.qos.logback.core.pattern.parser.Token',
'ch.qos.logback.core.pattern.parser.OptionTokenizer',
'ch.qos.logback.core.pattern.parser.TokenStream',
'ch.qos.logback.core.pattern.parser.CompositeNode',
'ch.qos.logback.core.pattern.parser.FormattingNode',
'ch.qos.logback.core.pattern.parser.SimpleKeywordNode',
'ch.qos.logback.core.pattern.Converter',
'ch.qos.logback.core.pattern.PatternLayoutEncoderBase',
'ch.qos.logback.core.pattern.LiteralConverter',
'ch.qos.logback.core.pattern.PostCompileProcessor',
'ch.qos.logback.core.pattern.util.RegularEscapeUtil',
'ch.qos.logback.core.pattern.util.AsIsEscapeUtil',
'ch.qos.logback.core.pattern.util.AlmostAsIsEscapeUtil',
'ch.qos.logback.core.pattern.util.IEscapeUtil',
'ch.qos.logback.core.pattern.util.RestrictedEscapeUtil',
'ch.qos.logback.core.pattern.SpacePadder',
'ch.qos.logback.core.pattern.CompositeConverter',
'ch.qos.logback.core.pattern.PatternLayoutBase',
'ch.qos.logback.core.pattern.DynamicConverter',
'ch.qos.logback.core.pattern.color.YellowCompositeConverter',
'ch.qos.logback.core.pattern.color.ANSIConstants',
'ch.qos.logback.core.pattern.color.BoldYellowCompositeConverter',
'ch.qos.logback.core.pattern.color.BoldBlueCompositeConverter',
'ch.qos.logback.core.pattern.color.BoldWhiteCompositeConverter',
'ch.qos.logback.core.pattern.color.CyanCompositeConverter',
'ch.qos.logback.core.pattern.color.MagentaCompositeConverter',
'ch.qos.logback.core.pattern.color.BlueCompositeConverter',
'ch.qos.logback.core.pattern.color.BlackCompositeConverter',
'ch.qos.logback.core.pattern.color.ForegroundCompositeConverterBase',
'ch.qos.logback.core.pattern.color.GrayCompositeConverter',
'ch.qos.logback.core.pattern.color.BoldMagentaCompositeConverter',
'ch.qos.logback.core.pattern.color.BoldCyanCompositeConverter',
'ch.qos.logback.core.pattern.color.RedCompositeConverter',
'ch.qos.logback.core.pattern.color.BoldGreenCompositeConverter',
'ch.qos.logback.core.pattern.color.BoldRedCompositeConverter',
'ch.qos.logback.core.pattern.color.GreenCompositeConverter',
'ch.qos.logback.core.pattern.color.WhiteCompositeConverter',
'ch.qos.logback.core.pattern.FormattingConverter',
'ch.qos.logback.core.pattern.IdentityCompositeConverter',
'ch.qos.logback.core.pattern.FormatInfo',
'ch.qos.logback.core.OutputStreamAppender',
'ch.qos.logback.core.boolex.JaninoEventEvaluatorBase',
'ch.qos.logback.core.boolex.Matcher',
'ch.qos.logback.core.boolex.EventEvaluatorBase',
'ch.qos.logback.core.boolex.EvaluationException',
'ch.qos.logback.core.boolex.EventEvaluator',
'ch.qos.logback.core.read.CyclicBufferAppender',
'ch.qos.logback.core.read.ListAppender',
'ch.qos.logback.core.Context',
'ch.qos.logback.core.ContextBase',
'ch.qos.logback.core.status.StatusListenerAsList',
'ch.qos.logback.core.status.StatusBase',
'ch.qos.logback.core.status.NopStatusListener',
'ch.qos.logback.core.status.StatusUtil',
'ch.qos.logback.core.status.OnPrintStreamStatusListenerBase',
'ch.qos.logback.core.status.StatusManager',
'ch.qos.logback.core.status.ViewStatusMessagesServletBase',
'ch.qos.logback.core.status.ErrorStatus',
'ch.qos.logback.core.status.Status',
'ch.qos.logback.core.status.StatusListener',
'ch.qos.logback.core.status.InfoStatus',
'ch.qos.logback.core.status.OnConsoleStatusListener',
'ch.qos.logback.core.status.WarnStatus',
'ch.qos.logback.core.status.OnErrorConsoleStatusListener',
'ch.qos.logback.core.filter.EvaluatorFilter',
'ch.qos.logback.core.filter.Filter',
'ch.qos.logback.core.filter.AbstractMatcherFilter',
'ch.qos.logback.core.Layout',
'ch.qos.logback.classic.ViewStatusMessagesServlet',
'ch.qos.logback.classic.ClassicConstants',
'ch.qos.logback.classic.layout.TTLLLayout',
'ch.qos.logback.classic.helpers.MDCInsertingServletFilter',
'ch.qos.logback.classic.Level',
'ch.qos.logback.classic.Level.off',
'ch.qos.logback.classic.Level.error',
'ch.qos.logback.classic.Level.warn',
'ch.qos.logback.classic.Level.info',
'ch.qos.logback.classic.Level.debug',
'ch.qos.logback.classic.Level.trace',
'ch.qos.logback.classic.Level.all,',
'ch.qos.logback.classic.net.SSLSocketReceiver',
'ch.qos.logback.classic.net.ReceiverBase',
'ch.qos.logback.classic.net.SimpleSocketServer',
'ch.qos.logback.classic.net.SimpleSSLSocketServer',
'ch.qos.logback.classic.net.SocketNode',
'ch.qos.logback.classic.net.SMTPAppender',
'ch.qos.logback.classic.net.SocketReceiver',
'ch.qos.logback.classic.net.SocketAcceptor',
'ch.qos.logback.classic.net.SSLSocketAppender',
'ch.qos.logback.classic.net.LoggingEventPreSerializationTransformer',
'ch.qos.logback.classic.net.server.RemoteAppenderStreamClient',
'ch.qos.logback.classic.net.server.RemoteAppenderServerListener',
'ch.qos.logback.classic.net.server.SSLServerSocketAppender',
'ch.qos.logback.classic.net.server.RemoteAppenderClient',
'ch.qos.logback.classic.net.server.HardenedLoggingEventInputStream',
'ch.qos.logback.classic.net.server.ServerSocketAppender',
'ch.qos.logback.classic.net.server.SSLServerSocketReceiver',
'ch.qos.logback.classic.net.server.RemoteAppenderServerRunner',
'ch.qos.logback.classic.net.server.ServerSocketReceiver',
'ch.qos.logback.classic.net.SocketAppender',
'ch.qos.logback.classic.net.SyslogAppender',
'ch.qos.logback.classic.PatternLayout',
'ch.qos.logback.classic.util.ContextSelectorStaticBinder',
'ch.qos.logback.classic.util.StatusViaSLF4JLoggerFactory',
'ch.qos.logback.classic.util.JNDIUtil',
'ch.qos.logback.classic.util.LevelToSyslogSeverity',
'ch.qos.logback.classic.util.LoggerNameUtil',
'ch.qos.logback.classic.util.LogbackMDCAdapter',
'ch.qos.logback.classic.util.CopyOnInheritThreadLocal',
'ch.qos.logback.classic.util.ContextInitializer',
'ch.qos.logback.classic.util.EnvUtil',
'ch.qos.logback.classic.util.DefaultNestedComponentRules',
'ch.qos.logback.classic.AsyncAppender',
'ch.qos.logback.classic.jul.JULHelper',
'ch.qos.logback.classic.jul.LevelChangePropagator',
'ch.qos.logback.classic.encoder.PatternLayoutEncoder',
'ch.qos.logback.classic.db.names.DBNameResolver',
'ch.qos.logback.classic.db.names.ColumnName',
'ch.qos.logback.classic.db.names.TableName',
'ch.qos.logback.classic.db.names.DefaultDBNameResolver',
'ch.qos.logback.classic.db.names.SimpleDBNameResolver',
'ch.qos.logback.classic.log4j.XMLLayout',
'ch.qos.logback.classic.LoggerContext',
'ch.qos.logback.classic.turbo.TurboFilter',
'ch.qos.logback.classic.turbo.MDCFilter',
'ch.qos.logback.classic.turbo.ReconfigureOnChangeFilter',
'ch.qos.logback.classic.turbo.DuplicateMessageFilter',
'ch.qos.logback.classic.turbo.MarkerFilter',
'ch.qos.logback.classic.turbo.MDCValueLevelPair',
'ch.qos.logback.classic.turbo.DynamicThresholdFilter',
'ch.qos.logback.classic.turbo.MatchingFilter',
'ch.qos.logback.classic.turbo.LRUMessageCache',
'ch.qos.logback.classic.selector.servlet.LoggerContextFilter',
'ch.qos.logback.classic.selector.servlet.ContextDetachingSCL',
'ch.qos.logback.classic.selector.ContextJNDISelector',
'ch.qos.logback.classic.selector.DefaultContextSelector',
'ch.qos.logback.classic.selector.ContextSelector',
'ch.qos.logback.classic.sift.MDCBasedDiscriminator',
'ch.qos.logback.classic.sift.SiftingJoranConfigurator',
'ch.qos.logback.classic.sift.JNDIBasedContextDiscriminator',
'ch.qos.logback.classic.sift.AppenderFactoryUsingJoran',
'ch.qos.logback.classic.sift.ContextBasedDiscriminator',
'ch.qos.logback.classic.sift.SiftingAppender',
'ch.qos.logback.classic.sift.SiftAction',
'ch.qos.logback.classic.html.UrlCssBuilder',
'ch.qos.logback.classic.html.HTMLLayout',
'ch.qos.logback.classic.html.DefaultCssBuilder',
'ch.qos.logback.classic.html.DefaultThrowableRenderer',
'ch.qos.logback.classic.Logger',
'ch.qos.logback.classic.pattern.ThrowableHandlingConverter',
'ch.qos.logback.classic.pattern.ContextNameConverter',
'ch.qos.logback.classic.pattern.LocalSequenceNumberConverter',
'ch.qos.logback.classic.pattern.ClassOfCallerConverter',
'ch.qos.logback.classic.pattern.PrefixCompositeConverter',
'ch.qos.logback.classic.pattern.LineOfCallerConverter',
'ch.qos.logback.classic.pattern.EnsureExceptionHandling',
'ch.qos.logback.classic.pattern.TargetLengthBasedClassNameAbbreviator',
'ch.qos.logback.classic.pattern.FileOfCallerConverter',
'ch.qos.logback.classic.pattern.LevelConverter',
'ch.qos.logback.classic.pattern.ExtendedThrowableProxyConverter',
'ch.qos.logback.classic.pattern.NamedConverter',
'ch.qos.logback.classic.pattern.ClassicConverter',
'ch.qos.logback.classic.pattern.NopThrowableInformationConverter',
'ch.qos.logback.classic.pattern.RootCauseFirstThrowableProxyConverter',
'ch.qos.logback.classic.pattern.MethodOfCallerConverter',
'ch.qos.logback.classic.pattern.CallerDataConverter',
'ch.qos.logback.classic.pattern.ClassNameOnlyAbbreviator',
'ch.qos.logback.classic.pattern.MarkerConverter',
'ch.qos.logback.classic.pattern.RelativeTimeConverter',
'ch.qos.logback.classic.pattern.DateConverter',
'ch.qos.logback.classic.pattern.PropertyConverter',
'ch.qos.logback.classic.pattern.ThreadConverter',
'ch.qos.logback.classic.pattern.LineSeparatorConverter',
'ch.qos.logback.classic.pattern.MDCConverter',
'ch.qos.logback.classic.pattern.color.HighlightingCompositeConverter',
'ch.qos.logback.classic.pattern.ThrowableProxyConverter',
'ch.qos.logback.classic.pattern.Abbreviator',
'ch.qos.logback.classic.pattern.Util',
'ch.qos.logback.classic.pattern.LoggerConverter',
'ch.qos.logback.classic.pattern.SyslogStartConverter',
'ch.qos.logback.classic.pattern.MessageConverter',
'ch.qos.logback.classic.gaffer.GafferUtil',
'ch.qos.logback.classic.boolex.OnMarkerEvaluator',
'ch.qos.logback.classic.boolex.JaninoEventEvaluator',
'ch.qos.logback.classic.boolex.OnErrorEvaluator',
'ch.qos.logback.classic.boolex.GEventEvaluator',
'ch.qos.logback.classic.boolex.IEvaluator',
'ch.qos.logback.classic.filter.ThresholdFilter',
'ch.qos.logback.classic.filter.LevelFilter',
'java.lang.System',
'java.lang.System.getenv',
'java.lang.System.getProperty',
'java.lang.System.getenv',
'java.util.Map.getOrDefault',
'com.kotlindiscord.kord.extensions.utils._EnvironmentKt.envOrNull',
]