Kiskae / DiscordKt

[Unmaintained] Opinionated Discord client written in Kotlin
MIT License
1 stars 0 forks source link

DiscordKt Build Status Download

An opinionated Discord client written in Kotlin.

Usage

Dependencies

The project is split into two subprojects. api contains the interfaces that the user should use to access the client. impl contains the implementation of the client.

By using the following set-up the client will only be able to access api classes and only make the implementation available during runtime.

Gradle

repositories {
    maven {
        url "http://dl.bintray.com/kiskae/maven"
    }
}

dependencies {
    compile 'net.serverpeon:discordkt-api:<version>'
    runtime 'net.serverpeon:discordkt-impl:<version>'
}

Maven

<repositories>
  <repository>
    <id>bintray-kiskae-maven</id>
    <name>bintray</name>
    <url>http://dl.bintray.com/kiskae/maven</url>
  </repository>
</repositories>
<dependencies>
  <dependency>
    <groupId>net.serverpeon</groupId>
    <artifactId>discordkt-api</artifactId>
    <version>1.0-alpha1</version>
    <type>pom</type>
  </dependency>
  <dependency>
    <groupId>net.serverpeon</groupId>
    <artifactId>discordkt-impl</artifactId>
    <version>1.0-alpha1</version>
    <type>pom</type>
    <scope>runtime</scope>
  </dependency>
</dependencies>

For users of SLF4J: The implementation contains a number of logging statements that will be very spammy if the logging level is set to TRACE. Adding the following logger configuration to the log4j2.xml configuration will present this spam:

<Logger name="net.serverpeon.discord.internal" level="info" additivity="false">
    <Appenders...>
</Logger>

Creating the Client

The client can be obtained by using the fluent builder created using DiscordClient.newBuilder(). After the client is built it is not connected to Discord until data is accessed or the DiscordClient#startEmittingEvents() method is called.

DiscordClient client = DiscordClient.newBuilder()
        .login("hello@discord.gg", "somepassword")
        .build()

Using the Netty-inspired DiscordClient.closeFuture() 'closing' future the user can block until the client is closed. This is usually applied in the following way:

public void main(String[] args) {
  DiscordClient client = ...

  // Add event listeners
  client.eventBus.register(...);

  // Connect to discord
  client.startEmittingEvents();

  // Block until completion or exception.
  client.closeFuture().await();
}

Observing events

Events can be observed by listening on the client's EventBus

A full listing of events can be found here: net.serverpeon.discord.event

DiscordClient client = ...

client.eventBus().register(new Object() {
    @Subscribe
    public void onMessage(MessageCreateEvent event) {
      // Called each time a new message is posted to a channel the user is in.
    }
});

// Triggers connection to Discord, accessing the model will do the same thing.
client.startEmittingEvents();

Accessing data

Almost all data can be accessed through Observable collections representing the relationships between objects.

In the following example find a server with the name "" and print all text channels within that guild:

DiscordClient client = ...

client.guilds()
        .first(g -> "<ServerName>".equals(g.getName()))
        .flatMap(Guild::getChannels)
        .filter(c -> c.getType() == Channel.Type.TEXT)
        .subscribe(c -> {
            System.out.printf("Guild: %s - Channel: %s%n", c.getGuild().getName(), c.getName());
        });

All observables are also lazy; this means that it can be used multiple times and it will always return the most up-to-date answer at that time.

Observable<Channel.Public> publicChannels = client.guilds()
        .filter(c -> "<ServerName>".equals(c.getName()))
        .flatMap(Guild::getChannels);

publicChannels.subscribe(System.out::println);

// undetermined amount of time later

publicChannels.subscribe(System.out::println);

More examples can be found for Java and Kotlin.

Opinionated Design

The primary motivation writing this client is the fact that many of the existing Java clients/wrappers do not encapsulate the asynchronous nature of the api very well. This client deals with these issues by encapsulating all of the data with well-defined asynchronous libraries.

TODO