]> jfr.im git - irc/quakenet/qwebirc.git/blob - js/irc/ircclient.js
1d14327f45e7200dd5b1c733e42d4e43bb4a3cbc
[irc/quakenet/qwebirc.git] / js / irc / ircclient.js
1 qwebirc.irc.IRCClient = new Class({
2 Extends: qwebirc.irc.BaseIRCClient,
3 options: {
4 nickname: "qwebirc",
5 autojoin: ""
6 },
7 initialize: function(options, ui) {
8 this.parent(options);
9
10 this.ui = ui;
11
12 this.prefixes = "@+";
13 this.modeprefixes = "ov";
14 this.windows = {};
15
16 this.commandparser = new qwebirc.irc.CommandParser(this);
17 this.exec = this.commandparser.dispatch.bind(this.commandparser);
18
19 this.statusWindow = this.ui.newClient(this);
20 },
21 newLine: function(window, type, data) {
22 if(!data)
23 data = {};
24
25 var w = this.getWindow(window);
26 if(w) {
27 w.addLine(type, data);
28 } else {
29 this.statusWindow.addLine(type, data);
30 }
31 },
32 newChanLine: function(channel, type, user, extra) {
33 if(!extra)
34 extra = {};
35
36 extra["n"] = user.hostToNick();
37 extra["h"] = user.hostToHost();
38 extra["c"] = channel;
39 extra["-"] = this.nickname;
40
41 this.newLine(channel, type, extra);
42 },
43 newServerLine: function(type, data) {
44 this.statusWindow.addLine(type, data);
45 },
46 newActiveLine: function(type, data) {
47 this.ui.getActiveWindow().addLine(type, data);
48 },
49 updateNickList: function(channel) {
50 var n1 = this.tracker.getChannel(channel);
51 var names = new Array();
52 var tff = String.fromCharCode(255);
53 var nh = {}
54
55 /* MEGAHACK */
56 for(var n in n1) {
57 var nc = n1[n];
58 var nx;
59
60 if(nc.prefixes.length > 0) {
61 var c = nc.prefixes.charAt(0);
62 nx = String.fromCharCode(this.prefixes.indexOf(c)) + n.toIRCLower();
63 nh[nx] = c + n;
64 } else {
65 nx = tff + n.toIRCLower();
66 nh[nx] = n;
67 }
68 names.push(nx);
69 };
70
71 names.sort();
72
73 var sortednames = new Array();
74 names.each(function(name) {
75 sortednames.push(nh[name]);
76 });
77
78 var w = this.getWindow(channel);
79 if(w)
80 w.updateNickList(sortednames);
81 },
82 getWindow: function(name) {
83 return this.windows[name];
84 },
85 newWindow: function(name, type, select) {
86 var w = this.getWindow(name);
87 if(!w) {
88 w = this.windows[name] = this.ui.newWindow(this, type, name);
89
90 w.addEvent("close", function(w) {
91 delete this.windows[name];
92 }.bind(this));
93 }
94
95 if(select)
96 this.ui.selectWindow(w);
97
98 return w;
99 },
100 getActiveWindow: function() {
101 return this.ui.getActiveWindow();
102 },
103 getNickname: function() {
104 return this.nickname;
105 },
106 addPrefix: function(nickchanentry, prefix) {
107 var ncp = nickchanentry.prefixes + prefix;
108 var prefixes = [];
109
110 /* O(n^2) */
111 for(var i=0;i<this.prefixes.length;i++) {
112 var pc = this.prefixes.charAt(i);
113 var index = ncp.indexOf(pc);
114 if(index != -1)
115 prefixes.push(pc);
116 }
117
118 nickchanentry.prefixes = prefixes.join("");
119 },
120 removePrefix: function(nickchanentry, prefix) {
121 nickchanentry.prefixes = nickchanentry.prefixes.replaceAll(prefix, "");
122 },
123
124 /* from here down are events */
125 rawNumeric: function(numeric, prefix, params) {
126 this.newServerLine("RAW", {"n": "numeric", "m": params.slice(1).join(" ")});
127 },
128 signedOn: function(nickname) {
129 this.tracker = new qwebirc.irc.IRCTracker();
130 this.nickname = nickname;
131 this.newServerLine("SIGNON");
132
133 if(this.options.autojoin)
134 this.send("JOIN " + this.options.autojoin);
135 },
136 userJoined: function(user, channel) {
137 var nick = user.hostToNick();
138 var host = user.hostToHost();
139
140 if((nick == this.nickname) && !this.getWindow(channel))
141 this.newWindow(channel, qwebirc.ui.WINDOW_CHANNEL, true);
142 this.tracker.addNickToChannel(nick, channel);
143
144 if(nick == this.nickname) {
145 this.newChanLine(channel, "OURJOIN", user);
146 } else {
147 this.newChanLine(channel, "JOIN", user);
148 }
149 this.updateNickList(channel);
150 },
151 userPart: function(user, channel, message) {
152 var nick = user.hostToNick();
153 var host = user.hostToHost();
154
155 if(nick == this.nickname) {
156 this.tracker.removeChannel(channel);
157 } else {
158 this.tracker.removeNickFromChannel(nick, channel);
159 this.newChanLine(channel, "PART", user, {"m": message});
160 }
161
162 this.updateNickList(channel);
163
164 if(nick == this.nickname) {
165 var w = this.getWindow(channel)
166 if(w)
167 w.close();
168 }
169 },
170 userKicked: function(kicker, channel, kickee, message) {
171 if(kickee == this.nickname) {
172 this.tracker.removeChannel(channel);
173 this.getWindow(channel).close();
174 } else {
175 this.tracker.removeNickFromChannel(kickee, channel);
176 this.updateNickList(channel);
177 }
178
179 this.newChanLine(channel, "KICK", kicker, {"v": kickee, "m": message});
180 },
181 channelMode: function(user, channel, modes, raw) {
182 modes.each(function(mo) {
183 var direction = mo[0];
184 var mode = mo[1];
185
186 var prefixindex = this.modeprefixes.indexOf(mode);
187 if(prefixindex == -1)
188 return;
189
190 var nick = mo[2];
191 var prefixchar = this.prefixes.charAt(prefixindex);
192
193 var nc = this.tracker.getOrCreateNickOnChannel(nick, channel);
194 if(direction == "-") {
195 this.removePrefix(nc, prefixchar);
196 } else {
197 this.addPrefix(nc, prefixchar);
198 }
199 }, this);
200
201 this.newChanLine(channel, "MODE", user, {"m": raw.join(" ")});
202
203 this.updateNickList(channel);
204 },
205 userQuit: function(user, message) {
206 var nick = user.hostToNick();
207
208 var channels = this.tracker.getNick(nick);
209
210 var clist = [];
211 for(var c in channels) {
212 clist.push(c);
213 this.newChanLine(c, "QUIT", user, {"m": message});
214 }
215
216 this.tracker.removeNick(nick);
217
218 clist.each(function(cli) {
219 this.updateNickList(cli);
220 }, this);
221 },
222 nickChanged: function(user, newnick) {
223 var oldnick = user.hostToNick();
224
225 if(oldnick == this.nickname)
226 this.nickname = newnick;
227
228 this.tracker.renameNick(oldnick, newnick);
229
230 var channels = this.tracker.getNick(newnick);
231
232 for(var c in channels) {
233 this.newChanLine(c, "NICK", user, {"w": newnick});
234 /* TODO: rename queries */
235 this.updateNickList(c);
236 }
237
238 this.newChanLine(undefined, "NICK", user, {"w": newnick});
239 },
240 channelTopic: function(user, channel, topic) {
241 this.newChanLine(channel, "TOPIC", user, {"m": topic});
242 this.getWindow(channel).updateTopic(topic);
243 },
244 initialTopic: function(channel, topic) {
245 this.getWindow(channel).updateTopic(topic);
246 },
247 channelCTCP: function(user, channel, type, args) {
248 if(args == undefined)
249 args = "";
250
251 if(type == "ACTION") {
252 this.newChanLine(channel, "CHANACTION", user, {"m": args, "c": channel});
253 return;
254 }
255
256 this.newChanLine(channel, "CHANCTCP", user, {"x": type, "m": args, "c": channel});
257 },
258 userCTCP: function(user, type, args) {
259 var nick = user.hostToNick();
260 var host = user.hostToHost();
261 if(args == undefined)
262 args = "";
263
264 if(type == "ACTION") {
265 this.newWindow(nick, qwebirc.ui.WINDOW_QUERY);
266 this.newLine(nick, "PRIVACTION", {"m": args, "x": type, "h": host, "n": nick});
267 return;
268 }
269
270 if(this.getWindow(nick)) {
271 this.newLine(nick, "PRIVCTCP", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
272 } else {
273 this.newActiveLine("PRIVCTCP", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
274 }
275 },
276 userCTCPReply: function(user, type, args) {
277 var nick = user.hostToNick();
278 var host = user.hostToHost();
279 if(args == undefined)
280 args = "";
281
282 if(this.getWindow(nick)) {
283 this.newLine(nick, "CTCPREPLY", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
284 } else {
285 this.newActiveLine("CTCPREPLY", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
286 }
287 },
288 channelPrivmsg: function(user, channel, message) {
289 this.newChanLine(channel, "CHANMSG", user, {"m": message});
290 },
291 channelNotice: function(user, channel, message) {
292 this.newChanLine(channel, "CHANNOTICE", user, {"m": message});
293 },
294 userPrivmsg: function(user, message) {
295 var nick = user.hostToNick();
296 var host = user.hostToHost();
297
298 this.newWindow(nick, qwebirc.ui.WINDOW_QUERY);
299
300 this.newLine(nick, "PRIVMSG", {"m": message, "h": host, "n": nick});
301 },
302 serverNotice: function(message) {
303 this.newServerLine("SERVERNOTICE", {"m": message});
304 },
305 userNotice: function(user, message) {
306 var nick = user.hostToNick();
307 var host = user.hostToHost();
308
309 if(this.getWindow(nick)) {
310 this.newLine(nick, "PRIVNOTICE", {"m": message, "h": host, "n": nick});
311 } else {
312 this.newActiveLine("PRIVNOTICE", {"m": message, "h": host, "n": nick});
313 }
314 },
315 userInvite: function(user, channel) {
316 var nick = user.hostToNick();
317 var host = user.hostToHost();
318
319 this.newServerLine("INVITE", {"c": channel, "h": host, "n": nick});
320 },
321 userMode: function(modes) {
322 this.newServerLine("UMODE", {"m": modes, "n": this.nickname});
323 },
324 channelNames: function(channel, names) {
325 if(names.length == 0) {
326 this.updateNickList(channel);
327 return;
328 }
329
330 names.each(function(nick) {
331 var prefixes = [];
332 var splitnick = nick.split("");
333
334 splitnick.every(function(c, i) {
335 if(this.prefixes.indexOf(c) == -1) {
336 nick = nick.substr(i);
337 return false;
338 }
339
340 prefixes.push(c);
341 return true;
342 }, this);
343
344 var nc = this.tracker.addNickToChannel(nick, channel);
345 prefixes.each(function(p) {
346 this.addPrefix(nc, p);
347 }, this);
348 }, this);
349 },
350 disconnected: function(message) {
351 for(var x in this.windows) {
352 var w = this.windows[x];
353 if(w.type == qwebirc.ui.WINDOW_CHANNEL)
354 w.close();
355 }
356 this.tracker = undefined;
357
358 this.newServerLine("DISCONNECT", {"m": message});
359 },
360 supported: function(key, value) {
361 if(key == "PREFIX") {
362 var l = (value.length - 2) / 2;
363
364 this.modeprefixes = value.substr(1, l);
365 this.prefixes = value.substr(l + 2, l);
366 }
367 },
368 connected: function() {
369 this.newServerLine("CONNECT");
370 },
371 serverError: function(message) {
372 this.newServerLine("ERROR", {"m": message});
373 },
374 quit: function(message) {
375 this.send("QUIT :" + message);
376 this.disconnect();
377 }
378 });