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