@sockethub/irc2as 4.0.0-alpha.10

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/src/index.js ADDED
@@ -0,0 +1,308 @@
1
+ import events from "node:events";
2
+ import debug from "debug";
3
+ import { ASEmitter } from "./as-emitter.js";
4
+
5
+ const log = debug("irc2as");
6
+
7
+ const EVENT_INCOMING = "incoming";
8
+ // EVENT_ERROR = 'error',
9
+ const EVENT_PONG = "pong";
10
+ const EVENT_PING = "ping";
11
+ const EVENT_UNPROCESSED = "unprocessed";
12
+
13
+ const ERR_BAD_NICK = "432";
14
+ const ERR_CHAN_PRIVS = "482";
15
+ const ERR_NICK_IN_USE = "433";
16
+ const ERR_TEMP_UNAVAIL = "437";
17
+ const ERR_NO_CHANNEL = "403";
18
+ const ERR_NOT_INVITED = "471";
19
+ const ERR_BADMODE = "472";
20
+ const ERR_INVITE_ONLY = "473";
21
+ const ERR_BANNED = "474";
22
+ const ERR_BADKEY = "475";
23
+ const ERR_BADMASK = "476";
24
+ const ERR_NOCHANMODES = "477";
25
+ const ERR_BANLISTFULL = "478";
26
+ const JOIN = "JOIN";
27
+ const MODE = "MODE";
28
+ const MOTD = "372";
29
+ const MOTD_END = "376";
30
+ const NAMES = "353";
31
+ // NAMES_END = "366",
32
+ const NICK = "NICK";
33
+ const NOTICE = "NOTICE";
34
+ const PART = "PART";
35
+ const PING = "PING";
36
+ const PONG = "PONG";
37
+ const PRIVMSG = "PRIVMSG";
38
+ const QUIT = "QUIT";
39
+ const TOPIC_CHANGE = "TOPIC";
40
+ const TOPIC_IS = "332";
41
+ const TOPIC_SET_BY = "333";
42
+ const WHO = "352";
43
+ const WHO_OLD = "354";
44
+ // WHO_END = "315";
45
+
46
+ const ROLE = {
47
+ "@": "owner",
48
+ "%": "admin",
49
+ "*": "participant",
50
+ };
51
+
52
+ const MODES = {
53
+ o: "owner",
54
+ h: "admin",
55
+ v: "participant",
56
+ };
57
+
58
+ function getNickFromServer(server) {
59
+ return server.split(/^:/)[1].split("!")[0];
60
+ }
61
+
62
+ export class IrcToActivityStreams {
63
+ constructor(cfg) {
64
+ const config = cfg || {};
65
+ this.server = config.server;
66
+ this.events = new events.EventEmitter();
67
+ this.__buffer = {};
68
+ this.__buffer[NAMES] = {};
69
+ }
70
+
71
+ input(payload) {
72
+ log(payload);
73
+ if (typeof payload !== "string") {
74
+ log("unable to process incoming message as it was not a string.");
75
+ return false;
76
+ }
77
+ if (payload.length < 3) {
78
+ log("unable to process incoming string, length smaller than 3.");
79
+ return false;
80
+ }
81
+ const incoming = payload.trim();
82
+ const [metadata, content] = incoming.split(" :");
83
+ const [server, code, pos1, pos2, pos3, ...msg] = metadata.split(" ");
84
+ const channel =
85
+ typeof pos1 === "string" && pos1.startsWith("#")
86
+ ? pos1
87
+ : typeof pos2 === "string" && pos2.startsWith("#")
88
+ ? pos2
89
+ : typeof pos3 === "string" && pos3.startsWith("#")
90
+ ? pos3
91
+ : undefined;
92
+ if (metadata === PING) {
93
+ this.events.emit(EVENT_PING, `${Date.now()}`);
94
+ return true;
95
+ }
96
+ log(
97
+ `[${code}] server: ${server} channel: ${channel} 1: ${pos1}, 2: ${pos2}, 3: ${pos3}. content: `,
98
+ content,
99
+ );
100
+ this.__processIRCCodes(
101
+ code,
102
+ server,
103
+ channel,
104
+ pos1,
105
+ pos2,
106
+ pos3,
107
+ content,
108
+ msg,
109
+ incoming,
110
+ );
111
+ }
112
+
113
+ __processIRCCodes(
114
+ code,
115
+ server,
116
+ channel,
117
+ pos1,
118
+ pos2,
119
+ pos3,
120
+ content,
121
+ msg,
122
+ incoming,
123
+ ) {
124
+ const ase = new ASEmitter(this.events, this.server);
125
+ let nick;
126
+ let type;
127
+ let role;
128
+
129
+ switch (code) {
130
+ /** */
131
+ case ERR_CHAN_PRIVS:
132
+ case ERR_NOT_INVITED:
133
+ case ERR_BADMODE:
134
+ case ERR_INVITE_ONLY:
135
+ case ERR_BANNED:
136
+ case ERR_BADKEY:
137
+ case ERR_BADMASK:
138
+ case ERR_NOCHANMODES:
139
+ case ERR_BANLISTFULL:
140
+ ase.channelError(channel, pos1, content);
141
+ break;
142
+
143
+ /** */
144
+ case ERR_NICK_IN_USE: // nick conflict
145
+ case ERR_BAD_NICK:
146
+ ase.serviceError(pos2, content);
147
+ break;
148
+
149
+ /** */
150
+ case ERR_NO_CHANNEL: // no such channel
151
+ ase.joinError(pos2);
152
+ break;
153
+
154
+ /** */
155
+ case ERR_TEMP_UNAVAIL: // nick conflict
156
+ ase.nickError(pos2, content);
157
+ break;
158
+
159
+ /** */
160
+ case JOIN: // room join
161
+ ase.joinRoom(channel, getNickFromServer(server));
162
+ break;
163
+
164
+ // custom event indicating a channel mode has been updated, used to re-query user or channel
165
+ case MODE: {
166
+ const user_mode = pos2 || content;
167
+ if (!channel) {
168
+ break;
169
+ } // don't handle cases with no channel defined
170
+ if (!pos3) {
171
+ break;
172
+ } // we need target user
173
+ role = MODES[user_mode[1]] || "member";
174
+ type = "add";
175
+ if (user_mode[0] === "-") {
176
+ type = "remove";
177
+ }
178
+ ase.role(type, getNickFromServer(server), pos3, role, channel);
179
+ break;
180
+ }
181
+
182
+ /** */
183
+ case MOTD: // MOTD
184
+ if (!this.__buffer[MOTD]) {
185
+ this.__buffer[MOTD] = {
186
+ context: "irc",
187
+ type: "update",
188
+ actor: {
189
+ type: "service",
190
+ id: this.server,
191
+ name: this.server,
192
+ },
193
+ object: {
194
+ type: "topic",
195
+ content: content,
196
+ },
197
+ };
198
+ } else {
199
+ this.__buffer[MOTD].object.content += ` ${content}`;
200
+ }
201
+ break;
202
+ case MOTD_END: // end of MOTD
203
+ if (!this.__buffer[MOTD]) {
204
+ break;
205
+ }
206
+ ase.emitEvent(EVENT_INCOMING, this.__buffer[MOTD]);
207
+ delete this.__buffer[MOTD];
208
+ break;
209
+
210
+ /** */
211
+ case NAMES: // user list
212
+ for (const entry of content.split(" ")) {
213
+ role = "member";
214
+ let username = entry;
215
+ if (ROLE[entry[0]]) {
216
+ username = entry.substr(1);
217
+ role = ROLE[entry[0]];
218
+ }
219
+ ase.presence(username, role, channel);
220
+ }
221
+ break;
222
+
223
+ /** */
224
+ case NICK: // nick change
225
+ // log(`- 2 nick: ${nick} from content: ${content}`);
226
+ ase.nickChange(getNickFromServer(server), content);
227
+ break;
228
+
229
+ /** */
230
+ case NOTICE: // notice
231
+ ase.notice(pos1, content);
232
+ break;
233
+
234
+ /** */
235
+ case PART: // leaving
236
+ ase.userPart(channel, getNickFromServer(server));
237
+ break;
238
+
239
+ /** */
240
+ case PONG: // ping response received
241
+ this.events.emit(EVENT_PONG, `${Date.now()}`);
242
+ break;
243
+
244
+ /** */
245
+ case PRIVMSG: // msg
246
+ ase.privMsg(getNickFromServer(server), pos1, content);
247
+ break;
248
+
249
+ /** */
250
+ case QUIT: // quit user
251
+ ase.userQuit(getNickFromServer(server));
252
+ break;
253
+
254
+ /** */
255
+ case TOPIC_CHANGE: // topic changed now
256
+ ase.topicChange(channel, getNickFromServer(server), content);
257
+ break;
258
+
259
+ /** */
260
+ case TOPIC_IS: // topic currently set to
261
+ this.__buffer[TOPIC_IS] = {
262
+ context: "irc",
263
+ type: "update",
264
+ actor: undefined,
265
+ target: {
266
+ type: "room",
267
+ id: `${this.server}/${channel}`,
268
+ name: channel,
269
+ },
270
+ object: {
271
+ type: "topic",
272
+ content: content,
273
+ },
274
+ };
275
+ break;
276
+ case TOPIC_SET_BY: // current topic set by
277
+ if (!this.__buffer[TOPIC_IS]) {
278
+ break;
279
+ }
280
+ nick = pos3.split("!")[0];
281
+ this.__buffer[TOPIC_IS].actor = {
282
+ type: "person",
283
+ id: `${nick}@${this.server}`,
284
+ name: nick,
285
+ };
286
+ this.__buffer[TOPIC_IS].published = msg[0];
287
+ ase.emitEvent(EVENT_INCOMING, this.__buffer[TOPIC_IS]);
288
+ delete this.__buffer[TOPIC_IS];
289
+ break;
290
+
291
+ /** */
292
+ case WHO:
293
+ case WHO_OLD:
294
+ nick = msg[3].length <= 2 ? msg[2] : msg[3];
295
+ if (nick === "undefined") {
296
+ break;
297
+ }
298
+ role = MODES[pos2[1]] || "member";
299
+ ase.presence(nick, role, channel);
300
+ break;
301
+
302
+ /** */
303
+ default:
304
+ this.events.emit(EVENT_UNPROCESSED, incoming);
305
+ break;
306
+ }
307
+ }
308
+ }
@@ -0,0 +1,86 @@
1
+ :hitchcock.freenode.net 376 hyper_slvrbckt :End of /MOTD command.
2
+ :hitchcock.freenode.net 372 hyper_slvrbckt :- on the https://freenode.live website for our call for volunteers and call for
3
+ :hitchcock.freenode.net 372 hyper_slvrbckt :- participation. If you are interested in sponsoring next year's event, please
4
+ :hitchcock.freenode.net 372 hyper_slvrbckt :- send us an e-mail to sponsor@freenode.live
5
+ :hitchcock.freenode.net 372 hyper_slvrbckt :-
6
+ :hitchcock.freenode.net 372 hyper_slvrbckt :- Thank you for using freenode!
7
+ :hitchcock.freenode.net 372 hyper_slvrbckt :-
8
+ :hitchcock.freenode.net 372 hyper_slvrbckt :-
9
+ :hitchcock.freenode.net 376 hyper_slvrbckt :End of /MOTD command.
10
+ :hitchcock.freenode.net 315 hyper_slvrbckt undefined :End of /WHO list.
11
+ :hitchcock.freenode.net 353 hyper_slvrbckt @ #kosmos-random :hyper_slvrbckt gregkare hal8000
12
+ :hitchcock.freenode.net 366 hyper_slvrbckt #kosmos-random :End of /NAMES list.
13
+ :hitchcock.freenode.net 352 hyper_slvrbckt #kosmos-random ~hyper_slv 154.65.34.210 hitchcock.freenode.net hyper_slvrbckt H :0 hyper_slvrbckt
14
+ :adams.freenode.net 372 hyper_slvrbckt :-
15
+ :adams.freenode.net 372 hyper_slvrbckt :-
16
+ :adams.freenode.net 376 hyper_slvrbckt :End of /MOTD command.
17
+ :bob MODE hyper_slvrbckt :+i
18
+ :alice MODE #Finnish +o Kilroy
19
+ :bob MODE #room_a +v alice
20
+ :alice MODE #room_b +h bob
21
+ PING :moon.freenode.net
22
+ :adams.freenode.net 352 hyper_slvrbckt * ~undefined 75-140-253-250.dhcp.ftwo.tx.charter.com livingstone.freenode.net undefined H :0 undefined
23
+ :adams.freenode.net 315 hyper_slvrbckt undefined :End of /WHO list.
24
+ :adams.freenode.net 352 hyper_slvrbckt #kosmos-random ~hyper_slv 154.65.34.210 adams.freenode.net hyper_slvrbckt H :0 hyper_slvrbckt
25
+ :adams.freenode.net 315 hyper_slvrbckt hyper_slvrbckt :End of /WHO list.
26
+ :hitchcock.freenode.net 366 hyper_slvrbckt #kosmos-random :End of /NAMES list.
27
+ :karatkievich.freenode.net PONG karatkievich.freenode.net :LAG1516614421150
28
+ :jarlaxl_!~jarlaxl@user123.intek.cz QUIT :Client Quit
29
+ :karatkievich.freenode.net 403 slvrbckt sdfsdfsdfsdfsdf :No such channel
30
+ :slvrbckt!~slvtbckt@154.65.34.210 PART #debian :"Leaving"
31
+ :karatkievich.freenode.net PONG karatkievich.freenode.net :LAG1516615441149
32
+ :slvrbckt!~slvtbckt@154.65.34.210 NICK :donkey2018
33
+ PING :moon.freenode.net
34
+ :donkey2018!~slvtbckt@154.65.34.210 NICK :slvrbckt
35
+ :weber.freenode.net 333 hyper_slvrbckt #kosmos-random lio17!~lio17@ns350827.ip-37-187-174.eu 1516730003
36
+ :karatkievich.freenode.net PONG karatkievich.freenode.net :1516615578917
37
+ :karatkievich.freenode.net 433 slvrbckt nkj :Nickname is already in use.
38
+ :hyper_slvrbckt!~hyper_slv@154.65.34.210 PRIVMSG #kosmos-random :-ssssssss
39
+ :lio17!~lio17@ns350827.ip-37-187-174.eu TOPIC #kosmos-random :testing123
40
+ :card.freenode.net 482 slvrbckt #kosmos-random :You're not a channel operator
41
+ :weber.freenode.net 332 hyper_slvrbckt #kosmos-random :no longer boating in senegal
42
+ :weber.freenode.net 333 hyper_slvrbckt #kosmos-random lio17!~lio17@ns350827.ip-37-187-174.eu 1516730003
43
+ :raucao!~raucao@5.148.180.93 PRIVMSG #kosmos-random :+ACTION is thinking about sending someone to get b33rz
44
+ :verne.freenode.net 255 hyper_slvrbckt :I have 4681 clients and 3 servers
45
+ :verne.freenode.net 265 hyper_slvrbckt 4681 7978 :Current local users 4681, max 7978
46
+ :verne.freenode.net 266 hyper_slvrbckt 89501 97718 :Current global users 89501, max 97718
47
+ :verne.freenode.net 250 hyper_slvrbckt :Highest connection count: 7980 (7978 clients) (4267730 connections received)
48
+ :verne.freenode.net 375 hyper_slvrbckt :- verne.freenode.net Message of the Day -
49
+ :leguin.freenode.net 254 hyper_slvrbckt 50699 :channels formed
50
+ :leguin.freenode.net 255 hyper_slvrbckt :I have 3642 clients and 1 servers
51
+ :leguin.freenode.net 265 hyper_slvrbckt 3642 3657 :Current local users 3642, max 3657
52
+ :leguin.freenode.net 266 hyper_slvrbckt 89518 91820 :Current global users 89518, max 91820
53
+ :leguin.freenode.net 250 hyper_slvrbckt :Highest connection count: 3658 (3657 clients) (32451 connections received)
54
+ :leguin.freenode.net 375 hyper_slvrbckt :- leguin.freenode.net Message of the Day -
55
+ :card.freenode.net 352 hyper_slvrbckt #kosmos-random ~hyper_slv cell01228.qcell.gm card.freenode.net hyper_slvrbckt H :0 hyper_slvrbckt +311ms
56
+ :card.freenode.net 315 hyper_slvrbckt hyper_slvrbckt :End of /WHO list.
57
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~slvtbckt cell01228.qcell.gm leguin.freenode.net slvrbckt H slvrbckt :realname
58
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~lio17 ns350827.ip-37-187-174.eu niven.freenode.net lio17 H lio17 :bumi
59
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos silverbuck gateway/shell/matrix.org/x-kwavgootllgoshlq sinisalo.freenode.net M-silverbucket H 0 :@silverbucket:matrix.org
60
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~nodebot static.171.39.76.144.clients.your-server.de leguin.freenode.net botka1 H 0 :nodeJS IRC client
61
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos sid186430 gateway/web/irccloud.com/x-ztwqqtwigkgoieax kornbluth.freenode.net derbumi H derbumi :bumi
62
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ChanServ services. services. ChanServ H@ 0 :Channel Services
63
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~bkero osuosl/staff/bkero tolkien.freenode.net bkero- H bkero :bkero
64
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~galfert f00bar.de orwell.freenode.net galfert H galfert :galfert
65
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~raucao 5.148.180.93 hitchcock.freenode.net raucao G binbasti :Basti
66
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~nodebot static.171.39.76.144.clients.your-server.de sinisalo.freenode.net hal8000 H hal8000 :nodeJS IRC client
67
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~kare 2a03:b0c0:3:d0::15d:6001 livingstone.freenode.net gregkare H gregkare :kare
68
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos ~bkero osuosl/staff/bkero hitchcock.freenode.net bkero H bkero :bkero
69
+ :leguin.freenode.net 354 slvrbckt 152 #kosmos bumimatrix gateway/shell/matrix.org/x-aeqgcnylcgbinlmx roddenberry.freenode.net bumi[m] H 0 :@bumi:matrix.org
70
+ :leguin.freenode.net 315 slvrbckt #kosmos :End of /WHO list.
71
+ :card.freenode.net 352 hyper_slvrbckt #kosmos-random ~hyper_slv cell01228.qcell.gm card.freenode.net hyper_slvrbckt H :0 hyper_slvrbckt +311ms
72
+ :card.freenode.net 315 hyper_slvrbckt hyper_slvrbckt :End of /WHO list.
73
+ :moon.freenode.net 473 hyper_slvrbckt #freenode-sponsors :Cannot join channel (+i) - you must be invited
74
+ :weber.freenode.net 482 slvrbckt #debian :You're not a channel operator
75
+ :NickServ!NickServ@services. NOTICE boo :This nickname is registered. Please choose a different nickname, or identify via /msg NickServ identify <password>.
76
+ :NickServ!NickServ@services. NOTICE boo :You have 30 seconds to identify to your nickname before it is changed.
77
+ :NickServ!NickServ@services. NOTICE boo :You failed to identify in time for the nickname boo
78
+ :asimov.freenode.net 437 sh-mhJLD boo :Nick/channel is temporarily unavailable
79
+ :wilhelm.freenode.net 433 sh-4a3LB slvrbckt :Nickname is already in use.
80
+ :sh-WjwOE!~sh-WjwOE@194.228.76.203 NICK :woooo
81
+ :SaslServ!SaslServ@services.libera.chat NOTICE slvrbckt :Last login from: ~slvrbckt@localhost on Feb 09 18:45:19 2022 +0000.
82
+ :myuser!~myuser@2a02:8308:7080:4100:41fa:f0ec:594e:771f JOIN #kosmos-random slvrbckt :myuser
83
+ :tungsten.libera.chat 353 myuser @ #kosmos-random :myuser @botka foouser
84
+ :tungsten.libera.chat 366 myuser #kosmos-random :End of /NAMES list.
85
+ :tungsten.libera.chat 324 myuser #kosmos-random +Cnst
86
+ :tungsten.libera.chat 329 myuser #kosmos-random 1642793393