]> jfr.im git - irc/quakenet/qwebirc.git/blob - js/irc/ircclient.js
Dos2Unix
[irc/quakenet/qwebirc.git] / js / irc / ircclient.js
1 var IRCClient = new Class({
2 Extends: BaseIRCClient,
3 options: {
4 nickname: "WCunset",
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 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 IRCTracker();
130 this.nickname = nickname;
131 this.newServerLine("SIGNON");
132
133 if(this.autojoin)
134 this.send("JOIN " + this.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, WINDOW_CHANNEL, true);
142 this.tracker.addNickToChannel(nick, channel);
143
144 this.newChanLine(channel, "JOIN", user);
145 this.updateNickList(channel);
146 },
147 userPart: function(user, channel, message) {
148 var nick = user.hostToNick();
149 var host = user.hostToHost();
150
151 if(nick == this.nickname) {
152 this.tracker.removeChannel(channel);
153 } else {
154 this.tracker.removeNickFromChannel(nick, channel);
155 this.newChanLine(channel, "PART", user, {"m": message});
156 }
157
158 this.updateNickList(channel);
159
160 var w = this.getWindow(channel)
161 if(w)
162 w.close();
163 },
164 userKicked: function(kicker, channel, kickee, message) {
165 if(kickee == this.nickname) {
166 this.tracker.removeChannel(channel);
167 this.getWindow(channel).close();
168 } else {
169 this.tracker.removeNickFromChannel(kickee, channel);
170 this.updateNickList(channel);
171 }
172
173 this.newChanLine(channel, "KICK", kicker, {"v": kickee, "m": message});
174 },
175 channelMode: function(user, channel, modes, raw) {
176 modes.each(function(mo) {
177 var direction = mo[0];
178 var mode = mo[1];
179
180 var prefixindex = this.modeprefixes.indexOf(mode);
181 if(prefixindex == -1)
182 return;
183
184 var nick = mo[2];
185 var prefixchar = this.prefixes.charAt(prefixindex);
186
187 var nc = this.tracker.getOrCreateNickOnChannel(nick, channel);
188 if(direction == "-") {
189 this.removePrefix(nc, prefixchar);
190 } else {
191 this.addPrefix(nc, prefixchar);
192 }
193 }, this);
194
195 this.newChanLine(channel, "MODE", user, {"m": raw.join(" ")});
196
197 this.updateNickList(channel);
198 },
199 userQuit: function(user, message) {
200 var nick = user.hostToNick();
201
202 var channels = this.tracker.getNick(nick);
203
204 var clist = [];
205 for(var c in channels) {
206 clist.push(c);
207 this.newChanLine(c, "QUIT", user, {"m": message});
208 }
209
210 this.tracker.removeNick(nick);
211
212 clist.each(function(cli) {
213 this.updateNickList(cli);
214 }, this);
215 },
216 nickChanged: function(user, newnick) {
217 var oldnick = user.hostToNick();
218
219 if(oldnick == this.nickname)
220 this.nickname = newnick;
221
222 this.tracker.renameNick(oldnick, newnick);
223
224 var channels = this.tracker.getNick(newnick);
225
226 for(var c in channels) {
227 this.newChanLine(c, "NICK", user, {"w": newnick});
228 /* TODO: rename queries */
229 this.updateNickList(c);
230 }
231 },
232 channelTopic: function(user, channel, topic) {
233 this.newChanLine(channel, "TOPIC", user, {"m": topic});
234 this.getWindow(channel).updateTopic(topic);
235 },
236 initialTopic: function(channel, topic) {
237 this.getWindow(channel).updateTopic(topic);
238 },
239 channelCTCP: function(user, channel, type, args) {
240 if(args == undefined)
241 args = "";
242
243 if(type == "ACTION") {
244 this.newChanLine(channel, "CHANACTION", user, {"m": args, "c": channel});
245 return;
246 }
247
248 this.newChanLine(channel, "CHANCTCP", user, {"x": type, "m": args, "c": channel});
249 },
250 userCTCP: function(user, type, args) {
251 var nick = user.hostToNick();
252 var host = user.hostToHost();
253 if(args == undefined)
254 args = "";
255
256 if(type == "ACTION") {
257 this.newWindow(nick, WINDOW_QUERY);
258 this.newLine(nick, "PRIVACTION", {"m": args, "x": type, "h": host, "n": nick});
259 return;
260 }
261
262 if(this.getWindow(nick)) {
263 this.newLine(nick, "PRIVCTCP", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
264 } else {
265 this.newActiveLine("PRIVCTCP", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
266 }
267 },
268 userCTCPReply: function(user, type, args) {
269 var nick = user.hostToNick();
270 var host = user.hostToHost();
271 if(args == undefined)
272 args = "";
273
274 if(this.getWindow(nick)) {
275 this.newLine(nick, "CTCPREPLY", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
276 } else {
277 this.newActiveLine("CTCPREPLY", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
278 }
279 },
280 channelPrivmsg: function(user, channel, message) {
281 this.newChanLine(channel, "CHANMSG", user, {"m": message});
282 },
283 channelNotice: function(user, channel, message) {
284 this.newChanLine(channel, "CHANNOTICE", user, {"m": message});
285 },
286 userPrivmsg: function(user, message) {
287 var nick = user.hostToNick();
288 var host = user.hostToHost();
289
290 this.newWindow(nick, WINDOW_QUERY);
291
292 this.newLine(nick, "PRIVMSG", {"m": message, "h": host, "n": nick});
293 },
294 serverNotice: function(message) {
295 this.newServerLine("SERVERNOTICE", {"m": message});
296 },
297 userNotice: function(user, message) {
298 var nick = user.hostToNick();
299 var host = user.hostToHost();
300
301 if(this.getWindow(nick)) {
302 this.newLine(nick, "PRIVNOTICE", {"m": message, "h": host, "n": nick});
303 } else {
304 this.newActiveLine("PRIVNOTICE", {"m": message, "h": host, "n": nick});
305 }
306 },
307 userInvite: function(user, channel) {
308 var nick = user.hostToNick();
309 var host = user.hostToHost();
310
311 this.newServerLine("INVITE", {"c": channel, "h": host, "n": nick});
312 },
313 userMode: function(modes) {
314 this.newServerLine("UMODE", {"m": modes, "n": this.nickname});
315 },
316 channelNames: function(channel, names) {
317 if(names.length == 0) {
318 this.updateNickList(channel);
319 return;
320 }
321
322 names.each(function(nick) {
323 var prefixes = [];
324 var splitnick = nick.split("");
325
326 splitnick.every(function(c, i) {
327 if(this.prefixes.indexOf(c) == -1) {
328 nick = nick.substr(i);
329 return false;
330 }
331
332 prefixes.push(c);
333 return true;
334 }, this);
335
336 var nc = this.tracker.addNickToChannel(nick, channel);
337 prefixes.each(function(p) {
338 this.addPrefix(nc, p);
339 }, this);
340 }, this);
341 },
342 disconnected: function() {
343 for(var x in this.parent.channels)
344 this.ui.closeWindow(x);
345
346 this.tracker = undefined;
347
348 this.newServerLine("DISCONNECT");
349 },
350 supported: function(key, value) {
351 if(key == "PREFIX") {
352 var l = (value.length - 2) / 2;
353
354 this.modeprefixes = value.substr(1, l);
355 this.prefixes = value.substr(l + 2, l);
356 }
357 },
358 connected: function() {
359 this.newServerLine("CONNECT");
360 },
361 serverError: function(message) {
362 this.newServerLine("ERROR", {"m": message});
363 }
364 });