|
@@ -0,0 +1,500 @@
|
|
1
|
+= KtIrc {version}
|
|
2
|
+Chris Smith
|
|
3
|
+:version: 0.10.3
|
|
4
|
+:toc: left
|
|
5
|
+:toc-position: left
|
|
6
|
+:toclevels: 5
|
|
7
|
+
|
|
8
|
+== About KtIrc
|
|
9
|
+
|
|
10
|
+KtIrc is a Kotlin JVM library for connecting to and interacting with IRC servers.
|
|
11
|
+It is still in an early stage of development. Its main features:
|
|
12
|
+
|
|
13
|
+.Built for Kotlin
|
|
14
|
+KtIrc is written in and designed for use in Kotlin; it uses extension methods,
|
|
15
|
+DSLs, sealed classes, and so on, to make it much easier to use than an
|
|
16
|
+equivalent Java library.
|
|
17
|
+
|
|
18
|
+.Coroutine-powered
|
|
19
|
+KtIrc uses co-routines for all of its input/output which lets it deal with
|
|
20
|
+IRC messages in the background while your app does other things, without
|
|
21
|
+the overhead of creating a new thread per IRC client.
|
|
22
|
+
|
|
23
|
+.Modern IRC standards
|
|
24
|
+KtIrc supports many IRCv3 features such as SASL authentication, message IDs,
|
|
25
|
+server timestamps, replies, reactions, account tags, and more. These features
|
|
26
|
+(where server support is available) make it easier to develop bots and
|
|
27
|
+clients, and enhance IRC with new user-facing functionality.
|
|
28
|
+
|
|
29
|
+== Getting started
|
|
30
|
+
|
|
31
|
+=== Installing
|
|
32
|
+
|
|
33
|
+All you need to do to start using KtIrc is add a single dependency.
|
|
34
|
+KtIrc is published to JCenter, making it quick and easy to pull in
|
|
35
|
+to almost any project. The examples below show how to add the JCenter
|
|
36
|
+repository and then the KtIrc dependency; you may already be using
|
|
37
|
+JCenter for other dependencies -- in that case just skip the
|
|
38
|
+repository configuration!
|
|
39
|
+
|
|
40
|
+[TIP]
|
|
41
|
+====
|
|
42
|
+KtIrc adheres to semantic versioning: you can expect to upgrade between
|
|
43
|
+minor versions without problems (e.g. from `0.1.2` to `0.13.7`); major
|
|
44
|
+version changes may include breaking changes such as the removal of
|
|
45
|
+deprecated methods. You should check the changelog before updating to
|
|
46
|
+a new major version.
|
|
47
|
+====
|
|
48
|
+
|
|
49
|
+.Gradle (using Kotlin DSL)
|
|
50
|
+[source,kotlin,subs="attributes"]
|
|
51
|
+----
|
|
52
|
+repositories {
|
|
53
|
+ jcenter()
|
|
54
|
+}
|
|
55
|
+
|
|
56
|
+dependencies {
|
|
57
|
+ implementation("com.dmdirc:ktirc:{version}")
|
|
58
|
+}
|
|
59
|
+----
|
|
60
|
+
|
|
61
|
+.Gradle (using Groovy DSL)
|
|
62
|
+[source,groovy,subs="attributes"]
|
|
63
|
+----
|
|
64
|
+buildscript {
|
|
65
|
+ repositories {
|
|
66
|
+ jcenter()
|
|
67
|
+ }
|
|
68
|
+}
|
|
69
|
+
|
|
70
|
+implementation 'com.dmdirc:ktirc:{version}'
|
|
71
|
+----
|
|
72
|
+
|
|
73
|
+.Maven
|
|
74
|
+[source,xml,subs="attributes"]
|
|
75
|
+----
|
|
76
|
+<repositories>
|
|
77
|
+ <repository>
|
|
78
|
+ <id>jcenter</id>
|
|
79
|
+ <url>https://jcenter.bintray.com</url>
|
|
80
|
+ </repository>
|
|
81
|
+</repositories>
|
|
82
|
+
|
|
83
|
+<dependencies>
|
|
84
|
+ <dependency>
|
|
85
|
+ <groupId>com.dmdirc</groupId>
|
|
86
|
+ <artifactId>ktirc</artifactId>
|
|
87
|
+ <version>{version}</version>
|
|
88
|
+ </dependency>
|
|
89
|
+</dependencies>
|
|
90
|
+----
|
|
91
|
+
|
|
92
|
+=== Creating your first client
|
|
93
|
+
|
|
94
|
+KtIrc provides a DSL ("domain specific language") for configuring a
|
|
95
|
+client that allows you to set the connection details, the user's
|
|
96
|
+details, and configure the behaviour of KtIrc itself. The DSL is
|
|
97
|
+accessed through the `IrcClient` function. For full details of all
|
|
98
|
+supported options, see the <<IrcClient DSL>> reference.
|
|
99
|
+
|
|
100
|
+A basic client will look like this:
|
|
101
|
+
|
|
102
|
+[source,kotlin]
|
|
103
|
+----
|
|
104
|
+val client = IrcClient {
|
|
105
|
+ server {
|
|
106
|
+ host = "my.server.com"
|
|
107
|
+ }
|
|
108
|
+ profile {
|
|
109
|
+ nickname = "nick"
|
|
110
|
+ username = "username"
|
|
111
|
+ realName = "Hi there"
|
|
112
|
+ }
|
|
113
|
+}
|
|
114
|
+----
|
|
115
|
+
|
|
116
|
+=== Connecting and handling events
|
|
117
|
+
|
|
118
|
+Getting KtIrc to start connecting is as simple as calling the `connect()`
|
|
119
|
+method, but before that we probably want to add an event listener to deal
|
|
120
|
+with incoming messages:
|
|
121
|
+
|
|
122
|
+[source,kotlin]
|
|
123
|
+----
|
|
124
|
+client.onEvent { event -> <1>
|
|
125
|
+ when (event) { <2>
|
|
126
|
+ is ServerReady ->
|
|
127
|
+ client.sendJoin("#ktirc") <3>
|
|
128
|
+ is ServerDisconnected ->
|
|
129
|
+ client.connect()
|
|
130
|
+ is MessageReceived ->
|
|
131
|
+ if (event.message == "!test") <4>
|
|
132
|
+ client.reply(event, "Test successful!") <5>
|
|
133
|
+ }
|
|
134
|
+}
|
|
135
|
+
|
|
136
|
+client.connect() <6>
|
|
137
|
+----
|
|
138
|
+<1> An event listener is registered using the `onEvent` method. It receives
|
|
139
|
+ a single IrcEvent.
|
|
140
|
+<2> A Kotlin `when` statement provides a convenient way to switch on the
|
|
141
|
+ type of event received.
|
|
142
|
+<3> Most common IRC commands have `send` methods defined to quickly and
|
|
143
|
+ safely send the message with the right formatting.
|
|
144
|
+<4> Kotlin smart-casts the event, so you can access the properties specific
|
|
145
|
+ to the matched event class, such as `message`.
|
|
146
|
+<5> The IrcClient class provides useful methods to react and respond to
|
|
147
|
+ events.
|
|
148
|
+<6> The connect() method starts connecting and returns immediately. You'll
|
|
149
|
+ receive events updating you on the progress.
|
|
150
|
+
|
|
151
|
+In this example, we're waiting for three events: `ServerReady`, which occurs
|
|
152
|
+after we have connected and the server has sent us all of the pre-amble
|
|
153
|
+such as its configuration and capabilities; `ServerDisconnected` which
|
|
154
|
+is raised whenever KtIrc gets disconnected from (or fails to connect to) the
|
|
155
|
+IRC server; and `MessageReceived` which occurs, unsuprisingly, whenever a
|
|
156
|
+message is received. KtIrc has many events: for more information, see the
|
|
157
|
+<<Events>> reference.
|
|
158
|
+
|
|
159
|
+[CAUTION]
|
|
160
|
+====
|
|
161
|
+With this code, KtIrc will immediately try to reconnect as soon as it is
|
|
162
|
+disconnected. If the server closes the connection early (due to, for
|
|
163
|
+example, a bad password or the user being banned) this will result in a
|
|
164
|
+huge number of connection attempts in a short time. In real code you should
|
|
165
|
+always delay reconnections -- preferably with a backoff -- to avoid
|
|
166
|
+excessive connection attempts.
|
|
167
|
+====
|
|
168
|
+
|
|
169
|
+You can see that KtIrc provides a number of useful methods for sending
|
|
170
|
+requests to the server, and reacting and responding to events. IRC
|
|
171
|
+commands that KtIrc supports can be invoked using the `send*` methods,
|
|
172
|
+which are documented in the <<Messages>> reference. Other useful methods
|
|
173
|
+such as `reply` can be found in the <<Utility methods>> reference.
|
|
174
|
+
|
|
175
|
+== Reference
|
|
176
|
+
|
|
177
|
+=== IrcClient DSL
|
|
178
|
+
|
|
179
|
+The DSL for creating a new `IrcClient` allows you to set a number of
|
|
180
|
+options relating to how KtIrc connects, what user details it provides,
|
|
181
|
+and how it behaves. The full range of options available in the DSL is
|
|
182
|
+shown below:
|
|
183
|
+
|
|
184
|
+[source,kotlin]
|
|
185
|
+----
|
|
186
|
+server {
|
|
187
|
+ host = "irc.example.com"
|
|
188
|
+ port = 6667
|
|
189
|
+ useTls = true
|
|
190
|
+ password = "H4ckTh3Pl4n3t"
|
|
191
|
+}
|
|
192
|
+
|
|
193
|
+profile {
|
|
194
|
+ nickname = "MyBot"
|
|
195
|
+ username = "bot"
|
|
196
|
+ realName = "Botomatic v1.2"
|
|
197
|
+}
|
|
198
|
+
|
|
199
|
+behaviour {
|
|
200
|
+ requestModesOnJoin = true
|
|
201
|
+ alwaysEchoMessages = true
|
|
202
|
+}
|
|
203
|
+
|
|
204
|
+sasl {
|
|
205
|
+ mechanisms += "PLAIN"
|
|
206
|
+ username = "botaccount"
|
|
207
|
+ password = "s3cur3"
|
|
208
|
+}
|
|
209
|
+----
|
|
210
|
+
|
|
211
|
+==== Server settings
|
|
212
|
+
|
|
213
|
+The server block allows you to specify the details of the IRC server you
|
|
214
|
+wish to connect to:
|
|
215
|
+
|
|
216
|
+ * `host` - the hostname or IP address of the server *(required)*
|
|
217
|
+ * `port` - the port to connect on _(default: 6667)_
|
|
218
|
+ * `useTls` - whether to use a secure connection or not _(default: false)_
|
|
219
|
+ * `password` - the password to provide to the server _(default: null)_
|
|
220
|
+
|
|
221
|
+An alternative more compact syntax is available for configuring server details:
|
|
222
|
+
|
|
223
|
+[source,kotlin]
|
|
224
|
+----
|
|
225
|
+server("irc.example.com", 6667, true, "H4ckTh3Pl4n3t")
|
|
226
|
+----
|
|
227
|
+
|
|
228
|
+You can, if you wish, combine the two or use named parameters:
|
|
229
|
+
|
|
230
|
+[source,kotlin]
|
|
231
|
+----
|
|
232
|
+server(useTls = true, port = 6697) {
|
|
233
|
+ host = "irc.example.com"
|
|
234
|
+ password = "H4ckTh3Pl4n3t"
|
|
235
|
+}
|
|
236
|
+----
|
|
237
|
+
|
|
238
|
+==== User profile
|
|
239
|
+
|
|
240
|
+The user profile controls how KtIrc will present itself to the IRC server, and
|
|
241
|
+how other users on that server will see the KtIrc user:
|
|
242
|
+
|
|
243
|
+ * `nickname` - the initial nickname you wish to use *(required)*
|
|
244
|
+ * `username` - the "username" to provide to the server _(default: KtIrc)_
|
|
245
|
+ * `realName` - the "real name" that will be seen by other clients
|
|
246
|
+ _(default: KtIrc User)_
|
|
247
|
+
|
|
248
|
+[TIP]
|
|
249
|
+====
|
|
250
|
+The "username" is sometimes called the "ident" or "gecos". Some IRC servers
|
|
251
|
+will check for an ident reply from your host and use that in place of the
|
|
252
|
+username provided if it gets a response. The username (or ident reply)
|
|
253
|
+becomes part of your client's hostmask, and is visible to other users. It
|
|
254
|
+is unrelated to nickserv or other account usernames.
|
|
255
|
+====
|
|
256
|
+
|
|
257
|
+As with the <<Server settings>> you can use a more compact syntax:
|
|
258
|
+
|
|
259
|
+[source,kotlin]
|
|
260
|
+----
|
|
261
|
+profile("nickname", "username", "real name")
|
|
262
|
+----
|
|
263
|
+
|
|
264
|
+==== Behaviour
|
|
265
|
+
|
|
266
|
+The behaviour block allows you to tweak how KtIrc itself operates. These
|
|
267
|
+options allow you perform common operations automatically, or enjoy more
|
|
268
|
+advanced IRC features even if the server doesn't support them:
|
|
269
|
+
|
|
270
|
+ * `requestModesOnJoin` - if enabled, automatically requests channel modes
|
|
271
|
+ when the client joins a new channel _(default: false)_
|
|
272
|
+ * `alwaysEchoMessages` - if enabled, every message you send will result
|
|
273
|
+ in a `MessageReceived` event being returned. Servers that support the
|
|
274
|
+ IRCv3 `echo-message` capability will do this automatically; enabling the
|
|
275
|
+ behaviour will make all servers act the same way _(default: false)_
|
|
276
|
+
|
|
277
|
+The behaviour block is optional in its entirety.
|
|
278
|
+
|
|
279
|
+==== SASL configuration
|
|
280
|
+
|
|
281
|
+SASL ("Simple Authentication and Security Layer") is a standard mechanism
|
|
282
|
+for securely authenticating to a service that has recently been adopted
|
|
283
|
+for use in IRC. SASL supports a number of 'mechanisms' that describe how
|
|
284
|
+the data will be exchanged between the client and server. KtIrc supports
|
|
285
|
+the following mechanisms:
|
|
286
|
+
|
|
287
|
+ * `EXTERNAL` - the server uses some external means to authenticate the
|
|
288
|
+ client, instead of a username and password. On most servers this
|
|
289
|
+ means checking the client certificate against one registered with
|
|
290
|
+ the user's account. _(disabled by default)_
|
|
291
|
+ * `PLAIN` - the client sends the username and password in plain text
|
|
292
|
+ during the connection phase. This offers slightly more security
|
|
293
|
+ than calling `nickserv identify` (for example) after connecting.
|
|
294
|
+ * `SCRAM-SHA-1` - this mechanism involves a "salted challenge" being
|
|
295
|
+ completed which results in both the server and the client proving that
|
|
296
|
+ they know the user's password, but without it every being transmitted.
|
|
297
|
+ This is based on the `SHA-1` algorithm which has known issues, but is
|
|
298
|
+ more than sufficient when used in this manner.
|
|
299
|
+ * `SCRAM-SHA-256` - the same as `SCRAM-SHA-1` but using the `SHA-256`
|
|
300
|
+ algorithm instead, which is more modern and secure.
|
|
301
|
+
|
|
302
|
+To use `PLAIN`, `SCRAM-SHA-1` or `SCRAM-SHA-256`, you must supply a username
|
|
303
|
+and password in the configuration:
|
|
304
|
+
|
|
305
|
+[source,kotlin]
|
|
306
|
+----
|
|
307
|
+sasl {
|
|
308
|
+ username = "botaccount"
|
|
309
|
+ password = "s3cur3"
|
|
310
|
+}
|
|
311
|
+----
|
|
312
|
+
|
|
313
|
+KtIrc enables `SCRAM-SHA-256`, `SCRAM-SHA-1` and `PLAIN` by default, and will
|
|
314
|
+use them in that order of preference if the server supports more than one.
|
|
315
|
+You can modify the `mechanisms` parameter if you wish to disable one:
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+[source,kotlin]
|
|
319
|
+----
|
|
320
|
+sasl {
|
|
321
|
+ mechanisms -= "PLAIN"
|
|
322
|
+ username = "botaccount"
|
|
323
|
+ password = "s3cur3"
|
|
324
|
+}
|
|
325
|
+----
|
|
326
|
+
|
|
327
|
+You can also clear all the default mechanisms and provide your own list:
|
|
328
|
+
|
|
329
|
+[source,kotlin]
|
|
330
|
+----
|
|
331
|
+sasl {
|
|
332
|
+ mechanisms("SCRAM-SHA-256", "PLAIN")
|
|
333
|
+ username = "botaccount"
|
|
334
|
+ password = "s3cur3"
|
|
335
|
+}
|
|
336
|
+----
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+If you wish to enable the `EXTERNAL` mechanism, you do not need to provide
|
|
340
|
+a username or password:
|
|
341
|
+
|
|
342
|
+[source,kotlin]
|
|
343
|
+----
|
|
344
|
+sasl {
|
|
345
|
+ mechanisms("EXTERNAL")
|
|
346
|
+}
|
|
347
|
+----
|
|
348
|
+
|
|
349
|
+Alternatively, if you wish to enable `EXTERNAL` but fall back to other
|
|
350
|
+mechanisms if it doesn't work:
|
|
351
|
+
|
|
352
|
+[source,kotlin]
|
|
353
|
+----
|
|
354
|
+sasl {
|
|
355
|
+ mechanisms += "EXTERNAL"
|
|
356
|
+ username = "botaccount"
|
|
357
|
+ password = "s3cur3"
|
|
358
|
+}
|
|
359
|
+----
|
|
360
|
+
|
|
361
|
+The SASL block is optional in its entirety.
|
|
362
|
+
|
|
363
|
+=== State
|
|
364
|
+
|
|
365
|
+KtIrc attempts to track all reasonable state of the IRC network. This includes
|
|
366
|
+details about the server, channels the client is joined to, and users that are
|
|
367
|
+also in those channels. The state is exposed in a several fields accessible
|
|
368
|
+from the `IrcClient`:
|
|
369
|
+
|
|
370
|
+==== ServerState
|
|
371
|
+
|
|
372
|
+The server state provides information about the server, and our connection to
|
|
373
|
+it.
|
|
374
|
+
|
|
375
|
+[IMPORTANT]
|
|
376
|
+====
|
|
377
|
+The server state will be updated frequently while KtIrc is connecting to a
|
|
378
|
+server. The values within it should not be relied upon until a `ServerReady`
|
|
379
|
+event is received, as they may be incomplete or estimates before then.
|
|
380
|
+====
|
|
381
|
+
|
|
382
|
+.serverState.status (ServerStatus)
|
|
383
|
+Provides an enum containing the current server state. One of:
|
|
384
|
+
|
|
385
|
+* `Disconnected` - the server is not connected
|
|
386
|
+* `Connecting` - we are attempting to establish a connection
|
|
387
|
+* `Negotiating` - we are logging in, negotiating capabilities, etc
|
|
388
|
+* `Ready` - we are connected and commands may be sent
|
|
389
|
+
|
|
390
|
+.serverState.localNickname (String)
|
|
391
|
+The current nickname we are using on the IRC server. While connecting this
|
|
392
|
+will default to the nickname from the <<User profile>>, but it may be updated
|
|
393
|
+if e.g. the nick is in use or not allowed.
|
|
394
|
+
|
|
395
|
+.serverState.serverName (String)
|
|
396
|
+The name the server uses for itself. While connecting this defaults to the
|
|
397
|
+hostname given in the <<Server settings>>, but it will be updated to the
|
|
398
|
+value provided by the server. For example, you may connect to
|
|
399
|
+`irc.example.com` and during the negotiation phase KtIrc will see that it
|
|
400
|
+is actually talking to `server3.uk.irc.example.com` and update the
|
|
401
|
+serverName to reflect that.
|
|
402
|
+
|
|
403
|
+[TIP]
|
|
404
|
+====
|
|
405
|
+For a user-friendly identifier most servers provide a `NETWORK` token in
|
|
406
|
+the ISUPPORT reply, which is available via the <<Features>> property.
|
|
407
|
+====
|
|
408
|
+
|
|
409
|
+.serverState.channelModePrefix (ModePrefixMapping)
|
|
410
|
+Provides a mapping from channel user modes (such as "o" for op, "v" for
|
|
411
|
+voice) to the prefixes used before nicknames (such as "@" and "+").
|
|
412
|
+
|
|
413
|
+To map prefixes to modes, you can use the `getMode()` or `getModes()`
|
|
414
|
+functions:
|
|
415
|
+
|
|
416
|
+[source,kotlin]
|
|
417
|
+----
|
|
418
|
+'o' == getMode('@')
|
|
419
|
+"ov" == getModes("@+")
|
|
420
|
+----
|
|
421
|
+
|
|
422
|
+.serverState.channelTypes (String)
|
|
423
|
+Contains the types of channels that are allowed by the server, such as
|
|
424
|
+`\#&` for normal channels ("#") and local channels ("&").
|
|
425
|
+
|
|
426
|
+===== Capabilities
|
|
427
|
+
|
|
428
|
+The IRCv3 specifications introduce the concept of 'capability negotiation'.
|
|
429
|
+This allows the client and server to negotiate and enable new capabilities
|
|
430
|
+that are mutually supported.
|
|
431
|
+
|
|
432
|
+The capabilities state contains the following properties:
|
|
433
|
+
|
|
434
|
+.serverState.capabilities.negotiationState (CapabilitiesNegotiationState)
|
|
435
|
+The current state of negotiating with the server. One of:
|
|
436
|
+
|
|
437
|
+* `AWAITING_LIST` - we have requested a list of capabitilies and are awaiting
|
|
438
|
+ a reply
|
|
439
|
+* `AWAITING_ACK` - we have sent the capabilities we want to enable, and are
|
|
440
|
+ waitin for the server to acknowledge them
|
|
441
|
+* `AUTHENTICATING` - we are attempting to authenticate with SASL
|
|
442
|
+* `FINISHED` - we have completed negotiation
|
|
443
|
+
|
|
444
|
+Where a server does not support IRCv3 capability negotiation, the state will
|
|
445
|
+remain at `AWAITING_LIST`.
|
|
446
|
+
|
|
447
|
+.serverState.capabilities.advertisedCapabilities (Map<String, String>)
|
|
448
|
+Contains a map of capability names to values that the server offered. This
|
|
449
|
+should only be required for advance use cases, such as looking up the
|
|
450
|
+languages offered by a server when providing the user with a choice of
|
|
451
|
+translations.
|
|
452
|
+
|
|
453
|
+.serverState.capabilities.enabledCapabilities (Map<Capability, String>)
|
|
454
|
+Contains a map of capabilities that KtIrc has successfully negotiated with
|
|
455
|
+the server.
|
|
456
|
+
|
|
457
|
+====== Supported capabilities
|
|
458
|
+
|
|
459
|
+* `sasl` - used to perform SASL authentication during connection
|
|
460
|
+* `message-tags` - allows arbitrary tags on messages
|
|
461
|
+* `server-time` - the server adds a timestamp tag to each incoming message
|
|
462
|
+* `account-tag` - the server adds an account tag to incoming user messages
|
|
463
|
+* `userhost-in-names` - the NAMES reply includes users hosts not just nicknames
|
|
464
|
+* `multi-prefix` - all modes are included in nick prefixes (e.g. `@+nick`)
|
|
465
|
+* `extended-join` - more information is sent when a user joins a channel
|
|
466
|
+* `batch` - allows multi-line responses to be batched together
|
|
467
|
+* `echo-message` - echos the client's own messages back to it
|
|
468
|
+* `draft/labeled-responses` - responses are labeled so the client knows which
|
|
469
|
+ incoming message corresponds to which command it sent
|
|
470
|
+* `account-notify` - the server sends a message when a user's account changes
|
|
471
|
+* `away-notify` - the server sends a message when a user's away state changes
|
|
472
|
+* `chghost` - the server sends a message when a user's host changes
|
|
473
|
+
|
|
474
|
+===== Features
|
|
475
|
+
|
|
476
|
+TODO
|
|
477
|
+
|
|
478
|
+==== UserState
|
|
479
|
+
|
|
480
|
+TODO
|
|
481
|
+
|
|
482
|
+==== ChannelState
|
|
483
|
+
|
|
484
|
+TODO
|
|
485
|
+
|
|
486
|
+=== Events
|
|
487
|
+
|
|
488
|
+TODO
|
|
489
|
+
|
|
490
|
+=== Messages
|
|
491
|
+
|
|
492
|
+TODO
|
|
493
|
+
|
|
494
|
+=== Utility methods
|
|
495
|
+
|
|
496
|
+TODO
|
|
497
|
+
|
|
498
|
+=== IRCv3 support
|
|
499
|
+
|
|
500
|
+TODO
|