Commit | Line | Data |
---|---|---|
3ec786bc JA |
1 | var _ = require('lodash'), |
2 | irc_numerics, | |
3 | IrcCommands, | |
4 | handlers, | |
5 | unknownCommand; | |
6 | ||
7 | irc_numerics = { | |
8 | '001': 'RPL_WELCOME', | |
9 | '004': 'RPL_MYINFO', | |
10 | '005': 'RPL_ISUPPORT', | |
11 | '006': 'RPL_MAPMORE', | |
12 | '007': 'RPL_MAPEND', | |
13 | '250': 'RPL_STATSCONN', | |
14 | '251': 'RPL_LUSERCLIENT', | |
15 | '252': 'RPL_LUSEROP', | |
16 | '253': 'RPL_LUSERUNKNOWN', | |
17 | '254': 'RPL_LUSERCHANNELS', | |
18 | '255': 'RPL_LUSERME', | |
19 | '265': 'RPL_LOCALUSERS', | |
20 | '266': 'RPL_GLOBALUSERS', | |
21 | '301': 'RPL_AWAY', | |
22 | '307': 'RPL_WHOISREGNICK', | |
23 | '311': 'RPL_WHOISUSER', | |
24 | '312': 'RPL_WHOISSERVER', | |
25 | '313': 'RPL_WHOISOPERATOR', | |
5989f3f4 | 26 | '314': 'RPL_WHOWASUSER', |
3ab39028 | 27 | '315': 'RPL_ENDOFWHO', |
3ec786bc JA |
28 | '317': 'RPL_WHOISIDLE', |
29 | '318': 'RPL_ENDOFWHOIS', | |
30 | '319': 'RPL_WHOISCHANNELS', | |
31 | '321': 'RPL_LISTSTART', | |
32 | '322': 'RPL_LIST', | |
33 | '323': 'RPL_LISTEND', | |
72db27e4 D |
34 | '324': 'RPL_CHANNELMODEIS', |
35 | '328': 'RPL_CHANNEL_URL', | |
36 | '329': 'RPL_CREATIONTIME', | |
3d753975 | 37 | '330': 'RPL_WHOISACCOUNT', |
3ec786bc JA |
38 | '331': 'RPL_NOTOPIC', |
39 | '332': 'RPL_TOPIC', | |
40 | '333': 'RPL_TOPICWHOTIME', | |
9a1da609 | 41 | '341': 'RPL_INVITING', |
3ab39028 | 42 | '352': 'RPL_WHOREPLY', |
3ec786bc JA |
43 | '353': 'RPL_NAMEREPLY', |
44 | '364': 'RPL_LINKS', | |
45 | '365': 'RPL_ENDOFLINKS', | |
46 | '366': 'RPL_ENDOFNAMES', | |
47 | '367': 'RPL_BANLIST', | |
48 | '368': 'RPL_ENDOFBANLIST', | |
5989f3f4 | 49 | '369': 'RPL_ENDOFWHOWAS', |
3ec786bc JA |
50 | '372': 'RPL_MOTD', |
51 | '375': 'RPL_MOTDSTART', | |
52 | '376': 'RPL_ENDOFMOTD', | |
3d753975 | 53 | '378': 'RPL_WHOISHOST', |
3ec786bc JA |
54 | '379': 'RPL_WHOISMODES', |
55 | '401': 'ERR_NOSUCHNICK', | |
56 | '404': 'ERR_CANNOTSENDTOCHAN', | |
57 | '405': 'ERR_TOOMANYCHANNELS', | |
5989f3f4 | 58 | '406': 'ERR_WASNOSUCHNICK', |
3ec786bc JA |
59 | '421': 'ERR_UNKNOWNCOMMAND', |
60 | '422': 'ERR_NOMOTD', | |
66c980d3 | 61 | '432': 'ERR_ERRONEUSNICKNAME', |
3ec786bc JA |
62 | '433': 'ERR_NICKNAMEINUSE', |
63 | '441': 'ERR_USERNOTINCHANNEL', | |
64 | '442': 'ERR_NOTONCHANNEL', | |
3d753975 | 65 | '443': 'ERR_USERONCHANNEL', |
3ec786bc JA |
66 | '451': 'ERR_NOTREGISTERED', |
67 | '464': 'ERR_PASSWDMISMATCH', | |
68 | '470': 'ERR_LINKCHANNEL', | |
69 | '471': 'ERR_CHANNELISFULL', | |
70 | '473': 'ERR_INVITEONLYCHAN', | |
71 | '474': 'ERR_BANNEDFROMCHAN', | |
72 | '475': 'ERR_BADCHANNELKEY', | |
73 | '481': 'ERR_NOPRIVILEGES', | |
74 | '482': 'ERR_CHANOPRIVSNEEDED', | |
75 | '670': 'RPL_STARTTLS', | |
3d753975 | 76 | '671': 'RPL_WHOISSECURE', |
3ec786bc JA |
77 | '900': 'RPL_SASLAUTHENTICATED', |
78 | '903': 'RPL_SASLLOGGEDIN', | |
79 | '904': 'ERR_SASLNOTAUTHORISED', | |
80 | '906': 'ERR_SASLABORTED', | |
81 | '907': 'ERR_SASLALREADYAUTHED' | |
a8bf3ea4 JA |
82 | }; |
83 | ||
84 | ||
cced0091 | 85 | IrcCommands = function (irc_connection) { |
a8bf3ea4 | 86 | this.irc_connection = irc_connection; |
a8bf3ea4 | 87 | }; |
2a8e95d1 | 88 | module.exports = IrcCommands; |
a8bf3ea4 | 89 | |
3ec786bc JA |
90 | IrcCommands.prototype.dispatch = function (command, data) { |
91 | command += ''; | |
92 | if (irc_numerics[command]) { | |
93 | command = irc_numerics[command]; | |
94 | } | |
95 | if (handlers[command]) { | |
96 | handlers[command].call(this, data); | |
97 | } else { | |
3d753975 | 98 | unknownCommand.call(this, command, data); |
3ec786bc JA |
99 | } |
100 | }; | |
2a8e95d1 | 101 | |
3ec786bc JA |
102 | IrcCommands.addHandler = function (command, handler) { |
103 | if (typeof handler !== 'function') { | |
104 | return false; | |
105 | } | |
106 | handlers[command] = handler; | |
a8bf3ea4 JA |
107 | }; |
108 | ||
3ec786bc JA |
109 | IrcCommands.addNumeric = function (numeric, handler_name) { |
110 | irc_numerics[numeric + ''] = handler_name +''; | |
c08717da D |
111 | }; |
112 | ||
3ec786bc | 113 | unknownCommand = function (command, data) { |
3d753975 D |
114 | var params = _.clone(data.params); |
115 | ||
116 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' unknown_command', { | |
117 | command: command, | |
17dfa698 | 118 | params: params |
3d753975 | 119 | }); |
17dfa698 | 120 | }; |
2a8e95d1 D |
121 | |
122 | ||
3ec786bc | 123 | handlers = { |
a49e0dcf JA |
124 | 'RPL_WELCOME': function (command) { |
125 | var nick = command.params[0]; | |
126 | this.irc_connection.registered = true; | |
992e681c | 127 | this.cap_negotiation = false; |
d9285da9 | 128 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' connect', { |
1cc056b8 JA |
129 | nick: nick |
130 | }); | |
a49e0dcf | 131 | }, |
3ec786bc | 132 | |
a49e0dcf JA |
133 | 'RPL_ISUPPORT': function (command) { |
134 | var options, i, option, matches, j; | |
135 | options = command.params; | |
136 | for (i = 1; i < options.length; i++) { | |
137 | option = options[i].split("=", 2); | |
138 | option[0] = option[0].toUpperCase(); | |
139 | this.irc_connection.options[option[0]] = (typeof option[1] !== 'undefined') ? option[1] : true; | |
140 | if (_.include(['NETWORK', 'PREFIX', 'CHANTYPES', 'CHANMODES', 'NAMESX'], option[0])) { | |
141 | if (option[0] === 'PREFIX') { | |
142 | matches = /\(([^)]*)\)(.*)/.exec(option[1]); | |
143 | if ((matches) && (matches.length === 3)) { | |
144 | this.irc_connection.options.PREFIX = []; | |
145 | for (j = 0; j < matches[2].length; j++) { | |
146 | this.irc_connection.options.PREFIX.push({symbol: matches[2].charAt(j), mode: matches[1].charAt(j)}); | |
a8bf3ea4 JA |
147 | } |
148 | } | |
a49e0dcf JA |
149 | } else if (option[0] === 'CHANTYPES') { |
150 | this.irc_connection.options.CHANTYPES = this.irc_connection.options.CHANTYPES.split(''); | |
151 | } else if (option[0] === 'CHANMODES') { | |
152 | this.irc_connection.options.CHANMODES = option[1].split(','); | |
153 | } else if ((option[0] === 'NAMESX') && (!_.contains(this.irc_connection.cap.enabled, 'multi-prefix'))) { | |
154 | this.irc_connection.write('PROTOCTL NAMESX'); | |
a8bf3ea4 | 155 | } |
a49e0dcf JA |
156 | } |
157 | } | |
d9285da9 | 158 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' options', { |
1cc056b8 JA |
159 | options: this.irc_connection.options, |
160 | cap: this.irc_connection.cap.enabled | |
161 | }); | |
a49e0dcf | 162 | }, |
3ec786bc | 163 | |
a49e0dcf | 164 | 'RPL_ENDOFWHOIS': function (command) { |
d9285da9 | 165 | this.irc_connection.emit('user ' + command.params[1] + ' endofwhois', { |
692163ca | 166 | nick: command.params[1], |
17dfa698 | 167 | msg: command.params[command.params.length - 1] |
692163ca | 168 | }); |
a49e0dcf | 169 | }, |
3ec786bc | 170 | |
f701d5ba D |
171 | 'RPL_AWAY': function (command) { |
172 | this.irc_connection.emit('user ' + command.params[1] + ' whoisaway', { | |
173 | nick: command.params[1], | |
17dfa698 | 174 | reason: command.params[command.params.length - 1] |
f701d5ba D |
175 | }); |
176 | }, | |
3ec786bc | 177 | |
a49e0dcf | 178 | 'RPL_WHOISUSER': function (command) { |
d9285da9 | 179 | this.irc_connection.emit('user ' + command.params[1] + ' whoisuser', { |
692163ca JA |
180 | nick: command.params[1], |
181 | ident: command.params[2], | |
182 | host: command.params[3], | |
17dfa698 | 183 | msg: command.params[command.params.length - 1] |
692163ca | 184 | }); |
a49e0dcf | 185 | }, |
3ec786bc | 186 | |
a49e0dcf | 187 | 'RPL_WHOISSERVER': function (command) { |
d9285da9 | 188 | this.irc_connection.emit('user ' + command.params[1] + ' whoisserver', { |
692163ca | 189 | nick: command.params[1], |
5989f3f4 | 190 | irc_server: command.params[2], |
17dfa698 | 191 | server_info: command.params[command.params.length - 1] |
692163ca | 192 | }); |
a49e0dcf | 193 | }, |
3ec786bc | 194 | |
a49e0dcf | 195 | 'RPL_WHOISOPERATOR': function (command) { |
d9285da9 | 196 | this.irc_connection.emit('user ' + command.params[1] + ' whoisoperator', { |
692163ca | 197 | nick: command.params[1], |
17dfa698 | 198 | msg: command.params[command.params.length - 1] |
692163ca | 199 | }); |
a49e0dcf | 200 | }, |
3ec786bc | 201 | |
a49e0dcf | 202 | 'RPL_WHOISCHANNELS': function (command) { |
d9285da9 | 203 | this.irc_connection.emit('user ' + command.params[1] + ' whoischannels', { |
692163ca | 204 | nick: command.params[1], |
17dfa698 | 205 | chans: command.params[command.params.length - 1] |
692163ca | 206 | }); |
a49e0dcf | 207 | }, |
3ec786bc | 208 | |
a49e0dcf | 209 | 'RPL_WHOISMODES': function (command) { |
d9285da9 | 210 | this.irc_connection.emit('user ' + command.params[1] + ' whoismodes', { |
692163ca | 211 | nick: command.params[1], |
17dfa698 | 212 | msg: command.params[command.params.length - 1] |
692163ca | 213 | }); |
a49e0dcf | 214 | }, |
3ec786bc | 215 | |
a49e0dcf | 216 | 'RPL_WHOISIDLE': function (command) { |
d9285da9 | 217 | this.irc_connection.emit('user ' + command.params[1] + ' whoisidle', { |
692163ca JA |
218 | nick: command.params[1], |
219 | idle: command.params[2], | |
220 | logon: command.params[3] || undefined | |
221 | }); | |
a49e0dcf | 222 | }, |
3ec786bc | 223 | |
a49e0dcf | 224 | 'RPL_WHOISREGNICK': function (command) { |
d9285da9 | 225 | this.irc_connection.emit('user ' + command.params[1] + ' whoisregnick', { |
692163ca | 226 | nick: command.params[1], |
17dfa698 | 227 | msg: command.params[command.params.length - 1] |
692163ca | 228 | }); |
a49e0dcf | 229 | }, |
3ec786bc | 230 | |
3d753975 D |
231 | 'RPL_WHOISHOST': function (command) { |
232 | this.irc_connection.emit('user ' + command.params[1] + ' whoishost', { | |
233 | nick: command.params[1], | |
17dfa698 | 234 | msg: command.params[command.params.length - 1] |
3d753975 D |
235 | }); |
236 | }, | |
237 | ||
238 | 'RPL_WHOISSECURE': function (command) { | |
239 | this.irc_connection.emit('user ' + command.params[1] + ' whoissecure', { | |
240 | nick: command.params[1] | |
241 | }); | |
242 | }, | |
243 | ||
244 | 'RPL_WHOISACCOUNT': function (command) { | |
245 | this.irc_connection.emit('user ' + command.params[1] + ' whoisaccount', { | |
246 | nick: command.params[1], | |
247 | account: command.params[2] | |
248 | }); | |
249 | }, | |
250 | ||
5989f3f4 JA |
251 | 'RPL_WHOWASUSER': function (command) { |
252 | this.irc_connection.emit('user ' + command.params[1] + ' whowas', { | |
253 | nick: command.params[1], | |
254 | ident: command.params[2], | |
255 | host: command.params[3], | |
17dfa698 | 256 | real_name: command.params[command.params.length - 1] |
5989f3f4 JA |
257 | }); |
258 | }, | |
259 | ||
260 | 'RPL_ENDOFWHOWAS': function (command) { | |
261 | this.irc_connection.emit('user ' + command.params[1] + ' endofwhowas', { | |
262 | nick: command.params[1] | |
263 | }); | |
264 | }, | |
265 | ||
266 | 'ERR_WASNOSUCHNICK': function (command) { | |
267 | this.irc_connection.emit('user ' + command.params[1] + ' wasnosucknick', { | |
268 | nick: command.params[1] | |
269 | }); | |
270 | }, | |
271 | ||
a49e0dcf | 272 | 'RPL_LISTSTART': function (command) { |
d9285da9 | 273 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_start', {}); |
a49e0dcf | 274 | }, |
3ec786bc | 275 | |
a49e0dcf | 276 | 'RPL_LISTEND': function (command) { |
d9285da9 | 277 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_end', {}); |
a49e0dcf | 278 | }, |
3ec786bc | 279 | |
a49e0dcf | 280 | 'RPL_LIST': function (command) { |
d9285da9 | 281 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' list_channel', { |
fb1b18bc | 282 | channel: command.params[1], |
25edd441 | 283 | num_users: parseInt(command.params[2], 10), |
5301ab32 | 284 | topic: command.params[3] || '' |
fb1b18bc | 285 | }); |
a49e0dcf | 286 | }, |
3ec786bc | 287 | |
72db27e4 D |
288 | 'RPL_CHANNELMODEIS': function (command) { |
289 | var channel = command.params[1], | |
290 | modes = parseModeList.call(this, command.params[2], command.params.slice(3)); | |
291 | ||
292 | this.irc_connection.emit('channel ' + channel + ' info', { | |
293 | channel: channel, | |
294 | modes: modes | |
295 | }); | |
296 | }, | |
297 | ||
298 | 'RPL_CREATIONTIME': function (command) { | |
299 | var channel = command.params[1]; | |
300 | ||
301 | this.irc_connection.emit('channel ' + channel + ' info', { | |
302 | channel: channel, | |
303 | created_at: parseInt(command.params[2], 10) | |
304 | }); | |
305 | }, | |
306 | ||
307 | 'RPL_CHANNEL_URL': function (command) { | |
308 | var channel = command.params[1]; | |
309 | ||
310 | this.irc_connection.emit('channel ' + channel + ' info', { | |
311 | channel: channel, | |
17dfa698 | 312 | url: command.params[command.params.length - 1] |
72db27e4 D |
313 | }); |
314 | }, | |
315 | ||
a49e0dcf | 316 | 'RPL_MOTD': function (command) { |
d9285da9 | 317 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd', { |
17dfa698 | 318 | motd: command.params[command.params.length - 1] + '\n' |
1cc056b8 | 319 | }); |
a49e0dcf | 320 | }, |
3ec786bc | 321 | |
a49e0dcf | 322 | 'RPL_MOTDSTART': function (command) { |
d9285da9 | 323 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd_start', {}); |
a49e0dcf | 324 | }, |
3ec786bc | 325 | |
a49e0dcf | 326 | 'RPL_ENDOFMOTD': function (command) { |
d9285da9 | 327 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' motd_end', {}); |
a49e0dcf | 328 | }, |
3ec786bc | 329 | |
a49e0dcf | 330 | 'RPL_NAMEREPLY': function (command) { |
17dfa698 | 331 | var members = command.params[command.params.length - 1].split(' '); |
a49e0dcf JA |
332 | var member_list = []; |
333 | var that = this; | |
a49e0dcf | 334 | _.each(members, function (member) { |
b8d390b0 JA |
335 | var i = 0, |
336 | j = 0, | |
337 | modes = []; | |
30b4d43a D |
338 | |
339 | // Make sure we have some prefixes already | |
340 | if (that.irc_connection.options.PREFIX) { | |
b8d390b0 JA |
341 | for (j = 0; j < that.irc_connection.options.PREFIX.length; j++) { |
342 | if (member.charAt(i) === that.irc_connection.options.PREFIX[j].symbol) { | |
343 | modes.push(that.irc_connection.options.PREFIX[j].mode); | |
344 | i++; | |
a8bf3ea4 | 345 | } |
a8bf3ea4 | 346 | } |
a49e0dcf | 347 | } |
30b4d43a | 348 | |
a49e0dcf | 349 | member_list.push({nick: member, modes: modes}); |
a49e0dcf | 350 | }); |
e2752476 | 351 | |
d9285da9 | 352 | this.irc_connection.emit('channel ' + command.params[2] + ' userlist', { |
e2752476 D |
353 | users: member_list, |
354 | channel: command.params[2] | |
355 | }); | |
a49e0dcf | 356 | }, |
e2752476 | 357 | |
a49e0dcf | 358 | 'RPL_ENDOFNAMES': function (command) { |
d9285da9 | 359 | this.irc_connection.emit('channel ' + command.params[1] + ' userlist_end', { |
e2752476 D |
360 | channel: command.params[1] |
361 | }); | |
a49e0dcf | 362 | }, |
e2752476 | 363 | |
3ab39028 D |
364 | 'RPL_WHOREPLY': function (command) { |
365 | // For the time being, NOOP this command so they don't get passed | |
366 | // down to the client. Waste of bandwidth since we do not use it yet | |
367 | // TODO: Impliment RPL_WHOREPLY | |
368 | }, | |
369 | ||
370 | 'RPL_ENDOFWHO': function (command) { | |
371 | // For the time being, NOOP this command so they don't get passed | |
372 | // down to the client. Waste of bandwidth since we do not use it yet | |
373 | // TODO: Impliment RPL_ENDOFWHO | |
374 | }, | |
375 | ||
a49e0dcf | 376 | 'RPL_BANLIST': function (command) { |
d9285da9 | 377 | this.irc_connection.emit('channel ' + command.params[1] + ' banlist', { |
059f4918 JA |
378 | channel: command.params[1], |
379 | banned: command.params[2], | |
380 | banned_by: command.params[3], | |
381 | banned_at: command.params[4] | |
382 | }); | |
a49e0dcf | 383 | }, |
3ec786bc | 384 | |
a49e0dcf | 385 | 'RPL_ENDOFBANLIST': function (command) { |
d9285da9 | 386 | this.irc_connection.emit('channel ' + command.params[1] + ' banlist_end', { |
aa22caa9 | 387 | channel: command.params[1] |
059f4918 | 388 | }); |
a49e0dcf | 389 | }, |
3ec786bc | 390 | |
a49e0dcf | 391 | 'RPL_TOPIC': function (command) { |
d9285da9 | 392 | this.irc_connection.emit('channel ' + command.params[1] + ' topic', { |
059f4918 | 393 | channel: command.params[1], |
17dfa698 | 394 | topic: command.params[command.params.length - 1] |
059f4918 | 395 | }); |
a49e0dcf | 396 | }, |
3ec786bc | 397 | |
a49e0dcf | 398 | 'RPL_NOTOPIC': function (command) { |
d9285da9 | 399 | this.irc_connection.emit('channel ' + command.params[1] + ' topic', { |
059f4918 JA |
400 | channel: command.params[1], |
401 | topic: '' | |
402 | }); | |
a49e0dcf | 403 | }, |
3ec786bc | 404 | |
a49e0dcf | 405 | 'RPL_TOPICWHOTIME': function (command) { |
d9285da9 | 406 | this.irc_connection.emit('channel ' + command.params[1] + ' topicsetby', { |
059f4918 JA |
407 | nick: command.params[2], |
408 | channel: command.params[1], | |
409 | when: command.params[3] | |
410 | }); | |
a49e0dcf | 411 | }, |
3ec786bc | 412 | |
9a1da609 D |
413 | 'RPL_INVITING': function (command) { |
414 | this.irc_connection.emit('channel ' + command.params[1] + ' invited', { | |
415 | nick: command.params[0], | |
416 | channel: command.params[1] | |
417 | }); | |
418 | }, | |
419 | ||
a49e0dcf | 420 | 'PING': function (command) { |
17dfa698 | 421 | this.irc_connection.write('PONG ' + command.params[command.params.length - 1]); |
a49e0dcf | 422 | }, |
e2752476 | 423 | |
a49e0dcf | 424 | 'JOIN': function (command) { |
d10c74a6 | 425 | var channel, time; |
17dfa698 | 426 | if (typeof command.params[0] === 'string' && command.params[0] !== '') { |
a49e0dcf JA |
427 | channel = command.params[0]; |
428 | } | |
3ec786bc | 429 | |
50263ea0 D |
430 | // Check if we have a server-time |
431 | time = getServerTime.call(this, command); | |
d10c74a6 | 432 | |
d9285da9 | 433 | this.irc_connection.emit('channel ' + channel + ' join', { |
e2752476 D |
434 | nick: command.nick, |
435 | ident: command.ident, | |
436 | hostname: command.hostname, | |
d10c74a6 JA |
437 | channel: channel, |
438 | time: time | |
e2752476 | 439 | }); |
a49e0dcf | 440 | }, |
e2752476 | 441 | |
a49e0dcf | 442 | 'PART': function (command) { |
81198d7e | 443 | var time, channel, message; |
d10c74a6 | 444 | |
50263ea0 D |
445 | // Check if we have a server-time |
446 | time = getServerTime.call(this, command); | |
d10c74a6 | 447 | |
17dfa698 JA |
448 | channel = command.params[0]; |
449 | if (command.params.length > 1) { | |
450 | message = command.params[command.params.length - 1]; | |
81198d7e D |
451 | } |
452 | ||
f96620b7 | 453 | this.irc_connection.emit('channel ' + channel + ' part', { |
e2752476 D |
454 | nick: command.nick, |
455 | ident: command.ident, | |
456 | hostname: command.hostname, | |
81198d7e D |
457 | channel: channel, |
458 | message: message, | |
d10c74a6 | 459 | time: time |
e2752476 | 460 | }); |
a49e0dcf | 461 | }, |
e2752476 | 462 | |
a49e0dcf | 463 | 'KICK': function (command) { |
d10c74a6 JA |
464 | var time; |
465 | ||
50263ea0 D |
466 | // Check if we have a server-time |
467 | time = getServerTime.call(this, command); | |
d10c74a6 | 468 | |
d9285da9 | 469 | this.irc_connection.emit('channel ' + command.params[0] + ' kick', { |
e2752476 D |
470 | kicked: command.params[1], |
471 | nick: command.nick, | |
472 | ident: command.ident, | |
473 | hostname: command.hostname, | |
474 | channel: command.params[0], | |
17dfa698 | 475 | message: command.params[command.params.length - 1], |
d10c74a6 | 476 | time: time |
e2752476 | 477 | }); |
a49e0dcf | 478 | }, |
e2752476 | 479 | |
a49e0dcf | 480 | 'QUIT': function (command) { |
d10c74a6 JA |
481 | var time; |
482 | ||
50263ea0 D |
483 | // Check if we have a server-time |
484 | time = getServerTime.call(this, command); | |
d10c74a6 | 485 | |
d9285da9 | 486 | this.irc_connection.emit('user ' + command.nick + ' quit', { |
e2752476 D |
487 | nick: command.nick, |
488 | ident: command.ident, | |
489 | hostname: command.hostname, | |
17dfa698 | 490 | message: command.params[command.params.length - 1], |
d10c74a6 | 491 | time: time |
e2752476 | 492 | }); |
a49e0dcf | 493 | }, |
e2752476 | 494 | |
a49e0dcf | 495 | 'NOTICE': function (command) { |
d10c74a6 | 496 | var namespace, |
17dfa698 JA |
497 | time, |
498 | msg; | |
d10c74a6 | 499 | |
50263ea0 D |
500 | // Check if we have a server-time |
501 | time = getServerTime.call(this, command); | |
d10c74a6 | 502 | |
17dfa698 JA |
503 | msg = command.params[command.params.length - 1]; |
504 | if ((msg.charAt(0) === String.fromCharCode(1)) && (msg.charAt(msg.length - 1) === String.fromCharCode(1))) { | |
a49e0dcf | 505 | // It's a CTCP response |
17dfa698 | 506 | namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel'; |
d9285da9 | 507 | this.irc_connection.emit(namespace + ' ' + command.params[0] + ' ctcp_response', { |
e2752476 D |
508 | nick: command.nick, |
509 | ident: command.ident, | |
510 | hostname: command.hostname, | |
511 | channel: command.params[0], | |
17dfa698 | 512 | msg: msg.substring(1, msg.length - 1), |
d10c74a6 | 513 | time: time |
e2752476 | 514 | }); |
a49e0dcf | 515 | } else { |
17dfa698 | 516 | namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase() || command.params[0] === '*') ? |
0190c2c9 D |
517 | 'user' : |
518 | 'channel'; | |
519 | ||
d9285da9 | 520 | this.irc_connection.emit(namespace + ' ' + command.params[0] + ' notice', { |
0190c2c9 D |
521 | from_server: command.prefix ? true : false, |
522 | nick: command.nick || command.prefix || undefined, | |
e2752476 D |
523 | ident: command.ident, |
524 | hostname: command.hostname, | |
525 | target: command.params[0], | |
17dfa698 | 526 | msg: msg, |
d10c74a6 | 527 | time: time |
e2752476 | 528 | }); |
a49e0dcf JA |
529 | } |
530 | }, | |
3ec786bc | 531 | |
a49e0dcf | 532 | 'NICK': function (command) { |
d10c74a6 JA |
533 | var time; |
534 | ||
50263ea0 D |
535 | // Check if we have a server-time |
536 | time = getServerTime.call(this, command); | |
d10c74a6 | 537 | |
d9285da9 | 538 | this.irc_connection.emit('user ' + command.nick + ' nick', { |
692163ca JA |
539 | nick: command.nick, |
540 | ident: command.ident, | |
541 | hostname: command.hostname, | |
17dfa698 | 542 | newnick: command.params[0], |
d10c74a6 | 543 | time: time |
692163ca | 544 | }); |
a49e0dcf | 545 | }, |
3ec786bc | 546 | |
a49e0dcf | 547 | 'TOPIC': function (command) { |
d10c74a6 JA |
548 | var time; |
549 | ||
30b4d43a | 550 | // If we don't have an associated channel, no need to continue |
17dfa698 JA |
551 | if (!command.params[0]) { |
552 | return; | |
553 | } | |
30b4d43a | 554 | |
50263ea0 D |
555 | // Check if we have a server-time |
556 | time = getServerTime.call(this, command); | |
d10c74a6 | 557 | |
30b4d43a | 558 | var channel = command.params[0], |
17dfa698 | 559 | topic = command.params[command.params.length - 1] || ''; |
30b4d43a | 560 | |
d9285da9 | 561 | this.irc_connection.emit('channel ' + channel + ' topic', { |
f4ec5774 D |
562 | nick: command.nick, |
563 | channel: channel, | |
d10c74a6 JA |
564 | topic: topic, |
565 | time: time | |
f4ec5774 | 566 | }); |
a49e0dcf | 567 | }, |
3ec786bc | 568 | |
d9285da9 | 569 | 'MODE': function (command) { |
72db27e4 | 570 | var modes = [], event, time; |
d10c74a6 | 571 | |
50263ea0 D |
572 | // Check if we have a server-time |
573 | time = getServerTime.call(this, command); | |
3ec786bc | 574 | |
72db27e4 | 575 | // Get a JSON representation of the modes |
17dfa698 | 576 | modes = parseModeList.call(this, command.params[1], command.params.slice(2)); |
d9285da9 | 577 | event = (_.contains(this.irc_connection.options.CHANTYPES, command.params[0][0]) ? 'channel ' : 'user ') + command.params[0] + ' mode'; |
3ec786bc | 578 | |
a7973dfb | 579 | this.irc_connection.emit(event, { |
a49e0dcf JA |
580 | target: command.params[0], |
581 | nick: command.nick || command.prefix || '', | |
d10c74a6 JA |
582 | modes: modes, |
583 | time: time | |
a49e0dcf JA |
584 | }); |
585 | }, | |
3ec786bc | 586 | |
a49e0dcf | 587 | 'PRIVMSG': function (command) { |
17dfa698 | 588 | var tmp, namespace, time, msg; |
d10c74a6 | 589 | |
50263ea0 D |
590 | // Check if we have a server-time |
591 | time = getServerTime.call(this, command); | |
d10c74a6 | 592 | |
17dfa698 JA |
593 | msg = command.params[command.params.length - 1]; |
594 | if ((msg.charAt(0) === String.fromCharCode(1)) && (msg.charAt(msg.length - 1) === String.fromCharCode(1))) { | |
a49e0dcf | 595 | //CTCP request |
17dfa698 | 596 | if (msg.substr(1, 6) === 'ACTION') { |
d10c74a6 JA |
597 | this.irc_connection.clientEvent('action', { |
598 | nick: command.nick, | |
599 | ident: command.ident, | |
600 | hostname: command.hostname, | |
601 | channel: command.params[0], | |
17dfa698 | 602 | msg: msg.substring(8, msg.length - 1), |
d10c74a6 JA |
603 | time: time |
604 | }); | |
17dfa698 JA |
605 | } else if (msg.substr(1, 4) === 'KIWI') { |
606 | tmp = msg.substring(6, msg.length - 1); | |
a49e0dcf | 607 | namespace = tmp.split(' ', 1)[0]; |
d10c74a6 JA |
608 | this.irc_connection.clientEvent('kiwi', { |
609 | namespace: namespace, | |
610 | data: tmp.substr(namespace.length + 1), | |
611 | time: time | |
612 | }); | |
17dfa698 | 613 | } else if (msg.substr(1, 7) === 'VERSION') { |
a49e0dcf | 614 | this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'VERSION KiwiIRC' + String.fromCharCode(1)); |
17dfa698 | 615 | } else if (msg.substr(1, 6) === 'SOURCE') { |
b39bb331 | 616 | this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'SOURCE http://www.kiwiirc.com/' + String.fromCharCode(1)); |
17dfa698 | 617 | } else if (msg.substr(1, 10) === 'CLIENTINFO') { |
b39bb331 | 618 | this.irc_connection.write('NOTICE ' + command.nick + ' :' + String.fromCharCode(1) + 'CLIENTINFO SOURCE VERSION TIME' + String.fromCharCode(1)); |
a49e0dcf | 619 | } else { |
17dfa698 | 620 | namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase()) ? 'user' : 'channel'; |
d9285da9 | 621 | this.irc_connection.emit(namespace + ' ' + command.nick + ' ctcp_request', { |
b39bb331 D |
622 | nick: command.nick, |
623 | ident: command.ident, | |
624 | hostname: command.hostname, | |
625 | target: command.params[0], | |
17dfa698 JA |
626 | type: (msg.substring(1, msg.length - 1).split(' ') || [null])[0], |
627 | msg: msg.substring(1, msg.length - 1), | |
d10c74a6 | 628 | time: time |
b39bb331 | 629 | }); |
a49e0dcf JA |
630 | } |
631 | } else { | |
e2752476 | 632 | // A message to a user (private message) or to a channel? |
17dfa698 | 633 | namespace = (command.params[0].toLowerCase() === this.irc_connection.nick.toLowerCase()) ? 'user ' + command.nick : 'channel ' + command.params[0]; |
d9285da9 | 634 | this.irc_connection.emit(namespace + ' privmsg', { |
ffbbc70f D |
635 | nick: command.nick, |
636 | ident: command.ident, | |
637 | hostname: command.hostname, | |
638 | channel: command.params[0], | |
17dfa698 | 639 | msg: msg, |
d10c74a6 | 640 | time: time |
b09157de | 641 | }); |
a49e0dcf JA |
642 | } |
643 | }, | |
3ec786bc | 644 | |
a49e0dcf JA |
645 | 'CAP': function (command) { |
646 | // TODO: capability modifiers | |
647 | // i.e. - for disable, ~ for requires ACK, = for sticky | |
17dfa698 | 648 | var capabilities = command.params[command.params.length - 1].replace(/(?:^| )[\-~=]/, '').split(' '); |
a49e0dcf | 649 | var request; |
259d9b96 JA |
650 | |
651 | // Which capabilities we want to enable | |
50263ea0 | 652 | var want = ['multi-prefix', 'away-notify', 'server-time', 'znc.in/server-time-iso', 'znc.in/server-time']; |
259d9b96 | 653 | |
a49e0dcf JA |
654 | if (this.irc_connection.password) { |
655 | want.push('sasl'); | |
656 | } | |
259d9b96 | 657 | |
a49e0dcf JA |
658 | switch (command.params[1]) { |
659 | case 'LS': | |
259d9b96 | 660 | // Compute which of the available capabilities we want and request them |
a49e0dcf JA |
661 | request = _.intersection(capabilities, want); |
662 | if (request.length > 0) { | |
663 | this.irc_connection.cap.requested = request; | |
664 | this.irc_connection.write('CAP REQ :' + request.join(' ')); | |
665 | } else { | |
666 | this.irc_connection.write('CAP END'); | |
992e681c | 667 | this.irc_connection.cap_negotiation = false; |
a8bf3ea4 | 668 | } |
a49e0dcf JA |
669 | break; |
670 | case 'ACK': | |
671 | if (capabilities.length > 0) { | |
259d9b96 | 672 | // Update list of enabled capabilities |
a49e0dcf | 673 | this.irc_connection.cap.enabled = capabilities; |
259d9b96 | 674 | // Update list of capabilities we would like to have but that aren't enabled |
a49e0dcf | 675 | this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities); |
703d2778 | 676 | } |
259d9b96 | 677 | if (this.irc_connection.cap.enabled.length > 0) { |
a49e0dcf JA |
678 | if (_.contains(this.irc_connection.cap.enabled, 'sasl')) { |
679 | this.irc_connection.sasl = true; | |
680 | this.irc_connection.write('AUTHENTICATE PLAIN'); | |
a8bf3ea4 | 681 | } else { |
a49e0dcf | 682 | this.irc_connection.write('CAP END'); |
992e681c | 683 | this.irc_connection.cap_negotiation = false; |
a8bf3ea4 | 684 | } |
a8bf3ea4 | 685 | } |
a49e0dcf JA |
686 | break; |
687 | case 'NAK': | |
688 | if (capabilities.length > 0) { | |
689 | this.irc_connection.cap.requested = _.difference(this.irc_connection.cap.requested, capabilities); | |
7dfe47c6 | 690 | } |
a49e0dcf | 691 | if (this.irc_connection.cap.requested.length > 0) { |
7dfe47c6 | 692 | this.irc_connection.write('CAP END'); |
992e681c | 693 | this.irc_connection.cap_negotiation = false; |
7dfe47c6 | 694 | } |
a49e0dcf JA |
695 | break; |
696 | case 'LIST': | |
697 | // should we do anything here? | |
698 | break; | |
699 | } | |
700 | }, | |
3ec786bc | 701 | |
a49e0dcf JA |
702 | 'AUTHENTICATE': function (command) { |
703 | var b = new Buffer(this.irc_connection.nick + "\0" + this.irc_connection.nick + "\0" + this.irc_connection.password, 'utf8'); | |
704 | var b64 = b.toString('base64'); | |
705 | if (command.params[0] === '+') { | |
706 | while (b64.length >= 400) { | |
707 | this.irc_connection.write('AUTHENTICATE ' + b64.slice(0, 399)); | |
708 | b64 = b64.slice(399); | |
a8bf3ea4 | 709 | } |
a49e0dcf JA |
710 | if (b64.length > 0) { |
711 | this.irc_connection.write('AUTHENTICATE ' + b64); | |
712 | } else { | |
713 | this.irc_connection.write('AUTHENTICATE +'); | |
714 | } | |
715 | } else { | |
716 | this.irc_connection.write('CAP END'); | |
992e681c | 717 | this.irc_connection.cap_negotiation = false; |
a49e0dcf JA |
718 | } |
719 | }, | |
3ec786bc | 720 | |
a49e0dcf | 721 | 'AWAY': function (command) { |
d10c74a6 JA |
722 | var time; |
723 | ||
50263ea0 D |
724 | // Check if we have a server-time |
725 | time = getServerTime.call(this, command); | |
d10c74a6 | 726 | |
d9285da9 | 727 | this.irc_connection.emit('user ' + command.nick + ' away', { |
692163ca | 728 | nick: command.nick, |
17dfa698 | 729 | msg: command.params[command.params.length - 1], |
d10c74a6 | 730 | time: time |
692163ca | 731 | }); |
a49e0dcf | 732 | }, |
3ec786bc | 733 | |
a49e0dcf JA |
734 | 'RPL_SASLAUTHENTICATED': function (command) { |
735 | this.irc_connection.write('CAP END'); | |
992e681c | 736 | this.irc_connection.cap_negotiation = false; |
a49e0dcf JA |
737 | this.irc_connection.sasl = true; |
738 | }, | |
3ec786bc | 739 | |
a49e0dcf | 740 | 'RPL_SASLLOGGEDIN': function (command) { |
992e681c | 741 | if (this.irc_connection.cap_negotiation === true) { |
a49e0dcf | 742 | this.irc_connection.write('CAP END'); |
992e681c | 743 | this.irc_connection.cap_negotiation = false; |
a49e0dcf JA |
744 | } |
745 | }, | |
3ec786bc | 746 | |
a49e0dcf | 747 | 'ERR_SASLNOTAUTHORISED': function (command) { |
3ec786bc | 748 | this.irc_connection.write('CAP END'); |
992e681c | 749 | this.irc_connection.cap_negotiation = false; |
3ec786bc JA |
750 | }, |
751 | ||
a49e0dcf JA |
752 | 'ERR_SASLABORTED': function (command) { |
753 | this.irc_connection.write('CAP END'); | |
992e681c | 754 | this.irc_connection.cap_negotiation = false; |
a49e0dcf | 755 | }, |
3ec786bc | 756 | |
a49e0dcf JA |
757 | 'ERR_SASLALREADYAUTHED': function (command) { |
758 | // noop | |
759 | }, | |
3ec786bc | 760 | |
a49e0dcf | 761 | 'ERROR': function (command) { |
d9285da9 | 762 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' error', { |
17dfa698 | 763 | reason: command.params[command.params.length - 1] |
1cc056b8 | 764 | }); |
a49e0dcf | 765 | }, |
ebe178d6 | 766 | ERR_PASSWDMISMATCH: function (command) { |
d9285da9 | 767 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' password_mismatch', {}); |
ebe178d6 | 768 | }, |
3ec786bc | 769 | |
a49e0dcf | 770 | ERR_LINKCHANNEL: function (command) { |
d9285da9 | 771 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_redirect', { |
1cc056b8 JA |
772 | from: command.params[1], |
773 | to: command.params[2] | |
774 | }); | |
a49e0dcf | 775 | }, |
3ec786bc | 776 | |
a49e0dcf | 777 | ERR_NOSUCHNICK: function (command) { |
d9285da9 | 778 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' no_such_nick', { |
1cc056b8 | 779 | nick: command.params[1], |
17dfa698 | 780 | reason: command.params[command.params.length - 1] |
1cc056b8 | 781 | }); |
a49e0dcf | 782 | }, |
3ec786bc | 783 | |
a49e0dcf | 784 | ERR_CANNOTSENDTOCHAN: function (command) { |
d9285da9 | 785 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' cannot_send_to_chan', { |
1cc056b8 | 786 | channel: command.params[1], |
17dfa698 | 787 | reason: command.params[command.params.length - 1] |
1cc056b8 | 788 | }); |
a49e0dcf | 789 | }, |
3ec786bc | 790 | |
a49e0dcf | 791 | ERR_TOOMANYCHANNELS: function (command) { |
d9285da9 | 792 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' too_many_channels', { |
1cc056b8 | 793 | channel: command.params[1], |
17dfa698 | 794 | reason: command.params[command.params.length - 1] |
1cc056b8 | 795 | }); |
a49e0dcf | 796 | }, |
3ec786bc | 797 | |
a49e0dcf | 798 | ERR_USERNOTINCHANNEL: function (command) { |
d9285da9 | 799 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' user_not_in_channel', { |
1cc056b8 JA |
800 | nick: command.params[0], |
801 | channel: command.params[1], | |
17dfa698 | 802 | reason: command.params[command.params.length - 1] |
1cc056b8 | 803 | }); |
a49e0dcf | 804 | }, |
3ec786bc | 805 | |
a49e0dcf | 806 | ERR_NOTONCHANNEL: function (command) { |
d9285da9 | 807 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' not_on_channel', { |
1cc056b8 | 808 | channel: command.params[1], |
17dfa698 | 809 | reason: command.params[command.params.length - 1] |
1cc056b8 | 810 | }); |
a49e0dcf | 811 | }, |
3ec786bc | 812 | |
3d753975 D |
813 | ERR_USERONCHANNEL: function (command) { |
814 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' user_on_channel', { | |
815 | nick: command.params[1], | |
816 | channel: command.params[2] | |
817 | }); | |
818 | }, | |
819 | ||
a49e0dcf | 820 | ERR_CHANNELISFULL: function (command) { |
3ec786bc JA |
821 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' channel_is_full', { |
822 | channel: command.params[1], | |
17dfa698 | 823 | reason: command.params[command.params.length - 1] |
3ec786bc JA |
824 | }); |
825 | }, | |
826 | ||
a49e0dcf | 827 | ERR_INVITEONLYCHAN: function (command) { |
d9285da9 | 828 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' invite_only_channel', { |
1cc056b8 | 829 | channel: command.params[1], |
17dfa698 | 830 | reason: command.params[command.params.length - 1] |
1cc056b8 | 831 | }); |
a49e0dcf | 832 | }, |
3ec786bc | 833 | |
a49e0dcf | 834 | ERR_BANNEDFROMCHAN: function (command) { |
d9285da9 | 835 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' banned_from_channel', { |
1cc056b8 | 836 | channel: command.params[1], |
17dfa698 | 837 | reason: command.params[command.params.length - 1] |
1cc056b8 | 838 | }); |
a49e0dcf | 839 | }, |
3ec786bc | 840 | |
a49e0dcf | 841 | ERR_BADCHANNELKEY: function (command) { |
d9285da9 | 842 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' bad_channel_key', { |
1cc056b8 | 843 | channel: command.params[1], |
17dfa698 | 844 | reason: command.params[command.params.length - 1] |
1cc056b8 | 845 | }); |
a49e0dcf | 846 | }, |
3ec786bc | 847 | |
a49e0dcf | 848 | ERR_CHANOPRIVSNEEDED: function (command) { |
d9285da9 | 849 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' chanop_privs_needed', { |
1cc056b8 | 850 | channel: command.params[1], |
17dfa698 | 851 | reason: command.params[command.params.length - 1] |
1cc056b8 | 852 | }); |
a49e0dcf | 853 | }, |
3ec786bc | 854 | |
a49e0dcf | 855 | ERR_NICKNAMEINUSE: function (command) { |
d9285da9 | 856 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' nickname_in_use', { |
1cc056b8 | 857 | nick: command.params[1], |
17dfa698 | 858 | reason: command.params[command.params.length - 1] |
1cc056b8 | 859 | }); |
a49e0dcf | 860 | }, |
3ec786bc | 861 | |
66c980d3 JA |
862 | ERR_ERRONEUSNICKNAME: function(command) { |
863 | this.irc_connection.emit('server ' + this.irc_connection.irc_host.hostname + ' erroneus_nickname', { | |
864 | nick: command.params[1], | |
17dfa698 | 865 | reason: command.params[command.params.length - 1] |
66c980d3 JA |
866 | }); |
867 | }, | |
868 | ||
a49e0dcf | 869 | ERR_NOTREGISTERED: function (command) { |
cea1f25b D |
870 | }, |
871 | ||
872 | RPL_MAPMORE: function (command) { | |
873 | var params = _.clone(command.params); | |
874 | params.shift(); | |
17dfa698 | 875 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
cea1f25b | 876 | }, |
3ec786bc | 877 | |
cea1f25b D |
878 | RPL_MAPEND: function (command) { |
879 | var params = _.clone(command.params); | |
880 | params.shift(); | |
17dfa698 | 881 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
cea1f25b D |
882 | }, |
883 | ||
884 | RPL_LINKS: function (command) { | |
885 | var params = _.clone(command.params); | |
886 | params.shift(); | |
17dfa698 | 887 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
cea1f25b | 888 | }, |
3ec786bc | 889 | |
cea1f25b D |
890 | RPL_ENDOFLINKS: function (command) { |
891 | var params = _.clone(command.params); | |
892 | params.shift(); | |
17dfa698 | 893 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
cea1f25b D |
894 | }, |
895 | ||
896 | ERR_UNKNOWNCOMMAND: function (command) { | |
897 | var params = _.clone(command.params); | |
898 | params.shift(); | |
17dfa698 | 899 | genericNotice.call(this, command, '`' + params.slice(0, -1).join(', ') + '` ' + command.params[command.params.length - 1]); |
cea1f25b D |
900 | }, |
901 | ||
902 | ERR_NOMOTD: function (command) { | |
903 | var params = _.clone(command.params); | |
904 | params.shift(); | |
17dfa698 | 905 | genericNotice.call(this, command, command.params[command.params.length - 1]); |
cea1f25b D |
906 | }, |
907 | ||
908 | ERR_NOPRIVILEGES: function (command) { | |
909 | var params = _.clone(command.params); | |
910 | params.shift(); | |
17dfa698 | 911 | genericNotice.call(this, command, command.params[command.params.length - 1]); |
28ce8b75 D |
912 | }, |
913 | ||
914 | RPL_STATSCONN: function (command) { | |
915 | var params = _.clone(command.params); | |
916 | params.shift(); | |
17dfa698 | 917 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
28ce8b75 D |
918 | }, |
919 | ||
920 | RPL_LUSERCLIENT: function (command) { | |
921 | var params = _.clone(command.params); | |
922 | params.shift(); | |
17dfa698 | 923 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
28ce8b75 D |
924 | }, |
925 | ||
926 | RPL_LUSEROP: function (command) { | |
927 | var params = _.clone(command.params); | |
928 | params.shift(); | |
17dfa698 | 929 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
28ce8b75 D |
930 | }, |
931 | ||
932 | RPL_LUSERUNKNOWN: function (command) { | |
933 | var params = _.clone(command.params); | |
934 | params.shift(); | |
17dfa698 | 935 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
28ce8b75 D |
936 | }, |
937 | ||
938 | RPL_LUSERCHANNELS: function (command) { | |
939 | var params = _.clone(command.params); | |
940 | params.shift(); | |
17dfa698 | 941 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
28ce8b75 D |
942 | }, |
943 | ||
944 | RPL_LUSERME: function (command) { | |
945 | var params = _.clone(command.params); | |
946 | params.shift(); | |
17dfa698 | 947 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
28ce8b75 D |
948 | }, |
949 | ||
950 | RPL_LOCALUSERS: function (command) { | |
951 | var params = _.clone(command.params); | |
952 | params.shift(); | |
17dfa698 | 953 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
28ce8b75 | 954 | }, |
3ec786bc | 955 | |
28ce8b75 D |
956 | RPL_GLOBALUSERS: function (command) { |
957 | var params = _.clone(command.params); | |
958 | params.shift(); | |
17dfa698 | 959 | genericNotice.call(this, command, params.slice(0, -1).join(', ') + ' ' + command.params[command.params.length - 1]); |
a49e0dcf | 960 | } |
a8bf3ea4 | 961 | }; |
cea1f25b D |
962 | |
963 | ||
964 | ||
965 | ||
966 | function genericNotice (command, msg, is_error) { | |
967 | // Default to being an error | |
968 | if (typeof is_error !== 'boolean') | |
969 | is_error = true; | |
970 | ||
cced0091 | 971 | this.irc_connection.clientEvent('notice', { |
0190c2c9 | 972 | from_server: true, |
cea1f25b D |
973 | nick: command.prefix, |
974 | ident: '', | |
975 | hostname: '', | |
976 | target: command.params[0], | |
977 | msg: msg, | |
978 | numeric: parseInt(command.command, 10) | |
979 | }); | |
aef6e2a7 | 980 | } |
0d14bcf8 | 981 | |
50263ea0 | 982 | |
72db27e4 D |
983 | /** |
984 | * Convert a mode string such as '+k pass', or '-i' to a readable | |
985 | * format. | |
986 | * [ { mode: '+k', param: 'pass' } ] | |
987 | * [ { mode: '-i', param: null } ] | |
988 | */ | |
989 | function parseModeList(mode_string, mode_params) { | |
990 | var chanmodes = this.irc_connection.options.CHANMODES || [], | |
991 | prefixes = this.irc_connection.options.PREFIX || [], | |
992 | always_param = (chanmodes[0] || '').concat((chanmodes[1] || '')), | |
993 | modes = [], | |
994 | has_param, i, j, add; | |
995 | ||
996 | prefixes = _.reduce(prefixes, function (list, prefix) { | |
997 | list.push(prefix.mode); | |
998 | return list; | |
999 | }, []); | |
1000 | always_param = always_param.split('').concat(prefixes); | |
1001 | ||
1002 | has_param = function (mode, add) { | |
1003 | if (_.find(always_param, function (m) { | |
1004 | return m === mode; | |
1005 | })) { | |
1006 | return true; | |
1007 | } else if (add && _.find((chanmodes[2] || '').split(''), function (m) { | |
1008 | return m === mode; | |
1009 | })) { | |
1010 | return true; | |
1011 | } else { | |
1012 | return false; | |
1013 | } | |
1014 | }; | |
1015 | ||
1016 | j = 0; | |
1017 | for (i = 0; i < mode_string.length; i++) { | |
1018 | switch (mode_string[i]) { | |
1019 | case '+': | |
1020 | add = true; | |
1021 | break; | |
1022 | case '-': | |
1023 | add = false; | |
1024 | break; | |
1025 | default: | |
1026 | if (has_param(mode_string[i], add)) { | |
1027 | modes.push({mode: (add ? '+' : '-') + mode_string[i], param: mode_params[j]}); | |
1028 | j++; | |
1029 | } else { | |
1030 | modes.push({mode: (add ? '+' : '-') + mode_string[i], param: null}); | |
1031 | } | |
1032 | } | |
1033 | } | |
1034 | ||
1035 | return modes; | |
1036 | } | |
1037 | ||
1038 | ||
50263ea0 D |
1039 | function getServerTime(command) { |
1040 | var time; | |
1041 | ||
1042 | // No tags? No times. | |
1043 | if (!command.tags || command.tags.length === 0) { | |
1044 | return time; | |
1045 | } | |
1046 | ||
1047 | if (capContainsAny.call(this, ['server-time', 'znc.in/server-time', 'znc.in/server-time-iso'])) { | |
1048 | time = _.find(command.tags, function (tag) { | |
1049 | return tag.tag === 'time'; | |
1050 | }); | |
1051 | ||
1052 | time = time ? time.value : undefined; | |
1053 | ||
1054 | // Convert the time value to a unixtimestamp | |
1055 | if (typeof time === 'string') { | |
1056 | if (time.indexOf('T') > -1) { | |
75d92a37 | 1057 | time = parseISO8601(time); |
50263ea0 D |
1058 | |
1059 | } else if(time.match(/^[0-9.]+$/)) { | |
1060 | // A string formatted unix timestamp | |
1061 | time = new Date(time * 1000); | |
1062 | } | |
1063 | ||
1064 | time = time.getTime(); | |
1065 | ||
1066 | } else if (typeof time === 'number') { | |
1067 | time = new Date(time * 1000); | |
1068 | time = time.getTime(); | |
1069 | } | |
1070 | } | |
1071 | ||
1072 | return time; | |
1073 | } | |
1074 | ||
1075 | ||
0d14bcf8 JA |
1076 | function capContainsAny (caps) { |
1077 | var intersection; | |
50263ea0 | 1078 | if (!caps instanceof Array) { |
0d14bcf8 JA |
1079 | caps = [caps]; |
1080 | } | |
1081 | intersection = _.intersection(this.irc_connection.cap.enabled, caps); | |
1082 | return intersection.length > 0; | |
1083 | } | |
50263ea0 D |
1084 | |
1085 | ||
1086 | // Code based on http://anentropic.wordpress.com/2009/06/25/javascript-iso8601-parser-and-pretty-dates/#comment-154 | |
1087 | function parseISO8601(str) { | |
1088 | if (Date.prototype.toISOString) { | |
1089 | return new Date(str); | |
1090 | } else { | |
1091 | var parts = str.split('T'), | |
1092 | dateParts = parts[0].split('-'), | |
1093 | timeParts = parts[1].split('Z'), | |
1094 | timeSubParts = timeParts[0].split(':'), | |
1095 | timeSecParts = timeSubParts[2].split('.'), | |
1096 | timeHours = Number(timeSubParts[0]), | |
1097 | _date = new Date(); | |
1098 | ||
1099 | _date.setUTCFullYear(Number(dateParts[0])); | |
1100 | _date.setUTCDate(1); | |
1101 | _date.setUTCMonth(Number(dateParts[1])-1); | |
1102 | _date.setUTCDate(Number(dateParts[2])); | |
1103 | _date.setUTCHours(Number(timeHours)); | |
1104 | _date.setUTCMinutes(Number(timeSubParts[1])); | |
1105 | _date.setUTCSeconds(Number(timeSecParts[0])); | |
1106 | if (timeSecParts[1]) { | |
1107 | _date.setUTCMilliseconds(Number(timeSecParts[1])); | |
1108 | } | |
1109 | ||
1110 | return _date; | |
1111 | } | |
1112 | } |