]> jfr.im git - irc/quakenet/qwebirc.git/blob - static/js/irc/baseirc.js
12139042187b1d5cd6b922cad440f7694f47bf97
[irc/quakenet/qwebirc.git] / static / js / irc / baseirc.js
1 Numerics = {"001": "RPL_WELCOME", "433": "ERR_NICKNAMEINUSE", "004": "RPL_MYINFO", "005": "RPL_ISUPPORT", "353": "RPL_NAMREPLY", "366": "RPL_ENDOFNAMES", "331": "RPL_NOTOPIC", "332": "RPL_TOPIC", "333": "RPL_TOPICWHOTIME"};
2
3 registeredCTCPs = {
4 "VERSION": function(x) {
5 return "qwebirc v" + QWEBIRC_VERSION + ", copyright (C) Chris Porter 2008 -- user agent: " + getBrowserDetails();
6 },
7 "USERINFO": function(x) { return "qwebirc"; },
8 "TIME": function(x) {
9 function pad(x) { x = "" + x; if(x.length == 1) x = "0" + x; return x; }
10
11 var d = new Date();
12
13 return DaysOfWeek[d.getDay()] + " " + MonthsOfYear[d.getMonth()] + " " + pad(d.getDate()) + " " + pad(d.getHours()) + ":" + pad(d.getMinutes()) + ":" + pad(d.getSeconds()) + " " + d.getFullYear()
14 },
15 "PING": function(x) { return x; },
16 "CLIENTINFO": function(x) { return "PING VERSION TIME USERINFO CLIENTINFO"; }
17 };
18
19 function BaseIRCClient(nickname, view) {
20 var self = this;
21 this.nickname = nickname;
22 this.signedOn = false;
23 this.pmodes = ["b", "k,", "o", "l", "v"];
24 this.channels = {}
25 var nextctcp = 0;
26
27 /* attempt javascript inheritence! */
28 this.dispatch = function(data) {
29 var message = data[0];
30 if(message == "connect") {
31 view.connected();
32 } else if(message == "disconnect") {
33 view.disconnected();
34 } else if(message == "c") {
35 var command = data[1];
36
37 var prefix = data[2];
38 var sl = data[3];
39 var n = Numerics[command];
40
41 var x = n;
42 if(!n)
43 n = command;
44
45 var o = view["irc_" + n];
46 if(!o)
47 o = self["irc_" + n];
48
49 if(o) {
50 var r = o(prefix, sl);
51 if(!r)
52 view.rawNumeric(command, prefix, sl);
53 } else {
54 view.rawNumeric(command, prefix, sl);
55 }
56 }
57 }
58
59 this.irc_RPL_WELCOME = function(prefix, params) {
60 self.nickname = params[0];
61
62 self.signedOn = true;
63 view.signedOn(self.nickname);
64 }
65
66 this.irc_ERR_NICKNAMEINUSE = function(prefix, params) {
67 if(self.signedOn == false) {
68 var newnick = params[1] + "_";
69 if(newnick == self.lastnick)
70 newnick = "webchat" + Math.floor(Math.random() * 1024 * 1024);
71
72 self.send("NICK " + newnick);
73 self.lastnick = newnick;
74 }
75 }
76
77 this.irc_NICK = function(prefix, params) {
78 var user = prefix;
79 var oldnick = hosttonick(user);
80 var newnick = params[0];
81
82 if(self.nickname == oldnick)
83 self.nickname = newnick;
84
85 view.nickChanged(user, newnick);
86
87 return true;
88 }
89
90 this.irc_QUIT = function(prefix, params) {
91 var user = prefix;
92
93 var message = indexFromEnd(params, -1);
94
95 view.userQuit(user, message);
96
97 return true;
98 }
99
100 this.irc_PART = function(prefix, params) {
101 var user = prefix;
102 var channel = params[0];
103 var message = params[1];
104
105 var nick = hosttonick(user);
106
107 if((nick == self.nickname) && self.channels[channel])
108 delete self.channels[channel];
109 view.userPart(user, channel, message);
110
111 return true;
112 }
113
114 this.irc_KICK = function(prefix, params) {
115 var kicker = prefix;
116 var channel = params[0];
117 var kickee = params[1];
118 var message = params[2];
119
120 if((kickee == self.nickname) && self.channels[channel])
121 delete self.channels[channel];
122 view.userKicked(kicker, channel, kickee, message);
123
124 return true;
125 }
126
127 this.irc_PING = function(prefix, params) {
128 self.send("PONG :" + indexFromEnd(params, -1));
129
130 return true;
131 }
132
133 this.irc_JOIN = function(prefix, params) {
134 var channel = params[0];
135 var user = prefix;
136 var nick = hosttonick(user);
137
138 if(nick == self.nickname)
139 self.channels[channel] = true;
140
141 view.userJoined(user, channel);
142
143 return true;
144 }
145
146 this.irc_TOPIC = function(prefix, params) {
147 var user = prefix;
148 var channel = params[0];
149 var topic = indexFromEnd(params, -1);
150
151 view.channelTopic(user, channel, topic);
152
153 return true;
154 }
155
156 var processCTCP = function(message) {
157 if(message.charAt(0) == "\x01") {
158 if(message.charAt(message.length - 1) == "\x01") {
159 message = message.substr(1, message.length - 2);
160 } else {
161 message = message.substr(1);
162 }
163 return message.splitMax(" ", 2);
164 }
165 }
166
167 this.irc_PRIVMSG = function(prefix, params) {
168 var user = prefix;
169 var target = params[0];
170 var message = indexFromEnd(params, -1);
171
172 var ctcp = processCTCP(message);
173 if(ctcp) {
174 var type = ctcp[0].toUpperCase();
175
176 var replyfn = registeredCTCPs[type];
177 if(replyfn) {
178 var t = new Date().getTime() / 1000;
179 if(t > nextctcp)
180 self.send("NOTICE " + hosttonick(user) + " :\x01" + type + " " + replyfn(ctcp[1]) + "\x01");
181 nextctcp = t + 5;
182 }
183
184 if(target == self.nickname) {
185 view.userCTCP(user, type, ctcp[1]);
186 } else {
187 view.channelCTCP(user, target, type, ctcp[1]);
188 }
189 } else {
190 if(target == self.nickname) {
191 view.userPrivmsg(user, message);
192 } else {
193 view.channelPrivmsg(user, target, message);
194 }
195 }
196
197 return true;
198 }
199
200 this.irc_NOTICE = function(prefix, params) {
201 var user = prefix;
202 var target = params[0];
203 var message = indexFromEnd(params, -1);
204
205 if(user == "") {
206 view.serverNotice(message);
207 } else if(target == self.nickname) {
208 var ctcp = processCTCP(message);
209 if(ctcp) {
210 view.userCTCPReply(user, ctcp[0], ctcp[1]);
211 } else {
212 view.userNotice(user, message);
213 }
214 } else {
215 view.channelNotice(user, target, message);
216 }
217
218 return true;
219 }
220
221 this.irc_INVITE = function(prefix, params) {
222 var user = prefix;
223 var channel = indexFromEnd(params, -1);
224
225 view.userInvite(user, channel);
226
227 return true;
228 }
229
230 this.irc_ERROR = function(prefix, params) {
231 var message = indexFromEnd(params, -1);
232
233 view.serverError(message);
234
235 return true;
236 }
237
238 this.irc_MODE = function(prefix, params) {
239 var user = prefix;
240 var target = params[0];
241 var args = params.slice(1);
242
243 if(target == self.nickname) {
244 view.userMode(args);
245 } else {
246 var modes = args[0].split("");
247 var xargs = args.slice(1);
248
249 var data = []
250 var carg = 0;
251 var pos = 0;
252 var cmode = "+";
253
254 forEach(modes, function(mode) {
255 if((mode == "+") || (mode == "-")) {
256 cmode = mode;
257 return;
258 }
259
260 if(self.pmodes[mode]) {
261 d = [cmode, mode, xargs[carg++]]
262 } else {
263 d = [cmode, mode]
264 }
265
266 data.push(d);
267 });
268
269 view.channelMode(user, target, data, args);
270 }
271
272 return true;
273 }
274
275 this.irc_RPL_ISUPPORT = function(prefix, params) {
276 var supported = params.slice(1, -1);
277 var supportedhash = {};
278
279 for(var i=0;i<supported.length;i++) {
280 var l = supported[i].splitMax("=", 2);
281 view.supported(l[0], l[1]);
282 }
283 }
284
285 this.irc_RPL_MYINFO = function(prefix, params) {
286 var pmodes = params[5].split("");
287 self.pmodes = {}
288 forEach(pmodes, function(pmode) {
289 self.pmodes[pmode] = true;
290 });
291 }
292
293 this.irc_RPL_NAMREPLY = function(prefix, params) {
294 var channel = params[2];
295 var names = params[3];
296
297 view.channelNames(channel, names.split(" "));
298
299 return true;
300 }
301
302 this.irc_RPL_ENDOFNAMES = function(prefix, params) {
303 var channel = params[1];
304
305 view.channelNames(channel, []);
306 return true;
307 }
308
309 this.irc_RPL_NOTOPIC = function(prefix, params) {
310 return true;
311 }
312
313 this.irc_RPL_TOPIC = function(prefix, params) {
314 var channel = params[1];
315 var topic = indexFromEnd(params, -1);
316
317 if(self.channels[channel]) {
318 view.initialTopic(channel, topic);
319 return true;
320 }
321 }
322
323 this.irc_RPL_TOPICWHOTIME = function(prefix, params) {
324 return true;
325 }
326
327 this.connection = new TCPConnection(nickname, this);
328 this.send = this.connection.send;
329 this.connect = this.connection.connect;
330 this.disconnect = this.connection.disconnect;
331 }