1 qwebirc
.irc
.PMODE_LIST
= 0;
2 qwebirc
.irc
.PMODE_SET_UNSET
= 1;
3 qwebirc
.irc
.PMODE_SET_ONLY
= 2;
4 qwebirc
.irc
.PMODE_REGULAR_MODE
= 3;
6 qwebirc
.irc
.RegisteredCTCPs
= new QHash({
7 "VERSION": function(x
) {
8 return "qwebirc v" + qwebirc
.VERSION
+ ", copyright (C) 2008-2018 Chris Porter and the qwebirc project -- transport: " + this.connection
.transportStatus
+ " -- " + qwebirc
.util
.browserVersion();
10 "USERINFO": function(x
) { return "qwebirc"; },
11 "TIME": function(x
) { return qwebirc
.irc
.IRCDate(new Date()); },
12 "PING": function(x
) { return x
; },
13 "CLIENTINFO": function(x
) { return "PING VERSION TIME USERINFO CLIENTINFO WEBSITE"; },
14 "WEBSITE": function(x
) { return window
== window
.top
? "direct" : document
.referrer
; }
17 qwebirc
.irc
.BaseIRCClient
= new Class({
18 Implements: [Options
, Events
],
22 initialize: function(options
) {
23 this.setOptions(options
);
25 this.toIRCLower
= qwebirc
.irc
.RFC1459toIRCLower
;
27 this.nickname
= this.options
.nickname
;
28 this.lowerNickname
= this.toIRCLower(this.nickname
);
30 this.__signedOn
= false;
31 this.pmodes
= new QHash({b: qwebirc
.irc
.PMODE_LIST
, l: qwebirc
.irc
.PMODE_SET_ONLY
, k: qwebirc
.irc
.PMODE_SET_UNSET
, o: qwebirc
.irc
.PMODE_SET_UNSET
, v: qwebirc
.irc
.PMODE_SET_UNSET
});
32 this.channels
= new QSet();
33 this.chanPrefixes
= new QSet("#", "&");
36 this.connection
= new qwebirc
.irc
.IRCConnection({
37 initialNickname: this.nickname
,
38 onRecv: this.dispatch
.bind(this),
39 serverPassword: this.options
.serverPassword
42 this.send
= this.connection
.send
.bind(this.connection
);
43 this.disconnect
= this.connection
.disconnect
.bind(this.connection
);
45 this.setupGenericErrors();
48 this.connection
.connect
.apply(this.connection
);
50 dispatch: function(data
) {
51 var message
= data
[0];
52 if(message
== "connect") {
54 } else if(message
== "disconnect") {
55 if(data
.length
== 0) {
56 this.disconnected("No error!");
58 this.disconnected(data
[1]);
61 } else if(message
== "c") {
62 var command
= data
[1].toUpperCase();
66 var n
= qwebirc
.irc
.Numerics
.get(command
);
72 var o
= this["irc_" + n
];
75 var r
= o
.run([prefix
, sl
], this);
77 this.rawNumeric(command
, prefix
, sl
);
79 this.rawNumeric(command
, prefix
, sl
);
83 isChannel: function(target
) {
84 var c
= target
.charAt(0);
85 return this.chanPrefixes
.contains(c
);
87 supported: function(key
, value
) {
88 if(key
== "CASEMAPPING") {
89 if(value
== "ascii") {
90 this.toIRCLower
= qwebirc
.irc
.ASCIItoIRCLower
;
91 } else if(value
== "rfc1459") {
96 this.lowerNickname
= this.toIRCLower(this.nickname
);
97 } else if(key
== "CHANMODES") {
98 var smodes
= value
.split(",");
99 for(var i
=0;i
<smodes
.length
;i
++)
100 for(var j
=0;j
<smodes
[i
].length
;j
++)
101 this.pmodes
.put(smodes
[i
].charAt(j
), i
);
102 } else if(key
== "CHANTYPES") {
103 this.chanPrefixes
= new QSet();
104 for(var i
=0;i
<value
.length
;i
++)
105 this.chanPrefixes
.add(value
.charAt(i
));
106 } else if(key
== "PREFIX") {
107 var l
= (value
.length
- 2) / 2;
109 var modeprefixes
= value
.substr(1, l
).split("");
110 modeprefixes
.each(function(modeprefix
) {
111 this.pmodes
.put(modeprefix
, qwebirc
.irc
.PMODE_SET_UNSET
);
115 irc_RPL_WELCOME: function(prefix
, params
) {
116 this.nickname
= params
[0];
117 this.lowerNickname
= this.toIRCLower(this.nickname
);
118 this.__signedOn
= true;
119 this.signedOn(this.nickname
);
121 irc_ERR_NICKNAMEINUSE: function(prefix
, params
) {
122 this.genericError(params
[1], params
.indexFromEnd(-1).replace("in use.", "in use"));
127 var newnick
= params
[1] + "_";
128 if(newnick
== this.lastnick
)
129 newnick
= "qwebirc" + Math
.floor(Math
.random() * 1024 * 1024);
131 this.send("NICK " + newnick
);
132 this.lastnick
= newnick
;
135 irc_NICK: function(prefix
, params
) {
137 var oldnick
= user
.hostToNick();
138 var newnick
= params
[0];
140 if(this.nickname
== oldnick
) {
141 this.nickname
= newnick
;
142 this.lowerNickname
= this.toIRCLower(this.nickname
);
145 this.nickChanged(user
, newnick
);
149 irc_QUIT: function(prefix
, params
) {
152 var message
= params
.indexFromEnd(-1);
154 this.userQuit(user
, message
);
158 irc_PART: function(prefix
, params
) {
160 var channel
= params
[0];
161 var message
= params
[1];
163 var nick
= user
.hostToNick();
165 if((nick
== this.nickname
) && this.__getChannel(channel
))
166 this.__killChannel(channel
);
168 this.userPart(user
, channel
, message
);
172 __getChannel: function(name
) {
173 return this.channels
.contains(this.toIRCLower(name
));
175 __killChannel: function(name
) {
176 this.channels
.remove(this.toIRCLower(name
));
178 __nowOnChannel: function(name
) {
179 this.channels
.add(this.toIRCLower(name
));
181 irc_KICK: function(prefix
, params
) {
183 var channel
= params
[0];
184 var kickee
= params
[1];
185 var message
= params
[2];
187 if((kickee
== this.nickname
) && this.__getChannel(channel
))
188 this.__killChannel(channel
);
190 this.userKicked(kicker
, channel
, kickee
, message
);
194 irc_PING: function(prefix
, params
) {
195 this.send("PONG :" + params
.indexFromEnd(-1));
199 irc_JOIN: function(prefix
, params
) {
200 var channel
= params
[0];
202 var nick
= user
.hostToNick();
204 if(nick
== this.nickname
)
205 this.__nowOnChannel(channel
);
207 this.userJoined(user
, channel
);
211 irc_TOPIC: function(prefix
, params
) {
213 var channel
= params
[0];
214 var topic
= params
.indexFromEnd(-1);
216 this.channelTopic(user
, channel
, topic
);
220 processCTCP: function(message
) {
221 if(message
.charAt(0) != "\x01")
224 if(message
.charAt(message
.length
- 1) == "\x01") {
225 message
= message
.substr(1, message
.length
- 2);
227 message
= message
.substr(1);
229 return message
.splitMax(" ", 2);
231 irc_PRIVMSG: function(prefix
, params
) {
233 var target
= params
[0];
234 var message
= params
.indexFromEnd(-1);
236 var ctcp
= this.processCTCP(message
);
238 var type
= ctcp
[0].toUpperCase();
240 var replyfn
= qwebirc
.irc
.RegisteredCTCPs
.get(type
);
242 var t
= new Date().getTime() / 1000;
243 if(t
> this.nextctcp
) {
244 this.send("NOTICE " + user
.hostToNick() + " :\x01" + type
+ " " + replyfn
.call(this, ctcp
[1]) + "\x01");
245 this.nextctcp
= t
+ 10;
249 if(target
== this.nickname
) {
250 this.userCTCP(user
, type
, ctcp
[1]);
252 this.channelCTCP(user
, target
, type
, ctcp
[1]);
255 if(target
== this.nickname
) {
256 this.userPrivmsg(user
, message
);
258 this.channelPrivmsg(user
, target
, message
);
264 irc_NOTICE: function(prefix
, params
) {
266 var target
= params
[0];
267 var message
= params
.indexFromEnd(-1);
269 if((user
== "") || (user
.indexOf("!") == -1)) {
270 this.serverNotice(user
, message
);
271 } else if(target
== this.nickname
) {
272 var ctcp
= this.processCTCP(message
);
274 this.userCTCPReply(user
, ctcp
[0], ctcp
[1]);
276 this.userNotice(user
, message
);
279 this.channelNotice(user
, target
, message
);
284 irc_INVITE: function(prefix
, params
) {
286 var channel
= params
.indexFromEnd(-1);
288 this.userInvite(user
, channel
);
292 irc_ERROR: function(prefix
, params
) {
293 var message
= params
.indexFromEnd(-1);
295 this.serverError(message
);
299 irc_MODE: function(prefix
, params
) {
301 var target
= params
[0];
302 var args
= params
.slice(1);
304 if(target
== this.nickname
) {
307 var modes
= args
[0].split("");
308 var xargs
= args
.slice(1);
315 modes
.each(function(mode
) {
316 if((mode
== "+") || (mode
== "-")) {
322 var pmode
= this.pmodes
.get(mode
);
323 if(pmode
== qwebirc
.irc
.PMODE_LIST
|| pmode
== qwebirc
.irc
.PMODE_SET_UNSET
|| (cmode
== "+" && pmode
== qwebirc
.irc
.PMODE_SET_ONLY
)) {
324 d
= [cmode
, mode
, xargs
[carg
++]]
332 this.channelMode(user
, target
, data
, args
);
337 irc_RPL_ISUPPORT: function(prefix
, params
) {
338 var supported
= params
.slice(1, -1);
340 var items
= new QSet();
341 for(var i
=0;i
<supported
.length
;i
++) {
342 var l
= supported
[i
].splitMax("=", 2);
346 if(items
.contains("CHANMODES") && items
.contains("PREFIX")) /* nasty hack */
347 this.pmodes
= new QHash();
349 for(var i
=0;i
<supported
.length
;i
++) {
350 var l
= supported
[i
].splitMax("=", 2);
351 this.supported(l
[0], l
[1]);
354 irc_RPL_NAMREPLY: function(prefix
, params
) {
355 var channel
= params
[2];
356 var names
= params
[3];
358 this.channelNames(channel
, names
.split(" "));
362 irc_RPL_ENDOFNAMES: function(prefix
, params
) {
363 var channel
= params
[1];
365 this.channelNames(channel
, []);
368 irc_RPL_NOTOPIC: function(prefix
, params
) {
369 var channel
= params
[1];
371 if(this.__getChannel(channel
)) {
372 this.initialTopic(channel
, "");
376 irc_RPL_TOPIC: function(prefix
, params
) {
377 var channel
= params
[1];
378 var topic
= params
.indexFromEnd(-1);
380 if(this.__getChannel(channel
)) {
381 this.initialTopic(channel
, topic
);
385 irc_RPL_TOPICWHOTIME: function(prefix
, params
) {
388 irc_RPL_WHOISUSER: function(prefix
, params
) {
389 var nick
= params
[1];
390 this.whoisNick
= nick
;
392 return this.whois(nick
, "user", {ident: params
[2], hostname: params
[3], realname: params
.indexFromEnd(-1)});
394 irc_RPL_WHOISSERVER: function(prefix
, params
) {
395 var nick
= params
[1];
396 var server
= params
[2];
397 var serverdesc
= params
.indexFromEnd(-1);
399 return this.whois(nick
, "server", {server: params
[2], serverdesc: params
.indexFromEnd(-1)});
401 irc_RPL_WHOISOPERATOR: function(prefix
, params
) {
402 var nick
= params
[1];
403 var text
= params
.indexFromEnd(-1);
405 return this.whois(nick
, "oper", {opertext: params
.indexFromEnd(-1)});
407 irc_RPL_WHOISIDLE: function(prefix
, params
) {
408 var nick
= params
[1];
410 return this.whois(nick
, "idle", {idle: params
[2], connected: params
[3]});
412 irc_RPL_WHOISCHANNELS: function(prefix
, params
) {
413 var nick
= params
[1];
415 return this.whois(nick
, "channels", {channels: params
.indexFromEnd(-1)});
417 irc_RPL_WHOISACCOUNT: function(prefix
, params
) {
418 var nick
= params
[1];
420 return this.whois(nick
, "account", {account: params
[2]});
422 irc_RPL_WHOISACTUALLY: function(prefix
, params
) {
423 var nick
= params
[1];
425 return this.whois(nick
, "actually", {hostmask: params
[2], ip: params
[3]});
427 irc_RPL_WHOISOPERNAME: function(prefix
, params
) {
428 var nick
= params
[1];
429 var opername
= params
[2];
431 return this.whois(nick
, "opername", {opername: params
[2]});
433 irc_RPL_WHOISGENERICTEXT: function(prefix
, params
) {
434 var nick
= params
[1];
435 var text
= params
.indexFromEnd(-1);
437 return this.whois(nick
, "generictext", {text: text
});
439 irc_RPL_WHOISWEBIRC: function(prefix
, params
) {
440 var nick
= params
[1];
441 var text
= params
.indexFromEnd(-1);
443 return this.whois(nick
, "generictext", {text: text
});
445 irc_RPL_WHOISSECURE: function(prefix
, params
) {
446 var nick
= params
[1];
447 var text
= params
.indexFromEnd(-1);
449 return this.whois(nick
, "generictext", {text: text
});
451 irc_RPL_ENDOFWHOIS: function(prefix
, params
) {
452 var nick
= params
[1];
453 var text
= params
.indexFromEnd(-1);
454 this.whoisNick
= null;
456 return this.whois(nick
, "end", {});
458 irc_genericError: function(prefix
, params
) {
459 var target
= params
[1];
460 var message
= params
.indexFromEnd(-1);
462 this.genericError(target
, message
);
465 irc_genericQueryError: function(prefix
, params
) {
466 var target
= params
[1];
467 var message
= params
.indexFromEnd(-1);
469 this.genericQueryError(target
, message
);
472 setupGenericErrors: function() {
473 this.irc_ERR_CHANOPPRIVSNEEDED
= this.irc_ERR_CANNOTSENDTOCHAN
= this.irc_genericError
;
474 this.irc_ERR_NOSUCHNICK
= this.irc_genericQueryError
;
477 irc_RPL_AWAY: function(prefix
, params
) {
478 var nick
= params
[1];
479 var text
= params
.indexFromEnd(-1);
481 if(this.whoisNick
&& (this.whoisNick
== nick
))
482 return this.whois(nick
, "away", {"away": text
});
484 this.awayMessage(nick
, text
);
487 irc_RPL_NOWAWAY: function(prefix
, params
) {
488 this.awayStatus(true, params
.indexFromEnd(-1));
491 irc_RPL_UNAWAY: function(prefix
, params
) {
492 this.awayStatus(false, params
.indexFromEnd(-1));
495 irc_WALLOPS: function(prefix
, params
) {
497 var text
= params
.indexFromEnd(-1);
499 this.wallops(user
, text
);
502 irc_RPL_CREATIONTIME: function(prefix
, params
) {
503 var channel
= params
[1];
504 var time
= params
[2];
506 this.channelCreationTime(channel
, time
);
509 irc_RPL_CHANNELMODEIS: function(prefix
, params
) {
510 var channel
= params
[1];
511 var modes
= params
.slice(2);
513 this.channelModeIs(channel
, modes
);
516 irc_SILENCE: function(prefix
, params
) {
517 var host
= params
[0];
521 irc_QWEBIRCIMAGE: function(prefix
, params
) {
522 var target
= params
[0];
523 var url
= params
.indexFromEnd(-1);
524 return this.qwebircImage(target
, url
);