]> jfr.im git - irc/quakenet/qwebirc.git/blob - js/irc/baseircclient.js
012e2f28ba4d67271b856e9a03c146d112f71cf9
[irc/quakenet/qwebirc.git] / js / irc / baseircclient.js
1 qwebirc.irc.RegisteredCTCPs = {
2 "VERSION": function(x) {
3 return "qwebirc v" + qwebirc.VERSION + ", copyright (C) Chris Porter 2008-2009 -- " + qwebirc.util.browserVersion();
4 },
5 "USERINFO": function(x) { return "qwebirc"; },
6 "TIME": function(x) { return qwebirc.irc.IRCDate(new Date()); },
7 "PING": function(x) { return x; },
8 "CLIENTINFO": function(x) { return "PING VERSION TIME USERINFO CLIENTINFO"; },
9 "WEBSITE": function(x) { return window == window.top ? "direct" : document.referrer; }
10 };
11
12 qwebirc.irc.BaseIRCClient = new Class({
13 Implements: [Options],
14 options: {
15 nickname: "qwebirc"
16 },
17 initialize: function(options) {
18 this.setOptions(options);
19
20 this.toIRCLower = qwebirc.irc.RFC1459toIRCLower;
21
22 this.nickname = this.options.nickname;
23 this.lowerNickname = this.toIRCLower(this.nickname);
24
25 this.__signedOn = false;
26 this.pmodes = {b: true, k: true, o: true, l: true, v: true};
27 this.channels = {}
28 this.nextctcp = 0;
29
30 this.connection = new qwebirc.irc.IRCConnection({
31 initialNickname: this.nickname,
32 onRecv: this.dispatch.bind(this),
33 serverPassword: this.options.serverPassword
34 });
35
36 this.send = this.connection.send.bind(this.connection);
37 this.connect = this.connection.connect.bind(this.connection);
38 this.disconnect = this.connection.disconnect.bind(this.connection);
39
40 this.setupGenericErrors();
41 },
42 dispatch: function(data) {
43 var message = data[0];
44 if(message == "connect") {
45 this.connected();
46 } else if(message == "disconnect") {
47 if(data.length == 0) {
48 this.disconnected("No error!");
49 } else {
50 this.disconnected(data[1]);
51 }
52 this.disconnect();
53 } else if(message == "c") {
54 var command = data[1].toUpperCase();
55
56 var prefix = data[2];
57 var sl = data[3];
58 var n = qwebirc.irc.Numerics[command];
59
60 var x = n;
61 if(!n)
62 n = command;
63
64 var o = this["irc_" + n];
65
66 if(o) {
67 var r = o.run([prefix, sl], this);
68 if(!r)
69 this.rawNumeric(command, prefix, sl);
70 } else {
71 this.rawNumeric(command, prefix, sl);
72 }
73 }
74 },
75 isChannel: function(target) {
76 var c = target.charAt(0);
77 return c == '#';
78 },
79 supported: function(key, value) {
80 if(key == "CASEMAPPING") {
81 if(value == "ascii") {
82 this.toIRCLower = qwebirc.irc.ASCIItoIRCLower;
83 } else if(value == "rfc1459") {
84 /* IGNORE */
85 } else {
86 /* TODO: warn */
87 }
88 }
89 this.lowerNickname = this.toIRCLower(this.nickname);
90 },
91 irc_RPL_WELCOME: function(prefix, params) {
92 this.nickname = params[0];
93 this.lowerNickname = this.toIRCLower(this.nickname);
94 this.__signedOn = true;
95 this.signedOn(this.nickname);
96 },
97 irc_ERR_NICKNAMEINUSE: function(prefix, params) {
98 this.genericError(params[1], params.indexFromEnd(-1).replace("in use.", "in use"));
99
100 if(this.__signedOn)
101 return true;
102
103 var newnick = params[1] + "_";
104 if(newnick == this.lastnick)
105 newnick = "qwebirc" + Math.floor(Math.random() * 1024 * 1024);
106
107 this.send("NICK " + newnick);
108 this.lastnick = newnick;
109 return true;
110 },
111 irc_NICK: function(prefix, params) {
112 var user = prefix;
113 var oldnick = user.hostToNick();
114 var newnick = params[0];
115
116 if(this.nickname == oldnick) {
117 this.nickname = newnick;
118 this.lowerNickname = this.toIRCLower(this.nickname);
119 }
120
121 this.nickChanged(user, newnick);
122
123 return true;
124 },
125 irc_QUIT: function(prefix, params) {
126 var user = prefix;
127
128 var message = params.indexFromEnd(-1);
129
130 this.userQuit(user, message);
131
132 return true;
133 },
134 irc_PART: function(prefix, params) {
135 var user = prefix;
136 var channel = params[0];
137 var message = params[1];
138
139 var nick = user.hostToNick();
140
141 if((nick == this.nickname) && this.__getChannel(channel))
142 this.__killChannel(channel);
143
144 this.userPart(user, channel, message);
145
146 return true;
147 },
148 __getChannel: function(name) {
149 return this.channels[this.toIRCLower(name)];
150 },
151 __killChannel: function(name) {
152 delete this.channels[this.toIRCLower(name)];
153 },
154 __nowOnChannel: function(name) {
155 this.channels[this.toIRCLower(name)] = 1;
156 },
157 irc_KICK: function(prefix, params) {
158 var kicker = prefix;
159 var channel = params[0];
160 var kickee = params[1];
161 var message = params[2];
162
163 if((kickee == this.nickname) && this.__getChannel(channel))
164 this.__killChannel(channel);
165
166 this.userKicked(kicker, channel, kickee, message);
167
168 return true;
169 },
170 irc_PING: function(prefix, params) {
171 this.send("PONG :" + params.indexFromEnd(-1));
172
173 return true;
174 },
175 irc_JOIN: function(prefix, params) {
176 var channel = params[0];
177 var user = prefix;
178 var nick = user.hostToNick();
179
180 if(nick == this.nickname)
181 this.__nowOnChannel(channel);
182
183 this.userJoined(user, channel);
184
185 return true;
186 },
187 irc_TOPIC: function(prefix, params) {
188 var user = prefix;
189 var channel = params[0];
190 var topic = params.indexFromEnd(-1);
191
192 this.channelTopic(user, channel, topic);
193
194 return true;
195 },
196 processCTCP: function(message) {
197 if(message.charAt(0) != "\x01")
198 return;
199
200 if(message.charAt(message.length - 1) == "\x01") {
201 message = message.substr(1, message.length - 2);
202 } else {
203 message = message.substr(1);
204 }
205 return message.splitMax(" ", 2);
206 },
207 irc_PRIVMSG: function(prefix, params) {
208 var user = prefix;
209 var target = params[0];
210 var message = params.indexFromEnd(-1);
211
212 var ctcp = this.processCTCP(message);
213 if(ctcp) {
214 var type = ctcp[0].toUpperCase();
215
216 var replyfn = qwebirc.irc.RegisteredCTCPs[type];
217 if(replyfn) {
218 var t = new Date().getTime() / 1000;
219 if(t > this.nextctcp)
220 this.send("NOTICE " + user.hostToNick() + " :\x01" + type + " " + replyfn(ctcp[1]) + "\x01");
221 this.nextctcp = t + 5;
222 }
223
224 if(target == this.nickname) {
225 this.userCTCP(user, type, ctcp[1]);
226 } else {
227 this.channelCTCP(user, target, type, ctcp[1]);
228 }
229 } else {
230 if(target == this.nickname) {
231 this.userPrivmsg(user, message);
232 } else {
233 this.channelPrivmsg(user, target, message);
234 }
235 }
236
237 return true;
238 },
239 irc_NOTICE: function(prefix, params) {
240 var user = prefix;
241 var target = params[0];
242 var message = params.indexFromEnd(-1);
243
244 if((user == "") || (user.indexOf("!") == -1)) {
245 this.serverNotice(user, message);
246 } else if(target == this.nickname) {
247 var ctcp = this.processCTCP(message);
248 if(ctcp) {
249 this.userCTCPReply(user, ctcp[0], ctcp[1]);
250 } else {
251 this.userNotice(user, message);
252 }
253 } else {
254 this.channelNotice(user, target, message);
255 }
256
257 return true;
258 },
259 irc_INVITE: function(prefix, params) {
260 var user = prefix;
261 var channel = params.indexFromEnd(-1);
262
263 this.userInvite(user, channel);
264
265 return true;
266 },
267 irc_ERROR: function(prefix, params) {
268 var message = params.indexFromEnd(-1);
269
270 this.serverError(message);
271
272 return true;
273 },
274 irc_MODE: function(prefix, params) {
275 var user = prefix;
276 var target = params[0];
277 var args = params.slice(1);
278
279 if(target == this.nickname) {
280 this.userMode(args);
281 } else {
282 var modes = args[0].split("");
283 var xargs = args.slice(1);
284
285 var data = []
286 var carg = 0;
287 var pos = 0;
288 var cmode = "+";
289
290 modes.each(function(mode) {
291 if((mode == "+") || (mode == "-")) {
292 cmode = mode;
293 return;
294 }
295
296 var d;
297 if(this.pmodes[mode]) {
298 d = [cmode, mode, xargs[carg++]]
299 } else {
300 d = [cmode, mode]
301 }
302
303 data.push(d);
304 }, this);
305
306 this.channelMode(user, target, data, args);
307 }
308
309 return true;
310 },
311 irc_RPL_ISUPPORT: function(prefix, params) {
312 var supported = params.slice(1, -1);
313 var supportedhash = {};
314
315 for(var i=0;i<supported.length;i++) {
316 var l = supported[i].splitMax("=", 2);
317 this.supported(l[0], l[1]);
318 }
319 },
320 irc_RPL_MYINFO: function(prefix, params) {
321 if(params.length < 6)
322 return;
323
324 var pmodes = params[5].split("");
325 this.pmodes = {}
326
327 pmodes.each(function(pmode) {
328 this.pmodes[pmode] = true;
329 }, this);
330 },
331 irc_RPL_NAMREPLY: function(prefix, params) {
332 var channel = params[2];
333 var names = params[3];
334
335 this.channelNames(channel, names.split(" "));
336
337 return true;
338 },
339 irc_RPL_ENDOFNAMES: function(prefix, params) {
340 var channel = params[1];
341
342 this.channelNames(channel, []);
343 return true;
344 },
345 irc_RPL_NOTOPIC: function(prefix, params) {
346 var channel = params[1];
347
348 if(this.__getChannel(channel)) {
349 this.initialTopic(channel, "");
350 return true;
351 }
352 },
353 irc_RPL_TOPIC: function(prefix, params) {
354 var channel = params[1];
355 var topic = params.indexFromEnd(-1);
356
357 if(this.__getChannel(channel)) {
358 this.initialTopic(channel, topic);
359 return true;
360 }
361 },
362 irc_RPL_TOPICWHOTIME: function(prefix, params) {
363 return true;
364 },
365 irc_RPL_WHOISUSER: function(prefix, params) {
366 var nick = params[1];
367 this.whoisNick = nick;
368
369 return this.whois(nick, "user", {ident: params[2], hostname: params[3], realname: params.indexFromEnd(-1)});
370 },
371 irc_RPL_WHOISSERVER: function(prefix, params) {
372 var nick = params[1];
373 var server = params[2];
374 var serverdesc = params.indexFromEnd(-1);
375
376 return this.whois(nick, "server", {server: params[2], serverdesc: params.indexFromEnd(-1)});
377 },
378 irc_RPL_WHOISOPERATOR: function(prefix, params) {
379 var nick = params[1];
380 var text = params.indexFromEnd(-1);
381
382 return this.whois(nick, "oper", {opertext: params.indexFromEnd(-1)});
383 },
384 irc_RPL_WHOISIDLE: function(prefix, params) {
385 var nick = params[1];
386
387 return this.whois(nick, "idle", {idle: params[2], connected: params[3]});
388 },
389 irc_RPL_WHOISCHANNELS: function(prefix, params) {
390 var nick = params[1];
391
392 return this.whois(nick, "channels", {channels: params.indexFromEnd(-1)});
393 },
394 irc_RPL_WHOISACCOUNT: function(prefix, params) {
395 var nick = params[1];
396
397 return this.whois(nick, "account", {account: params[2]});
398 },
399 irc_RPL_WHOISACTUALLY: function(prefix, params) {
400 var nick = params[1];
401
402 return this.whois(nick, "actually", {hostmask: params[2], ip: params[3]});
403 },
404 irc_RPL_WHOISOPERNAME: function(prefix, params) {
405 var nick = params[1];
406 var opername = params[2];
407
408 return this.whois(nick, "opername", {opername: params[2]});
409 },
410 irc_RPL_WHOISGENERICTEXT: function(prefix, params) {
411 var nick = params[1];
412 var text = params.indexFromEnd(-1);
413
414 return this.whois(nick, "generictext", {text: text});
415 },
416 irc_RPL_WHOISWEBIRC: function(prefix, params) {
417 var nick = params[1];
418 var text = params.indexFromEnd(-1);
419
420 return this.whois(nick, "generictext", {text: text});
421 },
422 irc_RPL_WHOISSECURE: function(prefix, params) {
423 var nick = params[1];
424 var text = params.indexFromEnd(-1);
425
426 return this.whois(nick, "generictext", {text: text});
427 },
428 irc_RPL_ENDOFWHOIS: function(prefix, params) {
429 var nick = params[1];
430 var text = params.indexFromEnd(-1);
431 this.whoisNick = null;
432
433 return this.whois(nick, "end", {});
434 },
435 irc_genericError: function(prefix, params) {
436 var target = params[1];
437 var message = params.indexFromEnd(-1);
438
439 this.genericError(target, message);
440 return true;
441 },
442 irc_genericQueryError: function(prefix, params) {
443 var target = params[1];
444 var message = params.indexFromEnd(-1);
445
446 this.genericQueryError(target, message);
447 return true;
448 },
449 setupGenericErrors: function() {
450 this.irc_ERR_CHANOPPRIVSNEEDED = this.irc_ERR_CANNOTSENDTOCHAN = this.irc_genericError;
451 this.irc_ERR_NOSUCHNICK = this.irc_genericQueryError;
452 return true;
453 },
454 irc_RPL_AWAY: function(prefix, params) {
455 var nick = params[1];
456 var text = params.indexFromEnd(-1);
457
458 if(this.whoisNick && (this.whoisNick == nick))
459 return this.whois(nick, "away", {"away": text});
460
461 this.awayMessage(nick, text);
462 return true;
463 },
464 irc_RPL_NOWAWAY: function(prefix, params) {
465 this.awayStatus(true, params.indexFromEnd(-1));
466 return true;
467 },
468 irc_RPL_UNAWAY: function(prefix, params) {
469 this.awayStatus(false, params.indexFromEnd(-1));
470 return true;
471 },
472 irc_WALLOPS: function(prefix, params) {
473 var user = prefix;
474 var text = params.indexFromEnd(-1);
475
476 this.wallops(user, text);
477 return true;
478 },
479 irc_RPL_CREATIONTIME: function(prefix, params) {
480 var channel = params[1];
481 var time = params[2];
482
483 this.channelCreationTime(channel, time);
484 return true;
485 },
486 irc_RPL_CHANNELMODEIS: function(prefix, params) {
487 var channel = params[1];
488 var modes = params.slice(2);
489
490 this.channelModeIs(channel, modes);
491 return true;
492 }
493 });