summaryrefslogtreecommitdiff
path: root/src/_posts/2021-05-13-a-new-irc-client.md
blob: e52cc37661946616085225b9c1eb00535c0fd8dd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
---
layout: post
tags: Raku IRC Programming
title: A New IRC::Client
social:
  email: mailto:~tyil/public-inbox@lists.sr.ht&subject=A New IRC::Client
description: >
  Due to the current iteration of IRC::Client in the Raku programming
  language's ecosystem being unmaintained, I've decided to make my own
  implementation with the intent of replacing it.
---

The Raku programming language has a popular module for creating IRC bots,
[`IRC::Client`](https://github.com/raku-community-modules/IRC-Client). However,
it's been stale for quite a while, and one of the bots I host,
[Geth](https://github.com/Raku/geth), is having troubles on a regular basis.

I've looked at the source code, and found a lot of neat tricks, but when
maintaining a library, I generally want clean and straightforward code instead.
To that end, I decided to just write my own from scratch. Given that [the IRC
protocol is rather simple](https://tools.ietf.org/html/rfc2812), this was the
easiest way to go about it.

Sure enough, after a couple hours of playing around, I had something that
worked reasonably well. A few more hours a day afterwards brought me to an
`IRC::Client` that is usable in mostly the same way as the current
`IRC::Client`, to save me effort in getting my current bots to make use of it
for a few test runs.

Geth was my main target, as I wanted it to stop from getting timed out so
often. For the past week, Geth has been running stable, without any time
out, so I think I've succeeded in the main goal.

However, how to continue next? Since it is mostly compatible, but not
*completely* compatible, if I were to adopt `IRC::Client` from the Raku
ecosystem and push my version, many people's IRC bots would break when people
update their dependencies. There is a solution for this built into the entire
ecosystem, which is using the correct `:ver` and `:auth` (and in some cases,
`:api`) so you can ensure your project is always getting the "correct"
dependency. However, from personal experience, I know these additional
dependency restrictions are rarely used in practice.

I hope that with this blog post, I can inform the community in time about the
changes that are coming to `IRC::Client`, so people have ample time to set
their dependencies just right to keep their projects working. Of course, the
real solution for the long term would be to make the small changes required to
use the latest `IRC::Client` again.

For convenience sake, I've added a small number of methods for backwards
compatibility as well, though these will generate [a deprecation
warning](https://docs.raku.org/routine/is%20DEPRECATED), and will be removed in
a later `IRC::Client` release.

There's two major changes that are not backwards compatible, however. The first
one is the removal of the ability to have a single `IRC::Client` connect to
multiple servers. This is also the easiest to remedy, by simply creating
multiple instances of `IRC::Client`.

The second major incompatible change is how events are dispatched to plugins.
This used to be handled by going through all the plugins sequentially, allowing
one plugin to stop the dispatch to another plugin. In my new version, events
are dispatched to all plugins in parallel. This allows for faster execution,
and for multiple plugins to handle an event without having to use `$*NEXT`
(which has been removed). My main motivation is that a buggy plugin will no
longer interfere with the interactions provided by other plugins. The ordering
of your plugins will also stop being an issue to worry about.

Geth's updates to actually use my updated `IRC::Client` module was introduced
in
[`edc6b08`](https://github.com/Raku/geth/commit/edc6b08036c8ede08afdea39fd1768655a2766aa),
and most if it was updates to the way it handled logging. The actual changes
needed to make Geth play nice were

- [Adding the `IRC::Client::Plugin` role to `Geth::Plugin::Info`](https://github.com/Raku/geth/commit/edc6b08036c8ede08afdea39fd1768655a2766aa#diff-104b5cdb61f2aa423eb941ce32a4412b4cb814014728cae968e5aeff7dc587d2R14);
- [And to `Geth::Plugin::Uptime`](https://github.com/Raku/geth/commit/edc6b08036c8ede08afdea39fd1768655a2766aa#diff-104b5cdb61f2aa423eb941ce32a4412b4cb814014728cae968e5aeff7dc587d2R24);
- [Using `nicks` instead of `nick`](https://github.com/Raku/geth/commit/edc6b08036c8ede08afdea39fd1768655a2766aa#diff-104b5cdb61f2aa423eb941ce32a4412b4cb814014728cae968e5aeff7dc587d2R34);
- [Using `start` instead of `run`](https://github.com/Raku/geth/commit/edc6b08036c8ede08afdea39fd1768655a2766aa#diff-104b5cdb61f2aa423eb941ce32a4412b4cb814014728cae968e5aeff7dc587d2R46);
- [Using `privmsg` instead of `send`](https://github.com/Raku/geth/commit/edc6b08036c8ede08afdea39fd1768655a2766aa#diff-c388af832470886cdd4304aeb17c4c2f406ac184d33afb956b0ef8a92b69855bR57);

The last two changes aren't strictly necessary, as there are backwards
compatibility methods made for these, but it's a rather small change and
reduces the amount of noise in the logs.

With this, I hope everyone using `IRC::Client` is prepared for the coming
changes. If you have any comments or questions, do not hesitate to reach out to
me and share your thoughts!