]> jfr.im git - irc/quakenet/qwebirc.git/blob - js/irc/ircclient.js
add highres icon + make app mobile webapp aware
[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 maxnicks: 10
7 },
8 initialize: function(options, ui) {
9 this.parent(options);
10
11 this.ui = ui;
12
13 this.prefixes = "@+";
14 this.modeprefixes = "ov";
15 this.windows = new QHash();
16
17 this.commandparser = new qwebirc.irc.Commands(this);
18 this.exec = this.commandparser.dispatch.bind(this.commandparser);
19
20 this.statusWindow = this.ui.newClient(this);
21 this.lastNicks = [];
22
23 this.inviteChanList = [];
24 this.activeTimers = {};
25
26 this.loginRegex = new RegExp(this.ui.options.loginRegex);
27 this.tracker = new qwebirc.irc.IRCTracker(this);
28
29 this.__silenceSupported = false;
30 this.__silenced = null;
31 this.ignoreController = new qwebirc.irc.IgnoreController(function(x) { return this.toIRCLower(x) }.bind(this));
32 },
33 connect: function() {
34 this.parent();
35 this.newServerInfoLine("CONNECTING", "");
36 },
37 newLine: function(window, type, data) {
38 if(!data)
39 data = {};
40
41 var w = this.getWindow(window);
42 if(w) {
43 w.addLine(type, data);
44 } else {
45 this.statusWindow.addLine(type, data);
46 }
47 },
48 newChanLine: function(channel, type, user, extra) {
49 if(!extra)
50 extra = {};
51
52 if($defined(user)) {
53 extra["n"] = user.hostToNick();
54 extra["h"] = user.hostToHost();
55 }
56 extra["c"] = channel;
57 extra["-"] = this.nickname;
58
59 if(!(this.ui.uiOptions.NICK_OV_STATUS))
60 delete extra["@"];
61
62 this.newLine(channel, type, extra);
63 },
64 newServerLine: function(type, data) {
65 this.statusWindow.addLine(type, data);
66 },
67 newServerInfoLine: function(type, data) {
68 this.statusWindow.infoMessage(type, data);
69 },
70 newActiveLine: function(type, data) {
71 this.getActiveWindow().addLine(type, data);
72 },
73 newTargetOrActiveLine: function(target, type, data) {
74 if(this.getWindow(target)) {
75 this.newLine(target, type, data);
76 } else {
77 this.newActiveLine(type, data);
78 }
79 },
80 getPrefixPriority: function(prefixes) {
81 if (prefixes.length > 0) {
82 var c = prefixes.charAt(0);
83 var p = this.prefixes.indexOf(c);
84 if(p > -1)
85 return p;
86 }
87 return Infinity;
88 },
89 updateNickList: function(channel) {
90 var names = [];
91 var nh = new QHash();
92
93 var n1 = this.tracker.getChannel(channel);
94 if($defined(n1)) {
95 n1.each(function (n, nc) {
96 var prefix, pri = this.getPrefixPriority(nc.prefixes);
97 if(nc.prefixes.length > 0) {
98 prefix = nc.prefixes.charAt(0);
99 } else {
100 prefix = "";
101 }
102 names.push([pri, this.toIRCLower(n), prefix + n]);
103 }, this);
104 }
105 names.sort(qwebirc.util.arrayCmp);
106
107 var sortednames = [];
108 names.each(function(name) {
109 sortednames.push(name[2]);
110 });
111
112 var w = this.getWindow(channel);
113 if(w)
114 w.updateNickList(sortednames);
115 },
116 getWindow: function(name) {
117 return this.windows.get(this.toIRCLower(name));
118 },
119 renameWindow: function(oldname, newname) {
120 var oldwindow = this.getWindow(oldname);
121 if(!oldwindow || this.getWindow(newname))
122 return;
123
124 var window = this.ui.renameWindow(oldwindow, newname);
125 if(window) {
126 this.windows.put(this.toIRCLower(newname), window);
127 this.windows.remove(this.toIRCLower(oldname));
128 }
129 },
130 newWindow: function(name, type, select) {
131 var w = this.getWindow(name);
132 if(!w) {
133 w = this.ui.newWindow(this, type, name);
134 this.windows.put(this.toIRCLower(name), w);
135
136 w.addEvent("close", function(w) {
137 this.windows.remove(this.toIRCLower(name));
138 }.bind(this));
139 }
140
141 if(select)
142 this.ui.selectWindow(w);
143
144 return w;
145 },
146 getQueryWindow: function(name) {
147 return this.ui.getWindow(this, qwebirc.ui.WINDOW_QUERY, name);
148 },
149 newQueryWindow: function(name, privmsg) {
150 var e;
151
152 if(this.getQueryWindow(name))
153 return;
154
155 if(privmsg)
156 return this.newPrivmsgQueryWindow(name);
157 return this.newNoticeQueryWindow(name);
158 },
159 newPrivmsgQueryWindow: function(name) {
160 if(this.ui.uiOptions.DEDICATED_MSG_WINDOW) {
161 if(!this.ui.getWindow(this, qwebirc.ui.WINDOW_MESSAGES))
162 return this.ui.newWindow(this, qwebirc.ui.WINDOW_MESSAGES, "Messages");
163 } else {
164 return this.newWindow(name, qwebirc.ui.WINDOW_QUERY, false);
165 }
166 },
167 newNoticeQueryWindow: function(name) {
168 if(this.ui.uiOptions.DEDICATED_NOTICE_WINDOW)
169 if(!this.ui.getWindow(this, qwebirc.ui.WINDOW_MESSAGES))
170 return this.ui.newWindow(this, qwebirc.ui.WINDOW_MESSAGES, "Messages");
171 },
172 newQueryLine: function(window, type, data, privmsg, active) {
173 if(this.getQueryWindow(window))
174 return this.newLine(window, type, data);
175
176 var w = this.ui.getWindow(this, qwebirc.ui.WINDOW_MESSAGES);
177
178 var e;
179 if(privmsg) {
180 e = this.ui.uiOptions.DEDICATED_MSG_WINDOW;
181 } else {
182 e = this.ui.uiOptions.DEDICATED_NOTICE_WINDOW;
183 }
184 if(e && w) {
185 return w.addLine(type, data);
186 } else {
187 if(active) {
188 return this.newActiveLine(type, data);
189 } else {
190 return this.newLine(window, type, data);
191 }
192 }
193 },
194 newQueryOrActiveLine: function(window, type, data, privmsg) {
195 this.newQueryLine(window, type, data, privmsg, true);
196 },
197 getActiveWindow: function() {
198 return this.ui.getActiveIRCWindow(this);
199 },
200 getNickname: function() {
201 return this.nickname;
202 },
203 addPrefix: function(nickchanentry, prefix) {
204 var ncp = nickchanentry.prefixes + prefix;
205 var prefixes = [];
206
207 /* O(n^2) */
208 for(var i=0;i<this.prefixes.length;i++) {
209 var pc = this.prefixes.charAt(i);
210 var index = ncp.indexOf(pc);
211 if(index != -1)
212 prefixes.push(pc);
213 }
214
215 nickchanentry.prefixes = prefixes.join("");
216 },
217 stripPrefix: function(nick) {
218 var l = nick.charAt(0);
219 if(!l)
220 return nick;
221
222 if(this.prefixes.indexOf(l) != -1)
223 return nick.substring(1);
224
225 return nick;
226 },
227 removePrefix: function(nickchanentry, prefix) {
228 nickchanentry.prefixes = nickchanentry.prefixes.replaceAll(prefix, "");
229 },
230
231 /* from here down are events */
232 rawNumeric: function(numeric, prefix, params) {
233 this.newServerLine("RAW", {"n": "numeric", "m": params.slice(1).join(" ")});
234 },
235 signedOn: function(nickname) {
236 this.tracker = new qwebirc.irc.IRCTracker(this);
237 this.nickname = nickname;
238 this.newServerLine("SIGNON");
239
240 /* we guarantee that +x is sent out before the joins */
241 if(this.ui.uiOptions.USE_HIDDENHOST)
242 this.exec("/UMODE +x");
243
244 if(this.options.autojoin) {
245 if(qwebirc.auth.loggedin() && this.ui.uiOptions.USE_HIDDENHOST) {
246 var d = function() {
247 if($defined(this.activeTimers.autojoin))
248 this.ui.getActiveWindow().infoMessage("Waiting for login before joining channels...");
249 }.delay(5, this);
250 this.activeTimers.autojoin = function() {
251 var w = this.ui.getActiveWindow();
252 w.errorMessage("No login response in 10 seconds.");
253 w.errorMessage("You may want to try authing manually and then type: /autojoin (if you don't auth your host may be visible).");
254 }.delay(10000, this);
255 return;
256 }
257
258 this.exec("/AUTOJOIN");
259 } else {
260 var d = function() { this.newServerInfoLine("CONNECTED", ""); }.delay(1000, this);
261 }
262
263 this.fireEvent("signedOn");
264 },
265 userJoined: function(user, channel) {
266 var nick = user.hostToNick();
267 var host = user.hostToHost();
268
269 if((nick == this.nickname) && !this.getWindow(channel))
270 this.newWindow(channel, qwebirc.ui.WINDOW_CHANNEL, true);
271 this.tracker.addNickToChannel(nick, channel);
272
273 if(nick == this.nickname) {
274 this.newChanLine(channel, "OURJOIN", user);
275 } else {
276 if(!this.ui.uiOptions.HIDE_JOINPARTS) {
277 this.newChanLine(channel, "JOIN", user);
278 }
279 }
280 this.updateNickList(channel);
281 },
282 userPart: function(user, channel, message) {
283 var nick = user.hostToNick();
284 var host = user.hostToHost();
285
286 if(nick == this.nickname) {
287 this.tracker.removeChannel(channel);
288 } else {
289 this.tracker.removeNickFromChannel(nick, channel);
290 if(!this.ui.uiOptions.HIDE_JOINPARTS) {
291 this.newChanLine(channel, "PART", user, {"m": message});
292 }
293 }
294
295 this.updateNickList(channel);
296
297 if(nick == this.nickname) {
298 var w = this.getWindow(channel);
299 if(w)
300 w.close();
301 }
302 },
303 userKicked: function(kicker, channel, kickee, message) {
304 if(kickee == this.nickname) {
305 this.tracker.removeChannel(channel);
306 this.getWindow(channel).close();
307 } else {
308 this.tracker.removeNickFromChannel(kickee, channel);
309 this.updateNickList(channel);
310 }
311
312 this.newChanLine(channel, "KICK", kicker, {"v": kickee, "m": message});
313 },
314 channelMode: function(user, channel, modes, raw) {
315 modes.each(function(mo) {
316 var direction = mo[0];
317 var mode = mo[1];
318
319 var prefixindex = this.modeprefixes.indexOf(mode);
320 if(prefixindex == -1)
321 return;
322
323 var nick = mo[2];
324 var prefixchar = this.prefixes.charAt(prefixindex);
325
326 var nc = this.tracker.getOrCreateNickOnChannel(nick, channel);
327 if(direction == "-") {
328 this.removePrefix(nc, prefixchar);
329 } else {
330 this.addPrefix(nc, prefixchar);
331 }
332 }, this);
333
334 this.newChanLine(channel, "MODE", user, {"m": raw.join(" ")});
335
336 this.updateNickList(channel);
337 },
338 userQuit: function(user, message) {
339 var nick = user.hostToNick();
340
341 var clist = [];
342 var channels = this.tracker.getNick(nick);
343 if($defined(channels)) {
344 channels.each(function (c) {
345 clist.push(c);
346 if (!this.ui.uiOptions.HIDE_JOINPARTS) {
347 this.newChanLine(c, "QUIT", user, {"m": message});
348 }
349 }, this);
350 }
351 this.tracker.removeNick(nick);
352
353 clist.each(function(cli) {
354 this.updateNickList(cli);
355 }, this);
356 },
357 nickChanged: function(user, newnick) {
358 var oldnick = user.hostToNick();
359
360 if(oldnick == this.nickname)
361 this.nickname = newnick;
362
363 this.tracker.renameNick(oldnick, newnick);
364
365 var found = false;
366
367 var channels = this.tracker.getNick(newnick);
368 if($defined(channels)) {
369 channels.each(function (c) {
370 found = true;
371
372 this.newChanLine(c, "NICK", user, {"w": newnick});
373 this.updateNickList(c);
374 }, this);
375 }
376
377 if(this.getQueryWindow(oldnick)) {
378 found = true;
379 this.renameWindow(oldnick, newnick);
380 this.newLine(newnick, "NICK", {"n": oldnick, "w": newnick});
381 }
382
383 /* this is quite horrible */
384 if(!found)
385 this.newServerLine("NICK", {"w": newnick, n: user.hostToNick(), h: user.hostToHost(), "-": this.nickname});
386 },
387 channelTopic: function(user, channel, topic) {
388 this.newChanLine(channel, "TOPIC", user, {"m": topic});
389 this.getWindow(channel).updateTopic(topic);
390 },
391 initialTopic: function(channel, topic) {
392 this.getWindow(channel).updateTopic(topic);
393 },
394 channelCTCP: function(user, channel, type, args) {
395 if(args == undefined)
396 args = "";
397
398 var nick = user.hostToNick();
399 if(type == "ACTION") {
400 this.tracker.updateLastSpoke(nick, channel, new Date().getTime());
401 this.newChanLine(channel, "CHANACTION", user, {"m": args, "c": channel, "@": this.getNickStatus(channel, nick)});
402 return;
403 }
404
405 this.newChanLine(channel, "CHANCTCP", user, {"x": type, "m": args, "c": channel, "@": this.getNickStatus(channel, nick)});
406 },
407 userCTCP: function(user, type, args) {
408 var nick = user.hostToNick();
409 var host = user.hostToHost();
410 if(args == undefined)
411 args = "";
412
413 if(type == "ACTION") {
414 this.newQueryWindow(nick, true);
415 this.newQueryLine(nick, "PRIVACTION", {"m": args, "x": type, "h": host, "n": nick}, true);
416 return;
417 }
418
419 this.newTargetOrActiveLine(nick, "PRIVCTCP", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
420 },
421 userCTCPReply: function(user, type, args) {
422 var nick = user.hostToNick();
423 var host = user.hostToHost();
424 if(args == undefined)
425 args = "";
426
427 this.newTargetOrActiveLine(nick, "CTCPREPLY", {"m": args, "x": type, "h": host, "n": nick, "-": this.nickname});
428 },
429 getNickStatus: function(channel, nick) {
430 var n = this.tracker.getNickOnChannel(nick, channel);
431 if(!$defined(n))
432 return "";
433
434 if(n.prefixes.length == 0)
435 return "";
436
437 return n.prefixes.charAt(0);
438 },
439 channelPrivmsg: function(user, channel, message) {
440 var nick = user.hostToNick();
441 var host = user.hostToHost();
442
443 if(this.isIgnored(nick, host))
444 return;
445
446 this.tracker.updateLastSpoke(nick, channel, new Date().getTime());
447 this.newChanLine(channel, "CHANMSG", user, {"m": message, "@": this.getNickStatus(channel, nick)});
448 },
449 channelNotice: function(user, channel, message) {
450 var nick = user.hostToNick();
451 var host = user.hostToHost();
452
453 if(this.isIgnored(nick, host))
454 return;
455
456 this.newChanLine(channel, "CHANNOTICE", user, {"m": message, "@": this.getNickStatus(channel, user.hostToNick())});
457 },
458 userPrivmsg: function(user, message) {
459 var nick = user.hostToNick();
460 var host = user.hostToHost();
461
462 if(this.isIgnored(nick, host))
463 return;
464
465 this.newQueryWindow(nick, true);
466 this.pushLastNick(nick);
467 this.newQueryLine(nick, "PRIVMSG", {"m": message, "h": host, "n": nick}, true);
468
469 this.checkLogin(user, message);
470 },
471 checkLogin: function(user, message) {
472 if(this.isNetworkService(user) && $defined(this.activeTimers.autojoin)) {
473 if($defined(this.loginRegex) && message.match(this.loginRegex)) {
474 $clear(this.activeTimers.autojoin);
475 delete this.activeTimers["autojoin"];
476 this.ui.getActiveWindow().infoMessage("Joining channels...");
477 this.exec("/AUTOJOIN");
478 }
479 }
480 },
481 serverNotice: function(user, message) {
482 if(user == "") {
483 this.newServerLine("SERVERNOTICE", {"m": message});
484 } else {
485 this.newServerLine("PRIVNOTICE", {"m": message, "n": user});
486 }
487 },
488 userNotice: function(user, message) {
489 var nick = user.hostToNick();
490 var host = user.hostToHost();
491
492 if(this.isIgnored(nick, host))
493 return;
494
495 if(this.ui.uiOptions.DEDICATED_NOTICE_WINDOW) {
496 this.newQueryWindow(nick, false);
497 this.newQueryOrActiveLine(nick, "PRIVNOTICE", {"m": message, "h": host, "n": nick}, false);
498 } else {
499 this.newTargetOrActiveLine(nick, "PRIVNOTICE", {"m": message, "h": host, "n": nick});
500 }
501
502 this.checkLogin(user, message);
503 },
504 isNetworkService: function(user) {
505 return this.ui.options.networkServices.indexOf(user) > -1;
506 },
507 __joinInvited: function() {
508 this.exec("/JOIN " + this.inviteChanList.join(","));
509 this.inviteChanList = [];
510 delete this.activeTimers["serviceInvite"];
511 },
512 userInvite: function(user, channel) {
513 var nick = user.hostToNick();
514 var host = user.hostToHost();
515
516 if(this.isIgnored(nick, host))
517 return;
518
519 this.newServerLine("INVITE", {"c": channel, "h": host, "n": nick});
520 if(this.ui.uiOptions.ACCEPT_SERVICE_INVITES && this.isNetworkService(user)) {
521 if(this.activeTimers.serviceInvite)
522 $clear(this.activeTimers.serviceInvite);
523
524 /* we do this so we can batch the joins, i.e. instead of sending 5 JOIN comands we send 1 with 5 channels. */
525 this.activeTimers.serviceInvite = this.__joinInvited.delay(100, this);
526
527 this.inviteChanList.push(channel);
528 }
529 },
530 userMode: function(modes) {
531 this.newServerLine("UMODE", {"m": modes, "n": this.nickname});
532 },
533 channelNames: function(channel, names) {
534 if(names.length == 0) {
535 this.updateNickList(channel);
536 return;
537 }
538
539 names.each(function(nick) {
540 var prefixes = [];
541 var splitnick = nick.split("");
542
543 splitnick.every(function(c, i) {
544 if(this.prefixes.indexOf(c) == -1) {
545 nick = nick.substr(i);
546 return false;
547 }
548
549 prefixes.push(c);
550 return true;
551 }, this);
552
553 var nc = this.tracker.addNickToChannel(nick, channel);
554 prefixes.each(function(p) {
555 this.addPrefix(nc, p);
556 }, this);
557 }, this);
558 },
559 disconnected: function(message) {
560 var toClose = [];
561 this.windows.each(function(k, v) {
562 if(v.type == qwebirc.ui.WINDOW_CHANNEL)
563 toClose.push(v);
564 });
565 for(var i=0;i<toClose.length;i++)
566 toClose[i].close();
567
568 this.tracker = undefined;
569
570 qwebirc.connected = false;
571 this.newServerLine("DISCONNECT", {"m": message});
572 },
573 nickOnChanHasPrefix: function(nick, channel, prefix) {
574 var entry = this.tracker.getNickOnChannel(nick, channel);
575 if(!$defined(entry))
576 return false; /* shouldn't happen */
577
578 return entry.prefixes.indexOf(prefix) != -1;
579 },
580 nickOnChanHasAtLeastPrefix: function(nick, channel, prefix) {
581 var entry = this.tracker.getNickOnChannel(nick, channel);
582 if(!$defined(entry))
583 return false; /* shouldn't happen */
584
585 /* this array is sorted */
586 var pos = this.prefixes.indexOf(prefix);
587 if(pos == -1)
588 return false; /* shouldn't happen */
589
590 var modehash = new QSet();
591 this.prefixes.slice(0, pos + 1).split("").each(function(x) {
592 modehash.add(x);
593 });
594
595 var prefixes = entry.prefixes;
596 for(var i=0;i<prefixes.length;i++)
597 if(modehash.contains(prefixes.charAt(i)))
598 return true;
599
600 return false;
601 },
602 supported: function(key, value) {
603 if(key == "PREFIX") {
604 var l = (value.length - 2) / 2;
605
606 this.modeprefixes = value.substr(1, l);
607 this.prefixes = value.substr(l + 2, l);
608 } else if(key == "SILENCE") {
609 this.__silenceSupported = true;
610 }
611
612 this.parent(key, value);
613 },
614 connected: function() {
615 qwebirc.connected = true;
616 this.newServerInfoLine("CONNECT", "");
617 },
618 serverError: function(message) {
619 this.newServerLine("ERROR", {"m": message});
620 },
621 quit: function(message) {
622 this.send("QUIT :" + message, true);
623 this.disconnect();
624 },
625 disconnect: function() {
626 for(var k in this.activeTimers) {
627 this.activeTimers[k].cancel();
628 };
629 this.activeTimers = {};
630
631 this.parent();
632 },
633 awayMessage: function(nick, message) {
634 this.newQueryLine(nick, "AWAY", {"n": nick, "m": message}, true);
635 },
636 whois: function(nick, type, data) {
637 var ndata = {"n": nick};
638 var mtype;
639
640 var xsend = function() {
641 this.newTargetOrActiveLine(nick, "WHOIS" + mtype, ndata);
642 }.bind(this);
643
644 if(type == "user") {
645 mtype = "USER";
646 ndata.h = data.ident + "@" + data.hostname;
647 xsend();
648 mtype = "REALNAME";
649 ndata.m = data.realname;
650 } else if(type == "server") {
651 mtype = "SERVER";
652 ndata.x = data.server;
653 ndata.m = data.serverdesc;
654 } else if(type == "oper") {
655 mtype = "OPER";
656 } else if(type == "idle") {
657 mtype = "IDLE";
658 ndata.x = qwebirc.util.longtoduration(data.idle);
659 ndata.m = qwebirc.irc.IRCDate(new Date(data.connected * 1000));
660 } else if(type == "channels") {
661 mtype = "CHANNELS";
662 ndata.m = data.channels;
663 } else if(type == "account") {
664 mtype = "ACCOUNT";
665 ndata.m = data.account;
666 } else if(type == "away") {
667 mtype = "AWAY";
668 ndata.m = data.away;
669 } else if(type == "opername") {
670 mtype = "OPERNAME";
671 ndata.m = data.opername;
672 } else if(type == "actually") {
673 mtype = "ACTUALLY";
674 ndata.m = data.hostname;
675 ndata.x = data.ip;
676 } else if(type == "generictext") {
677 mtype = "GENERICTEXT";
678 ndata.m = data.text;
679 } else if(type == "end") {
680 mtype = "END";
681 } else {
682 return false;
683 }
684
685 xsend();
686 return true;
687 },
688 genericError: function(target, message) {
689 this.newTargetOrActiveLine(target, "GENERICERROR", {m: message, t: target});
690 },
691 genericQueryError: function(target, message) {
692 this.newQueryOrActiveLine(target, "GENERICERROR", {m: message, t: target}, true);
693 },
694 awayStatus: function(state, message) {
695 this.newActiveLine("GENERICMESSAGE", {m: message});
696 },
697 pushLastNick: function(nick) {
698 var i = this.lastNicks.indexOf(nick);
699 if(i != -1) {
700 this.lastNicks.splice(i, 1);
701 } else {
702 if(this.lastNicks.length == this.options.maxnicks)
703 this.lastNicks.pop();
704 }
705 this.lastNicks.unshift(nick);
706 },
707 wallops: function(user, text) {
708 var nick = user.hostToNick();
709 var host = user.hostToHost();
710
711 this.newServerLine("WALLOPS", {t: text, n: nick, h: host});
712 },
713 channelModeIs: function(channel, modes) {
714 this.newTargetOrActiveLine(channel, "CHANNELMODEIS", {c: channel, m: modes.join(" ")});
715 },
716 channelCreationTime: function(channel, time) {
717 this.newTargetOrActiveLine(channel, "CHANNELCREATIONTIME", {c: channel, m: qwebirc.irc.IRCDate(new Date(time * 1000))});
718 },
719 ignore: function(host) {
720 var host = this.ignoreController.ignore(host);
721 if(host === null)
722 return false;
723
724 if(this.__silenceSupported) {
725 this.__silenced = "+" + host;
726 this.exec("/SILENCE +" + host);
727 }
728
729 return true;
730 },
731 unignore: function(host) {
732 var host = this.ignoreController.unignore(host);
733 if(host === null)
734 return false;
735
736 if(this.__silenceSupported) {
737 this.__silenced = "-" + host;
738 this.exec("/SILENCE -" + host);
739 }
740
741 return true;
742 },
743 getIgnoreList: function() {
744 return this.ignoreController.get();
745 },
746 silenced: function(host) {
747 if (host === this.__silenced) {
748 this.__silenced = null;
749 return;
750 }
751
752 this.newServerLine("SILENCE", {h: host});
753 },
754 isIgnored: function(nick, host) {
755 return this.ignoreController.isIgnored(nick, host);
756 }
757 });