Redundant MediaMessages caching
[KiwiIRC.git] / server / irc / commands.js
CommitLineData
f9ff7686 1var _ = require('lodash');
a8bf3ea4
JA
2
3var irc_numerics = {
4 RPL_WELCOME: '001',
5 RPL_MYINFO: '004',
6 RPL_ISUPPORT: '005',
cea1f25b
D
7 RPL_MAPMORE: '006',
8 RPL_MAPEND: '007',
28ce8b75
D
9 RPL_STATSCONN: '250',
10 RPL_LUSERCLIENT: '251',
11 RPL_LUSEROP: '252',
12 RPL_LUSERUNKNOWN: '253',
13 RPL_LUSERCHANNELS: '254',
14 RPL_LUSERME: '255',
15 RPL_LOCALUSERS: '265',
16 RPL_GLOBALUSERS: '266',
f701d5ba 17 RPL_AWAY: '301',
f3766a0b 18 RPL_WHOISREGNICK: '307',
a8bf3ea4
JA
19 RPL_WHOISUSER: '311',
20 RPL_WHOISSERVER: '312',
21 RPL_WHOISOPERATOR: '313',
22 RPL_WHOISIDLE: '317',
23 RPL_ENDOFWHOIS: '318',
24 RPL_WHOISCHANNELS: '319',
25 RPL_LISTSTART: '321',
26 RPL_LIST: '322',
27 RPL_LISTEND: '323',
28 RPL_NOTOPIC: '331',
29 RPL_TOPIC: '332',
30 RPL_TOPICWHOTIME: '333',
31 RPL_NAMEREPLY: '353',
cea1f25b
D
32 RPL_LINKS: '364',
33 RPL_ENDOFLINKS: '365',
a8bf3ea4
JA
34 RPL_ENDOFNAMES: '366',
35 RPL_BANLIST: '367',
36 RPL_ENDOFBANLIST: '368',
37 RPL_MOTD: '372',
38 RPL_MOTDSTART: '375',
39 RPL_ENDOFMOTD: '376',
40 RPL_WHOISMODES: '379',
41 ERR_NOSUCHNICK: '401',
42 ERR_CANNOTSENDTOCHAN: '404',
43 ERR_TOOMANYCHANNELS: '405',
cea1f25b
D
44 ERR_UNKNOWNCOMMAND: '421',
45 ERR_NOMOTD: '422',
a8bf3ea4
JA
46 ERR_NICKNAMEINUSE: '433',
47 ERR_USERNOTINCHANNEL: '441',
48 ERR_NOTONCHANNEL: '442',
ebe178d6 49 ERR_PASSWDMISMATCH: '464',
a8bf3ea4
JA
50 ERR_NOTREGISTERED: '451',
51 ERR_LINKCHANNEL: '470',
52 ERR_CHANNELISFULL: '471',
53 ERR_INVITEONLYCHAN: '473',
54 ERR_BANNEDFROMCHAN: '474',
55 ERR_BADCHANNELKEY: '475',
cea1f25b 56 ERR_NOPRIVILEGES: '481',
a8bf3ea4 57 ERR_CHANOPRIVSNEEDED: '482',
7dfe47c6
JA
58 RPL_STARTTLS: '670',
59 RPL_SASLAUTHENTICATED: '900',
60 RPL_SASLLOGGEDIN: '903',
61 ERR_SASLNOTAUTHORISED: '904',
7dfe47c6
JA
62 ERR_SASLABORTED: '906',
63 ERR_SASLALREADYAUTHED: '907'
64
a8bf3ea4
JA
65};
66
67
2a8e95d1 68var IrcCommands = function (irc_connection, con_num, client) {
a8bf3ea4
JA
69 this.irc_connection = irc_connection;
70 this.con_num = con_num;
71 this.client = client;
72};
2a8e95d1 73module.exports = IrcCommands;
a8bf3ea4 74
2a8e95d1 75IrcCommands.prototype.bindEvents = function () {
a8bf3ea4 76 var that = this;
2a8e95d1 77
a8bf3ea4
JA
78 _.each(listeners, function (listener, command) {
79 var s = command.substr(0, 4);
80 if ((s === 'RPL_') || (s === 'ERR_')) {
81 command = irc_numerics[command];
82 }
83 that.irc_connection.on('irc_' + command, function () {
84 listener.apply(that, arguments);
85 });
86 });
87};
88
c08717da
D
89IrcCommands.prototype.dispose = function () {
90 this.removeAllListeners();
91};
92
2a8e95d1
D
93
94
a8bf3ea4 95var listeners = {
a49e0dcf
JA
96 'RPL_WELCOME': function (command) {
97 var nick = command.params[0];
98 this.irc_connection.registered = true;
99 this.cap_negotation = false;
d9285da9 100 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' connect', {
1cc056b8
JA
101 nick: nick
102 });
a49e0dcf
JA
103 },
104 'RPL_ISUPPORT': function (command) {
105 var options, i, option, matches, j;
106 options = command.params;
107 for (i = 1; i < options.length; i++) {
108 option = options[i].split("=", 2);
109 option[0] = option[0].toUpperCase();
110 this.irc_connection.options[option[0]] = (typeof option[1] !== 'undefined') ? option[1] : true;
111 if (_.include(['NETWORK', 'PREFIX', 'CHANTYPES', 'CHANMODES', 'NAMESX'], option[0])) {
112 if (option[0] === 'PREFIX') {
113 matches = /\(([^)]*)\)(.*)/.exec(option[1]);
114 if ((matches) && (matches.length === 3)) {
115 this.irc_connection.options.PREFIX = [];
116 for (j = 0; j < matches[2].length; j++) {
117 this.irc_connection.options.PREFIX.push({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)});
a8bf3ea4
JA
118 }
119 }
a49e0dcf
JA
120 } else if (option[0] === 'CHANTYPES') {
121 this.irc_connection.options.CHANTYPES = this.irc_connection.options.CHANTYPES.split('');
122 } else if (option[0] === 'CHANMODES') {
123 this.irc_connection.options.CHANMODES = option[1].split(',');
124 } else if ((option[0] === 'NAMESX') && (!_.contains(this.irc_connection.cap.enabled, 'multi-prefix'))) {
125 this.irc_connection.write('PROTOCTL NAMESX');
a8bf3ea4 126 }
a49e0dcf
JA
127 }
128 }
d9285da9 129 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' options', {
1cc056b8
JA
130 options: this.irc_connection.options,
131 cap: this.irc_connection.cap.enabled
132 });
a49e0dcf
JA
133 },
134 'RPL_ENDOFWHOIS': function (command) {
d9285da9 135 this.irc_connection.emit('user ' + command.params[1] + ' endofwhois', {
692163ca
JA
136 nick: command.params[1],
137 msg: command.trailing
138 });
a49e0dcf 139 },
f701d5ba
D
140 'RPL_AWAY': function (command) {
141 this.irc_connection.emit('user ' + command.params[1] + ' whoisaway', {
142 nick: command.params[1],
143 reason: command.trailing
144 });
145 },
a49e0dcf 146 'RPL_WHOISUSER': function (command) {
d9285da9 147 this.irc_connection.emit('user ' + command.params[1] + ' whoisuser', {
692163ca
JA
148 nick: command.params[1],
149 ident: command.params[2],
150 host: command.params[3],
151 msg: command.trailing
152 });
a49e0dcf
JA
153 },
154 'RPL_WHOISSERVER': function (command) {
d9285da9 155 this.irc_connection.emit('user ' + command.params[1] + ' whoisserver', {
692163ca
JA
156 nick: command.params[1],
157 irc_server: command.params[2]
158 });
a49e0dcf
JA
159 },
160 'RPL_WHOISOPERATOR': function (command) {
d9285da9 161 this.irc_connection.emit('user ' + command.params[1] + ' whoisoperator', {
692163ca
JA
162 nick: command.params[1],
163 msg: command.trailing
164 });
a49e0dcf
JA
165 },
166 'RPL_WHOISCHANNELS': function (command) {
d9285da9 167 this.irc_connection.emit('user ' + command.params[1] + ' whoischannels', {
692163ca 168 nick: command.params[1],
cefa0900 169 chans: command.trailing
692163ca 170 });
a49e0dcf
JA
171 },
172 'RPL_WHOISMODES': function (command) {
d9285da9 173 this.irc_connection.emit('user ' + command.params[1] + ' whoismodes', {
692163ca
JA
174 nick: command.params[1],
175 msg: command.trailing
176 });
a49e0dcf
JA
177 },
178 'RPL_WHOISIDLE': function (command) {
d9285da9 179 this.irc_connection.emit('user ' + command.params[1] + ' whoisidle', {
692163ca
JA
180 nick: command.params[1],
181 idle: command.params[2],
182 logon: command.params[3] || undefined
183 });
a49e0dcf
JA
184 },
185 'RPL_WHOISREGNICK': function (command) {
d9285da9 186 this.irc_connection.emit('user ' + command.params[1] + ' whoisregnick', {
692163ca
JA
187 nick: command.params[1],
188 msg: command.trailing
189 });
a49e0dcf
JA
190 },
191 'RPL_LISTSTART': function (command) {
d9285da9 192 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_start', {});
a49e0dcf
JA
193 },
194 'RPL_LISTEND': function (command) {
d9285da9 195 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_end', {});
a49e0dcf
JA
196 },
197 'RPL_LIST': function (command) {
d9285da9 198 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_channel', {
fb1b18bc 199 channel: command.params[1],
25edd441 200 num_users: parseInt(command.params[2], 10),
fb1b18bc
JA
201 topic: command.trailing
202 });
a49e0dcf
JA
203 },
204 'RPL_MOTD': function (command) {
d9285da9 205 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd', {
fb1b18bc 206 motd: command.trailing + '\n'
1cc056b8 207 });
a49e0dcf
JA
208 },
209 'RPL_MOTDSTART': function (command) {
d9285da9 210 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd_start', {});
a49e0dcf
JA
211 },
212 'RPL_ENDOFMOTD': function (command) {
d9285da9 213 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd_end', {});
a49e0dcf
JA
214 },
215 'RPL_NAMEREPLY': function (command) {
216 var members = command.trailing.split(' ');
217 var member_list = [];
218 var that = this;
219 var i = 0;
220 _.each(members, function (member) {
221 var j, k, modes = [];
30b4d43a
D
222
223 // Make sure we have some prefixes already
224 if (that.irc_connection.options.PREFIX) {
225 for (j = 0; j < member.length; j++) {
226 for (k = 0; k < that.irc_connection.options.PREFIX.length; k++) {
227 if (member.charAt(j) === that.irc_connection.options.PREFIX[k].symbol) {
228 modes.push(that.irc_connection.options.PREFIX[k].mode);
229 i++;
230 }
a8bf3ea4 231 }
a8bf3ea4 232 }
a49e0dcf 233 }
30b4d43a 234
a49e0dcf 235 member_list.push({nick: member, modes: modes});
a49e0dcf 236 });
e2752476 237
d9285da9 238 this.irc_connection.emit('channel ' + command.params[2] + ' userlist', {
e2752476
D
239 users: member_list,
240 channel: command.params[2]
241 });
a49e0dcf 242 },
e2752476
D
243
244
a49e0dcf 245 'RPL_ENDOFNAMES': function (command) {
d9285da9 246 this.irc_connection.emit('channel ' + command.params[1] + ' userlist_end', {
e2752476
D
247 channel: command.params[1]
248 });
a49e0dcf 249 },
e2752476
D
250
251
a49e0dcf 252 'RPL_BANLIST': function (command) {
d9285da9 253 this.irc_connection.emit('channel ' + command.params[1] + ' banlist', {
059f4918
JA
254 channel: command.params[1],
255 banned: command.params[2],
256 banned_by: command.params[3],
257 banned_at: command.params[4]
258 });
a49e0dcf
JA
259 },
260 'RPL_ENDOFBANLIST': function (command) {
d9285da9 261 this.irc_connection.emit('channel ' + command.params[1] + ' banlist_end', {
aa22caa9 262 channel: command.params[1]
059f4918 263 });
a49e0dcf
JA
264 },
265 'RPL_TOPIC': function (command) {
d9285da9 266 this.irc_connection.emit('channel ' + command.params[1] + ' topic', {
059f4918
JA
267 channel: command.params[1],
268 topic: command.trailing
269 });
a49e0dcf
JA
270 },
271 'RPL_NOTOPIC': function (command) {
d9285da9 272 this.irc_connection.emit('channel ' + command.params[1] + ' topic', {
059f4918
JA
273 channel: command.params[1],
274 topic: ''
275 });
a49e0dcf
JA
276 },
277 'RPL_TOPICWHOTIME': function (command) {
d9285da9 278 this.irc_connection.emit('channel ' + command.params[1] + ' topicsetby', {
059f4918
JA
279 nick: command.params[2],
280 channel: command.params[1],
281 when: command.params[3]
282 });
a49e0dcf
JA
283 },
284 'PING': function (command) {
285 this.irc_connection.write('PONG ' + command.trailing);
286 },
e2752476
D
287
288
a49e0dcf
JA
289 'JOIN': function (command) {
290 var channel;
291 if (typeof command.trailing === 'string' && command.trailing !== '') {
292 channel = command.trailing;
293 } else if (typeof command.params[0] === 'string' && command.params[0] !== '') {
294 channel = command.params[0];
295 }
296
d9285da9 297 this.irc_connection.emit('channel ' + channel + ' join', {
e2752476
D
298 nick: command.nick,
299 ident: command.ident,
300 hostname: command.hostname,
301 channel: channel
302 });
a49e0dcf 303 },
e2752476
D
304
305
a49e0dcf 306 'PART': function (command) {
d9285da9 307 this.irc_connection.emit('channel ' + command.params[0] + ' part', {
e2752476
D
308 nick: command.nick,
309 ident: command.ident,
310 hostname: command.hostname,
311 channel: command.params[0],
312 message: command.trailing
313 });
a49e0dcf 314 },
e2752476
D
315
316
a49e0dcf 317 'KICK': function (command) {
d9285da9 318 this.irc_connection.emit('channel ' + command.params[0] + ' kick', {
e2752476
D
319 kicked: command.params[1],
320 nick: command.nick,
321 ident: command.ident,
322 hostname: command.hostname,
323 channel: command.params[0],
324 message: command.trailing
325 });
a49e0dcf 326 },
e2752476
D
327
328
a49e0dcf 329 'QUIT': function (command) {
d9285da9 330 this.irc_connection.emit('user ' + command.nick + ' quit', {
e2752476
D
331 nick: command.nick,
332 ident: command.ident,
333 hostname: command.hostname,
334 message: command.trailing
335 });
a49e0dcf 336 },
e2752476
D
337
338
a49e0dcf 339 'NOTICE': function (command) {
e2752476
D
340 var namespace;
341
a49e0dcf
JA
342 if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
343 // It's a CTCP response
e2752476 344 namespace = (command.params[0] == this.irc_connection.nick) ? 'user' : 'channel';
d9285da9 345 this.irc_connection.emit(namespace + ' ' + command.params[0] + ' ctcp_response', {
e2752476
D
346 nick: command.nick,
347 ident: command.ident,
348 hostname: command.hostname,
349 channel: command.params[0],
350 msg: command.trailing.substr(1, command.trailing.length - 2)
351 });
a49e0dcf 352 } else {
e2752476 353 namespace = (command.params[0] == this.irc_connection.nick) ? 'user' : 'channel';
d9285da9 354 this.irc_connection.emit(namespace + ' ' + command.params[0] + ' notice', {
e2752476
D
355 nick: command.nick,
356 ident: command.ident,
357 hostname: command.hostname,
358 target: command.params[0],
359 msg: command.trailing
360 });
a49e0dcf
JA
361 }
362 },
363 'NICK': function (command) {
d9285da9 364 this.irc_connection.emit('user ' + command.nick + ' nick', {
692163ca
JA
365 nick: command.nick,
366 ident: command.ident,
367 hostname: command.hostname,
368 newnick: command.trailing || command.params[0]
369 });
a49e0dcf
JA
370 },
371 'TOPIC': function (command) {
30b4d43a
D
372 // If we don't have an associated channel, no need to continue
373 if (!command.params[0]) return;
374
375 var channel = command.params[0],
376 topic = command.trailing || '';
377
d9285da9 378 this.irc_connection.emit('channel ' + channel + ' topic', {
f4ec5774
D
379 nick: command.nick,
380 channel: channel,
381 topic: topic
382 });
a49e0dcf 383 },
d9285da9 384 'MODE': function (command) {
30b4d43a
D
385 var chanmodes = this.irc_connection.options.CHANMODES || [],
386 prefixes = this.irc_connection.options.PREFIX || [],
387 always_param = (chanmodes[0] || '').concat((chanmodes[1] || '')),
a49e0dcf 388 modes = [],
a7973dfb 389 has_param, i, j, add, event;
a49e0dcf
JA
390
391 prefixes = _.reduce(prefixes, function (list, prefix) {
392 list.push(prefix.mode);
393 return list;
394 }, []);
395 always_param = always_param.split('').concat(prefixes);
396
397 has_param = function (mode, add) {
398 if (_.find(always_param, function (m) {
399 return m === mode;
400 })) {
401 return true;
30b4d43a 402 } else if (add && _.find((chanmodes[2] || '').split(''), function (m) {
a49e0dcf
JA
403 return m === mode;
404 })) {
405 return true;
406 } else {
407 return false;
408 }
409 };
410
411 if (!command.params[1]) {
412 command.params[1] = command.trailing;
413 }
414 j = 0;
415 for (i = 0; i < command.params[1].length; i++) {
416 switch (command.params[1][i]) {
417 case '+':
418 add = true;
419 break;
420 case '-':
421 add = false;
422 break;
423 default:
424 if (has_param(command.params[1][i], add)) {
425 modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: command.params[2 + j]});
426 j++;
703d2778 427 } else {
a49e0dcf 428 modes.push({mode: (add ? '+' : '-') + command.params[1][i], param: null});
703d2778 429 }
a49e0dcf
JA
430 }
431 }
432
d9285da9 433 event = (_.contains(this.irc_connection.options.CHANTYPES, command.params[0][0]) ? 'channel ' : 'user ') + command.params[0] + ' mode';
a7973dfb
JA
434
435 this.irc_connection.emit(event, {
a49e0dcf
JA
436 target: command.params[0],
437 nick: command.nick || command.prefix || '',
438 modes: modes
439 });
440 },
441 'PRIVMSG': function (command) {
442 var tmp, namespace;
443 if ((command.trailing.charAt(0) === String.fromCharCode(1)) && (command.trailing.charAt(command.trailing.length - 1) === String.fromCharCode(1))) {
444 //CTCP request
445 if (command.trailing.substr(1, 6) === 'ACTION') {
446 this.client.sendIrcCommand('action', {server: this.con_num, nick: command.nick, ident: command.ident, hostname: command.hostname, channel: command.params[0], msg: command.trailing.substr(7, command.trailing.length - 2)});
447 } else if (command.trailing.substr(1, 4) === 'KIWI') {
448 tmp = command.trailing.substr(6, command.trailing.length - 2);
449 namespace = tmp.split(' ', 1)[0];
450 this.client.sendIrcCommand('kiwi', {server: this.con_num, namespace: namespace, data: tmp.substr(namespace.length + 1)});
451 } else if (command.trailing.substr(1, 7) === 'VERSION') {
452 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'VERSION KiwiIRC' + String.fromCharCode(1));
b39bb331
D
453 } else if (command.trailing.substr(1, 6) === 'SOURCE') {
454 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'SOURCE http://www.kiwiirc.com/' + String.fromCharCode(1));
455 } else if (command.trailing.substr(1, 10) === 'CLIENTINFO') {
456 this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'CLIENTINFO SOURCE VERSION TIME' + String.fromCharCode(1));
a49e0dcf 457 } else {
7d969e05 458 namespace = (command.params[0].toLowerCase() == this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel';
d9285da9 459 this.irc_connection.emit(namespace + ' ' + command.nick + ' ctcp_request', {
b39bb331
D
460 nick: command.nick,
461 ident: command.ident,
462 hostname: command.hostname,
463 target: command.params[0],
464 type: (command.trailing.substr(1, command.trailing.length - 2).split(' ') || [null])[0],
465 msg: command.trailing.substr(1, command.trailing.length - 2)
466 });
a49e0dcf
JA
467 }
468 } else {
e2752476 469 // A message to a user (private message) or to a channel?
d9285da9
JA
470 namespace = (command.params[0] === this.irc_connection.nick) ? 'user ' + command.nick : 'channel ' + command.params[0];
471 this.irc_connection.emit(namespace + ' privmsg', {
ffbbc70f
D
472 nick: command.nick,
473 ident: command.ident,
474 hostname: command.hostname,
475 channel: command.params[0],
476 msg: command.trailing
b09157de 477 });
a49e0dcf
JA
478 }
479 },
480 'CAP': function (command) {
481 // TODO: capability modifiers
482 // i.e. - for disable, ~ for requires ACK, = for sticky
483 var capabilities = command.trailing.replace(/[\-~=]/, '').split(' ');
484 var request;
259d9b96
JA
485
486 // Which capabilities we want to enable
a49e0dcf 487 var want = ['multi-prefix', 'away-notify'];
259d9b96 488
a49e0dcf
JA
489 if (this.irc_connection.password) {
490 want.push('sasl');
491 }
259d9b96 492
a49e0dcf
JA
493 switch (command.params[1]) {
494 case 'LS':
259d9b96 495 // Compute which of the available capabilities we want and request them
a49e0dcf
JA
496 request = _.intersection(capabilities, want);
497 if (request.length > 0) {
498 this.irc_connection.cap.requested = request;
499 this.irc_connection.write('CAP REQ :' + request.join(' '));
500 } else {
501 this.irc_connection.write('CAP END');
502 this.irc_connection.cap_negotation = false;
a8bf3ea4 503 }
a49e0dcf
JA
504 break;
505 case 'ACK':
506 if (capabilities.length > 0) {
259d9b96 507 // Update list of enabled capabilities
a49e0dcf 508 this.irc_connection.cap.enabled = capabilities;
259d9b96 509 // Update list of capabilities we would like to have but that aren't enabled
a49e0dcf 510 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
703d2778 511 }
259d9b96 512 if (this.irc_connection.cap.enabled.length > 0) {
a49e0dcf
JA
513 if (_.contains(this.irc_connection.cap.enabled, 'sasl')) {
514 this.irc_connection.sasl = true;
515 this.irc_connection.write('AUTHENTICATE PLAIN');
a8bf3ea4 516 } else {
a49e0dcf
JA
517 this.irc_connection.write('CAP END');
518 this.irc_connection.cap_negotation = false;
a8bf3ea4 519 }
a8bf3ea4 520 }
a49e0dcf
JA
521 break;
522 case 'NAK':
523 if (capabilities.length > 0) {
524 this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities);
7dfe47c6 525 }
a49e0dcf 526 if (this.irc_connection.cap.requested.length > 0) {
7dfe47c6
JA
527 this.irc_connection.write('CAP END');
528 this.irc_connection.cap_negotation = false;
7dfe47c6 529 }
a49e0dcf
JA
530 break;
531 case 'LIST':
532 // should we do anything here?
533 break;
534 }
535 },
536 'AUTHENTICATE': function (command) {
537 var b = new Buffer(this.irc_connection.nick + "\0" + this.irc_connection.nick + "\0" + this.irc_connection.password, 'utf8');
538 var b64 = b.toString('base64');
539 if (command.params[0] === '+') {
540 while (b64.length >= 400) {
541 this.irc_connection.write('AUTHENTICATE ' + b64.slice(0, 399));
542 b64 = b64.slice(399);
a8bf3ea4 543 }
a49e0dcf
JA
544 if (b64.length > 0) {
545 this.irc_connection.write('AUTHENTICATE ' + b64);
546 } else {
547 this.irc_connection.write('AUTHENTICATE +');
548 }
549 } else {
550 this.irc_connection.write('CAP END');
551 this.irc_connection.cap_negotation = false;
552 }
553 },
554 'AWAY': function (command) {
d9285da9 555 this.irc_connection.emit('user ' + command.nick + ' away', {
692163ca
JA
556 nick: command.nick,
557 msg: command.trailing
558 });
a49e0dcf
JA
559 },
560 'RPL_SASLAUTHENTICATED': function (command) {
561 this.irc_connection.write('CAP END');
562 this.irc_connection.cap_negotation = false;
563 this.irc_connection.sasl = true;
564 },
565 'RPL_SASLLOGGEDIN': function (command) {
566 if (this.irc_connection.cap_negotation === false) {
567 this.irc_connection.write('CAP END');
568 }
569 },
570 'ERR_SASLNOTAUTHORISED': function (command) {
571 this.irc_connection.write('CAP END');
572 this.irc_connection.cap_negotation = false;
573 },
574 'ERR_SASLABORTED': function (command) {
575 this.irc_connection.write('CAP END');
576 this.irc_connection.cap_negotation = false;
577 },
578 'ERR_SASLALREADYAUTHED': function (command) {
579 // noop
580 },
581 'ERROR': function (command) {
d9285da9 582 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' error', {
1cc056b8
JA
583 reason: command.trailing
584 });
a49e0dcf 585 },
ebe178d6 586 ERR_PASSWDMISMATCH: function (command) {
d9285da9 587 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' password_mismatch', {});
ebe178d6 588 },
a49e0dcf 589 ERR_LINKCHANNEL: function (command) {
d9285da9 590 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_redirect', {
1cc056b8
JA
591 from: command.params[1],
592 to: command.params[2]
593 });
a49e0dcf
JA
594 },
595 ERR_NOSUCHNICK: function (command) {
d9285da9 596 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' no_such_nick', {
1cc056b8
JA
597 nick: command.params[1],
598 reason: command.trailing
599 });
a49e0dcf
JA
600 },
601 ERR_CANNOTSENDTOCHAN: function (command) {
d9285da9 602 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' cannot_send_to_chan', {
1cc056b8
JA
603 channel: command.params[1],
604 reason: command.trailing
605 });
a49e0dcf
JA
606 },
607 ERR_TOOMANYCHANNELS: function (command) {
d9285da9 608 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' too_many_channels', {
1cc056b8
JA
609 channel: command.params[1],
610 reason: command.trailing
611 });
a49e0dcf
JA
612 },
613 ERR_USERNOTINCHANNEL: function (command) {
d9285da9 614 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' user_not_in_channel', {
1cc056b8
JA
615 nick: command.params[0],
616 channel: command.params[1],
617 reason: command.trailing
618 });
a49e0dcf
JA
619 },
620 ERR_NOTONCHANNEL: function (command) {
d9285da9 621 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' not_on_channel', {
1cc056b8
JA
622 channel: command.params[1],
623 reason: command.trailing
624 });
a49e0dcf
JA
625 },
626 ERR_CHANNELISFULL: function (command) {
d9285da9 627 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_is_full', {
1cc056b8
JA
628 channel: command.params[1],
629 reason: command.trailing
630 });
a49e0dcf
JA
631 },
632 ERR_INVITEONLYCHAN: function (command) {
d9285da9 633 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' invite_only_channel', {
1cc056b8
JA
634 channel: command.params[1],
635 reason: command.trailing
636 });
a49e0dcf
JA
637 },
638 ERR_BANNEDFROMCHAN: function (command) {
d9285da9 639 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' banned_from_channel', {
1cc056b8
JA
640 channel: command.params[1],
641 reason: command.trailing
642 });
a49e0dcf
JA
643 },
644 ERR_BADCHANNELKEY: function (command) {
d9285da9 645 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' bad_channel_key', {
1cc056b8
JA
646 channel: command.params[1],
647 reason: command.trailing
648 });
a49e0dcf
JA
649 },
650 ERR_CHANOPRIVSNEEDED: function (command) {
d9285da9 651 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' chanop_privs_needed', {
1cc056b8
JA
652 channel: command.params[1],
653 reason: command.trailing
654 });
a49e0dcf
JA
655 },
656 ERR_NICKNAMEINUSE: function (command) {
d9285da9 657 this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' nickname_in_use', {
1cc056b8
JA
658 nick: command.params[1],
659 reason: command.trailing
660 });
a49e0dcf
JA
661 },
662 ERR_NOTREGISTERED: function (command) {
cea1f25b
D
663 },
664
665 RPL_MAPMORE: function (command) {
666 var params = _.clone(command.params);
667 params.shift();
668 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
669 },
670 RPL_MAPEND: function (command) {
671 var params = _.clone(command.params);
672 params.shift();
673 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
674 },
675
676 RPL_LINKS: function (command) {
677 var params = _.clone(command.params);
678 params.shift();
679 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
680 },
681 RPL_ENDOFLINKS: function (command) {
682 var params = _.clone(command.params);
683 params.shift();
684 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
685 },
686
687 ERR_UNKNOWNCOMMAND: function (command) {
688 var params = _.clone(command.params);
689 params.shift();
690 genericNotice.call(this, command, '`' + params.join(', ') + '` ' + command.trailing);
691 },
692
693 ERR_NOMOTD: function (command) {
694 var params = _.clone(command.params);
695 params.shift();
696 genericNotice.call(this, command, command.trailing);
697 },
698
699 ERR_NOPRIVILEGES: function (command) {
700 var params = _.clone(command.params);
701 params.shift();
702 genericNotice.call(this, command, command.trailing);
28ce8b75
D
703 },
704
705 RPL_STATSCONN: function (command) {
706 var params = _.clone(command.params);
707 params.shift();
708 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
709 },
710
711 RPL_LUSERCLIENT: function (command) {
712 var params = _.clone(command.params);
713 params.shift();
714 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
715 },
716
717 RPL_LUSEROP: function (command) {
718 var params = _.clone(command.params);
719 params.shift();
720 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
721 },
722
723 RPL_LUSERUNKNOWN: function (command) {
724 var params = _.clone(command.params);
725 params.shift();
726 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
727 },
728
729 RPL_LUSERCHANNELS: function (command) {
730 var params = _.clone(command.params);
731 params.shift();
732 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
733 },
734
735 RPL_LUSERME: function (command) {
736 var params = _.clone(command.params);
737 params.shift();
738 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
739 },
740
741 RPL_LOCALUSERS: function (command) {
742 var params = _.clone(command.params);
743 params.shift();
744 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
745 },
746
747 RPL_GLOBALUSERS: function (command) {
748 var params = _.clone(command.params);
749 params.shift();
750 genericNotice.call(this, command, params.join(', ') + ' ' + command.trailing);
a49e0dcf 751 }
a8bf3ea4 752};
cea1f25b
D
753
754
755
756
757function genericNotice (command, msg, is_error) {
758 // Default to being an error
759 if (typeof is_error !== 'boolean')
760 is_error = true;
761
762 this.client.sendIrcCommand('notice', {
763 server: this.con_num,
764 nick: command.prefix,
765 ident: '',
766 hostname: '',
767 target: command.params[0],
768 msg: msg,
769 numeric: parseInt(command.command, 10)
770 });
771}