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