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