DisQuark is a reactive library that enables developers to write fast and performant JVM applications that leverage Discord's REST API. Includes support for REST interactions, OAuth2, and responding to interactions and executing webhooks without a bot token.
Powered by Vert.x, SmallRye Mutiny, and Immutables.
Get DisQuark by importing the io.disquark:disquark-rest
artifact (or the io.disquark:disquark-rest-kotlin
artifact if you prefer Kotlin) dependency using your preferred build tool.
The entrypoint to your DisQuark application depends on your use case.
-
DiscordBotClient
- a client tied to a bot account capable of doing anything a bot token allows you to do; can also receive and respond to interactions and execute webhooks using interaction and webhook tokens -
DiscordOAuth2Client
- a client tied to a user account's OAuth2 token capable of doing anything a bearer token allows you to do; can also receive and respond to interactions and execute webhooks using interaction and webhook tokens -
DiscordInteractionsClient
- a client capable of receiving and responding to incoming interactions using interaction tokens, not tied to a bot or user account -
DiscordWebhookClient
- a client capable of executing webhooks using webhook tokens, not tied to a bot or user account
Each client is created using create
or builder
static methods.
DisQuark provides a (WIP) idiomatic Kotlin API for users who prefer Kotlin. The API provides Kotlin DSLs as alternatives to Java builders and offers extension methods to translate SmallRye Mutiny constructs to Kotlin Coroutine Flow
s and suspended values. The Kotlin API is strongly recommended; the Kotlin DSL syntax is much easier to use to build requests than the Java builder syntax.
Get the Kotlin API by importing the io.disquark:disquark-rest-kotlin
dependency using your preferred build tool.
DisQuark's API should not be considered stable for now.
DisQuark currently does not support Discord's Gateway or Voice APIs. Interest in the project will determine whether time is invested to develop corresponding modules. For now, the project's development efforts are focused on improving and maintaining the REST module.
Using io.disquark:disquark-rest
:
class MyApp {
public static void main(String[] args) {
var botClient = DiscordBotClient.create(Vertx.vertx(), "TOKEN");
botClient.createMessage(new Snowflake(0L))
.withContent("Hello World!")
.subscribe().with(x -> {});
}
}
Using io.disquark:disquark-rest-kotlin
:
suspend fun main() {
val botClient = DiscordBotClient.create(Vertx.vertx(), "TOKEN")
botClient.createMessage(channelId = Snowflake(0L)) {
content = "Hello World!"
}.awaitSuspending()
}
Using io.disquark:disquark-rest
:
class MyApp {
public static void main(String[] args) {
var botClient = DiscordBotClient.create(Vertx.vertx(), "TOKEN");
botClient.bulkOverwriteGlobalApplicationCommands(new Snowflake(0L))
.withOverwrites(new GlobalApplicationCommandOverwrite("foo")
.withType(ApplicationCommand.Type.CHAT_INPUT)
.withDescription("Foo commands")
.withOptions(List.of(
new ApplicationCommand.Option(ApplicationCommand.Option.Type.SUB_COMMAND, "bar", "Foo bar command")
.withOptions(List.of(
new ApplicationCommand.Option(ApplicationCommand.Option.Type.STRING, "baz", "Baz option")
.withRequired(true)))))
).subscribe().with(x -> {});
}
}
Using io.disquark:disquark-rest-kotlin
:
suspend fun main() {
val botClient = DiscordBotClient.create(Vertx.vertx(), "TOKEN")
botClient.bulkOverwriteGlobalApplicationCommands(applicationId = Snowflake(0L)) {
chatInputCommand(name = "foo") {
description = "Foo commands"
subcommand(name = "bar", description = "Foo bar command") {
stringOption(name = "baz", description = "Baz option") {
required = true
}
}
}
}.onItem().ignoreAsUni().awaitSuspending()
}
By default, the web server launched by DisQuark will listen for incoming interactions on localhost:80
.
Verification of incoming interactions requires the org.bouncycastle:bcprov-jdk18on
dependency to be installed and for the BouncyCastleProvider
to be configured as Java's java.security.Provider
in your application. Incoming interactions won't have their signatures verified if you don't setup a BouncyCastleProvider
or change the default InteractionsValidator
.
class MyApp {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static void main(String[] args) {
var botClient = DiscordBotClient.create(Vertx.vertx(), "TOKEN");
botClient.on(applicationCommand().name("foo").with(option().type(ApplicationCommand.Option.Type.SUB_COMMAND).name("bar").with(option().name("baz"))))
.onItem().transformToUniAndMerge(interaction -> interaction.respond().withContent("Hello World!"))
.onItem().ignoreAsUni().await().indefinitely();
}
}
It's strongly recommended to use DisQuark with our Quarkiverse extension which minimizes the boilerplate needed to listen and respond to interactions.
DisQuark clients expose several configuration options via Builder
s accessible from corresponding static builder
methods.
You can configure your client's AccessTokenSource
to receive your access token asynchronously from an alternative source.
You can change the RateLimitStrategy
and the GlobalRateLimiter
implementation used by DisQuark to avoid being rate limited by Discord's API. There are pre-configured strategies to disable rate limiting logic or to only apply bucket or global rate limiting logic. This can be useful when you are creating a distributed application and want to synchronize rate limiting logic across your DisQuark application instances.
You can change the RequesterFactory
used to construct a Requester
instance that performs the actual request logic to Discord. This is useful if you need to configure the underlying HttpClient
used by the default Requester
or if you want to provide a different implementation altogether.
Logging in DisQuark is provided by the SLF4J API. Install an implementation using your preferred build tool and configure it appropriately to receive trace- and debug-level logs from your application.
The following configuration options are available for applications leveraging HTTP interactions:
router
- the Vert.xRouter
instance used to setup the interactions handlerverifyKey
- your Discord application's public key used to verify incoming interaction signatures, lazily fetched if not providedhandleCors
- whether to install a CORS handler to theRouter
to accept incomingPOST
requests fromdiscord.com
,true
by defaultinteractionsUrl
- the relative URL to receive interactions from,/
by defaultstartHttpServer
- whether to construct and start anHttpServer
when listening for incoming interactions,true
by defaulthttpServerSupplier
- the factory used to construct theHttpServer
ifstartHttpServer
is enabledvalidatorFactory
- the factory used to construct anInteractionsValidator
implementation from theverifyKey
DisQuark snapshots are automatically published with the version 999-SNAPSHOT
when commits are pushed to the main branch.
To use the latest snapshot in Maven, add the following repository to your pom.xml
:
<repositories>
<repository>
<id>ossrh</id>
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>