]>
jfr.im git - irc/quakenet/qwebirc.git/blob - js/irc/ircclient.js
5d138a30f5a1f4d6e46992bf3732445d83ec3470
1 qwebirc
.irc
.IRCClient
= new Class({
2 Extends: qwebirc
.irc
.BaseIRCClient
,
8 initialize: function(options
, ui
) {
14 this.modeprefixes
= "ov";
17 this.commandparser
= new qwebirc
.irc
.CommandParser(this);
18 this.exec
= this.commandparser
.dispatch
.bind(this.commandparser
);
20 this.statusWindow
= this.ui
.newClient(this);
23 this.inviteChanList
= [];
24 this.activeTimers
= {};
26 newLine: function(window
, type
, data
) {
30 var w
= this.getWindow(window
);
32 w
.addLine(type
, data
);
34 this.statusWindow
.addLine(type
, data
);
37 newChanLine: function(channel
, type
, user
, extra
) {
41 extra
["n"] = user
.hostToNick();
42 extra
["h"] = user
.hostToHost();
44 extra
["-"] = this.nickname
;
46 this.newLine(channel
, type
, extra
);
48 newServerLine: function(type
, data
) {
49 this.statusWindow
.addLine(type
, data
);
51 newActiveLine: function(type
, data
) {
52 this.getActiveWindow().addLine(type
, data
);
54 newTargetOrActiveLine: function(target
, type
, data
) {
55 if(this.getWindow(target
)) {
56 this.newLine(target
, type
, data
);
58 this.newActiveLine(type
, data
);
61 updateNickList: function(channel
) {
62 var n1
= this.tracker
.getChannel(channel
);
63 var names
= new Array();
64 var tff
= String
.fromCharCode(255);
72 if(nc
.prefixes
.length
> 0) {
73 var c
= nc
.prefixes
.charAt(0);
74 nx
= String
.fromCharCode(this.prefixes
.indexOf(c
)) + n
.toIRCLower();
77 nx
= tff
+ n
.toIRCLower();
85 var sortednames
= new Array();
86 names
.each(function(name
) {
87 sortednames
.push(nh
[name
]);
90 var w
= this.getWindow(channel
);
92 w
.updateNickList(sortednames
);
94 getWindow: function(name
) {
95 return this.windows
[name
.toIRCLower()];
97 newWindow: function(name
, type
, select
) {
98 var w
= this.getWindow(name
);
100 w
= this.windows
[name
.toIRCLower()] = this.ui
.newWindow(this, type
, name
);
102 w
.addEvent("close", function(w
) {
103 delete this.windows
[name
.toIRCLower()];
108 this.ui
.selectWindow(w
);
112 getQueryWindow: function(name
) {
113 return this.ui
.getWindow(this, qwebirc
.ui
.WINDOW_QUERY
, name
);
115 newQueryWindow: function(name
, privmsg
) {
118 e
= this.ui
.uiOptions
.DEDICATED_MSG_WINDOW
;
120 e
= this.ui
.uiOptions
.DEDICATED_NOTICE_WINDOW
;
122 if(e
&& !this.ui
.getWindow(this, qwebirc
.ui
.WINDOW_MESSAGES
) && !this.getQueryWindow(name
))
123 return this.ui
.newWindow(this, qwebirc
.ui
.WINDOW_MESSAGES
, "Messages");
126 return this.newWindow(name
, qwebirc
.ui
.WINDOW_QUERY
, false);
128 newQueryLine: function(window
, type
, data
, privmsg
, active
) {
129 if(this.getQueryWindow(window
))
130 return this.newLine(window
, type
, data
);
132 var w
= this.ui
.getWindow(this, qwebirc
.ui
.WINDOW_MESSAGES
);
136 e
= this.ui
.uiOptions
.DEDICATED_MSG_WINDOW
;
138 e
= this.ui
.uiOptions
.DEDICATED_NOTICE_WINDOW
;
141 return w
.addLine(type
, data
);
144 return this.newActiveLine(window
, type
, data
);
146 return this.newLine(window
, type
, data
);
150 newQueryOrActiveLine: function(window
, type
, data
, privmsg
) {
151 this.newQueryLine(window
, type
, data
, privmsg
, true);
153 getActiveWindow: function() {
154 return this.ui
.getActiveIRCWindow(this);
156 getNickname: function() {
157 return this.nickname
;
159 addPrefix: function(nickchanentry
, prefix
) {
160 var ncp
= nickchanentry
.prefixes
+ prefix
;
164 for(var i
=0;i
<this.prefixes
.length
;i
++) {
165 var pc
= this.prefixes
.charAt(i
);
166 var index
= ncp
.indexOf(pc
);
171 nickchanentry
.prefixes
= prefixes
.join("");
173 stripPrefix: function(nick
) {
174 var l
= nick
.charAt(0);
178 if(this.prefixes
.indexOf(l
) != -1)
179 return nick
.substring(1);
183 removePrefix: function(nickchanentry
, prefix
) {
184 nickchanentry
.prefixes
= nickchanentry
.prefixes
.replaceAll(prefix
, "");
187 /* from here down are events */
188 rawNumeric: function(numeric
, prefix
, params
) {
189 this.newServerLine("RAW", {"n": "numeric", "m": params
.slice(1).join(" ")});
191 signedOn: function(nickname
) {
192 this.tracker
= new qwebirc
.irc
.IRCTracker();
193 this.nickname
= nickname
;
194 this.newServerLine("SIGNON");
196 if(this.options
.autojoin
)
197 this.commandparser
.dispatch("/JOIN " + this.options
.autojoin
);
199 userJoined: function(user
, channel
) {
200 var nick
= user
.hostToNick();
201 var host
= user
.hostToHost();
203 if((nick
== this.nickname
) && !this.getWindow(channel
))
204 this.newWindow(channel
, qwebirc
.ui
.WINDOW_CHANNEL
, true);
205 this.tracker
.addNickToChannel(nick
, channel
);
207 if(nick
== this.nickname
) {
208 this.newChanLine(channel
, "OURJOIN", user
);
210 this.newChanLine(channel
, "JOIN", user
);
212 this.updateNickList(channel
);
214 userPart: function(user
, channel
, message
) {
215 var nick
= user
.hostToNick();
216 var host
= user
.hostToHost();
218 if(nick
== this.nickname
) {
219 this.tracker
.removeChannel(channel
);
221 this.tracker
.removeNickFromChannel(nick
, channel
);
222 this.newChanLine(channel
, "PART", user
, {"m": message
});
225 this.updateNickList(channel
);
227 if(nick
== this.nickname
) {
228 var w
= this.getWindow(channel
)
233 userKicked: function(kicker
, channel
, kickee
, message
) {
234 if(kickee
== this.nickname
) {
235 this.tracker
.removeChannel(channel
);
236 this.getWindow(channel
).close();
238 this.tracker
.removeNickFromChannel(kickee
, channel
);
239 this.updateNickList(channel
);
242 this.newChanLine(channel
, "KICK", kicker
, {"v": kickee
, "m": message
});
244 channelMode: function(user
, channel
, modes
, raw
) {
245 modes
.each(function(mo
) {
246 var direction
= mo
[0];
249 var prefixindex
= this.modeprefixes
.indexOf(mode
);
250 if(prefixindex
== -1)
254 var prefixchar
= this.prefixes
.charAt(prefixindex
);
256 var nc
= this.tracker
.getOrCreateNickOnChannel(nick
, channel
);
257 if(direction
== "-") {
258 this.removePrefix(nc
, prefixchar
);
260 this.addPrefix(nc
, prefixchar
);
264 this.newChanLine(channel
, "MODE", user
, {"m": raw
.join(" ")});
266 this.updateNickList(channel
);
268 userQuit: function(user
, message
) {
269 var nick
= user
.hostToNick();
271 var channels
= this.tracker
.getNick(nick
);
274 for(var c
in channels
) {
276 this.newChanLine(c
, "QUIT", user
, {"m": message
});
279 this.tracker
.removeNick(nick
);
281 clist
.each(function(cli
) {
282 this.updateNickList(cli
);
285 nickChanged: function(user
, newnick
) {
286 var oldnick
= user
.hostToNick();
288 if(oldnick
== this.nickname
)
289 this.nickname
= newnick
;
291 this.tracker
.renameNick(oldnick
, newnick
);
293 var channels
= this.tracker
.getNick(newnick
);
296 for(var c
in channels
) {
299 this.newChanLine(c
, "NICK", user
, {"w": newnick
});
300 /* TODO: rename queries */
301 this.updateNickList(c
);
305 this.newChanLine(undefined, "NICK", user
, {"w": newnick
});
307 channelTopic: function(user
, channel
, topic
) {
308 this.newChanLine(channel
, "TOPIC", user
, {"m": topic
});
309 this.getWindow(channel
).updateTopic(topic
);
311 initialTopic: function(channel
, topic
) {
312 this.getWindow(channel
).updateTopic(topic
);
314 channelCTCP: function(user
, channel
, type
, args
) {
315 if(args
== undefined)
318 var nick
= user
.hostToNick();
319 if(type
== "ACTION") {
320 this.tracker
.updateLastSpoke(nick
, channel
, new Date().getTime());
321 this.newChanLine(channel
, "CHANACTION", user
, {"m": args
, "c": channel
, "@": this.getNickStatus(channel
, nick
)});
325 this.newChanLine(channel
, "CHANCTCP", user
, {"x": type
, "m": args
, "c": channel
, "@": this.getNickStatus(channel
, nick
)});
327 userCTCP: function(user
, type
, args
) {
328 var nick
= user
.hostToNick();
329 var host
= user
.hostToHost();
330 if(args
== undefined)
333 if(type
== "ACTION") {
334 this.newQueryWindow(nick
, true);
335 this.newQueryLine(nick
, "PRIVACTION", {"m": args
, "x": type
, "h": host
, "n": nick
}, true);
339 this.newTargetOrActiveLine(nick
, "PRIVCTCP", {"m": args
, "x": type
, "h": host
, "n": nick
, "-": this.nickname
});
341 userCTCPReply: function(user
, type
, args
) {
342 var nick
= user
.hostToNick();
343 var host
= user
.hostToHost();
344 if(args
== undefined)
347 this.newTargetOrActiveLine(nick
, "CTCPREPLY", {"m": args
, "x": type
, "h": host
, "n": nick
, "-": this.nickname
});
349 getNickStatus: function(channel
, nick
) {
350 var n
= this.tracker
.getNickOnChannel(nick
, channel
);
354 if(n
.prefixes
.length
== 0)
357 return n
.prefixes
.charAt(0);
359 channelPrivmsg: function(user
, channel
, message
) {
360 var nick
= user
.hostToNick();
362 this.tracker
.updateLastSpoke(nick
, channel
, new Date().getTime());
363 this.newChanLine(channel
, "CHANMSG", user
, {"m": message
, "@": this.getNickStatus(channel
, nick
)});
365 channelNotice: function(user
, channel
, message
) {
366 this.newChanLine(channel
, "CHANNOTICE", user
, {"m": message
, "@": this.getNickStatus(channel
, user
.hostToNick())});
368 userPrivmsg: function(user
, message
) {
369 var nick
= user
.hostToNick();
370 var host
= user
.hostToHost();
372 this.newQueryWindow(nick
, true);
373 this.pushLastNick(nick
);
374 this.newQueryLine(nick
, "PRIVMSG", {"m": message
, "h": host
, "n": nick
}, true);
376 serverNotice: function(user
, message
) {
378 this.newServerLine("SERVERNOTICE", {"m": message
});
380 this.newServerLine("PRIVNOTICE", {"m": message
, "n": user
});
383 userNotice: function(user
, message
) {
384 var nick
= user
.hostToNick();
385 var host
= user
.hostToHost();
387 if(this.ui
.uiOptions
.DEDICATED_NOTICE_WINDOW
) {
388 this.newQueryWindow(nick
, false);
389 this.newQueryOrActiveLine(nick
, "PRIVNOTICE", {"m": message
, "h": host
, "n": nick
}, false);
391 this.newTargetOrActiveLine(nick
, "PRIVNOTICE", {"m": message
, "h": host
, "n": nick
});
394 isNetworkService: function(user
) {
396 return user
== "Q!TheQBot@CServe.quakenet.org";
398 __joinInvited: function() {
399 this.exec("/JOIN " + this.inviteChanList
.join(","));
400 this.inviteChanList
= [];
401 delete this.activeTimers
["serviceInvite"];
403 userInvite: function(user
, channel
) {
404 var nick
= user
.hostToNick();
405 var host
= user
.hostToHost();
407 this.newServerLine("INVITE", {"c": channel
, "h": host
, "n": nick
});
408 if(this.ui
.uiOptions
.ACCEPT_SERVICE_INVITES
&& this.isNetworkService(user
)) {
409 if(this.activeTimers
.serviceInvite
)
410 $clear(this.activeTimers
.serviceInvite
);
412 /* we do this so we can batch the joins, i.e. instead of sending 5 JOIN comands we send 1 with 5 channels. */
413 this.activeTimers
.serviceInvite
= this.__joinInvited
.delay(100, this);
415 this.inviteChanList
.push(channel
);
418 userMode: function(modes
) {
419 this.newServerLine("UMODE", {"m": modes
, "n": this.nickname
});
421 channelNames: function(channel
, names
) {
422 if(names
.length
== 0) {
423 this.updateNickList(channel
);
427 names
.each(function(nick
) {
429 var splitnick
= nick
.split("");
431 splitnick
.every(function(c
, i
) {
432 if(this.prefixes
.indexOf(c
) == -1) {
433 nick
= nick
.substr(i
);
441 var nc
= this.tracker
.addNickToChannel(nick
, channel
);
442 prefixes
.each(function(p
) {
443 this.addPrefix(nc
, p
);
447 disconnected: function(message
) {
448 for(var x
in this.windows
) {
449 var w
= this.windows
[x
];
450 if(w
.type
== qwebirc
.ui
.WINDOW_CHANNEL
)
453 this.tracker
= undefined;
455 this.newServerLine("DISCONNECT", {"m": message
});
457 supported: function(key
, value
) {
458 if(key
== "PREFIX") {
459 var l
= (value
.length
- 2) / 2;
461 this.modeprefixes
= value
.substr(1, l
);
462 this.prefixes
= value
.substr(l
+ 2, l
);
465 connected: function() {
466 this.newServerLine("CONNECT");
468 serverError: function(message
) {
469 this.newServerLine("ERROR", {"m": message
});
471 quit: function(message
) {
472 this.send("QUIT :" + message
);
475 disconnect: function() {
476 for(var k
in this.activeTimers
) {
477 this.activeTimers
[k
].cancel();
479 this.activeTimers
= {};
483 awayMessage: function(nick
, message
) {
484 this.newQueryLine(nick
, "AWAY", {"n": nick
, "m": message
}, true);
486 whois: function(nick
, type
, data
) {
487 var ndata
= {"n": nick
};
490 var xsend = function() {
491 this.newTargetOrActiveLine(nick
, "WHOIS" + mtype
, ndata
);
496 ndata
.h
= data
.ident
+ "@" + data
.hostname
;
499 ndata
.m
= data
.realname
;
500 } else if(type
== "server") {
502 ndata
.x
= data
.server
;
503 ndata
.m
= data
.serverdesc
;
504 } else if(type
== "oper") {
506 } else if(type
== "idle") {
508 ndata
.x
= qwebirc
.util
.longtoduration(data
.idle
);
509 ndata
.m
= qwebirc
.irc
.IRCDate(new Date(data
.connected
* 1000));
510 } else if(type
== "channels") {
512 ndata
.m
= data
.channels
;
513 } else if(type
== "account") {
515 ndata
.m
= data
.account
;
516 } else if(type
== "away") {
519 } else if(type
== "opername") {
521 ndata
.m
= data
.opername
;
522 } else if(type
== "actually") {
524 ndata
.m
= data
.hostname
;
526 } else if(type
== "end") {
535 genericError: function(target
, message
) {
536 this.newTargetOrActiveLine(target
, "GENERICERROR", {m: message
, t: target
});
538 genericQueryError: function(target
, message
) {
539 this.newQueryOrActiveLine(target
, "GENERICERROR", {m: message
, t: target
}, true);
541 awayStatus: function(state
, message
) {
542 this.newActiveLine("GENERICMESSAGE", {m: message
});
544 pushLastNick: function(nick
) {
545 var i
= this.lastNicks
.indexOf(nick
);
547 this.lastNicks
.splice(i
, 1);
549 if(this.lastNicks
.length
== this.options
.maxnicks
)
550 this.lastNicks
.pop();
552 this.lastNicks
.unshift(nick
);