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