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