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