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