Giter VIP home page Giter VIP logo

ktirc's Introduction

KtIrc

Build status Code quality Code coverage Latest version Documentation

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()

Documentation

You can view the latest documentation for KtIrc at https://ktirc.d11n.dev/.

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.

ktirc's People

Contributors

csmith avatar

Watchers

 avatar  avatar  avatar

Forkers

kajvdh

ktirc's Issues

Process user modes

Handle the RPL_UMODEIS (221) numeric, and store our user modes in ServerState

Handle channel user mode changes properly

At present a mode change on a channel such as +o user isn't handled properly, we treat it as an unknown (thus boolean) mode and discard the parameter.

The mode handling needs to check user modes.

Support multiple names for capabilities

As capabilities come out of draft, some IRCds may be sending draft/foo-3.3 while others will graduate to just foo. At the minute we only support one capability name per capability; it'd be good to support aliases for when this happens.

Exception when disconnecting

When disconnecting you get the following exception:

Exception in thread "DefaultDispatcher-worker-8" java.lang.IllegalStateException: Check failed.
	at com.dmdirc.ktirc.IrcClientImpl.connect(IrcClientImpl.kt:85)
	at com.dmdirc.Connection.connect(Connection.kt:86)
	at com.dmdirc.ServerContextMenu$$special$$inlined$apply$lambda$3$1.invokeSuspend(MainView.kt:54)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
	at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
com.dmdirc.ktirc.IrcClientImpl$connect$$inlined$with$lambda$1 invokeSuspend
java.util.concurrent.CancellationException: Channel closed due to job failure
	at kotlinx.coroutines.io.ByteBufferChannel$attachJob$1.invoke(ByteBufferChannel.kt:66)
	at kotlinx.coroutines.io.ByteBufferChannel$attachJob$1.invoke(ByteBufferChannel.kt:21)
	at kotlinx.coroutines.InvokeOnCancelling.invoke(JobSupport.kt:1315)
	at kotlinx.coroutines.JobSupport.notifyCancelling(JobSupport.kt:1354)
	at kotlinx.coroutines.JobSupport.tryMakeCancelling(JobSupport.kt:711)
	at kotlinx.coroutines.JobSupport.makeCancelling(JobSupport.kt:671)
	at kotlinx.coroutines.JobSupport.cancelImpl(JobSupport.kt:595)
	at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:575)
	at kotlinx.coroutines.JobSupport.cancel(JobSupport.kt:570)
	at kotlinx.coroutines.io.ChannelJob.cancel(Coroutines.kt)
	at io.ktor.network.sockets.NIOSocketImpl.close(NIOSocket.kt:59)
	at com.dmdirc.ktirc.io.KtorLineBufferedSocket.disconnect(LineBufferedSocket.kt:77)
	at com.dmdirc.ktirc.IrcClientImpl.disconnect(IrcClientImpl.kt:114)
	at com.dmdirc.Connection.disconnect(Connection.kt:154)
	at com.dmdirc.ServerContextMenu$$special$$inlined$apply$lambda$3$1.invokeSuspend(MainView.kt:52)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
	at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
	at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:742)
Caused by: kotlinx.coroutines.JobCancellationException: Job was cancelled; job=StandaloneCoroutine{Cancelled}@691fd2df

Process auth notices

Notices received on connection/authentication etc:

:irc.example.com NOTICE * :*** Looking up your username
@time=2019-02-04T21:24:50.986Z :irc.example.com NOTICE User :You're now logged in as UserName

BATCH support

Support IRCv3 batches

https://ircv3.net/specs/extensions/batch-3.2.html

It might make sense for the library user to be able to configure behaviour - either KtIrc buffers batches and emits them when they're finished, or it just emits each line as it arrives (and the user of KtIrc doesn't need to worry about handling them).

Add way to simulate echo-message on older networks

At the minute the KtIrc user needs to know whether echo-message is enabled or not to determine how to show messages. It'd be a lot easier if there were an option to just fake an echo on servers that don't support the cap.

Away Support

Parser needs away support, which should include

  • Setting away (or back)
  • Tracking the away state
  • Appropriate events for away/back

Buffer overflow exception connecting to bouncer

java.nio.BufferOverflowExceptionHeapByteBuffer.java:233
HeapByteBuffer.java:233java.nio.HeapByteBuffer.put
Tls.kt:130com.dmdirc.ktirc.io.TlsSocket.unwrap
Tls.kt:-1com.dmdirc.ktirc.io.TlsSocket$unwrap$1.invokeSuspend
ContinuationImpl.kt:32kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith
Dispatched.kt:233kotlinx.coroutines.DispatchedTask.run
CoroutineScheduler.kt:594kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely
CoroutineScheduler.kt:60kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely
CoroutineScheduler.kt:742kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run

Process channel topics

Handle topic commands, and the three topic numerics:

RPL_NOTOPIC (331)
RPL_TOPIC (332)
RPL_TOPICWHOTIME (333)

Process channel modes

Handle modes on channels, raise an event and store them in ChannelState.

This will need to check the server features to understand which modes take args etc.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.