1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333 |
- = KtIrc {version}
- Chris Smith
- :version: 1.0.1
- :toc: left
- :toc-position: left
- :toclevels: 5
-
- == About KtIrc
-
- KtIrc is a Kotlin JVM library for connecting to and interacting with IRC servers.
- It is still in an early stage of development. Its main 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.
-
- == Getting started
-
- === Installing
-
- All you need to do to start using KtIrc is add a single dependency.
- KtIrc is published to JCenter, making it quick and easy to pull in
- to almost any project. The examples below show how to add the JCenter
- repository and then the KtIrc dependency; you may already be using
- JCenter for other dependencies -- in that case just skip the
- repository configuration!
-
- [TIP]
- ====
- KtIrc adheres to semantic versioning: you can expect to upgrade between
- minor versions without problems (e.g. from `0.1.2` to `0.13.7`); major
- version changes may include breaking changes such as the removal of
- deprecated methods. You should check the changelog before updating to
- a new major version.
- ====
-
- .Gradle (using Kotlin DSL)
- [source,kotlin,subs="attributes"]
- ----
- repositories {
- jcenter()
- }
-
- dependencies {
- implementation("com.dmdirc:ktirc:{version}")
- }
- ----
-
- .Gradle (using Groovy DSL)
- [source,groovy,subs="attributes"]
- ----
- buildscript {
- repositories {
- jcenter()
- }
- }
-
- implementation 'com.dmdirc:ktirc:{version}'
- ----
-
- .Maven
- [source,xml,subs="attributes"]
- ----
- <repositories>
- <repository>
- <id>jcenter</id>
- <url>https://jcenter.bintray.com</url>
- </repository>
- </repositories>
-
- <dependencies>
- <dependency>
- <groupId>com.dmdirc</groupId>
- <artifactId>ktirc</artifactId>
- <version>{version}</version>
- </dependency>
- </dependencies>
- ----
-
- === Creating your first client
-
- KtIrc provides a DSL ("domain specific language") for configuring a
- client that allows you to set the connection details, the user's
- details, and configure the behaviour of KtIrc itself. The DSL is
- accessed through the `IrcClient` function. For full details of all
- supported options, see the <<IrcClient DSL>> reference.
-
- A basic client will look like this:
-
- [source,kotlin]
- ----
- val client = IrcClient {
- server {
- host = "my.server.com"
- }
- profile {
- nickname = "nick"
- username = "username"
- realName = "Hi there"
- }
- }
- ----
-
- === Connecting and handling events
-
- Getting KtIrc to start connecting is as simple as calling the `connect()`
- method, but before that we probably want to add an event listener to deal
- with incoming messages:
-
- [source,kotlin]
- ----
- client.onEvent { event -> <1>
- when (event) { <2>
- is ServerReady ->
- client.sendJoin("#ktirc") <3>
- is ServerDisconnected ->
- client.connect()
- is MessageReceived ->
- if (event.message == "!test") <4>
- client.reply(event, "Test successful!") <5>
- }
- }
-
- client.connect() <6>
- ----
- <1> An event listener is registered using the `onEvent` method. It receives
- a single IrcEvent.
- <2> A Kotlin `when` statement provides a convenient way to switch on the
- type of event received.
- <3> Most common IRC commands have `send` methods defined to quickly and
- safely send the message with the right formatting.
- <4> Kotlin smart-casts the event, so you can access the properties specific
- to the matched event class, such as `message`.
- <5> The IrcClient class provides useful methods to react and respond to
- events.
- <6> The connect() method starts connecting and returns immediately. You'll
- receive events updating you on the progress.
-
- In this example, we're waiting for three events: `ServerReady`, which occurs
- after we have connected and the server has sent us all of the pre-amble
- such as its configuration and capabilities; `ServerDisconnected` which
- is raised whenever KtIrc gets disconnected from (or fails to connect to) the
- IRC server; and `MessageReceived` which occurs, unsuprisingly, whenever a
- message is received. KtIrc has many events: for more information, see the
- <<Events>> reference.
-
- [CAUTION]
- ====
- With this code, KtIrc will immediately try to reconnect as soon as it is
- disconnected. If the server closes the connection early (due to, for
- example, a bad password or the user being banned) this will result in a
- huge number of connection attempts in a short time. In real code you should
- always delay reconnections -- preferably with a backoff -- to avoid
- excessive connection attempts.
- ====
-
- You can see that KtIrc provides a number of useful methods for sending
- requests to the server, and reacting and responding to events. IRC
- commands that KtIrc supports can be invoked using the `send*` methods,
- which are documented in the <<Messages>> reference. Other useful methods
- such as `reply` can be found in the <<Utility methods>> reference.
-
- === Mandatory event handling
-
- In order to properly connect to IRC, stay connected, and handle
- incoming messages properly, the following events MUST be handled:
-
- .<<NicknameChangeRequired>>
- The nickname change required event occurs when connecting to a server
- if our initial nickname is taken. A new nickname must be supplied
- to continue connecting.
-
- .<<ServerDisconnected>>
- When KtIrc becomes disconnected from a server, or fails a connection
- attempt, it will raise this event. If you wish to stay connected
- to IRC you must call the `connect()` method to start a reconnection
- attempt after an appropriate delay.
-
- .<<BatchReceived>>
- On servers that support the IRCv3 batch capability, some incoming
- messages may be sent inside a batch. These could include join or
- quit messages during a netsplit, or other important messages you
- may need to process. At minimum, when receiving a BatchReceived
- event you should apply your normal processing to all the events
- contained within.
-
-
- == IrcClient DSL
-
- The DSL for creating a new `IrcClient` allows you to set a number of
- options relating to how KtIrc connects, what user details it provides,
- and how it behaves. The full range of options available in the DSL is
- shown below:
-
- [source,kotlin]
- ----
- server {
- host = "irc.example.com"
- port = 6667
- useTls = true
- password = "H4ckTh3Pl4n3t"
- }
-
- profile {
- nickname = "MyBot"
- username = "bot"
- realName = "Botomatic v1.2"
- }
-
- behaviour {
- requestModesOnJoin = true
- alwaysEchoMessages = true
- }
-
- sasl {
- mechanisms += "PLAIN"
- username = "botaccount"
- password = "s3cur3"
- }
- ----
-
- === Server settings
-
- The server block allows you to specify the details of the IRC server you
- wish to connect to:
-
- * `host` - the hostname or IP address of the server *(required)*
- * `port` - the port to connect on _(default: 6697)_
- * `useTls` - whether to use a secure connection or not _(default: true)_
- * `password` - the password to provide to the server _(default: null)_
-
- An alternative more compact syntax is available for configuring server details:
-
- [source,kotlin]
- ----
- server("irc.example.com", 6667, true, "H4ckTh3Pl4n3t")
- ----
-
- You can, if you wish, combine the two or use named parameters:
-
- [source,kotlin]
- ----
- server(useTls = true, port = 6697) {
- host = "irc.example.com"
- password = "H4ckTh3Pl4n3t"
- }
- ----
-
- === User profile
-
- The user profile controls how KtIrc will present itself to the IRC server, and
- how other users on that server will see the KtIrc user:
-
- * `nickname` - the initial nickname you wish to use *(required)*
- * `username` - the "username" to provide to the server _(default: KtIrc)_
- * `realName` - the "real name" that will be seen by other clients
- _(default: KtIrc User)_
-
- [TIP]
- ====
- The "username" is sometimes called the "ident" or "gecos". Some IRC servers
- will check for an ident reply from your host and use that in place of the
- username provided if it gets a response. The username (or ident reply)
- becomes part of your client's hostmask, and is visible to other users. It
- is unrelated to nickserv or other account usernames.
- ====
-
- As with the <<Server settings>> you can use a more compact syntax:
-
- [source,kotlin]
- ----
- profile("nickname", "username", "real name")
- ----
-
- === Behaviour
-
- The behaviour block allows you to tweak how KtIrc itself operates. These
- options allow you perform common operations automatically, or enjoy more
- advanced IRC features even if the server doesn't support them:
-
- * `requestModesOnJoin` - if enabled, automatically requests channel modes
- when the client joins a new channel _(default: false)_
- * `alwaysEchoMessages` - if enabled, every message you send will result
- in a `MessageReceived` event being returned. Servers that support the
- IRCv3 `echo-message` capability will do this automatically; enabling the
- behaviour will make all servers act the same way _(default: false)_
- * `preferIPv6` - if enabled, KtIrc will prefer to connect over IPv6 if the
- server publishes AAAA DNS records. If disabled, KtIrc will prefer IPv4.
- If the server is available exclusively on IPv4 or IPv6 then this option
- has no effect. _(default: true)_
-
- The behaviour block is optional in its entirety.
-
- === SASL configuration
-
- SASL ("Simple Authentication and Security Layer") is a standard mechanism
- for securely authenticating to a service that has recently been adopted
- for use in IRC. SASL supports a number of 'mechanisms' that describe how
- the data will be exchanged between the client and server. KtIrc supports
- the following mechanisms:
-
- * `EXTERNAL` - the server uses some external means to authenticate the
- client, instead of a username and password. On most servers this
- means checking the client certificate against one registered with
- the user's account. _(disabled by default)_
- * `PLAIN` - the client sends the username and password in plain text
- during the connection phase. This offers slightly more security
- than calling `nickserv identify` (for example) after connecting.
- * `SCRAM-SHA-1` - this mechanism involves a "salted challenge" being
- completed which results in both the server and the client proving that
- they know the user's password, but without it every being transmitted.
- This is based on the `SHA-1` algorithm which has known issues, but is
- more than sufficient when used in this manner.
- * `SCRAM-SHA-256` - the same as `SCRAM-SHA-1` but using the `SHA-256`
- algorithm instead, which is more modern and secure.
-
- To use `PLAIN`, `SCRAM-SHA-1` or `SCRAM-SHA-256`, you must supply a username
- and password in the configuration:
-
- [source,kotlin]
- ----
- sasl {
- username = "botaccount"
- password = "s3cur3"
- }
- ----
-
- KtIrc enables `SCRAM-SHA-256`, `SCRAM-SHA-1` and `PLAIN` by default, and will
- use them in that order of preference if the server supports more than one.
- You can modify the `mechanisms` parameter if you wish to disable one:
-
-
- [source,kotlin]
- ----
- sasl {
- mechanisms -= "PLAIN"
- username = "botaccount"
- password = "s3cur3"
- }
- ----
-
- You can also clear all the default mechanisms and provide your own list:
-
- [source,kotlin]
- ----
- sasl {
- mechanisms("SCRAM-SHA-256", "PLAIN")
- username = "botaccount"
- password = "s3cur3"
- }
- ----
-
-
- If you wish to enable the `EXTERNAL` mechanism, you do not need to provide
- a username or password:
-
- [source,kotlin]
- ----
- sasl {
- mechanisms("EXTERNAL")
- }
- ----
-
- Alternatively, if you wish to enable `EXTERNAL` but fall back to other
- mechanisms if it doesn't work:
-
- [source,kotlin]
- ----
- sasl {
- mechanisms += "EXTERNAL"
- username = "botaccount"
- password = "s3cur3"
- }
- ----
-
- The SASL block is optional in its entirety.
-
- == State
-
- KtIrc attempts to track all reasonable state of the IRC network. This includes
- details about the server, channels the client is joined to, and users that are
- also in those channels. The state is exposed in a several fields accessible
- from the `IrcClient`:
-
- === ServerState
-
- The server state provides information about the server, and our connection to
- it.
-
- [IMPORTANT]
- ====
- The server state will be updated frequently while KtIrc is connecting to a
- server. The values within it should not be relied upon until a `ServerReady`
- event is received, as they may be incomplete or estimates before then.
- ====
-
- .serverState.status (ServerStatus)
- Provides an enum containing the current server state. One of:
-
- * `Disconnected` - the server is not connected
- * `Connecting` - we are attempting to establish a connection
- * `Negotiating` - we are logging in, negotiating capabilities, etc
- * `Ready` - we are connected and commands may be sent
-
- .serverState.localNickname (String)
- The current nickname we are using on the IRC server. While connecting this
- will default to the nickname from the <<User profile>>, but it may be updated
- if e.g. the nick is in use or not allowed.
-
- .serverState.serverName (String)
- The name the server uses for itself. While connecting this defaults to the
- hostname given in the <<Server settings>>, but it will be updated to the
- value provided by the server. For example, you may connect to
- `irc.example.com` and during the negotiation phase KtIrc will see that it
- is actually talking to `server3.uk.irc.example.com` and update the
- serverName to reflect that.
-
- [TIP]
- ====
- For a user-friendly identifier most servers provide a `NETWORK` token in
- the ISUPPORT reply, which is available via the <<Features>> property.
- ====
-
- .serverState.channelModePrefix (ModePrefixMapping)
- Provides a mapping from channel user modes (such as "o" for op, "v" for
- voice) to the prefixes used before nicknames (such as "@" and "+").
-
- To map prefixes to modes, you can use the `getMode()` or `getModes()`
- functions:
-
- [source,kotlin]
- ----
- getMode('@') == 'o'
- getModes("@+") == "ov"
- ----
-
- .serverState.channelTypes (String)
- Contains the types of channels that are allowed by the server, such as
- `\#&` for normal channels ("#") and local channels ("&").
-
- ==== Capabilities
-
- The IRCv3 specifications introduce the concept of 'capability negotiation'.
- This allows the client and server to negotiate and enable new capabilities
- that are mutually supported.
-
- The capabilities state contains the following properties:
-
- .serverState.capabilities.negotiationState (CapabilitiesNegotiationState)
- The current state of negotiating with the server. One of:
-
- * `AWAITING_LIST` - we have requested a list of capabitilies and are awaiting
- a reply
- * `AWAITING_ACK` - we have sent the capabilities we want to enable, and are
- waitin for the server to acknowledge them
- * `AUTHENTICATING` - we are attempting to authenticate with SASL
- * `FINISHED` - we have completed negotiation
-
- Where a server does not support IRCv3 capability negotiation, the state will
- remain at `AWAITING_LIST`.
-
- .serverState.capabilities.advertisedCapabilities (Map<String, String>)
- Contains a map of capability names to values that the server offered. This
- should only be required for advance use cases, such as looking up the
- languages offered by a server when providing the user with a choice of
- translations.
-
- .serverState.capabilities.enabledCapabilities (Map<Capability, String>)
- Contains a map of capabilities that KtIrc has successfully negotiated with
- the server.
-
- ===== Supported capabilities
-
- * `sasl` - used to perform SASL authentication during connection
- * `message-tags` - allows arbitrary tags on messages
- * `server-time` - the server adds a timestamp tag to each incoming message
- * `account-tag` - the server adds an account tag to incoming user messages
- * `userhost-in-names` - the NAMES reply includes users hosts not just nicknames
- * `multi-prefix` - all modes are included in nick prefixes (e.g. `@+nick`)
- * `extended-join` - more information is sent when a user joins a channel
- * `batch` - allows multi-line responses to be batched together
- * `echo-message` - echos the client's own messages back to it
- * `draft/labeled-responses` - responses are labeled so the client knows which
- incoming message corresponds to which command it sent
- * `account-notify` - the server sends a message when a user's account changes
- * `away-notify` - the server sends a message when a user's away state changes
- * `chghost` - the server sends a message when a user's host changes
-
- ==== Features
-
- Features are KtIrc's way of exposing the information the server declares in
- its ISUPPORT messages. These describe how the server is configured, and what
- limits are placed on clients. You access features using the `features` map
- in the server state:
-
- [source,kotlin]
- ----
- ircClient.serverState.features[ServerFeature.Network]
- ----
-
- The following features are available:
-
- * `Network` - the name of the network the server belongs to __(String?)__
- * `ServerCaseMapping` - the current case mapping of the server __(CaseMapping!)__
- * `Modeprefixes` - the user mode prefix mapping (e.g. ov to @+) __(ModePrefixMapping!)__
- * `MaximumChannels` - the maximum number of channels a user can join __(Int?)__
- * `ChannelModes` - the modes supported in channels __(Array<String>?)__
- * `ChannelTypes` - the types of channel supported (e.g. "#&") __(String!)__
- * `MaximumChannelNameLength` - how long channel names may be __(Int!)__
- * `WhoxSupport` - whether the server supports extended whos ("WHOX") __(Boolean!)__
-
- [NOTE]
- ====
- If the server does not define a feature, KtIrc will either fall back to a
- default value based on the IRC RFCs or common practice (for those features
- identified with a non-null type such as `Int!` or `String!`); otherwise
- the value of the feature will be `null` (such as for those identified as
- `Int?` or `String?` types).
- ====
-
- === UserState
-
- The client's UserState object tracks the details of all users in common
- channels. It can be used to find the most up-to-date and comprehensive
- information for those users, as well as the set of channels that we share
- with them.
-
- The UserState is accessed via the `userState` property of IrcClient and
- acts as a map, accessible using either a nickname or a `User` object:
-
- [source,kotlin]
- ----
- ircClient.userState["acidBurn"]
-
- val user: User = myIrcEvent.user
- ircClient.userState[user]
- ----
-
- The UserState returns a `KnownUser` object which exposes a `details`
- property containing the user details, and a `channels` property
- containing the common channel names. You can also use the `in`
- operator to check if the user is in a channel:
-
- [source,kotlin]
- ----
- ircClient.userState["acidBurn"]?.let { knownUser -> <1>
- val accountName = knownUser.account
- val inChannel = "#channel" in knownUser <2>
- val allChannels = knownUser.channels <3>
- }
- ----
- <1> If the user isn't known, the call to `get` (using the `[]` operator)
- returns null, so we use a `let` statement to deal only with the case
- that the user is found.
- <2> Check if the user is present on the common channel `#channel`. If
- the KtIrc client is not joined to that channel, it will always return
- false. You can also use the `contains("#channel")` method instead of
- the `in` operator.
- <3> Returns all common channels we share with the user; will never
- include channels that the KtIrc client is not joined to.
-
- === ChannelState
-
- The ChannelState keeps track of the state for all channels that the client
- is joined to. It is indexed by channel name:
-
- [source,kotlin]
- ----
- ircClient.channelState["#ktirc"]
- ----
-
- Each channel's state contains the following properties:
-
- * `receivingUserList` - boolean value indicating whether we are in the process
- of receiving the list of users for the channel. If we are, the `users`
- property will be incomplete.
- * `modesDiscovered` - boolean value indicating whether we have received the
- full set of modes set on the channel. The `requestModesOnJoin` <<Behaviour>>
- allows you to make KtIrc request these automatically.
- * `topic` - a ChannelTopic object representing the current channel topic.
- If no topic is set, then a ChannelTopic with `null` properties will be
- provided.
- * `users` - a map of all known users in the channel, see <<Channel users>>
- for more information
- * `modes` - A map of the current channel modes and their values. Only
- complete if `modesDiscovered` is true.
-
- ==== Channel users
-
- Channel users are accessed using the `users` property, which provides an
- iterable map of nickname to `ChannelUser`. Each `ChannelUser` contains
- the nickname and current modes for that user. To get further details about
- a user, such as their hostmask or real name, you should query the <<UserState>>
- with the given nickname.
-
- [source,kotlin]
- ----
- ircClient.channelState["#ktirc"]?.users?.forEach { user ->
- println("${user.nickname} has modes ${user.modes}")
- }
- ----
-
- == Events
-
- Incoming lines from the IRC server are converted by KtIrc to subclasses of
- `IrcEvent`. These, along with other more advance events, are then published
- to users of the client using the `onEvent` method in `IrcClient`.
-
- All events extend `IrcEvent`, which offers a single `metadata` property.
- This contains details related to the event:
-
- * `time` - the time at which the message occurred (if the server supports
- the `server-time` capability), or the time at which we received it.
- Always present.
- * `batchId` - an opaque string identifier for the batch the message is
- part of (if the server supports the `batch` capability). Null for
- messages not in a batch.
- * `messageId` - a unique, opaque string identifier for the message if
- the server supports the `msgid` tag. Null otherwise.
- * `label` - a unique, opaque string identifier that ties a message to
- a labelled command that was sent by KtIrc, if the server supports
- the `labelled-replies` capability. Null otherwise.
-
- Several specialised versions of `IrcEvent` are used which allow for easier
- processing:
-
- .TargetedEvent
-
- A `TargetedEvent` is one that is targeted at either a user or a channel.
- `TargetedEvent` exposes a string `target` property that identifies the
- target of the message. This allows you to direct messages to the right
- handler or UI component more easily:
-
- [source,kotlin]
- ----
- ircClient.onEvent { event ->
- when (event) {
- is TargetedEvent -> dispatchEvent(event.target, event)
- }
- }
- ----
-
- .SourcedEvent
-
- A large number of events come from a remote IRC user, and it can be
- useful to handle these in the same way. KtIrc offers a `SourcedEvent`
- interface for all events that originate from a user, and it exposes
- a single `user` property:
-
- [source,kotlin]
- ----
- ircClient.onEvent { event ->
- when (event) {
- is SourcedEvent -> notifyAboutUserActivity(event.user)
- }
- }
- ----
-
- .ChannelMembershipAdjustment
-
- A number of events describe how the membership of a channel changes --
- namely, joins, parts, quits, kicks, names replies, and nick changes.
- All of these events implement the `ChannelMembershipAdjustment` interface
- which reduces the amount of logic you need to do if you wish to maintain
- a membership list (for example in a UI). The interface exposes three
- properties:
-
- * `addedUser` - a single nickname to be added _(String)_
- * `removedUser` - a single nickname to be removed _(String)_
- * `replacedUsers` - a list of nicknames to replace any existing ones with
- _(Array<String>)_
-
- All the properties are nullable, and most events will only populate
- one of the three.
-
- === Server events
-
- ==== ServerConnecting
- * Type: IrcEvent
- * Properties: _(none)_
-
- This event is raised by KtIrc as soon as it starts attempting to connect to
- a server. It will be followed by either a <<ServerConnected>> or a
- <<ServerConnectionError>> event at some point.
-
- ==== ServerConnected
- * Type: IrcEvent
- * Properties: _(none)_
-
- This event is raised by KtIrc when it has connected to the server, and is
- starting the process of registering, negotiating capabilities, etc.
- The server will *not* yet be ready for use - a <<ServerReady>> event will
- follow once all of the initial setup has completed.
-
- ==== ServerConnectionError
- * Type: IrcEvent
- * Properties:
- ** `error`: `ConnectionError` - the type of error that occurred
- ** `details`: `String?` - information about the error, if available
-
- This event is raised by KtIrc when a problem occurred while connecting
- to the server. The `ConnectionError` enum will provide the cause of
- the error, if known:
-
- * `UnresolvableAddress` - the hostname provided could not be resolved
- to an IP address
- * `ConnectionRefused` - the server did not answer a connection request
- on the given port
- * `BadTlsCertificate` - there was an issue with the TLS certificate the
- server presented (e.g. it was out of date, for the wrong domain, etc)
- * `Unknown` - the exact cause of the error isn't known
-
- This event will be followed by a <<ServerDisconnected>> event.
-
- ==== ServerWelcome
- * Type: IrcEvent
- * Properties:
- ** `server`: `String` - the name the server supplied for itself
- ** `localNick`: `String` - the nickname the server says we are using
-
- This event is raised in response to the server sending a 001 WELCOME
- message. It contains the name that the server supplied for itself
- (for example, KtIrc may connect to a round-robin address like
- `irc.example.com` and the server it actually connects to then
- identifies itself as `node3.uk.irc.example.com`), and the nickname
- that the server says we are using.
-
- ==== ServerReady
- * Type: IrcEvent
- * Properties: _(none)_
-
- This event is raised by KtIrc when it has connected to a server,
- registered with the IRC network, and received all of the server's
- initial data describing its configurations and its features.
-
- At this point it is safe to start issuing commands, checking
- state, joining channels, etc.
-
- ==== ServerDisconnected
- * Type: IrcEvent
- * Properties: _(none)_
-
- Raised in all cases where KtIrc has attempted to connect to an IRC server and
- has now been disconnected. KtIrc will not automatically attempt to reconnect;
- the `connect()` method should be called again after an appropriate delay.
-
- NOTE: All of KtIrc's internal state, such as details about users and
- channels, will be reset when disconnected from the server. State should not
- be queried until a new <<ServerReady>> event has been received, at which
- point it will have been recreated.
-
- ==== MotdLineReceived
- * Type: IrcEvent
- * Properties:
- ** `line`: `String` - the line of the message of the day that was received
- ** `first`: `Boolean` - true if the line is the first one received
-
- The MotdLineReceived event is raised whenever the server sends a single
- line of its Message of the Day. The `first` parameter is set on the
- first line of the MOTD so that special formatting or UI handling can
- be applied. When the MOTD is finished, a <<MotdFinished>> event is raised.
-
- ==== MotdFinished
- * Type: IrcEvent
- * Properties:
- ** `missing`: `Boolean` - indicates the MOTD was missing
-
- This event occurs in two circumstances: when the server has sent a
- series of <<MotdLineReceived>> events and has reached the end of the
- Message of the Day; or when the server has no MOTD to send and
- informs the client that the MOTD is missing.
-
- === Channel events
-
- NOTE: Many events such as <<MessageReceived>> apply to both channels and
- users. These are documented in the <<Channel/User events>> category.
-
- ==== ChannelJoined
- * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
- * Properties:
- ** `user`: `User` - the user that joined the channel
- ** `target`: `String` - the channel that was joined
-
- Raised whenever a user joins a channel, including the KtIrc client. You
- can determine whether the join applies to another user or the local client
- using the <<IsLocalClient>> utility method.
-
- When the local client joins a new channel, this event will typically be
- followed by one or more <<ChannelNamesReceived>> events, then
- <<ChannelNamesFinished>>, <<ChannelTopicDiscovered>> and if the
- `requestModesOnJoin` <<Behaviour>> is enabled a <<ModeChanged>> event.
-
- ==== ChannelJoinFailed
- * Type: IrcEvent, TargetedEvent
- * Properties:
- ** `target`: `String` - the channel that we tried to join
- ** `reason`: `JoinError` - the error that prevented us from joining
-
- The ChannelJoinFailed event is raised when we attempt to join a channel
- but the server doesn't allow us to do so. The reason parameter enumerates
- the possible problems:
-
- * `TooManyChannels` - we are already in the maximum number of channels allowed
- by the server.
- * `NoHiding` - the channel is no-hiding (+H), but we have invisible join/parts
- enabled.
- * `NeedKey` - the channel is keyed (+k) and a valid key was not provided
- * `NeedInvite` - the channel is invite only (+i) and no invite was received.
- * `NeedRegisteredNick` - the channel is limited to registered users only, and we
- are not registered.
- * `NeedTls` - the channel is secure-only, and we're not using TLS.
- * `NeedAdmin` - the channel is limited to server admins and we are not one.
- * `NeedOper` - the channel is limited to ircops and we are not one.
- * `Banned` - we are banned from the channel.
- * `ChannelFull` - the channel is limited (+l) and currently full.
- * `BadChannelName` - the channel name is disallowed by the server.
- * `Throttled` - we're trying to joiin too many channels and have been throttled.
- * `Unknown` - we don't know why.
-
- [WARNING]
- ====
- ChannelJoinFailed events are generated on a _best-effort_ basis by KtIrc. Error
- handling on IRC is very poorly standardised, and varies wildly between server
- implementations. For example, trying to join a secure-only channel on an
- ircd-seven server will send a NOTICE to the user instead of an error response,
- so no `ChannelJoinFailed` event will be raised.
-
- When tracking whether a join suceeded or failed you should combine monitoring
- for the response with a reasonable timeout, and assume failure if the timeout
- lapses without a <<ChannelJoined>> or <<ChannelJoinFailed>> event occurring.
- ====
-
- ==== ChannelParted
- * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
- * Properties:
- ** `user`: `User` - the user that parted the channel
- ** `target`: `String` - the channel that was parted
- ** `reason`: `String` - the user-supplied reason for parting
-
- Raised when any user parts a channel that we are on. Users can supply a reason
- when parting a channel; if they have done so the `reason` property will be
- non-empty.
-
- ==== ChannelUserKicked
- * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
- * Properties:
- ** `user`: `User` - the user that performed the kick
- ** `victim`: `String` - the nickname of the user that was kicked
- ** `target`: `String` - the channel that the victim was kicked from
- ** `reason`: `String` - the user-supplied reason for kicking
-
- This event occurs when a user is kicked (forcibly removed) from a channel.
-
- NOTE: The `user` is the one performing the kick, and will remain in the
- channel. The `victim` is the one being forcibly ejected.
-
- ==== ChannelQuit
- * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
- * Properties:
- ** `user`: `User` - the user that quit
- ** `target`: `String` - the channel that the user was in
- ** `reason`: `String` - the user-supplied reason for quitting
-
- After a <<UserQuit>> event, KtIrc will "fan out" the event to all of the
- channels that we share with the user and raise a `ChannelQuit` event for
- each channel. This is designed to make implementing certain features easier;
- if you fully handle a UserQuit event there is no need to also handle the
- ChannelQuit events, and vice-versa.
-
- Users and servers can supply a reason when a user quits; if supplied then
- the `reason` parameter will be non-empty.
-
- ==== ChannelNickChanged
- * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
- * Properties:
- ** `user`: `User` - the user who has changed their nickname
- ** `target`: `String` - the channel that the user is in
- ** `newNick`: `String` - the user's new nickname
-
- After a <<UserNickChanged>> event, KtIrc will "fan out" the event to
- all of the channels that we share with the user and raise a `ChannelNickChanged`
- event for each channel. This is designed to make implementing certain features
- easier; if you fully handle a UserNickChanged event there is no need to also
- handle the ChannelNickChanged events, and vice-versa.
-
- TIP: The user property will contain the user's old details, but you will
- not be able to access additional information from the <<UserState>> using
- these details as KtIrc will have internally renamed the user to use the
- new nickname.
-
- ==== ChannelNamesReceived
- * Type: IrcEvent, TargetedEvent
- * Properties:
- ** `target`: `String` - the channel that the user is in
- ** `names`: `List<String>` - the partial list of names that are in the channel
-
- When we join a channel (or manually request it) the IRC server sends the
- list of channel members in a sequence of NAMES messages. KtIrc raises a
- `ChannelNamesReceived` event for each of these messages.
-
- WARNING: The given names may not be a complete list of members of the channel,
- as more names could follow. The format of the names varies between IRC servers
- and depending on the IRCv3 <<Capabilities>> that KtIrc negotiated. Most
- implementations should simply wait for <<ChannelNamesFinished>> and then request
- the complete list of names from KtIrc's <<ChannelState>>.
-
- ==== ChannelNamesFinished
- * Type: IrcEvent, TargetedEvent, ChannelMembershipAdjustment
- * Properties:
- ** `target`: `String` - the channel whose names response has finished
-
- Raised when the IRC server has finished receiving all of the names of users
- that are currently in a channel. At this point you can query the channel's
- <<ChannelState>> to get a detailed list of members.
-
- ==== ChannelTopicDiscovered
- * Type: IrcEvent, TargetedEvent
- * Properties:
- ** `target`: `String` - the channel whose topic was discovered
- ** `topic`: `String?` - the topic in the channel, if any
-
- `ChannelTopicDiscovered` occurs when we join a channel (or manually request
- that the server repeats the current topic) and contains the current channel
- topic. If there is no topic set, the `topic` parameter will be `null`.
-
- Metadata about the topic, such as who set it and when, is contained in the
- <<ChannelTopicMetadataDiscovered>> event which should follow this one, if
- the topic was set.
-
- ==== ChannelTopicMetadataDiscovered
- * Type: IrcEvent, TargetedEvent
- * Properties:
- ** `target`: `String` - the channel whose topic metadata was discovered
- ** `user`: `User` - the user who set the topic
- ** `setTime`: `LocalDateTime` - the time at which the topic was set
-
- Provides meta-data relating to a topic that was previously set on the
- channel.
-
- NOTE: The given user may not exist on the network any more, or may have
- changed details since the topic was set. You should not expect to be able
- to look up the user's details in the <<UserState>>, or interact with them
- directly on IRC.
-
- ==== ChannelTopicChanged
- * Type: IrcEvent, TargetedEvent, SourcedEvent
- * Properties:
- ** `user`: `User` - the user who has changed the topic
- ** `target`: `String` - the channel that the topic was changed in
- ** `topic`: `String?` - the channel's new topic
-
- Raised when a user changes the topic of a channel we are joined to. If
- the topic was cleared/removed, the `topic` parameter will be `null`.
-
- ==== ChannelAway
- * Type: IrcEvent, TargetedEvent, SourcedEvent
- * Properties:
- ** `user`: `User` - the user whose away state has changed
- ** `target`: `String` - the channel that the user is in
- ** `message`: `String?` - the away message, or `null` if the user is back
-
- After a <<UserAway>> event, KtIrc will "fan out" the event to all of the
- channels that we share with the user and raise a `ChannelAway`
- event for each channel. This is designed to make implementing certain features
- easier; if you fully handle a UserAway event there is no need to also
- handle the ChannelAway events, and vice-versa.
-
- === Channel/User events
-
- TODO
-
- ==== MessageReceived
-
- TODO
-
- ==== NoticeReceived
-
- TODO
-
- ==== ActionReceived
-
- TODO
-
- ==== CtcpReceived
-
- TODO
-
- ==== CtcpReplyReceived
-
- TODO
-
- ==== UserAway
- * Type: IrcEvent, SourcedEvent
- * Properties:
- ** `user`: `User` - the user who has changed their away state
- ** `message`: `String?` - the away message, or `null` if the user is back
-
- Raised when we are informed that a user has changed away states. If the server
- supports the `away-notify` capability we will receive notifications for all
- users in our common channels; otherwise, we will only receive notifications
- for our own user.
-
- If the user is away but we don't know the reason for it, the `message`
- property will be empty.
-
- ==== UserQuit
-
- TODO
-
- ==== UserNickChanged
-
- TODO
-
- ==== UserHostChanged
-
- TODO
-
- ==== UserAccountChanged
-
- TODO
-
- ==== ModeChanged
-
- TODO
-
-
- === Other events
-
- ==== PingReceived
- * Type: IrcEvent
- * Properties:
- ** `nonce`: `ByteArray` - the unique data that must be included in the reply
-
- Raised when the IRC server sends a PING message to the client. KtIrc will
- automatically reply with an appropriate PONG.
-
- ==== ServerFeaturesUpdated
- * Type: IrcEvent
- * Properties:
- ** `serverFeatures`: `ServerFeatureMap` - the features supplied by the server
-
- Corresponds to the server sending a single 005 ISUPPORT line. Multiple
- events of this type may be raised in quick succession when features are
- split over multiple lines.
-
- In general, you should wait for a <<ServerReady>> event and then query the
- <<Features>> instead of relying on this event.
-
- ==== ServerCapabilitiesReceived
-
- TODO
-
- ==== ServerCapabilitiesAcknowledged
-
- TODO
-
- ==== ServerCapabilitiesFinished
-
- TODO
-
- ==== AuthenticationMessage
-
- TODO
-
- ==== SaslFinished
-
- TODO
-
- ==== SaslMechanismNotAvailableError
-
- TODO
-
- ==== BatchStarted
-
- TODO
-
- ==== BatchFinished
-
- TODO
-
- ==== BatchReceived
-
- TODO
-
- ==== NicknameChangeFailed
- * Type: IrcEvent
- * Properties:
- ** `cause`: `NicknameChangeError` - the reason the nickname must be changed
-
- Raised when the server informs us that our desired nickname is not available
- for some reason. The `cause` parameter will contain a specific reason given
- by the server:
-
- * `ErroneousNickname` - the nickname is not allowed by the server (e.g. it used
- restricted characters)
- * `AlreadyInUse` - the nickname is already in use
- * `Collision` - the nickname has collided with another somehow
- * `NoNicknameGiven` - no nickname was provided
-
- ==== NicknameChangeRequired
- * Type: IrcEvent, NicknameChangeFailed
- * Properties:
- ** `cause`: `NicknameChangeError` - the reason the nickname must be changed
-
- Raised during a connection attempt when there is a problem with the nickname
- that KtIrc was told to use. The exact problem will be detailed in the `cause`
- parameter, and has the same options as the <<NicknameChangeFailed>> event.
-
- Upon receiving this event, a new nickname MUST be chosen and sent to the
- server with the <<sendNickChange>> method. Failure to do so will result
- in the IRC server terminating the connection.
-
- WARNING: `NicknameChangeRequired` currently extends `NicknameChangeFailed`
- for backwards compatibility. This will be removed in KtIrc 2.0.0, and
- both events will need to be handled separately.
-
- == Messages
-
- TODO
-
- === sendNickChange
-
- TODO
-
- == Utility methods
-
- TODO
-
- === IsLocalClient
-
- TODO
-
- === React
-
- TODO
-
- === Reply
-
- TODO
-
- == IRCv3 support
-
- The following table shows KtIrc's IRCv3 support as of this release:
-
- [cols=3,options="header,autowidth"]
- |===
- | Feature
- | Status
- | Notes
-
- 3+h| Capability negotiation
-
- | https://ircv3.net/specs/core/capability-negotiation.html[CAP]
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See <<Supported capabilities>> for the caps KtIrc will negotiate
-
- | https://ircv3.net/specs/core/capability-negotiation.html#cap-ls-version[CAP 302]
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See <<Supported capabilities>> for the caps KtIrc will negotiate
-
- | https://ircv3.net/specs/core/capability-negotiation.html#cap-notify[cap-notify]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- 3+h| Published specifications
-
- | https://ircv3.net/specs/extensions/account-notify-3.1.html[account-notify] v3.1
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See <<UserAccountChanged>>
-
- | https://ircv3.net/specs/extensions/account-tag-3.2.html[account-tag] v3.2
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- Accounts are automatically added to `User` properties in events
-
- | https://ircv3.net/specs/extensions/away-notify-3.1.html[away-notify] v3.1
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See <<UserAway>>.
-
- | https://ircv3.net/specs/extensions/batch-3.2.html[batch] v3.2
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See <<BatchReceived>>
-
- | https://ircv3.net/specs/extensions/chghost-3.2.html[chghost] v3.2
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See <<UserHostChanged>>
-
- | https://ircv3.net/specs/extensions/echo-message-3.2.html[echo-message] v3.2
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See also the `alwaysEchoMessages` <<Behaviour>>
-
- | https://ircv3.net/specs/extensions/extended-join-3.1.html[extended-join] v3.1
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- Additional details are automatically added to `User` properties in events
-
- | https://ircv3.net/specs/extensions/invite-notify-3.2.html[invite-notify] v3.2
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://ircv3.net/specs/extensions/message-tags.html[message-tags]
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- Exposed in the metadata property of <<Events>>
-
- | https://ircv3.net/specs/core/monitor-3.2.html[monitor]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://ircv3.net/specs/extensions/multi-prefix-3.1.html[multi-prefix] v3.1
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- Automatically included in <<ChannelState>>
-
- | https://ircv3.net/specs/extensions/sasl-3.1.html[SASL] v3.1
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- See <<SASL configuration>>
-
- | https://ircv3.net/specs/extensions/sasl-3.2.html[SASL] v3.2
- | {set:cellbgcolor:#eeeeaa} Partial support
- | {set:cellbgcolor!}
- Notifications via `cap-notify` not yet supported. See <<SASL configuration>>
-
- | https://ircv3.net/specs/extensions/server-time-3.2.html[server-time] v3.2
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- Exposed in the metadata property of <<Events>>
-
- | https://ircv3.net/specs/extensions/sts.html[sts]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://ircv3.net/specs/extensions/userhost-in-names-3.2.html[userhost-in-names] v3.2
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- Automatically included in <<UserState>>
-
- | https://ircv3.net/specs/extensions/webirc.html[webirc]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- 3+h| Draft specifications
-
- | https://github.com/ircv3/ircv3-specifications/pull/363[brb]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/308[channel renaming]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/349[chathistory]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/346[delivered]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/304[editmsg]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://ircv3.net/specs/extensions/labeled-response.html[labeled-response]
- | {set:cellbgcolor:#a7eeaa} Supported
- | {set:cellbgcolor!}
- Exposed in the metadata property of <<Events>>
-
- | https://ircv3.net/specs/extensions/message-ids.html[message-ids]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/330[migrate]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://ircv3.net/specs/client-tags/react.html[react]
- | {set:cellbgcolor:#eeeeaa} Partial support
- | {set:cellbgcolor!}
- Sending via <<React>> method, no events generated
-
- | https://github.com/ircv3/ircv3-specifications/pull/347[read]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/276[register]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://ircv3.net/specs/client-tags/reply.html[reply]
- | {set:cellbgcolor:#eeeeaa} Partial support
- | {set:cellbgcolor!}
- Sending via <<Reply>> method, not processed on incoming messages
-
- | https://github.com/ircv3/ircv3-specifications/pull/306[resume]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/361[setname]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/357[standard replies]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- | https://github.com/ircv3/ircv3-specifications/pull/348[typing]
- | {set:cellbgcolor:#f7d5d3} No support
- | {set:cellbgcolor!}
-
- 3+h|Vendor specifications
-
- |===
|