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