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