diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml
index 46f3a757..11df61c2 100644
--- a/.github/workflows/wiki.yml
+++ b/.github/workflows/wiki.yml
@@ -11,7 +11,7 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: 3.x
- - run: pip install mkdocs-material
+ - run: pip install -r requirements.txt
- run: mkdocs build
- name: Deploy Wiki
uses: JamesIves/github-pages-deploy-action@v4
diff --git a/docs/assets/cookie-clicker.gif b/docs/assets/cookie-clicker.gif
new file mode 100644
index 00000000..48f06b19
Binary files /dev/null and b/docs/assets/cookie-clicker.gif differ
diff --git a/docs/assets/plugin.png b/docs/assets/plugin.png
new file mode 100644
index 00000000..938eac6b
Binary files /dev/null and b/docs/assets/plugin.png differ
diff --git a/docs/assets/runtime.png b/docs/assets/runtime.png
new file mode 100644
index 00000000..5b9433cf
Binary files /dev/null and b/docs/assets/runtime.png differ
diff --git a/docs/index.md b/docs/index.md
index 89d11eee..da20bd00 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -3,27 +3,37 @@
A declarative, annotation driven interaction framework for JDA. Our goal is to remove any boilerplate code, so
you can focus solely on the business logic of your bot - writing bots has never been easier:
-## Example
-```java
-@Interaction
-public class CookieClicker {
+=== "Code"
+ ```java
+ @Interaction
+ public class CookieClicker {
+
+ private int counter;//(1)!
+
+ @SlashCommand(value = "cookie clicker", desc = "Play cookie clicker")
+ public void onClicker(CommandEvent event) {
+ event.with().components("onCookie").reply("You've got %s cookie(s)!", counter);
+ }
+
+ @Button(value = "Collect", emoji = "🍪", style = ButtonStyle.SUCCESS)
+ public void onCookie(ComponentEvent event) {
+ event.reply("You've got %s cookie(s)!", ++counter);//(2)!
+ }
+ }
+ ```
- private int count;
+ 1. Yes, that's right! We can store the `counter` as a class variable. JDA-Commands will create a new instance of
+ `CookieClicker` for every command execution, so you don't need to worry about state. You can read more about
+ it [here](./start/runtime.md).
+ 2. This will edit the original message and will also keep the `🍪 Collect` button attached. You can find find more
+ about building replies [here](./interactions/reply.md).
- @SlashCommand(value = "cookie clicker", desc = "Play cookie clicker")
- public void onClicker(CommandEvent event) {
- event.with().components("onCookie").reply("You've got %s cookie(s)!", count);
- }
+=== "Execution"
+ ![Cookie Clicker](./assets/cookie-clicker.gif)
- @Button(value = "Collect", emoji = "🍪", style = ButtonStyle.SUCCESS)
- public void onCookie(ComponentEvent event) {
- event.reply("You've got %s cookie(s)!", ++count);
- }
-}
-```
-## Dependency
+## Adding to your Project
=== "Maven"
- ```xml
+ ```xml title="pom.xml"
io.github.kaktushose
jda-commands
@@ -31,7 +41,7 @@ public class CookieClicker {
```
=== "Gradle (Kotlin DSL)"
- ```kotlin
+ ```kotlin title="build.gradle.kts"
repositories {
mavenCentral()
}
@@ -40,7 +50,7 @@ public class CookieClicker {
}
```
=== "Gradle (Groovy DSL)"
- ```groovy
+ ```groovy title="build.gradle"
repositories {
mavenCentral()
}
@@ -49,7 +59,7 @@ public class CookieClicker {
}
```
-## Resources
+## Additional Resources
You might also find the following resources helpful:
diff --git a/docs/start/installation.md b/docs/start/installation.md
index fbe0ce97..c758acb8 100644
--- a/docs/start/installation.md
+++ b/docs/start/installation.md
@@ -4,14 +4,14 @@
- Java 23 or later
- [JDA 5.x](https://github.com/discord-jda/JDA)
-- SLF4J Implementation _(not mandatory, but recommended)_
+- [SLF4J Implementation](https://jda.wiki/setup/logging/) _(not mandatory, but recommended)_
## Configuration
-JDA-Commands is distributed through Maven Central, or alternately you can download the latest version
-[here](https://github.com/Kaktushose/jda-commands/releases/latest)
+JDA-Commands is distributed through Maven Central. Alternatively you can download the latest version
+[here](https://github.com/Kaktushose/jda-commands/releases/latest).
=== "Maven"
- ```xml
+ ```xml title="pom.xml"
io.github.kaktushose
jda-commands
@@ -19,7 +19,7 @@ JDA-Commands is distributed through Maven Central, or alternately you can downlo
```
=== "Gradle (Kotlin DSL)"
- ```kotlin
+ ```kotlin title="build.gradle.kts"
repositories {
mavenCentral()
}
@@ -28,11 +28,19 @@ JDA-Commands is distributed through Maven Central, or alternately you can downlo
}
```
=== "Gradle (Groovy DSL)"
- ```groovy
+ ```groovy title="build.gradle"
repositories {
mavenCentral()
}
dependencies {
implementation 'io.github.kaktushose:jda-commands:v4.0.0-beta.4"'
}
- ```
\ No newline at end of file
+ ```
+
+## IntelliJ Plugin
+
+We also provide an IntelliJ Plugin that performs some Code Inspection. It validates method references, which are
+commonly used in jda-commands. You can find it [here](https://plugins.jetbrains.com/plugin/25977-jda-commands-inspection).
+
+![Plugin Example](../assets/plugin.png)
+
diff --git a/docs/start/quick-start.md b/docs/start/quick-start.md
index fde1285a..41525ccc 100644
--- a/docs/start/quick-start.md
+++ b/docs/start/quick-start.md
@@ -5,7 +5,7 @@ public class Main {
public static void main(String[] args) {
JDA jda = yourJDABuilding();
- JDACommands jdaCommands = JDACommands.start(jda, Main.class);
+ JDACommands.start(jda, Main.class);
}
}
```
diff --git a/docs/start/runtime.md b/docs/start/runtime.md
new file mode 100644
index 00000000..98d78801
--- /dev/null
+++ b/docs/start/runtime.md
@@ -0,0 +1,101 @@
+# Runtime Concept
+
+## Overview
+
+One of the core concepts in JDA-Commands is the so-called `Runtime`. It will be mentioned frequently here and in the
+[Javadocs](https://kaktushose.github.io/jda-commands/javadocs/latest/). A `Runtime` delegates the JDA events to their
+corresponding `EventHandlers` and manages the used virtual threads.
+
+A new `Runtime` is created each time a:
+
+- [`SlashCommandInteractionEvent`](https://javadoc.io/doc/net.dv8tion/JDA/latest/net/dv8tion/jda/api/events/interaction/command/SlashCommandInteractionEvent.html)
+- [`GenericContextInteractionEvent`](https://javadoc.io/doc/net.dv8tion/JDA/latest/net/dv8tion/jda/api/events/interaction/command/GenericContextInteractionEvent.html)
+- [`CommandAutoCompleteInteractionEvent`](https://javadoc.io/doc/net.dv8tion/JDA/latest/net/dv8tion/jda/api/events/interaction/command/CommandAutoCompleteInteractionEvent.html)
+
+is provided by JDA or if an interaction is marked as [*independent*](#components).
+
+Runtimes are executed in parallel, but events are processed sequentially by each `Runtime`.
+Every `EventHandler` called by a `Runtime` is executed in its own virtual thread, isolated from the runtime one.
+
+See [`Lifetime`](#Lifetime) for
+details when a `Runtime` will close.
+
+## Threading Model
+
+JDA-Commands will listen for incoming events on the `JDA MainWS-ReadThread`. It will then create a new `Runtime`
+or use an existing one, depending on the type of event _(see the flowchart below for details)._ The incoming event is
+then passed to the corresponding `Runtime`.
+
+Each `Runtime` will run in its own virtual thread, called `JDAC Runtime-Thread `. The `Runtime` will wait for new
+incoming events and then delegate them to the correct `EventHandler`. For instance, a
+[`SlashCommandInteractionEvent`](https://javadoc.io/doc/net.dv8tion/JDA/latest/net/dv8tion/jda/api/events/interaction/command/SlashCommandInteractionEvent.html)
+will be passed to the `SlashCommandHandler`.
+
+The `EventHandler` will _again_ run in its own virtual thread, named `JDAC EventHandler-Thread `, isolated from
+the runtime one. Other incoming events are only executed when the previous one has finished.
+
+!!! tip "Blocking Methods"
+ Because each event has its own virtual thread, you can call blocking methods like JDAs `RestAction#complete` safely
+ without blocking the `JDA MainWS-ReadThread`.
+
+![Runtime Flowchart](../assets/runtime.png)
+
+## Lifetime
+
+By default, JDA-Commands will handle the lifetime of Runtimes for you. Every `Runtime` will be closed **15 minutes**
+after its creation. This time span is oriented towards the lifespan of the
+[`InteractionHook`](https://javadoc.io/doc/net.dv8tion/JDA/latest/net/dv8tion/jda/api/interactions/InteractionHook.html).
+
+### Explicit
+
+You can disable the default behaviour by setting the
+[`ExpirationStrategy`](https://kaktushose.github.io/jda-commands/javadocs/latest/jda.commands/com/github/kaktushose/jda/commands/dispatching/expiration/ExpirationStrategy.html) to
+[`EXPLICIT`](https://kaktushose.github.io/jda-commands/javadocs/latest/jda.commands/com/github/kaktushose/jda/commands/dispatching/expiration/ExpirationStrategy.Explicit.html).
+
+
+```java title="Main.java"
+JDACommands.builder(jda, Main.class)
+ .expirationStrategy(ExpirationStrategy.EXPLICIT)
+ .start();
+```
+
+This will prevent any `Runtime` from closing until [`closeRuntime`](https://kaktushose.github.io/jda-commands/javadocs/latest/jda.commands/com/github/kaktushose/jda/commands/dispatching/events/Event.html#closeRuntime())
+is explicitly called.
+
+!!! example
+ ```java title="GreetCommand.java" hl_lines="4"
+ @SlashCommand("greet")
+ public void onCommand(CommandEvent event) {
+ event.reply("Hello World!");
+ event.closeRuntime();
+ }
+ ```
+
+### Inactivity
+You can also adjust the time frame until a `Runtime` gets closed.
+
+!!! example
+ ```java title="Main.java" hl_lines="2"
+ JDACommands.builder(jda, Main.class)
+ .expirationStrategy(new ExpirationStrategy.Inactivity(20))//(1)!
+ .start();
+ ```
+
+ 1. Note: the duration is always passed as minutes.
+
+## Components and Modals
+
+### Runtime-bound
+
+By default, Buttons, SelectMenus and Modals are `runtime-bound`. This means that any incoming event will use the same
+`Runtime` as the interaction that replied with them.
+
+However, this also means that they cannot be executed anymore after the `Runtime` is closed. JDA-Commands will handle
+that case and remove the component in question. It will also send an ephemeral reply to the user, saying that the
+component is no longer available.
+
+
+### Independent
+
+!!! info
+ Modals cannot be independent because they always need a parent interaction that triggers them!
\ No newline at end of file
diff --git a/mkdocs.yml b/mkdocs.yml
index 7f6df10c..016efc09 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -43,6 +43,9 @@ extra:
copyright: Copyright © 2025 Kaktushose
+plugins:
+ - open-in-new-tab
+
markdown_extensions:
- admonition
- pymdownx.details
@@ -67,7 +70,8 @@ nav:
- Getting Started:
- Installation: start/installation.md
- Quick Start Guide: start/quick-start.md
- - Interactions: interactions.d
+ - Runtime Concept: start/runtime.md
+ - Interactions: interactions.md
- Middlewares: middlewares.md
- Dependency Injection: di.md
- Misc: misc.md
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..95bdfdbd
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,2 @@
+mkdocs-material
+mkdocs-open-in-new-tab
\ No newline at end of file