You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Chris Smith a1aad4dbc7 Convert event tests to use mockk 5 hours ago
docs Architecture info 2 weeks ago
gradle/wrapper Topic support 1 week ago
src Convert event tests to use mockk 5 hours ago
.gitignore Support message tags v3.3, replies 2 weeks ago
.travis.yml 0.6.0, travis tweaks 2 weeks ago
CHANGELOG Add TargetedEvent class, fix caps negotiation 7 hours ago
LICENCE Licence 2 weeks ago
README.md Allow SASL methods to be configured, add EXTERNAL 1 week ago
build.gradle.kts Add always echo messages behaviour 7 hours ago
gradlew Update dependencies, gradle 2 weeks ago
gradlew.bat Update dependencies, gradle 2 weeks ago

README.md

KtIrc

Build Status Codacy Badge codecov Download

KtIrc is a Kotlin JVM library for connecting to and interacting with IRC servers. It is still in an early stage of development.

Features

Built for Kotlin

KtIrc is written in and designed for use in Kotlin; it uses extension methods, DSLs, sealed classes, and so on, to make it much easier to use than an equivalent Java library.

Coroutine-powered

KtIrc uses co-routines for all of its input/output which lets it deal with IRC messages in the background while your app does other things, without the overhead of creating a new thread per IRC client.

Modern IRC standards

KtIrc supports many IRCv3 features such as SASL authentication, message IDs, server timestamps, replies, reactions, account tags, and more. These features (where server support is available) make it easier to develop bots and clients, and enhance IRC with new user-facing functionality.

Setup

KtIrc is published to JCenter, so adding it to a gradle build is as simple as:

repositories {
    jcenter()
}

dependencies {
    implementation("com.dmdirc:ktirc:<VERSION>")
}

Usage

Clients are created using a DSL and the IrcClient function. At a minimum you must specify a server and a profile. A simple bot might look like:

val client = IrcClient {
    server {
        host = "my.server.com"
    } 
    profile {
        nickname = "nick"
        username = "username"
        realName = "Hi there"
    }
}

client.onEvent { event ->
    when (event) {
        is ServerReady ->
            client.sendJoin("#ktirc")
        is ServerDisconnected ->
            client.connect()
        is MessageReceived ->
            if (event.message == "!test")
                client.reply(event, "Test successful!")
    }
}

client.connect()

Known issues / FAQ

java.lang.IllegalStateException: Check failed when connecting to some servers

This happens when the IRC server requests an optional client certificate (for use in SASL EXTERNAL auth, usually). At present there is no support for client certificates in the networking library used by KtIrc. This is fixed in the upstream library and will be included as soon as snapshot builds are available. There is no workaround other than using an insecure connection.

KtIrc connects over IPv4 even when host has IPv6

This is an issue with the Java standard library. You can change its behaviour by defining the system property java.net.preferIPv6Addresses to true, e.g. by running Java with -Djava.net.preferIPv6Addresses=true or calling System.setProperty("java.net.preferIPv6Addresses","true"); in code.

Developing KtIrc

Lifecycle of a message

architecture diagram

The LineBufferedSocket class receives bytes from the IRC server. Whenever it encounters a complete line (terminated by a CR, LF or CRLF), it passes it to the IrcClient as a ByteArray. The MessageParser breaks up the line into its component parts (tags, prefixes, commands, and parameters) and returns them as an IrcMessage.

The IrcMessage is given to the MessageHandler, which tries to find a processor that can handle the command in the message. The processor’s job is to convert the message into an IrcEvent subclass. Processors do not get given any contextual information or state, their job is simply to convert the message as received into an event.

The events are returned to the MessageHandler which then passes them on to all registered event handlers. The job of the event handlers is twofold: firstly, use the events to update the state of KtIrc (for example, after receiving a JOIN message, the ChannelStateHandler will add the user to the list of users in the channel, while the UserStateHandler may update the user’s hostname if we hadn’t previously seen it). Secondly, the event handlers may themselves raise events. This is useful for higher-order events such as ServerReady that depend on a variety of factors and states.

Handlers themselves may not keep state, as they will be shared across multiple instances of IrcClient and won’t be reset on reconnection. State is instead stored in the various *State properties of the IrcClient such as serverState and channelState. Fields that should not be exposed to users of KtIrc can be placed in these public state objects but marked as internal.

All the generated events (from processors or from event handlers) are passed to the IrcClient, which in turn passes them to the library user via the delegates passed to the onEvent method.

Contributing

Contributing is welcomed and encouraged! Please try to add unit tests for new features, and maintain a code style consistent with the existing code.

Licence

The code in this repository is released under the MIT licence. See the LICENCE file for more info.