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.

index.adoc 43KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306
  1. = KtIrc {version}
  2. Chris Smith
  3. :version: 1.0.1
  4. :toc: left
  5. :toc-position: left
  6. :toclevels: 5
  7. == About KtIrc
  8. KtIrc is a Kotlin JVM library for connecting to and interacting with IRC servers.
  9. It is still in an early stage of development. Its main features:
  10. .Built for Kotlin
  11. KtIrc is written in and designed for use in Kotlin; it uses extension methods,
  12. DSLs, sealed classes, and so on, to make it much easier to use than an
  13. equivalent Java library.
  14. .Coroutine-powered
  15. KtIrc uses co-routines for all of its input/output which lets it deal with
  16. IRC messages in the background while your app does other things, without
  17. the overhead of creating a new thread per IRC client.
  18. .Modern IRC standards
  19. KtIrc supports many IRCv3 features such as SASL authentication, message IDs,
  20. server timestamps, replies, reactions, account tags, and more. These features
  21. (where server support is available) make it easier to develop bots and
  22. clients, and enhance IRC with new user-facing functionality.
  23. == Getting started
  24. === Installing
  25. All you need to do to start using KtIrc is add a single dependency.
  26. KtIrc is published to JCenter, making it quick and easy to pull in
  27. to almost any project. The examples below show how to add the JCenter
  28. repository and then the KtIrc dependency; you may already be using
  29. JCenter for other dependencies -- in that case just skip the
  30. repository configuration!
  31. [TIP]
  32. ====
  33. KtIrc adheres to semantic versioning: you can expect to upgrade between
  34. minor versions without problems (e.g. from `0.1.2` to `0.13.7`); major
  35. version changes may include breaking changes such as the removal of
  36. deprecated methods. You should check the changelog before updating to
  37. a new major version.
  38. ====
  39. .Gradle (using Kotlin DSL)
  40. [source,kotlin,subs="attributes"]
  41. ----
  42. repositories {
  43. jcenter()
  44. }
  45. dependencies {
  46. implementation("com.dmdirc:ktirc:{version}")
  47. }
  48. ----
  49. .Gradle (using Groovy DSL)
  50. [source,groovy,subs="attributes"]
  51. ----
  52. buildscript {
  53. repositories {
  54. jcenter()
  55. }
  56. }
  57. implementation 'com.dmdirc:ktirc:{version}'
  58. ----
  59. .Maven
  60. [source,xml,subs="attributes"]
  61. ----
  62. <repositories>
  63. <repository>
  64. <id>jcenter</id>
  65. <url>https://jcenter.bintray.com</url>
  66. </repository>
  67. </repositories>
  68. <dependencies>
  69. <dependency>
  70. <groupId>com.dmdirc</groupId>
  71. <artifactId>ktirc</artifactId>
  72. <version>{version}</version>
  73. </dependency>
  74. </dependencies>
  75. ----
  76. === Creating your first client
  77. KtIrc provides a DSL ("domain specific language") for configuring a
  78. client that allows you to set the connection details, the user's
  79. details, and configure the behaviour of KtIrc itself. The DSL is
  80. accessed through the `IrcClient` function. For full details of all
  81. supported options, see the <<IrcClient DSL>> reference.
  82. A basic client will look like this:
  83. [source,kotlin]
  84. ----
  85. val client = IrcClient {
  86. server {
  87. host = "my.server.com"
  88. }
  89. profile {
  90. nickname = "nick"
  91. username = "username"
  92. realName = "Hi there"
  93. }
  94. }
  95. ----
  96. === Connecting and handling events
  97. Getting KtIrc to start connecting is as simple as calling the `connect()`
  98. method, but before that we probably want to add an event listener to deal
  99. with incoming messages:
  100. [source,kotlin]
  101. ----
  102. client.onEvent { event -> <1>
  103. when (event) { <2>
  104. is ServerReady ->
  105. client.sendJoin("#ktirc") <3>
  106. is ServerDisconnected ->
  107. client.connect()
  108. is MessageReceived ->
  109. if (event.message == "!test") <4>
  110. client.reply(event, "Test successful!") <5>
  111. }
  112. }
  113. client.connect() <6>
  114. ----
  115. <1> An event listener is registered using the `onEvent` method. It receives
  116. a single IrcEvent.
  117. <2> A Kotlin `when` statement provides a convenient way to switch on the
  118. type of event received.
  119. <3> Most common IRC commands have `send` methods defined to quickly and
  120. safely send the message with the right formatting.
  121. <4> Kotlin smart-casts the event, so you can access the properties specific
  122. to the matched event class, such as `message`.
  123. <5> The IrcClient class provides useful methods to react and respond to
  124. events.
  125. <6> The connect() method starts connecting and returns immediately. You'll
  126. receive events updating you on the progress.
  127. In this example, we're waiting for three events: `ServerReady`, which occurs
  128. after we have connected and the server has sent us all of the pre-amble
  129. such as its configuration and capabilities; `ServerDisconnected` which
  130. is raised whenever KtIrc gets disconnected from (or fails to connect to) the
  131. IRC server; and `MessageReceived` which occurs, unsuprisingly, whenever a
  132. message is received. KtIrc has many events: for more information, see the
  133. <<Events>> reference.
  134. [CAUTION]
  135. ====
  136. With this code, KtIrc will immediately try to reconnect as soon as it is
  137. disconnected. If the server closes the connection early (due to, for
  138. example, a bad password or the user being banned) this will result in a
  139. huge number of connection attempts in a short time. In real code you should
  140. always delay reconnections -- preferably with a backoff -- to avoid
  141. excessive connection attempts.
  142. ====
  143. You can see that KtIrc provides a number of useful methods for sending
  144. requests to the server, and reacting and responding to events. IRC
  145. commands that KtIrc supports can be invoked using the `send*` methods,
  146. which are documented in the <<Messages>> reference. Other useful methods
  147. such as `reply` can be found in the <<Utility methods>> reference.
  148. === Mandatory event handling
  149. In order to properly connect to IRC, stay connected, and handle
  150. incoming messages properly, the following events MUST be handled:
  151. .<<NicknameChangeRequired>>
  152. The nickname change required event occurs when connecting to a server
  153. if our initial nickname is taken. A new nickname must be supplied
  154. to continue connecting.
  155. .<<ServerDisconnected>>
  156. When KtIrc becomes disconnected from a server, or fails a connection
  157. attempt, it will raise this event. If you wish to stay connected
  158. to IRC you must call the `connect()` method to start a reconnection
  159. attempt after an appropriate delay.
  160. .<<BatchReceived>>
  161. On servers that support the IRCv3 batch capability, some incoming
  162. messages may be sent inside a batch. These could include join or
  163. quit messages during a netsplit, or other important messages you
  164. may need to process. At minimum, when receiving a BatchReceived
  165. event you should apply your normal processing to all the events
  166. contained within.
  167. == IrcClient DSL
  168. The DSL for creating a new `IrcClient` allows you to set a number of
  169. options relating to how KtIrc connects, what user details it provides,
  170. and how it behaves. The full range of options available in the DSL is
  171. shown below:
  172. [source,kotlin]
  173. ----
  174. server {
  175. host = "irc.example.com"
  176. port = 6667
  177. useTls = true
  178. password = "H4ckTh3Pl4n3t"
  179. }
  180. profile {
  181. nickname = "MyBot"
  182. username = "bot"
  183. realName = "Botomatic v1.2"
  184. }
  185. behaviour {
  186. requestModesOnJoin = true
  187. alwaysEchoMessages = true
  188. }
  189. sasl {
  190. mechanisms += "PLAIN"
  191. username = "botaccount"
  192. password = "s3cur3"
  193. }
  194. ----
  195. === Server settings
  196. The server block allows you to specify the details of the IRC server you
  197. wish to connect to:
  198. * `host` - the hostname or IP address of the server *(required)*
  199. * `port` - the port to connect on _(default: 6697)_
  200. * `useTls` - whether to use a secure connection or not _(default: true)_
  201. * `password` - the password to provide to the server _(default: null)_
  202. An alternative more compact syntax is available for configuring server details:
  203. [source,kotlin]
  204. ----
  205. server("irc.example.com", 6667, true, "H4ckTh3Pl4n3t")
  206. ----
  207. You can, if you wish, combine the two or use named parameters:
  208. [source,kotlin]
  209. ----
  210. server(useTls = true, port = 6697) {
  211. host = "irc.example.com"
  212. password = "H4ckTh3Pl4n3t"
  213. }
  214. ----
  215. === User profile
  216. The user profile controls how KtIrc will present itself to the IRC server, and
  217. how other users on that server will see the KtIrc user:
  218. * `nickname` - the initial nickname you wish to use *(required)*
  219. * `username` - the "username" to provide to the server _(default: KtIrc)_
  220. * `realName` - the "real name" that will be seen by other clients
  221. _(default: KtIrc User)_
  222. [TIP]
  223. ====
  224. The "username" is sometimes called the "ident" or "gecos". Some IRC servers
  225. will check for an ident reply from your host and use that in place of the
  226. username provided if it gets a response. The username (or ident reply)
  227. becomes part of your client's hostmask, and is visible to other users. It
  228. is unrelated to nickserv or other account usernames.
  229. ====
  230. As with the <<Server settings>> you can use a more compact syntax:
  231. [source,kotlin]
  232. ----
  233. profile("nickname", "username", "real name")
  234. ----
  235. === Behaviour
  236. The behaviour block allows you to tweak how KtIrc itself operates. These
  237. options allow you perform common operations automatically, or enjoy more
  238. advanced IRC features even if the server doesn't support them:
  239. * `requestModesOnJoin` - if enabled, automatically requests channel modes
  240. when the client joins a new channel _(default: false)_
  241. * `alwaysEchoMessages` - if enabled, every message you send will result
  242. in a `MessageReceived` event being returned. Servers that support the
  243. IRCv3 `echo-message` capability will do this automatically; enabling the
  244. behaviour will make all servers act the same way _(default: false)_
  245. * `preferIPv6` - if enabled, KtIrc will prefer to connect over IPv6 if the
  246. server publishes AAAA DNS records. If disabled, KtIrc will prefer IPv4.
  247. If the server is available exclusively on IPv4 or IPv6 then this option
  248. has no effect. _(default: true)_
  249. The behaviour block is optional in its entirety.
  250. === SASL configuration
  251. SASL ("Simple Authentication and Security Layer") is a standard mechanism
  252. for securely authenticating to a service that has recently been adopted
  253. for use in IRC. SASL supports a number of 'mechanisms' that describe how
  254. the data will be exchanged between the client and server. KtIrc supports
  255. the following mechanisms:
  256. * `EXTERNAL` - the server uses some external means to authenticate the
  257. client, instead of a username and password. On most servers this
  258. means checking the client certificate against one registered with
  259. the user's account. _(disabled by default)_
  260. * `PLAIN` - the client sends the username and password in plain text
  261. during the connection phase. This offers slightly more security
  262. than calling `nickserv identify` (for example) after connecting.
  263. * `SCRAM-SHA-1` - this mechanism involves a "salted challenge" being
  264. completed which results in both the server and the client proving that
  265. they know the user's password, but without it every being transmitted.
  266. This is based on the `SHA-1` algorithm which has known issues, but is
  267. more than sufficient when used in this manner.
  268. * `SCRAM-SHA-256` - the same as `SCRAM-SHA-1` but using the `SHA-256`
  269. algorithm instead, which is more modern and secure.
  270. To use `PLAIN`, `SCRAM-SHA-1` or `SCRAM-SHA-256`, you must supply a username
  271. and password in the configuration:
  272. [source,kotlin]
  273. ----
  274. sasl {
  275. username = "botaccount"
  276. password = "s3cur3"
  277. }
  278. ----
  279. KtIrc enables `SCRAM-SHA-256`, `SCRAM-SHA-1` and `PLAIN` by default, and will
  280. use them in that order of preference if the server supports more than one.
  281. You can modify the `mechanisms` parameter if you wish to disable one:
  282. [source,kotlin]
  283. ----
  284. sasl {
  285. mechanisms -= "PLAIN"
  286. username = "botaccount"
  287. password = "s3cur3"
  288. }
  289. ----
  290. You can also clear all the default mechanisms and provide your own list:
  291. [source,kotlin]
  292. ----
  293. sasl {
  294. mechanisms("SCRAM-SHA-256", "PLAIN")
  295. username = "botaccount"
  296. password = "s3cur3"
  297. }
  298. ----
  299. If you wish to enable the `EXTERNAL` mechanism, you do not need to provide
  300. a username or password:
  301. [source,kotlin]
  302. ----
  303. sasl {
  304. mechanisms("EXTERNAL")
  305. }
  306. ----
  307. Alternatively, if you wish to enable `EXTERNAL` but fall back to other
  308. mechanisms if it doesn't work:
  309. [source,kotlin]
  310. ----
  311. sasl {
  312. mechanisms += "EXTERNAL"
  313. username = "botaccount"
  314. password = "s3cur3"
  315. }
  316. ----
  317. The SASL block is optional in its entirety.
  318. == State
  319. KtIrc attempts to track all reasonable state of the IRC network. This includes
  320. details about the server, channels the client is joined to, and users that are
  321. also in those channels. The state is exposed in a several fields accessible
  322. from the `IrcClient`:
  323. === ServerState
  324. The server state provides information about the server, and our connection to
  325. it.
  326. [IMPORTANT]
  327. ====
  328. The server state will be updated frequently while KtIrc is connecting to a
  329. server. The values within it should not be relied upon until a `ServerReady`
  330. event is received, as they may be incomplete or estimates before then.
  331. ====
  332. .serverState.status (ServerStatus)
  333. Provides an enum containing the current server state. One of:
  334. * `Disconnected` - the server is not connected
  335. * `Connecting` - we are attempting to establish a connection
  336. * `Negotiating` - we are logging in, negotiating capabilities, etc
  337. * `Ready` - we are connected and commands may be sent
  338. .serverState.localNickname (String)
  339. The current nickname we are using on the IRC server. While connecting this
  340. will default to the nickname from the <<User profile>>, but it may be updated
  341. if e.g. the nick is in use or not allowed.
  342. .serverState.serverName (String)
  343. The name the server uses for itself. While connecting this defaults to the
  344. hostname given in the <<Server settings>>, but it will be updated to the
  345. value provided by the server. For example, you may connect to
  346. `irc.example.com` and during the negotiation phase KtIrc will see that it
  347. is actually talking to `server3.uk.irc.example.com` and update the
  348. serverName to reflect that.
  349. [TIP]
  350. ====
  351. For a user-friendly identifier most servers provide a `NETWORK` token in
  352. the ISUPPORT reply, which is available via the <<Features>> property.
  353. ====
  354. .serverState.channelModePrefix (ModePrefixMapping)
  355. Provides a mapping from channel user modes (such as "o" for op, "v" for
  356. voice) to the prefixes used before nicknames (such as "@" and "+").
  357. To map prefixes to modes, you can use the `getMode()` or `getModes()`
  358. functions:
  359. [source,kotlin]
  360. ----
  361. getMode('@') == 'o'
  362. getModes("@+") == "ov"
  363. ----
  364. .serverState.channelTypes (String)
  365. Contains the types of channels that are allowed by the server, such as
  366. `\#&amp;` for normal channels ("#") and local channels ("&").
  367. ==== Capabilities
  368. The IRCv3 specifications introduce the concept of 'capability negotiation'.
  369. This allows the client and server to negotiate and enable new capabilities
  370. that are mutually supported.
  371. The capabilities state contains the following properties:
  372. .serverState.capabilities.negotiationState (CapabilitiesNegotiationState)
  373. The current state of negotiating with the server. One of:
  374. * `AWAITING_LIST` - we have requested a list of capabitilies and are awaiting
  375. a reply
  376. * `AWAITING_ACK` - we have sent the capabilities we want to enable, and are
  377. waitin for the server to acknowledge them
  378. * `AUTHENTICATING` - we are attempting to authenticate with SASL
  379. * `FINISHED` - we have completed negotiation
  380. Where a server does not support IRCv3 capability negotiation, the state will
  381. remain at `AWAITING_LIST`.
  382. .serverState.capabilities.advertisedCapabilities (Map<String, String>)
  383. Contains a map of capability names to values that the server offered. This
  384. should only be required for advance use cases, such as looking up the
  385. languages offered by a server when providing the user with a choice of
  386. translations.
  387. .serverState.capabilities.enabledCapabilities (Map<Capability, String>)
  388. Contains a map of capabilities that KtIrc has successfully negotiated with
  389. the server.
  390. ===== Supported capabilities
  391. * `sasl` - used to perform SASL authentication during connection
  392. * `message-tags` - allows arbitrary tags on messages
  393. * `server-time` - the server adds a timestamp tag to each incoming message
  394. * `account-tag` - the server adds an account tag to incoming user messages
  395. * `userhost-in-names` - the NAMES reply includes users hosts not just nicknames
  396. * `multi-prefix` - all modes are included in nick prefixes (e.g. `@+nick`)
  397. * `extended-join` - more information is sent when a user joins a channel
  398. * `batch` - allows multi-line responses to be batched together
  399. * `echo-message` - echos the client's own messages back to it
  400. * `draft/labeled-responses` - responses are labeled so the client knows which
  401. incoming message corresponds to which command it sent
  402. * `account-notify` - the server sends a message when a user's account changes
  403. * `away-notify` - the server sends a message when a user's away state changes
  404. * `chghost` - the server sends a message when a user's host changes
  405. ==== Features
  406. Features are KtIrc's way of exposing the information the server declares in
  407. its ISUPPORT messages. These describe how the server is configured, and what
  408. limits are placed on clients. You access features using the `features` map
  409. in the server state:
  410. [source,kotlin]
  411. ----
  412. ircClient.serverState.features[ServerFeature.Network]
  413. ----
  414. The following features are available:
  415. * `Network` - the name of the network the server belongs to __(String?)__
  416. * `ServerCaseMapping` - the current case mapping of the server __(CaseMapping!)__
  417. * `Modeprefixes` - the user mode prefix mapping (e.g. ov to @+) __(ModePrefixMapping!)__
  418. * `MaximumChannels` - the maximum number of channels a user can join __(Int?)__
  419. * `ChannelModes` - the modes supported in channels __(Array<String>?)__
  420. * `ChannelTypes` - the types of channel supported (e.g. "#&") __(String!)__
  421. * `MaximumChannelNameLength` - how long channel names may be __(Int!)__
  422. * `WhoxSupport` - whether the server supports extended whos ("WHOX") __(Boolean!)__
  423. [NOTE]
  424. ====
  425. If the server does not define a feature, KtIrc will either fall back to a
  426. default value based on the IRC RFCs or common practice (for those features
  427. identified with a non-null type such as `Int!` or `String!`); otherwise
  428. the value of the feature will be `null` (such as for those identified as
  429. `Int?` or `String?` types).
  430. ====
  431. === UserState
  432. The client's UserState object tracks the details of all users in common
  433. channels. It can be used to find the most up-to-date and comprehensive
  434. information for those users, as well as the set of channels that we share
  435. with them.
  436. The UserState is accessed via the `userState` property of IrcClient and
  437. acts as a map, accessible using either a nickname or a `User` object:
  438. [source,kotlin]
  439. ----
  440. ircClient.userState["acidBurn"]
  441. val user: User = myIrcEvent.user
  442. ircClient.userState[user]
  443. ----
  444. The UserState returns a `KnownUser` object which exposes a `details`
  445. property containing the user details, and a `channels` property
  446. containing the common channel names. You can also use the `in`
  447. operator to check if the user is in a channel:
  448. [source,kotlin]
  449. ----
  450. ircClient.userState["acidBurn"]?.let { knownUser -> <1>
  451. val accountName = knownUser.account
  452. val inChannel = "#channel" in knownUser <2>
  453. val allChannels = knownUser.channels <3>
  454. }
  455. ----
  456. <1> If the user isn't known, the call to `get` (using the `[]` operator)
  457. returns null, so we use a `let` statement to deal only with the case
  458. that the user is found.
  459. <2> Check if the user is present on the common channel `#channel`. If
  460. the KtIrc client is not joined to that channel, it will always return
  461. false. You can also use the `contains("#channel")` method instead of
  462. the `in` operator.
  463. <3> Returns all common channels we share with the user; will never
  464. include channels that the KtIrc client is not joined to.
  465. === ChannelState
  466. The ChannelState keeps track of the state for all channels that the client
  467. is joined to. It is indexed by channel name:
  468. [source,kotlin]
  469. ----
  470. ircClient.channelState["#ktirc"]
  471. ----
  472. Each channel's state contains the following properties:
  473. * `receivingUserList` - boolean value indicating whether we are in the process
  474. of receiving the list of users for the channel. If we are, the `users`
  475. property will be incomplete.
  476. * `modesDiscovered` - boolean value indicating whether we have received the
  477. full set of modes set on the channel. The `requestModesOnJoin` <<Behaviour>>
  478. allows you to make KtIrc request these automatically.
  479. * `topic` - a ChannelTopic object representing the current channel topic.
  480. If no topic is set, then a ChannelTopic with `null` properties will be
  481. provided.
  482. * `users` - a map of all known users in the channel, see <<Channel users>>
  483. for more information
  484. * `modes` - A map of the current channel modes and their values. Only
  485. complete if `modesDiscovered` is true.
  486. ==== Channel users
  487. Channel users are accessed using the `users` property, which provides an
  488. iterable map of nickname to `ChannelUser`. Each `ChannelUser` contains
  489. the nickname and current modes for that user. To get further details about
  490. a user, such as their hostmask or real name, you should query the <<UserState>>
  491. with the given nickname.
  492. [source,kotlin]
  493. ----
  494. ircClient.channelState["#ktirc"]?.users?.forEach { user ->
  495. println("${user.nickname} has modes ${user.modes}")
  496. }
  497. ----
  498. == Events
  499. Incoming lines from the IRC server are converted by KtIrc to subclasses of
  500. `IrcEvent`. These, along with other more advance events, are then published
  501. to users of the client using the `onEvent` method in `IrcClient`.
  502. All events extend `IrcEvent`, which offers a single `metadata` property.
  503. This contains details related to the event:
  504. * `time` - the time at which the message occurred (if the server supports
  505. the `server-time` capability), or the time at which we received it.
  506. Always present.
  507. * `batchId` - an opaque string identifier for the batch the message is
  508. part of (if the server supports the `batch` capability). Null for
  509. messages not in a batch.
  510. * `messageId` - a unique, opaque string identifier for the message if
  511. the server supports the `msgid` tag. Null otherwise.
  512. * `label` - a unique, opaque string identifier that ties a message to
  513. a labelled command that was sent by KtIrc, if the server supports
  514. the `labelled-replies` capability. Null otherwise.
  515. Several specialised versions of `IrcEvent` are used which allow for easier
  516. processing:
  517. .TargetedEvent
  518. A `TargetedEvent` is one that is targeted at either a user or a channel.
  519. `TargetedEvent` exposes a string `target` property that identifies the
  520. target of the message. This allows you to direct messages to the right
  521. handler or UI component more easily:
  522. [source,kotlin]
  523. ----
  524. ircClient.onEvent { event ->
  525. when (event) {
  526. is TargetedEvent -> dispatchEvent(event.target, event)
  527. }
  528. }
  529. ----
  530. .SourcedEvent
  531. A large number of events come from a remote IRC user, and it can be
  532. useful to handle these in the same way. KtIrc offers a `SourcedEvent`
  533. interface for all events that originate from a user, and it exposes
  534. a single `user` property:
  535. [source,kotlin]
  536. ----
  537. ircClient.onEvent { event ->
  538. when (event) {
  539. is SourcedEvent -> notifyAboutUserActivity(event.user)
  540. }
  541. }
  542. ----
  543. .ChannelMembershipAdjustment
  544. A number of events describe how the membership of a channel changes --
  545. namely, joins, parts, quits, kicks, names replies, and nick changes.
  546. All of these events implement the `ChannelMembershipAdjustment` interface
  547. which reduces the amount of logic you need to do if you wish to maintain
  548. a membership list (for example in a UI). The interface exposes three
  549. properties:
  550. * `addedUser` - a single nickname to be added _(String)_
  551. * `removedUser` - a single nickname to be removed _(String)_
  552. * `replacedUsers` - a list of nicknames to replace any existing ones with
  553. _(Array<String>)_
  554. All the properties are nullable, and most events will only populate
  555. one of the three.
  556. === Server events
  557. ==== ServerConnecting
  558. * Type: IrcEvent
  559. * Properties: _(none)_
  560. This event is raised by KtIrc as soon as it starts attempting to connect to
  561. a server. It will be followed by either a <<ServerConnected>> or a
  562. <<ServerConnectionError>> event at some point.
  563. ==== ServerConnected
  564. * Type: IrcEvent
  565. * Properties: _(none)_
  566. This event is raised by KtIrc when it has connected to the server, and is
  567. starting the process of registering, negotiating capabilities, etc.
  568. The server will *not* yet be ready for use - a <<ServerReady>> event will
  569. follow once all of the initial setup has completed.
  570. ==== ServerConnectionError
  571. * Type: IrcEvent
  572. * Properties:
  573. ** `error`: `ConnectionError` - the type of error that occurred
  574. ** `details`: `String?` - information about the error, if available
  575. This event is raised by KtIrc when a problem occurred while connecting
  576. to the server. The `ConnectionError` enum will provide the cause of
  577. the error, if known:
  578. * `UnresolvableAddress` - the hostname provided could not be resolved
  579. to an IP address
  580. * `ConnectionRefused` - the server did not answer a connection request
  581. on the given port
  582. * `BadTlsCertificate` - there was an issue with the TLS certificate the
  583. server presented (e.g. it was out of date, for the wrong domain, etc)
  584. * `Unknown` - the exact cause of the error isn't known
  585. This event will be followed by a <<ServerDisconnected>> event.
  586. ==== ServerWelcome
  587. * Type: IrcEvent
  588. * Properties:
  589. ** `server`: `String` - the name the server supplied for itself
  590. ** `localNick`: `String` - the nickname the server says we are using
  591. This event is raised in response to the server sending a 001 WELCOME
  592. message. It contains the name that the server supplied for itself
  593. (for example, KtIrc may connect to a round-robin address like
  594. `irc.example.com` and the server it actually connects to then
  595. identifies itself as `node3.uk.irc.example.com`), and the nickname
  596. that the server says we are using.
  597. ==== ServerReady
  598. * Type: IrcEvent
  599. * Properties: _(none)_
  600. This event is raised by KtIrc when it has connected to a server,
  601. registered with the IRC network, and received all of the server's
  602. initial data describing its configurations and its features.
  603. At this point it is safe to start issuing commands, checking
  604. state, joining channels, etc.
  605. ==== ServerDisconnected
  606. * Type: IrcEvent
  607. * Properties: _(none)_
  608. Raised in all cases where KtIrc has attempted to connect to an IRC server and
  609. has now been disconnected. KtIrc will not automatically attempt to reconnect;
  610. the `connect()` method should be called again after an appropriate delay.
  611. NOTE: All of KtIrc's internal state, such as details about users and
  612. channels, will be reset when disconnected from the server. State should not
  613. be queried until a new <<ServerReady>> event has been received, at which
  614. point it will have been recreated.
  615. ==== MotdLineReceived
  616. * Type: IrcEvent
  617. * Properties:
  618. ** `line`: `String` - the line of the message of the day that was received
  619. ** `first`: `Boolean` - true if the line is the first one received
  620. The MotdLineReceived event is raised whenever the server sends a single
  621. line of its Message of the Day. The `first` parameter is set on the
  622. first line of the MOTD so that special formatting or UI handling can
  623. be applied. When the MOTD is finished, a <<MotdFinished>> event is raised.
  624. ==== MotdFinished
  625. * Type: IrcEvent
  626. * Properties:
  627. ** `missing`: `Boolean` - indicates the MOTD was missing
  628. This event occurs in two circumstances: when the server has sent a
  629. series of <<MotdLineReceived>> events and has reached the end of the
  630. Message of the Day; or when the server has no MOTD to send and
  631. informs the client that the MOTD is missing.
  632. === Channel events
  633. NOTE: Many events such as <<MessageReceived>> apply to both channels and
  634. users. These are documented in the <<Channel/User events>> category.
  635. ==== ChannelJoined
  636. * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
  637. * Properties:
  638. ** `user`: `User` - the user that joined the channel
  639. ** `target`: `String` - the channel that was joined
  640. Raised whenever a user joins a channel, including the KtIrc client. You
  641. can determine whether the join applies to another user or the local client
  642. using the <<IsLocalClient>> utility method.
  643. When the local client joins a new channel, this event will typically be
  644. followed by one or more <<ChannelNamesReceived>> events, then
  645. <<ChannelNamesFinished>>, <<ChannelTopicDiscovered>> and if the
  646. `requestModesOnJoin` <<Behaviour>> is enabled a <<ModeChanged>> event.
  647. ==== ChannelJoinFailed
  648. * Type: IrcEvent, TargetedEvent
  649. * Properties:
  650. ** `target`: `String` - the channel that we tried to join
  651. ** `reason`: `JoinError` - the error that prevented us from joining
  652. The ChannelJoinFailed event is raised when we attempt to join a channel
  653. but the server doesn't allow us to do so. The reason parameter enumerates
  654. the possible problems:
  655. * `TooManyChannels` - we are already in the maximum number of channels allowed
  656. by the server.
  657. * `NoHiding` - the channel is no-hiding (+H), but we have invisible join/parts
  658. enabled.
  659. * `NeedKey` - the channel is keyed (+k) and a valid key was not provided
  660. * `NeedInvite` - the channel is invite only (+i) and no invite was received.
  661. * `NeedRegisteredNick` - the channel is limited to registered users only, and we
  662. are not registered.
  663. * `NeedTls` - the channel is secure-only, and we're not using TLS.
  664. * `NeedAdmin` - the channel is limited to server admins and we are not one.
  665. * `NeedOper` - the channel is limited to ircops and we are not one.
  666. * `Banned` - we are banned from the channel.
  667. * `ChannelFull` - the channel is limited (+l) and currently full.
  668. * `BadChannelName` - the channel name is disallowed by the server.
  669. * `Throttled` - we're trying to joiin too many channels and have been throttled.
  670. * `Unknown` - we don't know why.
  671. [WARNING]
  672. ====
  673. ChannelJoinFailed events are generated on a _best-effort_ basis by KtIrc. Error
  674. handling on IRC is very poorly standardised, and varies wildly between server
  675. implementations. For example, trying to join a secure-only channel on an
  676. ircd-seven server will send a NOTICE to the user instead of an error response,
  677. so no `ChannelJoinFailed` event will be raised.
  678. When tracking whether a join suceeded or failed you should combine monitoring
  679. for the response with a reasonable timeout, and assume failure if the timeout
  680. lapses without a <<ChannelJoined>> or <<ChannelJoinFailed>> event occurring.
  681. ====
  682. ==== ChannelParted
  683. * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
  684. * Properties:
  685. ** `user`: `User` - the user that parted the channel
  686. ** `target`: `String` - the channel that was parted
  687. ** `reason`: `String` - the user-supplied reason for parting
  688. Raised when any user parts a channel that we are on. Users can supply a reason
  689. when parting a channel; if they have done so the `reason` property will be
  690. non-empty.
  691. ==== ChannelUserKicked
  692. * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
  693. * Properties:
  694. ** `user`: `User` - the user that performed the kick
  695. ** `victim`: `String` - the nickname of the user that was kicked
  696. ** `target`: `String` - the channel that the victim was kicked from
  697. ** `reason`: `String` - the user-supplied reason for kicking
  698. This event occurs when a user is kicked (forcibly removed) from a channel.
  699. NOTE: The `user` is the one performing the kick, and will remain in the
  700. channel. The `victim` is the one being forcibly ejected.
  701. ==== ChannelQuit
  702. * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
  703. * Properties:
  704. ** `user`: `User` - the user that quit
  705. ** `target`: `String` - the channel that the user was in
  706. ** `reason`: `String` - the user-supplied reason for quitting
  707. After a <<UserQuit>> event, KtIrc will "fan out" the event to all of the
  708. channels that we share with the user and raise a `ChannelQuit` event for
  709. each channel. This is designed to make implementing certain features easier;
  710. if you fully handle a UserQuit event there is no need to also handle the
  711. ChannelQuit events, and vice-versa.
  712. Users and servers can supply a reason when a user quits; if supplied then
  713. the `reason` parameter will be non-empty.
  714. ==== ChannelNickChanged
  715. * Type: IrcEvent, TargetedEvent, SourcedEvent, ChannelMembershipAdjustment
  716. * Properties:
  717. ** `user`: `User` - the user who has changed their nickname
  718. ** `target`: `String` - the channel that the user is in
  719. ** `newNick`: `String` - the user's new nickname
  720. After a <<UserNickChanged>> event, KtIrc will "fan out" the event to
  721. all of the channels that we share with the user and raise a `ChannelNickChanged`
  722. event for each channel. This is designed to make implementing certain features
  723. easier; if you fully handle a UserNickChanged event there is no need to also
  724. handle the ChannelNickChanged events, and vice-versa.
  725. TIP: The user property will contain the user's old details, but you will
  726. not be able to access additional information from the <<UserState>> using
  727. these details as KtIrc will have internally renamed the user to use the
  728. new nickname.
  729. ==== ChannelNamesReceived
  730. * Type: IrcEvent, TargetedEvent
  731. * Properties:
  732. ** `target`: `String` - the channel that the user is in
  733. ** `names`: `List<String>` - the partial list of names that are in the channel
  734. When we join a channel (or manually request it) the IRC server sends the
  735. list of channel members in a sequence of NAMES messages. KtIrc raises a
  736. `ChannelNamesReceived` event for each of these messages.
  737. WARNING: The given names may not be a complete list of members of the channel,
  738. as more names could follow. The format of the names varies between IRC servers
  739. and depending on the IRCv3 <<Capabilities>> that KtIrc negotiated. Most
  740. implementations should simply wait for <<ChannelNamesFinished>> and then request
  741. the complete list of names from KtIrc's <<ChannelState>>.
  742. ==== ChannelNamesFinished
  743. * Type: IrcEvent, TargetedEvent, ChannelMembershipAdjustment
  744. * Properties:
  745. ** `target`: `String` - the channel whose names response has finished
  746. Raised when the IRC server has finished receiving all of the names of users
  747. that are currently in a channel. At this point you can query the channel's
  748. <<ChannelState>> to get a detailed list of members.
  749. ==== ChannelTopicDiscovered
  750. * Type: IrcEvent, TargetedEvent
  751. * Properties:
  752. ** `target`: `String` - the channel whose topic was discovered
  753. ** `topic`: `String?` - the topic in the channel, if any
  754. `ChannelTopicDiscovered` occurs when we join a channel (or manually request
  755. that the server repeats the current topic) and contains the current channel
  756. topic. If there is no topic set, the `topic` parameter will be `null`.
  757. Metadata about the topic, such as who set it and when, is contained in the
  758. <<ChannelTopicMetadataDiscovered>> event which should follow this one, if
  759. the topic was set.
  760. ==== ChannelTopicMetadataDiscovered
  761. * Type: IrcEvent, TargetedEvent
  762. * Properties:
  763. ** `target`: `String` - the channel whose topic metadata was discovered
  764. ** `user`: `User` - the user who set the topic
  765. ** `setTime`: `LocalDateTime` - the time at which the topic was set
  766. Provides meta-data relating to a topic that was previously set on the
  767. channel.
  768. NOTE: The given user may not exist on the network any more, or may have
  769. changed details since the topic was set. You should not expect to be able
  770. to look up the user's details in the <<UserState>>, or interact with them
  771. directly on IRC.
  772. ==== ChannelTopicChanged
  773. * Type: IrcEvent, TargetedEvent, SourcedEvent
  774. * Properties:
  775. ** `user`: `User` - the user who has changed the topic
  776. ** `target`: `String` - the channel that the topic was changed in
  777. ** `topic`: `String?` - the channel's new topic
  778. Raised when a user changes the topic of a channel we are joined to. If
  779. the topic was cleared/removed, the `topic` parameter will be `null`.
  780. === Channel/User events
  781. TODO
  782. ==== MessageReceived
  783. TODO
  784. ==== NoticeReceived
  785. TODO
  786. ==== ActionReceived
  787. TODO
  788. ==== CtcpReceived
  789. TODO
  790. ==== CtcpReplyReceived
  791. TODO
  792. ==== UserQuit
  793. TODO
  794. ==== UserNickChanged
  795. TODO
  796. ==== UserHostChanged
  797. TODO
  798. ==== UserAccountChanged
  799. TODO
  800. ==== ModeChanged
  801. TODO
  802. === Other events
  803. ==== PingReceived
  804. * Type: IrcEvent
  805. * Properties:
  806. ** `nonce`: `ByteArray` - the unique data that must be included in the reply
  807. Raised when the IRC server sends a PING message to the client. KtIrc will
  808. automatically reply with an appropriate PONG.
  809. ==== ServerFeaturesUpdated
  810. * Type: IrcEvent
  811. * Properties:
  812. ** `serverFeatures`: `ServerFeatureMap` - the features supplied by the server
  813. Corresponds to the server sending a single 005 ISUPPORT line. Multiple
  814. events of this type may be raised in quick succession when features are
  815. split over multiple lines.
  816. In general, you should wait for a <<ServerReady>> event and then query the
  817. <<Features>> instead of relying on this event.
  818. ==== ServerCapabilitiesReceived
  819. TODO
  820. ==== ServerCapabilitiesAcknowledged
  821. TODO
  822. ==== ServerCapabilitiesFinished
  823. TODO
  824. ==== AuthenticationMessage
  825. TODO
  826. ==== SaslFinished
  827. TODO
  828. ==== SaslMechanismNotAvailableError
  829. TODO
  830. ==== BatchStarted
  831. TODO
  832. ==== BatchFinished
  833. TODO
  834. ==== BatchReceived
  835. TODO
  836. ==== NicknameChangeFailed
  837. * Type: IrcEvent
  838. * Properties:
  839. ** `cause`: `NicknameChangeError` - the reason the nickname must be changed
  840. Raised when the server informs us that our desired nickname is not available
  841. for some reason. The `cause` parameter will contain a specific reason given
  842. by the server:
  843. * `ErroneousNickname` - the nickname is not allowed by the server (e.g. it used
  844. restricted characters)
  845. * `AlreadyInUse` - the nickname is already in use
  846. * `Collision` - the nickname has collided with another somehow
  847. * `NoNicknameGiven` - no nickname was provided
  848. ==== NicknameChangeRequired
  849. * Type: IrcEvent, NicknameChangeFailed
  850. * Properties:
  851. ** `cause`: `NicknameChangeError` - the reason the nickname must be changed
  852. Raised during a connection attempt when there is a problem with the nickname
  853. that KtIrc was told to use. The exact problem will be detailed in the `cause`
  854. parameter, and has the same options as the <<NicknameChangeFailed>> event.
  855. Upon receiving this event, a new nickname MUST be chosen and sent to the
  856. server with the <<sendNickChange>> method. Failure to do so will result
  857. in the IRC server terminating the connection.
  858. WARNING: `NicknameChangeRequired` currently extends `NicknameChangeFailed`
  859. for backwards compatibility. This will be removed in KtIrc 2.0.0, and
  860. both events will need to be handled separately.
  861. == Messages
  862. TODO
  863. === sendNickChange
  864. TODO
  865. == Utility methods
  866. TODO
  867. === IsLocalClient
  868. TODO
  869. === React
  870. TODO
  871. === Reply
  872. TODO
  873. == IRCv3 support
  874. The following table shows KtIrc's IRCv3 support as of this release:
  875. [cols=3,options="header,autowidth"]
  876. |===
  877. | Feature
  878. | Status
  879. | Notes
  880. 3+h| Capability negotiation
  881. | https://ircv3.net/specs/core/capability-negotiation.html[CAP]
  882. | {set:cellbgcolor:green} Supported
  883. | {set:cellbgcolor!}
  884. See <<Supported capabilities>> for the caps KtIrc will negotiate
  885. | https://ircv3.net/specs/core/capability-negotiation.html#cap-ls-version[CAP 302]
  886. | {set:cellbgcolor:green} Supported
  887. | {set:cellbgcolor!}
  888. See <<Supported capabilities>> for the caps KtIrc will negotiate
  889. | https://ircv3.net/specs/core/capability-negotiation.html#cap-notify[cap-notify]
  890. | {set:cellbgcolor:red} Not yet supported
  891. | {set:cellbgcolor!}
  892. 3+h| Published specifications
  893. | https://ircv3.net/specs/extensions/account-notify-3.1.html[account-notify] v3.1
  894. | {set:cellbgcolor:green} Supported
  895. | {set:cellbgcolor!}
  896. See <<UserAccountChanged>>
  897. | https://ircv3.net/specs/extensions/account-tag-3.2.html[account-tag] v3.2
  898. | {set:cellbgcolor:green} Supported
  899. | {set:cellbgcolor!}
  900. Accounts are automatically added to `User` properties in events
  901. | https://ircv3.net/specs/extensions/away-notify-3.1.html[away-notify] v3.1
  902. | {set:cellbgcolor:orange} Partial support
  903. | {set:cellbgcolor!}
  904. Negotiated but not yet exposed as an event
  905. | https://ircv3.net/specs/extensions/batch-3.2.html[batch] v3.2
  906. | {set:cellbgcolor:green} Supported
  907. | {set:cellbgcolor!}
  908. See <<BatchReceived>>
  909. | https://ircv3.net/specs/extensions/chghost-3.2.html[chghost] v3.2
  910. | {set:cellbgcolor:green} Supported
  911. | {set:cellbgcolor!}
  912. See <<UserHostChanged>>
  913. | https://ircv3.net/specs/extensions/echo-message-3.2.html[echo-message] v3.2
  914. | {set:cellbgcolor:green} Supported
  915. | {set:cellbgcolor!}
  916. See also the `alwaysEchoMessages` <<Behaviour>>
  917. | https://ircv3.net/specs/extensions/extended-join-3.1.html[extended-join] v3.1
  918. | {set:cellbgcolor:green} Supported
  919. | {set:cellbgcolor!}
  920. Additional details are automatically added to `User` properties in events
  921. | https://ircv3.net/specs/extensions/invite-notify-3.2.html[invite-notify] v3.2
  922. | {set:cellbgcolor:red} Not yet supported
  923. | {set:cellbgcolor!}
  924. | https://ircv3.net/specs/extensions/message-tags.html[message-tags]
  925. | {set:cellbgcolor:green} Supported
  926. | {set:cellbgcolor!}
  927. Exposed in the metadata property of <<Events>>
  928. | https://ircv3.net/specs/core/monitor-3.2.html[monitor]
  929. | {set:cellbgcolor:red} Not yet supported
  930. | {set:cellbgcolor!}
  931. | https://ircv3.net/specs/extensions/multi-prefix-3.1.html[multi-prefix] v3.1
  932. | {set:cellbgcolor:green} Supported
  933. | {set:cellbgcolor!}
  934. Automatically included in <<ChannelState>>
  935. | https://ircv3.net/specs/extensions/sasl-3.1.html[SASL] v3.1
  936. | {set:cellbgcolor:green} Supported
  937. | {set:cellbgcolor!}
  938. See <<SASL configuration>>
  939. | https://ircv3.net/specs/extensions/sasl-3.2.html[SASL] v3.2
  940. | {set:cellbgcolor:orange} Partial support
  941. | {set:cellbgcolor!}
  942. Notifications via `cap-notify` not yet supported. See <<SASL configuration>>
  943. | https://ircv3.net/specs/extensions/server-time-3.2.html[server-time] v3.2
  944. | {set:cellbgcolor:green} Supported
  945. | {set:cellbgcolor!}
  946. Exposed in the metadata property of <<Events>>
  947. | https://ircv3.net/specs/extensions/sts.html[sts]
  948. | {set:cellbgcolor:red} Not yet supported
  949. | {set:cellbgcolor!}
  950. | https://ircv3.net/specs/extensions/userhost-in-names-3.2.html[userhost-in-names] v3.2
  951. | {set:cellbgcolor:green} Supported
  952. | {set:cellbgcolor!}
  953. Automatically included in <<UserState>>
  954. | https://ircv3.net/specs/extensions/webirc.html[webirc]
  955. | {set:cellbgcolor:red} Not yet supported
  956. | {set:cellbgcolor!}
  957. 3+h| Draft specifications
  958. | https://github.com/ircv3/ircv3-specifications/pull/363[brb]
  959. | {set:cellbgcolor:red} Not yet supported
  960. | {set:cellbgcolor!}
  961. | https://github.com/ircv3/ircv3-specifications/pull/308[channel renaming]
  962. | {set:cellbgcolor:red} Not yet supported
  963. | {set:cellbgcolor!}
  964. | https://github.com/ircv3/ircv3-specifications/pull/349[chathistory]
  965. | {set:cellbgcolor:red} Not yet supported
  966. | {set:cellbgcolor!}
  967. | https://github.com/ircv3/ircv3-specifications/pull/346[delivered]
  968. | {set:cellbgcolor:red} Not yet supported
  969. | {set:cellbgcolor!}
  970. | https://github.com/ircv3/ircv3-specifications/pull/304[editmsg]
  971. | {set:cellbgcolor:red} Not yet supported
  972. | {set:cellbgcolor!}
  973. | https://ircv3.net/specs/extensions/labeled-response.html[labeled-response]
  974. | {set:cellbgcolor:green} Supported
  975. | {set:cellbgcolor!}
  976. Exposed in the metadata property of <<Events>>
  977. | https://ircv3.net/specs/extensions/message-ids.html[message-ids]
  978. | {set:cellbgcolor:red} Not yet supported
  979. | {set:cellbgcolor!}
  980. | https://github.com/ircv3/ircv3-specifications/pull/330[migrate]
  981. | {set:cellbgcolor:red} Not yet supported
  982. | {set:cellbgcolor!}
  983. | https://ircv3.net/specs/client-tags/react.html[react]
  984. | {set:cellbgcolor:orange} Partial support
  985. | {set:cellbgcolor!}
  986. Sending via <<React>> method, no events generated
  987. | https://github.com/ircv3/ircv3-specifications/pull/347[read]
  988. | {set:cellbgcolor:red} Not yet supported
  989. | {set:cellbgcolor!}
  990. | https://github.com/ircv3/ircv3-specifications/pull/276[register]
  991. | {set:cellbgcolor:red} Not yet supported
  992. | {set:cellbgcolor!}
  993. | https://ircv3.net/specs/client-tags/reply.html[reply]
  994. | {set:cellbgcolor:orange} Partial support
  995. | {set:cellbgcolor!}
  996. Sending via <<Reply>> method, not processed on incoming messages
  997. | https://github.com/ircv3/ircv3-specifications/pull/306[resume]
  998. | {set:cellbgcolor:red} Not yet supported
  999. | {set:cellbgcolor!}
  1000. | https://github.com/ircv3/ircv3-specifications/pull/361[setname]
  1001. | {set:cellbgcolor:red} Not yet supported
  1002. | {set:cellbgcolor!}
  1003. | https://github.com/ircv3/ircv3-specifications/pull/357[standard replies]
  1004. | {set:cellbgcolor:red} Not yet supported
  1005. | {set:cellbgcolor!}
  1006. | https://github.com/ircv3/ircv3-specifications/pull/348[typing]
  1007. | {set:cellbgcolor:red} Not yet supported
  1008. | {set:cellbgcolor!}
  1009. 3+^h|Vendor specifications
  1010. |===