@sockethub/platform-irc 4.0.0-alpha.12 → 4.0.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,6 +18,10 @@ messages.
18
18
 
19
19
  ## Usage
20
20
 
21
+ IRC room targets use `channel@server` in `target.id` (for example
22
+ `general@irc.libera.chat`). When you include `target.name`, use the channel
23
+ name as it appears on IRC (for example `#general`).
24
+
21
25
  ### Send Message Example
22
26
 
23
27
  ```json
@@ -33,8 +37,9 @@ messages.
33
37
  "type": "person"
34
38
  },
35
39
  "target": {
36
- "id": "#general@irc.libera.chat",
37
- "type": "room"
40
+ "id": "general@irc.libera.chat",
41
+ "type": "room",
42
+ "name": "#general"
38
43
  },
39
44
  "object": {
40
45
  "type": "message",
@@ -58,8 +63,9 @@ messages.
58
63
  "type": "person"
59
64
  },
60
65
  "target": {
61
- "id": "#general@irc.libera.chat",
62
- "type": "room"
66
+ "id": "general@irc.libera.chat",
67
+ "type": "room",
68
+ "name": "#general"
63
69
  }
64
70
  }
65
71
  ```
@@ -89,6 +95,227 @@ messages.
89
95
  }
90
96
  ```
91
97
 
98
+ ### Update Topic Example
99
+
100
+ ```json
101
+ {
102
+ "type": "update",
103
+ "@context": [
104
+ "https://www.w3.org/ns/activitystreams",
105
+ "https://sockethub.org/ns/context/v1.jsonld",
106
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
107
+ ],
108
+ "actor": {
109
+ "id": "mynick@irc.libera.chat",
110
+ "type": "person"
111
+ },
112
+ "target": {
113
+ "id": "general@irc.libera.chat",
114
+ "type": "room",
115
+ "name": "#general"
116
+ },
117
+ "object": {
118
+ "type": "topic",
119
+ "content": "New channel topic"
120
+ }
121
+ }
122
+ ```
123
+
124
+ ### Update Nickname Example
125
+
126
+ ```json
127
+ {
128
+ "type": "update",
129
+ "@context": [
130
+ "https://www.w3.org/ns/activitystreams",
131
+ "https://sockethub.org/ns/context/v1.jsonld",
132
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
133
+ ],
134
+ "actor": {
135
+ "id": "mynick@irc.libera.chat",
136
+ "type": "person"
137
+ },
138
+ "target": {
139
+ "id": "newnick@irc.libera.chat",
140
+ "type": "person"
141
+ },
142
+ "object": {
143
+ "type": "address"
144
+ }
145
+ }
146
+ ```
147
+
148
+ ### Query Attendance Example
149
+
150
+ ```json
151
+ {
152
+ "type": "query",
153
+ "@context": [
154
+ "https://www.w3.org/ns/activitystreams",
155
+ "https://sockethub.org/ns/context/v1.jsonld",
156
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
157
+ ],
158
+ "actor": {
159
+ "id": "mynick@irc.libera.chat",
160
+ "type": "person"
161
+ },
162
+ "target": {
163
+ "id": "general@irc.libera.chat",
164
+ "type": "room",
165
+ "name": "#general"
166
+ },
167
+ "object": {
168
+ "type": "attendance"
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Query Attendance Response Example
174
+
175
+ ```json
176
+ {
177
+ "type": "query",
178
+ "@context": [
179
+ "https://www.w3.org/ns/activitystreams",
180
+ "https://sockethub.org/ns/context/v1.jsonld",
181
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
182
+ ],
183
+ "actor": {
184
+ "id": "general@irc.libera.chat",
185
+ "type": "room",
186
+ "name": "#general"
187
+ },
188
+ "target": {},
189
+ "object": {
190
+ "type": "attendance",
191
+ "members": ["alice", "bob", "carol"]
192
+ }
193
+ }
194
+ ```
195
+
196
+ ### Disconnect Example
197
+
198
+ ```json
199
+ {
200
+ "type": "disconnect",
201
+ "@context": [
202
+ "https://www.w3.org/ns/activitystreams",
203
+ "https://sockethub.org/ns/context/v1.jsonld",
204
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
205
+ ],
206
+ "actor": {
207
+ "id": "mynick@irc.libera.chat",
208
+ "type": "person"
209
+ }
210
+ }
211
+ ```
212
+
213
+ ## Authentication
214
+
215
+ Authenticated connections use SASL. Two mechanisms are supported:
216
+
217
+ * **`PLAIN`** — sends a username and secret via SASL PLAIN. This is the
218
+ default mechanism, and is supported by most IRC networks (Libera.Chat,
219
+ OFTC, etc.). Both `password` and `token` use PLAIN by default. Use
220
+ `token` for personal access tokens (e.g. Libera.Chat NickServ tokens)
221
+ to avoid storing primary account passwords.
222
+ * **`OAUTHBEARER`** — sends an OAuth 2.0 access token instead of a password
223
+ ([RFC 7628](https://datatracker.ietf.org/doc/html/rfc7628)). Requires
224
+ `saslMechanism: "OAUTHBEARER"` to be set explicitly. Adoption on
225
+ public IRC networks is still limited; the main deployment is SourceHut's
226
+ `chat.sr.ht` (via the [soju](https://soju.im/) bouncer). Major networks
227
+ such as Libera.Chat, OFTC, and Hackint do not currently advertise
228
+ OAUTHBEARER. See emersion's [IRC × OAuth 2.0](https://emersion.fr/blog/2022/irc-and-oauth2/)
229
+ writeup for background. How to obtain the token is provider-specific and
230
+ outside the scope of this module.
231
+
232
+ `password` and `token` are mutually exclusive. Both default to SASL PLAIN;
233
+ set `saslMechanism: "OAUTHBEARER"` explicitly for OAuth 2.0 bearer tokens.
234
+ Secure connections validate the IRC server's TLS certificate by default. The
235
+ optional `allowInvalidCert` field defaults to `false`; when set to `true`, it
236
+ disables TLS certificate validation for secure connections. Use this
237
+ security-relevant opt-out only for trusted self-signed IRC networks.
238
+
239
+ ### Credentials with password (SASL PLAIN)
240
+
241
+ ```json
242
+ {
243
+ "type": "credentials",
244
+ "@context": [
245
+ "https://www.w3.org/ns/activitystreams",
246
+ "https://sockethub.org/ns/context/v1.jsonld",
247
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
248
+ ],
249
+ "actor": {
250
+ "id": "mynick@irc.libera.chat",
251
+ "type": "person"
252
+ },
253
+ "object": {
254
+ "type": "credentials",
255
+ "nick": "mynick",
256
+ "server": "irc.libera.chat",
257
+ "password": "secret",
258
+ "port": 6697,
259
+ "secure": true
260
+ }
261
+ }
262
+ ```
263
+
264
+ ### Credentials with personal access token (SASL PLAIN)
265
+
266
+ Networks like Libera.Chat accept NickServ personal access tokens via
267
+ SASL PLAIN. Use the `token` field instead of `password` to make the
268
+ distinction clear:
269
+
270
+ ```json
271
+ {
272
+ "type": "credentials",
273
+ "@context": [
274
+ "https://www.w3.org/ns/activitystreams",
275
+ "https://sockethub.org/ns/context/v1.jsonld",
276
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
277
+ ],
278
+ "actor": {
279
+ "id": "mynick@irc.libera.chat",
280
+ "type": "person"
281
+ },
282
+ "object": {
283
+ "type": "credentials",
284
+ "nick": "mynick",
285
+ "server": "irc.libera.chat",
286
+ "token": "my-personal-access-token",
287
+ "port": 6697,
288
+ "secure": true
289
+ }
290
+ }
291
+ ```
292
+
293
+ ### Credentials with OAuth token (SASL OAUTHBEARER)
294
+
295
+ ```json
296
+ {
297
+ "type": "credentials",
298
+ "@context": [
299
+ "https://www.w3.org/ns/activitystreams",
300
+ "https://sockethub.org/ns/context/v1.jsonld",
301
+ "https://sockethub.org/ns/context/platform/irc/v1.jsonld"
302
+ ],
303
+ "actor": {
304
+ "id": "mynick@chat.sr.ht",
305
+ "type": "person"
306
+ },
307
+ "object": {
308
+ "type": "credentials",
309
+ "nick": "mynick",
310
+ "server": "chat.sr.ht",
311
+ "token": "oauth-access-token",
312
+ "saslMechanism": "OAUTHBEARER",
313
+ "port": 6697,
314
+ "secure": true
315
+ }
316
+ }
317
+ ```
318
+
92
319
  ## Features
93
320
 
94
321
  * **Channel communication**: Join and participate in IRC channels
@@ -106,4 +333,5 @@ messages.
106
333
 
107
334
  ## API
108
335
 
109
- Detailed API documentation can be found [here](API.md)
336
+ API reference docs are generated from the source JSDoc and are not committed to this repository.
337
+ Run `bun run doc` in this package to generate them locally.
@@ -0,0 +1,136 @@
1
+ /**
2
+ * This is a platform for Sockethub implementing IRC functionality.
3
+ *
4
+ * Developed by Nick Jennings (https://github.com/silverbucket)
5
+ *
6
+ * Sockethub is licensed under the LGPLv3.
7
+ * See the LICENSE file for details.
8
+ *
9
+ * The latest version of this module can be found here:
10
+ * git://github.com/sockethub/sockethub.git
11
+ *
12
+ * For more information about Sockethub visit http://sockethub.org/.
13
+ *
14
+ * This program is distributed in the hope that it will be useful,
15
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
+ */
18
+ import type { ActivityStream, PersistentPlatformConfig, PersistentPlatformInterface, PlatformCallback, PlatformSchemaStruct, PlatformSession } from "@sockethub/schemas";
19
+ import { type IrcSocketInstance } from "irc-socket-sasl";
20
+ import type { PlatformIrcCredentialsObject } from "./types.js";
21
+ export type { IrcSocketInstance } from "irc-socket-sasl";
22
+ export type { PlatformIrcCredentialsObject } from "./types.js";
23
+ export declare function flattenConnectOptions(options: Record<string, unknown>): Record<string, unknown>;
24
+ export type GetClientCallback = (err: string | null, client?: IrcSocketInstance) => void;
25
+ /**
26
+ * Handles all actions related to communication via the IRC protocol.
27
+ */
28
+ export declare class IRC implements PersistentPlatformInterface {
29
+ private readonly log;
30
+ credentialsHash: string | undefined;
31
+ config: PersistentPlatformConfig;
32
+ private readonly updateActor;
33
+ private readonly sendToClient;
34
+ private irc2as;
35
+ private forceDisconnect;
36
+ private clientConnecting;
37
+ private initialized;
38
+ private client?;
39
+ private jobQueue;
40
+ private channels;
41
+ private handledActors;
42
+ constructor(session: PlatformSession);
43
+ /**
44
+ * JSON schema defining the types this platform accepts.
45
+ *
46
+ * `password` and `token` are mutually exclusive. Both default to SASL
47
+ * PLAIN; set `saslMechanism: 'OAUTHBEARER'` explicitly for OAuth 2.0
48
+ * bearer tokens (RFC 7628). See the package README for canonical
49
+ * credentials payload examples.
50
+ */
51
+ get schema(): PlatformSchemaStruct;
52
+ /**
53
+ * Returns whether the platform is ready to handle jobs.
54
+ * For IRC, this means we have successfully connected to the server.
55
+ */
56
+ isInitialized(): boolean;
57
+ /**
58
+ * Function: connect
59
+ *
60
+ * Connect to an IRC server.
61
+ *
62
+ * @param {object} job activity streams object
63
+ * @param {object} credentials credentials object
64
+ * @param {object} done callback when job is done
65
+ */
66
+ connect(job: ActivityStream, credentials: PlatformIrcCredentialsObject, done: PlatformCallback): void;
67
+ /**
68
+ * Function: join
69
+ *
70
+ * Join a room or private conversation.
71
+ *
72
+ * @param {object} job activity streams object
73
+ * @param {object} done callback when job is done
74
+ */
75
+ join(job: ActivityStream, done: PlatformCallback): void;
76
+ /**
77
+ * Function leave
78
+ *
79
+ * Leave a room or private conversation.
80
+ *
81
+ * @param {object} job activity streams object
82
+ * @param {object} done callback when job is done
83
+ */
84
+ leave(job: ActivityStream, done: PlatformCallback): void;
85
+ /**
86
+ * Function: send
87
+ *
88
+ * Send a message to a room or private conversation.
89
+ *
90
+ * @param {object} job activity streams object
91
+ * @param {object} done callback when job is done
92
+ */
93
+ send(job: ActivityStream, done: PlatformCallback): void;
94
+ /**
95
+ * Function: update
96
+ *
97
+ * Indicate a change (i.e. room topic update, or nickname change).
98
+ *
99
+ * @param {object} job activity streams object
100
+ * @param {object} credentials credentials to verify this user is the right one
101
+ * @param {object} done callback when job is done
102
+ */
103
+ update(job: ActivityStream, credentials: PlatformIrcCredentialsObject, done: PlatformCallback): void;
104
+ /**
105
+ * Function: query
106
+ *
107
+ * Indicate an intent to query something (e.g. get a list of users in a room).
108
+ *
109
+ * @param {object} job activity streams object
110
+ * @param {object} done callback when job is done
111
+ */
112
+ query(job: ActivityStream, done: PlatformCallback): void;
113
+ /**
114
+ * Disconnect IRC client
115
+ * @param {object} job activity streams object
116
+ * @param done
117
+ */
118
+ disconnect(job: ActivityStream, done: PlatformCallback): void;
119
+ cleanup(done: PlatformCallback): any;
120
+ /**
121
+ * Resolve an IRC channel name from a job target. Prefers `target.name`,
122
+ * falling back to the channel segment of `target.id` (`<server>/<channel>`).
123
+ * Returns undefined when no valid `#channel` can be determined, so callers
124
+ * never emit a bare `NAMES` command (which floods the client with the
125
+ * server's entire channel list).
126
+ */
127
+ private resolveChannelName;
128
+ private isJoined;
129
+ private hasJoined;
130
+ private hasLeft;
131
+ private getClient;
132
+ private ircConnect;
133
+ private completeJob;
134
+ private registerListeners;
135
+ }
136
+ export default IRC;