1 var _
= require('lodash'),
10 '005': 'RPL_ISUPPORT',
13 '250': 'RPL_STATSCONN',
14 '251': 'RPL_LUSERCLIENT',
16 '253': 'RPL_LUSERUNKNOWN',
17 '254': 'RPL_LUSERCHANNELS',
19 '265': 'RPL_LOCALUSERS',
20 '266': 'RPL_GLOBALUSERS',
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',
35 '333': 'RPL_TOPICWHOTIME',
36 '353': 'RPL_NAMEREPLY',
38 '365': 'RPL_ENDOFLINKS',
39 '366': 'RPL_ENDOFNAMES',
41 '368': 'RPL_ENDOFBANLIST',
42 '369': 'RPL_ENDOFWHOWAS',
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',
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'
75 IrcCommands = function (irc_connection
) {
76 this.irc_connection
= irc_connection
;
78 module
.exports
= IrcCommands
;
80 IrcCommands
.prototype.dispatch = function (command
, data
) {
82 if (irc_numerics
[command
]) {
83 command
= irc_numerics
[command
];
85 if (handlers
[command
]) {
86 handlers
[command
].call(this, data
);
88 unknownCommand(command
, data
);
92 IrcCommands
.addHandler = function (command
, handler
) {
93 if (typeof handler
!== 'function') {
96 handlers
[command
] = handler
;
99 IrcCommands
.addNumeric = function (numeric
, handler_name
) {
100 irc_numerics
[numeric
+ ''] = handler_name
+'';
103 unknownCommand = function (command
, data
) {
104 // TODO: Do something here, log?
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', {
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
)});
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');
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
149 'RPL_ENDOFWHOIS': function (command
) {
150 this.irc_connection
.emit('user ' + command
.params
[1] + ' endofwhois', {
151 nick
: command
.params
[1],
152 msg
: command
.trailing
156 'RPL_AWAY': function (command
) {
157 this.irc_connection
.emit('user ' + command
.params
[1] + ' whoisaway', {
158 nick
: command
.params
[1],
159 reason
: command
.trailing
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
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
180 'RPL_WHOISOPERATOR': function (command
) {
181 this.irc_connection
.emit('user ' + command
.params
[1] + ' whoisoperator', {
182 nick
: command
.params
[1],
183 msg
: command
.trailing
187 'RPL_WHOISCHANNELS': function (command
) {
188 this.irc_connection
.emit('user ' + command
.params
[1] + ' whoischannels', {
189 nick
: command
.params
[1],
190 chans
: command
.trailing
194 'RPL_WHOISMODES': function (command
) {
195 this.irc_connection
.emit('user ' + command
.params
[1] + ' whoismodes', {
196 nick
: command
.params
[1],
197 msg
: command
.trailing
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
209 'RPL_WHOISREGNICK': function (command
) {
210 this.irc_connection
.emit('user ' + command
.params
[1] + ' whoisregnick', {
211 nick
: command
.params
[1],
212 msg
: command
.trailing
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
225 'RPL_ENDOFWHOWAS': function (command
) {
226 this.irc_connection
.emit('user ' + command
.params
[1] + ' endofwhowas', {
227 nick
: command
.params
[1]
231 'ERR_WASNOSUCHNICK': function (command
) {
232 this.irc_connection
.emit('user ' + command
.params
[1] + ' wasnosucknick', {
233 nick
: command
.params
[1]
237 'RPL_LISTSTART': function (command
) {
238 this.irc_connection
.emit('server ' + this.irc_connection
.irc_host
.hostname
+ ' list_start', {});
241 'RPL_LISTEND': function (command
) {
242 this.irc_connection
.emit('server ' + this.irc_connection
.irc_host
.hostname
+ ' list_end', {});
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
253 'RPL_MOTD': function (command
) {
254 this.irc_connection
.emit('server ' + this.irc_connection
.irc_host
.hostname
+ ' motd', {
255 motd
: command
.trailing
+ '\n'
259 'RPL_MOTDSTART': function (command
) {
260 this.irc_connection
.emit('server ' + this.irc_connection
.irc_host
.hostname
+ ' motd_start', {});
263 'RPL_ENDOFMOTD': function (command
) {
264 this.irc_connection
.emit('server ' + this.irc_connection
.irc_host
.hostname
+ ' motd_end', {});
267 'RPL_NAMEREPLY': function (command
) {
268 var members
= command
.trailing
.split(' ');
269 var member_list
= [];
271 _
.each(members
, function (member
) {
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
);
286 member_list
.push({nick
: member
, modes
: modes
});
289 this.irc_connection
.emit('channel ' + command
.params
[2] + ' userlist', {
291 channel
: command
.params
[2]
295 'RPL_ENDOFNAMES': function (command
) {
296 this.irc_connection
.emit('channel ' + command
.params
[1] + ' userlist_end', {
297 channel
: command
.params
[1]
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]
310 'RPL_ENDOFBANLIST': function (command
) {
311 this.irc_connection
.emit('channel ' + command
.params
[1] + ' banlist_end', {
312 channel
: command
.params
[1]
316 'RPL_TOPIC': function (command
) {
317 this.irc_connection
.emit('channel ' + command
.params
[1] + ' topic', {
318 channel
: command
.params
[1],
319 topic
: command
.trailing
323 'RPL_NOTOPIC': function (command
) {
324 this.irc_connection
.emit('channel ' + command
.params
[1] + ' topic', {
325 channel
: command
.params
[1],
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]
338 'PING': function (command
) {
339 this.irc_connection
.write('PONG ' + command
.trailing
);
342 'JOIN': function (command
) {
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];
350 this.irc_connection
.emit('channel ' + channel
+ ' join', {
352 ident
: command
.ident
,
353 hostname
: command
.hostname
,
358 'PART': function (command
) {
359 this.irc_connection
.emit('channel ' + command
.params
[0] + ' part', {
361 ident
: command
.ident
,
362 hostname
: command
.hostname
,
363 channel
: command
.params
[0],
364 message
: command
.trailing
368 'KICK': function (command
) {
369 this.irc_connection
.emit('channel ' + command
.params
[0] + ' kick', {
370 kicked
: command
.params
[1],
372 ident
: command
.ident
,
373 hostname
: command
.hostname
,
374 channel
: command
.params
[0],
375 message
: command
.trailing
379 'QUIT': function (command
) {
380 this.irc_connection
.emit('user ' + command
.nick
+ ' quit', {
382 ident
: command
.ident
,
383 hostname
: command
.hostname
,
384 message
: command
.trailing
388 'NOTICE': function (command
) {
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].toLowerCase() == this.irc_connection
.nick
.toLowerCase()) ? 'user' : 'channel';
394 this.irc_connection
.emit(namespace + ' ' + command
.params
[0] + ' ctcp_response', {
396 ident
: command
.ident
,
397 hostname
: command
.hostname
,
398 channel
: command
.params
[0],
399 msg
: command
.trailing
.substr(1, command
.trailing
.length
- 2)
402 namespace = (command
.params
[0].toLowerCase() == this.irc_connection
.nick
.toLowerCase() || command
.params
[0] == '*') ?
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
417 'NICK': function (command
) {
418 this.irc_connection
.emit('user ' + command
.nick
+ ' nick', {
420 ident
: command
.ident
,
421 hostname
: command
.hostname
,
422 newnick
: command
.trailing
|| command
.params
[0]
426 'TOPIC': function (command
) {
427 // If we don't have an associated channel, no need to continue
428 if (!command
.params
[0]) return;
430 var channel
= command
.params
[0],
431 topic
= command
.trailing
|| '';
433 this.irc_connection
.emit('channel ' + channel
+ ' topic', {
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] || '')),
445 has_param
, i
, j
, add
, event
;
447 prefixes
= _
.reduce(prefixes
, function (list
, prefix
) {
448 list
.push(prefix
.mode
);
451 always_param
= always_param
.split('').concat(prefixes
);
453 has_param = function (mode
, add
) {
454 if (_
.find(always_param
, function (m
) {
458 } else if (add
&& _
.find((chanmodes
[2] || '').split(''), function (m
) {
467 if (!command
.params
[1]) {
468 command
.params
[1] = command
.trailing
;
472 for (i
= 0; i
< command
.params
[1].length
; i
++) {
473 switch (command
.params
[1][i
]) {
481 if (has_param(command
.params
[1][i
], add
)) {
482 modes
.push({mode
: (add
? '+' : '-') + command
.params
[1][i
], param
: command
.params
[2 + j
]});
485 modes
.push({mode
: (add
? '+' : '-') + command
.params
[1][i
], param
: null});
490 event
= (_
.contains(this.irc_connection
.options
.CHANTYPES
, command
.params
[0][0]) ? 'channel ' : 'user ') + command
.params
[0] + ' mode';
492 this.irc_connection
.emit(event
, {
493 target
: command
.params
[0],
494 nick
: command
.nick
|| command
.prefix
|| '',
499 'PRIVMSG': function (command
) {
501 if ((command
.trailing
.charAt(0) === String
.fromCharCode(1)) && (command
.trailing
.charAt(command
.trailing
.length
- 1) === String
.fromCharCode(1))) {
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));
516 namespace = (command
.params
[0].toLowerCase() == this.irc_connection
.nick
.toLowerCase()) ? 'user' : 'channel';
517 this.irc_connection
.emit(namespace + ' ' + command
.nick
+ ' ctcp_request', {
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)
527 // A message to a user (private message) or to a channel?
528 namespace = (command
.params
[0].toLowerCase() == this.irc_connection
.nick
.toLowerCase()) ? 'user ' + command
.nick
: 'channel ' + command
.params
[0];
529 this.irc_connection
.emit(namespace + ' privmsg', {
531 ident
: command
.ident
,
532 hostname
: command
.hostname
,
533 channel
: command
.params
[0],
534 msg
: command
.trailing
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(' ');
545 // Which capabilities we want to enable
546 var want
= ['multi-prefix', 'away-notify'];
548 if (this.irc_connection
.password
) {
552 switch (command
.params
[1]) {
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(' '));
560 this.irc_connection
.write('CAP END');
561 this.irc_connection
.cap_negotation
= false;
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
);
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');
576 this.irc_connection
.write('CAP END');
577 this.irc_connection
.cap_negotation
= false;
582 if (capabilities
.length
> 0) {
583 this.irc_connection
.cap
.requested
= _
.difference(this.irc_connection
.cap
.requested
, capabilities
);
585 if (this.irc_connection
.cap
.requested
.length
> 0) {
586 this.irc_connection
.write('CAP END');
587 this.irc_connection
.cap_negotation
= false;
591 // should we do anything here?
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);
604 if (b64
.length
> 0) {
605 this.irc_connection
.write('AUTHENTICATE ' + b64
);
607 this.irc_connection
.write('AUTHENTICATE +');
610 this.irc_connection
.write('CAP END');
611 this.irc_connection
.cap_negotation
= false;
615 'AWAY': function (command
) {
616 this.irc_connection
.emit('user ' + command
.nick
+ ' away', {
618 msg
: command
.trailing
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;
628 'RPL_SASLLOGGEDIN': function (command
) {
629 if (this.irc_connection
.cap_negotation
=== false) {
630 this.irc_connection
.write('CAP END');
634 'ERR_SASLNOTAUTHORISED': function (command
) {
635 this.irc_connection
.write('CAP END');
636 this.irc_connection
.cap_negotation
= false;
639 'ERR_SASLABORTED': function (command
) {
640 this.irc_connection
.write('CAP END');
641 this.irc_connection
.cap_negotation
= false;
644 'ERR_SASLALREADYAUTHED': function (command
) {
648 'ERROR': function (command
) {
649 this.irc_connection
.emit('server ' + this.irc_connection
.irc_host
.hostname
+ ' error', {
650 reason
: command
.trailing
653 ERR_PASSWDMISMATCH: function (command
) {
654 this.irc_connection
.emit('server ' + this.irc_connection
.irc_host
.hostname
+ ' password_mismatch', {});
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]
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
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
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
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
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
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
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
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
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
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
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
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
749 ERR_NOTREGISTERED: function (command
) {
752 RPL_MAPMORE: function (command
) {
753 var params
= _
.clone(command
.params
);
755 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
758 RPL_MAPEND: function (command
) {
759 var params
= _
.clone(command
.params
);
761 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
764 RPL_LINKS: function (command
) {
765 var params
= _
.clone(command
.params
);
767 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
770 RPL_ENDOFLINKS: function (command
) {
771 var params
= _
.clone(command
.params
);
773 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
776 ERR_UNKNOWNCOMMAND: function (command
) {
777 var params
= _
.clone(command
.params
);
779 genericNotice
.call(this, command
, '`' + params
.join(', ') + '` ' + command
.trailing
);
782 ERR_NOMOTD: function (command
) {
783 var params
= _
.clone(command
.params
);
785 genericNotice
.call(this, command
, command
.trailing
);
788 ERR_NOPRIVILEGES: function (command
) {
789 var params
= _
.clone(command
.params
);
791 genericNotice
.call(this, command
, command
.trailing
);
794 RPL_STATSCONN: function (command
) {
795 var params
= _
.clone(command
.params
);
797 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
800 RPL_LUSERCLIENT: function (command
) {
801 var params
= _
.clone(command
.params
);
803 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
806 RPL_LUSEROP: function (command
) {
807 var params
= _
.clone(command
.params
);
809 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
812 RPL_LUSERUNKNOWN: function (command
) {
813 var params
= _
.clone(command
.params
);
815 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
818 RPL_LUSERCHANNELS: function (command
) {
819 var params
= _
.clone(command
.params
);
821 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
824 RPL_LUSERME: function (command
) {
825 var params
= _
.clone(command
.params
);
827 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
830 RPL_LOCALUSERS: function (command
) {
831 var params
= _
.clone(command
.params
);
833 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
836 RPL_GLOBALUSERS: function (command
) {
837 var params
= _
.clone(command
.params
);
839 genericNotice
.call(this, command
, params
.join(', ') + ' ' + command
.trailing
);
846 function genericNotice (command
, msg
, is_error
) {
847 // Default to being an error
848 if (typeof is_error
!== 'boolean')
851 this.irc_connection
.clientEvent('notice', {
853 nick
: command
.prefix
,
856 target
: command
.params
[0],
858 numeric
: parseInt(command
.command
, 10)