· 11 years ago · May 29, 2015, 02:36 PM
1var Client, Global, Network, confetti, confettiScript,
2 __slice = [].slice,
3 __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
4
5Client = client;
6
7Network = Client.network();
8
9Global = this;
10
11if (typeof confetti !== 'object') {
12 confetti = {
13 initialized: false,
14 silentReload: false,
15 cache: {
16 initialized: false
17 },
18 players: {},
19 ignoreNextChanMessage: false,
20 loginTime: 0
21 };
22 Network.playerLogin.connect(function() {
23 return confetti.loginTime = sys.time();
24 });
25}
26
27confetti.version = {
28 release: 2,
29 major: 1,
30 minor: 4
31};
32
33confetti.scriptUrl = 'https://theunknownone.github.io/PO-Client-Tools/';
34
35confetti.pluginsUrl = 'https://theunknownone.github.io/PO-Client-Tools/plugins/';
36
37confetti.dataDir = sys.scriptsFolder;
38
39confetti.cacheFile = 'confetti.json';
40
41(function() {
42 var addNameHighlights, an, escapeRegex, fancyJoin, isAlpha, random, shuffle, sortOnlineOffline, stripHtml, stripquotes, truncate, willFlash;
43 random = function(array) {
44 if (Array.isArray(array)) {
45 return array[sys.rand(0, array.length)];
46 } else {
47 return array;
48 }
49 };
50 shuffle = function(array) {
51 var i, length, t;
52 length = array.length;
53 while (length) {
54 i = Math.floor(Math.random() * length--);
55 t = array[length];
56 array[length] = array[i];
57 array[i] = t;
58 }
59 return array;
60 };
61 an = function(what) {
62 var _ref;
63 if ((_ref = what[0]) === 'a' || _ref === 'e' || _ref === 'u' || _ref === 'i' || _ref === 'o') {
64 return "an " + what;
65 } else {
66 return "a " + what;
67 }
68 };
69 fancyJoin = function(array, delimiter, lastDelimiter) {
70 var element, index, len, str, _i, _len;
71 if (delimiter == null) {
72 delimiter = ', ';
73 }
74 if (lastDelimiter == null) {
75 lastDelimiter = 'and';
76 }
77 str = '';
78 len = array.length;
79 if (len === 0) {
80 return '';
81 } else if (len === 1) {
82 return array[0];
83 } else if (len === 2) {
84 return "" + array[0] + " " + lastDelimiter + " " + array[1];
85 }
86 for (index = _i = 0, _len = array.length; _i < _len; index = ++_i) {
87 element = array[index];
88 if (len === (index + 1)) {
89 str += "" + lastDelimiter + " " + element;
90 break;
91 } else {
92 str += element + delimiter;
93 }
94 }
95 return str;
96 };
97 stripHtml = function(str) {
98 return str.replace(/<\/?[^>]*>/g, "");
99 };
100 escapeRegex = function(str) {
101 return str.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
102 };
103 sortOnlineOffline = function(arr) {
104 var name, offline, online, _i, _len;
105 online = [];
106 offline = [];
107 for (_i = 0, _len = arr.length; _i < _len; _i++) {
108 name = arr[_i];
109 if (Client.id(name) !== -1) {
110 online.push(name);
111 } else {
112 offline.push(name);
113 }
114 }
115 online.sort();
116 offline.sort();
117 return online.concat(offline);
118 };
119 truncate = function(str, len) {
120 var strlen;
121 strlen = str.length;
122 if (strlen > len) {
123 str = str.substr(0, len) + ("... [" + (strlen - len) + " more]");
124 }
125 return str;
126 };
127 stripquotes = function(str) {
128 return str.replace(/'/g, "\\'");
129 };
130 isAlpha = function(chr) {
131 chr = chr.toLowerCase();
132 return chr >= 'a' && chr <= 'z';
133 };
134 addNameHighlights = function(msg, name) {
135 return msg.replace(new RegExp("\\b(" + (escapeRegex(name)) + ")\\b(?![^\\s<]*>)", "i"), "<span class='name-hilight'>$1</span><ping/>");
136 };
137 willFlash = function(msg, name) {
138 var regex;
139 regex = new RegExp("\\b" + (escapeRegex(name)) + "\\b(?![^\\s<]*>)", "i");
140 return msg.search(regex) !== -1;
141 };
142 return confetti.util = {
143 random: random,
144 isAlpha: isAlpha,
145 shuffle: shuffle,
146 an: an,
147 fancyJoin: fancyJoin,
148 stripHtml: stripHtml,
149 sortOnlineOffline: sortOnlineOffline,
150 truncate: truncate,
151 escapeRegex: escapeRegex,
152 stripquotes: stripquotes,
153 addNameHighlights: addNameHighlights,
154 willFlash: willFlash
155 };
156})();
157
158(function() {
159 var deleteLocal, getRemoteFile, getRemoteJson, read, readJson, readLocal, readLocalJson, reloadScript, write, writeLocal;
160 read = function(file) {
161 if (sys.isSafeScripts()) {
162 return "";
163 }
164 sys.appendToFile(file, "");
165 return sys.getFileContent(file) || "";
166 };
167 readJson = function(file) {
168 return JSON.parse(read(file) || '{}');
169 };
170 readLocal = function(file) {
171 return read(confetti.dataDir + file);
172 };
173 readLocalJson = function(file) {
174 return readJson(confetti.dataDir + file);
175 };
176 write = function(file, data) {
177 if (sys.isSafeScripts()) {
178 return;
179 }
180 if (typeof data === 'object' && Object.prototype.toString(data) === '[object Object]') {
181 data = JSON.stringify(data);
182 }
183 return sys.writeToFile(file, data);
184 };
185 writeLocal = function(file, data) {
186 return write(confetti.dataDir + file, data);
187 };
188 deleteLocal = function(file) {
189 return sys.deleteFile(confetti.dataDir + file);
190 };
191 reloadScript = function(verbose) {
192 var file;
193 if (verbose == null) {
194 verbose = false;
195 }
196 file = read(sys.scriptsFolder + "scripts.js");
197 if (file) {
198 confetti.silentReload = !verbose;
199 sys.unsetAllTimers();
200 return sys.changeScript(file);
201 }
202 };
203 getRemoteFile = function(url, errback, callback) {
204 return sys.webCall(url, function(resp) {
205 var chan, errmsg;
206 if (resp === "") {
207 if (Array.isArray(errback)) {
208 errmsg = errback[0], chan = errback[1];
209 if (!errmsg) {
210 return;
211 }
212 return confetti.msg.bot(errmsg, chan);
213 } else if (typeof errback === 'function') {
214 return errback();
215 } else {
216 return;
217 }
218 }
219 return callback(resp);
220 });
221 };
222 getRemoteJson = function(url, errback, callback) {
223 return sys.webCall(url, function(resp) {
224 var chan, errmsg, ex, json;
225 try {
226 json = JSON.parse(resp);
227 } catch (_error) {
228 ex = _error;
229 if (Array.isArray(errback)) {
230 errmsg = errback[0], chan = errback[1];
231 if (!errmsg) {
232 return;
233 }
234 return confetti.msg.bot(errmsg, chan);
235 } else if (typeof errback === 'function') {
236 return errback();
237 } else {
238 return;
239 }
240 }
241 return callback(json, resp);
242 });
243 };
244 return confetti.io = {
245 read: read,
246 readJson: readJson,
247 readLocal: readLocal,
248 readLocalJson: readLocalJson,
249 write: write,
250 writeLocal: writeLocal,
251 writeLocalJson: writeLocal,
252 deleteLocal: deleteLocal,
253 reloadScript: reloadScript,
254 getRemoteFile: getRemoteFile,
255 getRemoteJson: getRemoteJson
256 };
257})();
258
259(function() {
260 var Cache;
261 Cache = (function() {
262 function Cache(file, hash) {
263 var ex;
264 this.file = file != null ? file : confetti.cacheFile;
265 this.hash = hash != null ? hash : {};
266 this.saved = 0;
267 try {
268 this.hash = confetti.io.readLocalJson(this.file);
269 } catch (_error) {
270 ex = _error;
271 confetti.io.writeLocalJson(this.file, {});
272 }
273 }
274
275 Cache.prototype.store = function(key, value, once) {
276 if (once == null) {
277 once = false;
278 }
279 if (once && this.hash.hasOwnProperty(key)) {
280 return this;
281 }
282 this.hash[key] = value;
283 this.saved += 1;
284 return this;
285 };
286
287 Cache.prototype.remove = function(key) {
288 if (typeof this.hash[key] !== 'undefined') {
289 delete this.hash[key];
290 this.saved += 1;
291 }
292 return this;
293 };
294
295 Cache.prototype.read = function(key) {
296 return this.hash[key];
297 };
298
299 Cache.prototype.get = function(key) {
300 return this.hash[key];
301 };
302
303 Cache.prototype.init = function(keys) {
304 var key, value;
305 for (key in keys) {
306 value = keys[key];
307 this.store(key, value, true);
308 }
309 return this;
310 };
311
312 Cache.prototype.save = function() {
313 if (this.saved > 0) {
314 confetti.io.writeLocalJson(this.file, this.hash);
315 this.saved = 0;
316 }
317 return this;
318 };
319
320 Cache.prototype.wipe = function() {
321 this.hash = {};
322 this.saved = 0;
323 confetti.io.writeLocalJson(this.file, {});
324 return this;
325 };
326
327 Cache.prototype.once = true;
328
329 return Cache;
330
331 })();
332 return confetti.Cache = Cache;
333})();
334
335(function() {
336 var authToName, battling, create, fancyName, name, status;
337 create = function(id) {
338 return {
339 id: id,
340 name: Client.name(id)
341 };
342 };
343 battling = function(id) {
344 if (Client.player == null) {
345 return false;
346 }
347 return (Client.player(id).flags & (1 << 2)) > 0;
348 };
349 authToName = function(auth) {
350 return ['User', 'Moderator', 'Administrator', 'Owner'][auth] || 'Invisible';
351 };
352 status = function(id, trackingResolve) {
353 var battlingPart;
354 if (typeof id === 'string') {
355 id = Client.id(id);
356 }
357 if (id === -1) {
358 return "(<font color='red'><b>Offline</b></font>)";
359 } else {
360 battlingPart = "";
361 if (battling(id)) {
362 battlingPart = " - <a href='po:watchplayer/" + id + "' style='text-decoration: none; color: blue;' title='Watch " + (confetti.util.stripquotes(name(id, trackingResolve))) + " battle'><b>Battling</b></a>";
363 }
364 return "(<a href='po:pm/" + id + "' style='text-decoration: none; color: green;'><b>Online</b></a>" + battlingPart + ")";
365 }
366 };
367 name = function(id, trackingResolve) {
368 var pname, storedname, trackName, tracked, _ref;
369 if (trackingResolve == null) {
370 trackingResolve = confetti.cache.get('trackingresolve');
371 }
372 if (typeof id === 'string') {
373 pname = Client.name(Client.id(id));
374 } else {
375 pname = Client.name(id);
376 }
377 if (pname === '~Unknown~') {
378 storedname = (_ref = confetti.players[id]) != null ? _ref.name : void 0;
379 return storedname != null ? storedname : id;
380 }
381 if (trackingResolve === false) {
382 return pname;
383 } else {
384 tracked = confetti.cache.get('tracked');
385 trackName = tracked[pname.toLowerCase()];
386 return trackName != null ? trackName : pname;
387 }
388 };
389 fancyName = function(id, tooltip, trackingResolve) {
390 var pid, pname, showInfo;
391 if (tooltip == null) {
392 tooltip = true;
393 }
394 pname = name(id, trackingResolve);
395 pid = typeof id === 'string' ? Client.id(id) : id;
396 showInfo = pid !== -1 && tooltip;
397 return "<a " + (showInfo ? 'href=\'po:info/' + pid + '\' ' : '') + ("style='text-decoration: none; color: " + (Client.color(pid)) + ";'") + (showInfo ? ' title="Challenge ' + confetti.util.stripquotes(pname) + '"' : '') + ("><b>" + pname + "</b></a>");
398 };
399 return confetti.player = {
400 create: create,
401 battling: battling,
402 authToName: authToName,
403 status: status,
404 name: name,
405 fancyName: fancyName
406 };
407})();
408
409(function() {
410 var channelIds, players;
411 channelIds = function() {
412 var chan, _i, _len, _ref, _results;
413 _ref = Client.myChannels();
414 _results = [];
415 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
416 chan = _ref[_i];
417 _results.push(Client.channelId(chan));
418 }
419 return _results;
420 };
421 players = function(chan) {
422 var channel, id;
423 channel = Client.channel(chan);
424 return (function() {
425 var _results;
426 _results = [];
427 for (id in confetti.players) {
428 if (channel.hasPlayer(id)) {
429 _results.push(parseInt(id, 10));
430 }
431 }
432 return _results;
433 })();
434 };
435 return confetti.channel = {
436 channelIds: channelIds,
437 players: players
438 };
439})();
440
441(function() {
442 var bold, bot, bullet, html, indent, notification, notify, pm, poIcon;
443 indent = " ";
444 bullet = "" + indent + "•";
445 poIcon = '<img width=16 height=16 src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAADBElEQVR42o2Tf0zNaxzHn+eL9JWrn4hFuIoTuwxnOqd0SUUT92KJRXOb8uNyRNM014+Jml91/XEtFYcZO8YNK3SSX7NK7PrDJWaYM1Nz/WGK1aFzXp462Eyz+9nee7Znn/f7+bw/n88jxDeBHLX61eAtJSRWVZFx+hyLs4rejw9Jfq6L/xVxlQa/VEdZct6H5j1HcR8v74SrqdTmKovLwfB9csSO9cKw3SmNJWgzrxGU9gxzTiur/3Rz4ATYL+EsOER29+SxednSsA05pgAZvhU5djcy8ggyvppe8+8zdeNbCsrg2mXYa+3I/sqzl8k6Wgz73Snn3VWko8jQLLTg35DDspRgPtJ8DJlUT/SGFvZZ4eoVnCl5zk92Jh4cpA3NLJXBS5E/FSIj8tH6p6L5JKD5z0UOzlAVbUZOttJjzm3Sdn7gxN90otQj8KPFLAcsaNL8flGvpqMNWOIhe8co/Izmm0SX+ChlL+YUI5a9YHsx2FRjxVY08UPYiiTRL94tfWLR+iqirk4vs4JJIdIj5DsHGbIcOa6IXrNqSS+Awzbc2XtbgoToHxUtAmLbpB6F9I5C661IXpORvolIfYpHqM80ZNBCZFgucoqN6TnvyS/BNTe3JVDMWlVpCB6X+kz4m5A+MaqjRgJC44hL2UXvkfPUnRLRlRW/2Z4qJv6FIbOJsMQ9jV0tsFrxPnaS4uSMI/QcaETow6k418zFC7As/zHC34hU1uTAFMTIlYgJuYRM28iOwobiL4O0lRN+voL2U6fbmLFgN9ft7/jnelenEUOmIkITCIxcQ2J6CTv3/8vLu7Q/aSD8qz2qqnCtra9RM7Z38GumlfV/VDN9YRFnTjpw3ILmO3C/Fv5rhNbHWLpdxit2LPdu0P6wHi5dhAd18LTBA8dteP2I9tanHZbv/QavJZtuRJ8521bz6KbrzetG3J1w3HG9qbvaUrmrsHpSZ063zOR1dXq8pTFs/Npmo5503KQn7DcHzi6PDVxUG6vPt5sD0mpNwak1ESGmdQEqXfvM+wh5BaahF9XRVgAAAABJRU5ErkJggg==">';
446 notify = function(msg, chan) {
447 if (typeof chan !== 'number' || !Client.hasChannel(chan)) {
448 return;
449 }
450 return Network.sendChanMessage(chan, msg);
451 };
452 pm = function(id, msg) {
453 if (!confetti.players.hasOwnProperty(id)) {
454 return;
455 }
456 return Network.sendPM(id, msg);
457 };
458 html = function(msg, chan) {
459 if (typeof chan === 'number' && chan !== -1) {
460 return Client.printChannelMessage(msg, chan, true);
461 } else {
462 return Client.printHtml(msg);
463 }
464 };
465 bold = function(title, msg, chan, color) {
466 if (msg == null) {
467 msg = '';
468 }
469 if (color == null) {
470 color = 'black';
471 }
472 return html("<timestamp/><b style='color:" + color + "'>" + title + ":</b> " + msg, chan);
473 };
474 notification = function(msg, title, allowActive, force) {
475 if (title == null) {
476 title = Client.windowTitle;
477 }
478 if (allowActive == null) {
479 allowActive = true;
480 }
481 if (force == null) {
482 force = false;
483 }
484 if (force === true || (confetti.cache.initialized !== false && confetti.cache.read('notifications') === true)) {
485 if (Client.windowActive()) {
486 if (allowActive) {
487 return html(" " + poIcon + " <b>" + title + "</b><br>" + bullet + " " + msg);
488 }
489 } else {
490 if (title !== Client.windowTitle) {
491 title = "" + Client.windowTitle + " - " + title;
492 }
493 return Client.trayMessage(title, confetti.util.stripHtml(msg));
494 }
495 }
496 };
497 bot = function(msg, chan) {
498 if (chan == null) {
499 chan = Client.currentChannel();
500 }
501 return html("<font color=" + (confetti.cache.get('botcolor')) + "><timestamp/><b>" + (confetti.cache.get('botname')) + ":</b></font> " + msg, chan);
502 };
503 return confetti.msg = {
504 notify: notify,
505 pm: pm,
506 html: html,
507 bold: bold,
508 notification: notification,
509 bot: bot,
510 bullet: bullet,
511 indent: indent,
512 poIcon: poIcon
513 };
514})();
515
516(function() {
517 var hooks, infoRequests;
518 hooks = {};
519 confetti._hooks = hooks;
520 confetti.hook = function(name, func) {
521 if (hooks[name] == null) {
522 hooks[name] = [];
523 }
524 return hooks[name].push(func);
525 };
526 confetti.callHooks = function() {
527 var args, event, hook, res, _i, _len, _ref;
528 event = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
529 if (!hooks.hasOwnProperty(event)) {
530 return args;
531 }
532 _ref = hooks[event];
533 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
534 hook = _ref[_i];
535 res = hook.apply(null, args);
536 if (res && res.length) {
537 args = res;
538 }
539 }
540 return args;
541 };
542 confetti.initCache = function() {
543 confetti.cache = new confetti.Cache;
544 confetti.cache.init({
545 botname: '±Confetti',
546 botcolor: '#07b581',
547 notifications: true,
548 commandindicator: '-',
549 lastuse: 0,
550 plugins: [],
551 tracked: {},
552 trackingresolve: true,
553 flashes: true,
554 ignorepms: false
555 });
556 confetti.callHooks('initCache');
557 return confetti.cache.save();
558 };
559 confetti.initFields = function(fields) {
560 return confetti.hook('initCache', function() {
561 return confetti.cache.init(fields);
562 });
563 };
564 confetti.initPlugins = function(id) {
565 var ex, pid, plugin, plugins, src, success, _i, _len, _ref;
566 plugins = confetti.cache.get('plugins');
567 if (plugins.length === 0) {
568 return;
569 }
570 if (sys.isSafeScripts()) {
571 return;
572 }
573 success = false;
574 for (_i = 0, _len = plugins.length; _i < _len; _i++) {
575 plugin = plugins[_i];
576 pid = plugin.id;
577 if (typeof id === 'string' && pid !== id) {
578 continue;
579 } else if (Array.isArray(id) && (_ref = !pid, __indexOf.call(id, _ref) >= 0)) {
580 continue;
581 }
582 src = confetti.io.readLocal("plugin-" + pid + ".js");
583 if (src) {
584 try {
585 sys["eval"](src, "plugin-" + pid + ".js");
586 success = true;
587 } catch (_error) {
588 ex = _error;
589 print("Couldn't load plugin " + plugin.name + ":");
590 print("" + ex + " on line " + ex.lineNumber);
591 if (ex.backtracetext) {
592 print(ex.backtracetext);
593 }
594 }
595 }
596 }
597 if (success) {
598 confetti.callHooks('initCache');
599 return confetti.cache.save();
600 }
601 };
602 infoRequests = {};
603 Network.userInfoReceived.connect(function(info) {
604 var callback, name, _i, _len, _ref;
605 name = info != null ? info.name.toLowerCase() : void 0;
606 if (info && infoRequests.hasOwnProperty(name)) {
607 _ref = infoRequests[name];
608 for (_i = 0, _len = _ref.length; _i < _len; _i++) {
609 callback = _ref[_i];
610 callback(info);
611 }
612 return delete infoRequests[name];
613 }
614 });
615 return confetti.requestUserInfo = function(n, callback) {
616 var name;
617 name = n.toLowerCase();
618 if (infoRequests[name]) {
619 return infoRequests[name].push(callback);
620 } else {
621 infoRequests[name] = [callback];
622 return Network.getUserInfo(name);
623 }
624 };
625})();
626
627(function() {
628 var CommandList, aliases, commands, reverseAliases;
629 commands = {};
630 aliases = {};
631 reverseAliases = {};
632 confetti.command = function(name, help, handler) {
633 var complete, desc, usage, _ref, _ref1;
634 usage = "";
635 desc = "";
636 complete = "";
637 if (typeof help === 'string') {
638 _ref = confetti.cmdhelp(name, help), usage = _ref[0], desc = _ref[1], complete = _ref[2];
639 } else if (typeof help === 'object' && !Array.isArray(help)) {
640 _ref1 = confetti.cmdhelp(name, help.desc || help.help, help.args, help.mode), usage = _ref1[0], desc = _ref1[1], complete = _ref1[2];
641 } else if (help.length === 2) {
642 usage = name;
643 desc = help[0], complete = help[1];
644 } else {
645 usage = help[0], desc = help[1], complete = help[2];
646 }
647 return commands[name] = {
648 name: name,
649 help: help,
650 handler: handler,
651 info: {
652 usage: usage,
653 desc: desc,
654 complete: complete
655 }
656 };
657 };
658 confetti.cmdhelp = function(name, desc, args, mode) {
659 var arg, argl, arglist, help, _i, _len;
660 if (args == null) {
661 args = [];
662 }
663 if (mode == null) {
664 mode = confetti.Send;
665 }
666 help = [];
667 if (args.length) {
668 mode = confetti.SetMsg;
669 }
670 switch (mode) {
671 case confetti.Send:
672 help = [name, desc, "send@" + name];
673 break;
674 case confetti.SetMsg:
675 argl = Array.isArray(args) ? args : args.split(' ');
676 arglist = [];
677 for (_i = 0, _len = argl.length; _i < _len; _i++) {
678 arg = argl[_i];
679 arglist.push("[" + arg + "]");
680 }
681 help = ["" + name + " " + (arglist.join(':')), desc, "setmsg@" + name + " " + (argl.join(':'))];
682 }
683 return help;
684 };
685 confetti.Send = 0;
686 confetti.SetMsg = 1;
687 confetti.alias = function(caliases, command) {
688 var alias, _i, _len, _results;
689 if (!Array.isArray(caliases)) {
690 caliases = caliases.split(', ');
691 }
692 if (reverseAliases[command] == null) {
693 reverseAliases[command] = [];
694 }
695 _results = [];
696 for (_i = 0, _len = caliases.length; _i < _len; _i++) {
697 alias = caliases[_i];
698 aliases[alias] = command;
699 _results.push(reverseAliases[command].push(alias));
700 }
701 return _results;
702 };
703 confetti.aliasesOf = function(command) {
704 return reverseAliases[command];
705 };
706 confetti.isCommand = function(message) {
707 var _ref;
708 return ((_ref = message[0]) === confetti.cache.get('commandindicator') || _ref === '-') && message.length > 1 && confetti.util.isAlpha(message[1]);
709 };
710 confetti.execCommand = function(command, data, message, chan) {
711 if (aliases.hasOwnProperty(command)) {
712 command = aliases[command];
713 }
714 if (commands.hasOwnProperty(command)) {
715 return commands[command].handler(data, chan, message);
716 } else {
717 return confetti.msg.bot("The command '" + command + "' doesn't exist!");
718 }
719 };
720 confetti.runCommand = function(message, chan) {
721 var command, data, space;
722 if (chan == null) {
723 chan = Client.currentChannel();
724 }
725 if (confetti.isCommand(message)) {
726 message = message.substr(1);
727 }
728 space = message.indexOf(' ');
729 command = "";
730 data = "";
731 if (space !== -1) {
732 command = message.substr(0, space);
733 data = message.substr(space + 1);
734 } else {
735 command = message;
736 }
737 return confetti.execCommand(command, data, message, chan);
738 };
739 confetti.commands = commands;
740 confetti.aliases = aliases;
741 CommandList = (function() {
742 function CommandList(name, highlight) {
743 var commandindicator;
744 this.name = name;
745 this.highlight = highlight != null ? highlight : [];
746 commandindicator = confetti.cache.get('commandindicator');
747 this.template = ["<table width=25%><tr><td><center><font size=5><b>" + this.name + "</b></font></center></td></tr></table>", "", "<b style='color:teal'>To use any of these commands, prefix them with '" + commandindicator + "' like so:</b> <u>" + commandindicator + "commands</u>", ""];
748 }
749
750 CommandList.prototype.cmd = function(name) {
751 var aliasstr, caliases, cmdname, command, desc, info, parts;
752 command = confetti.commands[name];
753 if (command) {
754 info = command.info;
755 parts = info.complete.split('@');
756 desc = typeof info.desc === 'function' ? info.desc() : info.desc;
757 caliases = confetti.aliasesOf(name);
758 aliasstr = '';
759 if (caliases) {
760 aliasstr = " (Alias" + (caliases.length === 1 ? '' : 'es') + ": <i>" + (caliases.join(', ')) + "</i>)";
761 }
762 cmdname = "<a href='po:" + parts[0] + "/-" + parts[1] + "' style='text-decoration:none;color:teal'>" + info.usage + "</a>";
763 if (__indexOf.call(this.highlight, name) >= 0) {
764 cmdname = "<b class='name-hilight'>" + cmdname + "</b>";
765 }
766 this.template.push("\u00bb " + cmdname + " - " + desc + aliasstr);
767 }
768 return this;
769 };
770
771 CommandList.prototype.cmds = function(names) {
772 var name, _i, _len;
773 if (typeof names === 'string') {
774 names = names.split(' ');
775 }
776 for (_i = 0, _len = names.length; _i < _len; _i++) {
777 name = names[_i];
778 this.cmd(name);
779 }
780 return this;
781 };
782
783 CommandList.prototype.group = function(name) {
784 this.whiteline();
785 this.template.push("<font size=4><b>" + name + "</b></font>");
786 this.whiteline();
787 return this;
788 };
789
790 CommandList.prototype.whiteline = function() {
791 this.template.push("");
792 return this;
793 };
794
795 CommandList.prototype.hooks = function(name) {
796 confetti.callHooks("commands:" + name, this);
797 return this;
798 };
799
800 CommandList.prototype.render = function(chan) {
801 if (chan == null) {
802 chan = Client.currentChannel();
803 }
804 this.whiteline();
805 return confetti.msg.html(this.template.join("<br>"), chan);
806 };
807
808 return CommandList;
809
810 })();
811 confetti.CommandList = CommandList;
812 return confetti.cmdlist = function(name, cmds, hooks) {
813 var list;
814 list = new CommandList(name).cmds(cmds);
815 if (hooks) {
816 list.hooks(hooks);
817 }
818 return list.render();
819 };
820})();
821
822(function() {
823 confetti.command('authsymbols', "Shows the auth symbols you have set.", function(_, chan) {
824 var auth, authlvl, authlvls, authsymbols, end, html, numSymbols, parts, start;
825 authsymbols = confetti.cache.get('authsymbols');
826 numSymbols = Object.keys(authsymbols).length;
827 if (numSymbols === 0) {
828 return confetti.msg.bot("You have not set any auth symbols.");
829 }
830 confetti.msg.bold("Auth symbols <small>[" + numSymbols + "]</small>", '', chan);
831 html = "";
832 start = "";
833 end = "";
834 authlvls = ["", "", "", "", ""];
835 for (auth in authsymbols) {
836 parts = authsymbols[auth];
837 start = parts[0], end = parts[1];
838 authlvls[auth] = "" + confetti.msg.bullet + " Auth <b>" + (confetti.player.authToName(auth)) + "</b> (" + auth + "): " + (sys.htmlEscape(start)) + "<b>Name</b>" + (sys.htmlEscape(end));
839 }
840 authlvls = (function() {
841 var _i, _len, _results;
842 _results = [];
843 for (_i = 0, _len = authlvls.length; _i < _len; _i++) {
844 authlvl = authlvls[_i];
845 if (authlvl !== "") {
846 _results.push(authlvl);
847 }
848 }
849 return _results;
850 })();
851 return confetti.msg.html(authlvls.join("<br>") + "<br>", chan);
852 });
853 confetti.alias('authsymbollist, authsymbolist', 'authsymbols');
854 confetti.command('authsymbol', ['authsymbol [auth]:[start]:[end?]', "Changes the auth symbol of [auth] (0 - User, 1 - Moderator, 2 - Administrator, 3 - Owner, or 4 - \"Invisible\") to [start]. [end?] is optional and will be inserted after the name (useful for HTML). If neither [start] nor [end?] is given, the auth symbol for [auth] is reset (if you want an empty auth symbol for auth level [auth], do <code>authsymbol:</code>).", 'setmsg@authsymbol auth:start'], function(data) {
855 var authl, authn, authsymbols, end, parts, start;
856 parts = data.split(':');
857 authl = parts[0], start = parts[1], end = parts[2];
858 authl = parseInt(authl, 10);
859 if (start != null) {
860 start = start.trim();
861 }
862 if (end != null) {
863 end = end.trim();
864 }
865 authsymbols = confetti.cache.get('authsymbols');
866 if (isNaN(authl)) {
867 return confetti.msg.bot("" + (sys.htmlEscape(parts[0])) + " is not a number. Give a number in the range 0-4.");
868 } else if (authl < 0) {
869 authl = 0;
870 } else if (authl > 4) {
871 authl = 4;
872 }
873 authn = confetti.player.authToName(authl);
874 if ((start == null) && (end == null)) {
875 if (authsymbols.hasOwnProperty(authl)) {
876 delete authsymbols[authl];
877 confetti.cache.store('authsymbols', authsymbols).save();
878 return confetti.msg.bot("Auth symbol for auth " + authn + " (" + authl + ") removed!");
879 } else {
880 return confetti.msg.bot("There is no auth symbol for auth " + authn + " (" + authl + "). Give a start and an end for the auth level.");
881 }
882 }
883 if (start == null) {
884 start = '';
885 }
886 if (end == null) {
887 end = '';
888 }
889 authsymbols[authl] = [start, end];
890 confetti.cache.store('authsymbols', authsymbols).save();
891 return confetti.msg.bot("Players whose auth is " + authn + " (" + authl + ") will now be formatted like so: " + start + "<b>Name</b>" + end);
892 });
893 confetti.initFields({
894 authsymbols: {}
895 });
896 return confetti.hook('manipulateChanPlayerMessage', function(from, fromId, message, playerMessage, _arg, chan, html, dirty) {
897 var auth, authSymbol, authsymbols, color, symbol;
898 color = _arg[0], auth = _arg[1], authSymbol = _arg[2];
899 authsymbols = confetti.cache.get('authsymbols');
900 if (auth > 4) {
901 auth = 4;
902 }
903 symbol = authsymbols[auth];
904 if (symbol) {
905 authSymbol = symbol;
906 dirty = true;
907 }
908 return [from, fromId, message, playerMessage, [color, auth, authSymbol], chan, html, dirty];
909 });
910})();
911
912(function() {
913 confetti.command('blocked', "Displays a list of blocked players.", function(_, chan) {
914 var blocked, blocklist, count, html, _i, _len;
915 blocklist = confetti.util.sortOnlineOffline(confetti.cache.get('blocked'));
916 if (blocklist.length === 0) {
917 return confetti.msg.bot("There is no one on your block list.");
918 }
919 confetti.msg.bold("Blocked players <small>[" + blocklist.length + "]</small>", '', chan);
920 html = "";
921 count = 0;
922 for (_i = 0, _len = blocklist.length; _i < _len; _i++) {
923 blocked = blocklist[_i];
924 count += 1;
925 html += "" + confetti.msg.bullet + " " + (confetti.player.fancyName(blocked)) + " " + (confetti.player.status(blocked));
926 if (count % 3 === 0) {
927 html += "<br>";
928 }
929 }
930 return confetti.msg.html(html, chan);
931 });
932 confetti.command('block', {
933 help: "Blocks a user by automatically ignoring them when they log in.",
934 args: ["name"]
935 }, function(data) {
936 var blocked, id, len, name;
937 len = data.length;
938 if (!data) {
939 return confetti.msg.bot("Specify a name!");
940 } else if (len > 20) {
941 return confetti.msg.bot("That name's a bit too long.");
942 }
943 name = confetti.player.name(data);
944 data = data.toLowerCase();
945 blocked = confetti.cache.get('blocked');
946 if (Client.ownName().toLowerCase() === data) {
947 return confetti.msg.bot("You can't block yourself!");
948 }
949 if (__indexOf.call(blocked, data) >= 0) {
950 return confetti.msg.bot("" + (sys.htmlEscape(name)) + " is already blocked!");
951 }
952 blocked.push(data);
953 confetti.cache.store('blocked', blocked).save();
954 id = Client.id(data);
955 if (id !== -1) {
956 Client.ignore(id, true);
957 }
958 return confetti.msg.bot("" + (sys.htmlEscape(name)) + " is now blocked!");
959 });
960 confetti.command('unblock', {
961 help: "Unblocks a user.",
962 args: ["name"]
963 }, function(data) {
964 var blocked, id, name;
965 data = data.toLowerCase();
966 name = confetti.player.name(data);
967 blocked = confetti.cache.get('blocked');
968 if (__indexOf.call(blocked, data) < 0) {
969 return confetti.msg.bot("" + (sys.htmlEscape(name)) + " isn't blocked!");
970 }
971 blocked.splice(blocked.indexOf(data), 1);
972 confetti.cache.store('blocked', blocked).save();
973 id = Client.id(data);
974 if (id !== -1) {
975 Client.ignore(id, false);
976 }
977 return confetti.msg.bot("You are no longer blocking " + (sys.htmlEscape(name)) + "!");
978 });
979 confetti.initFields({
980 blocked: []
981 });
982 return confetti.hook('onPlayerReceived', function(id) {
983 var blocked, name;
984 name = Client.name(id).toLowerCase();
985 blocked = confetti.cache.get('blocked');
986 if (__indexOf.call(blocked, name) >= 0) {
987 return Client.ignore(id, true);
988 }
989 });
990})();
991
992(function() {
993 return confetti.command('define', {
994 help: "Attempts to find a definition for the given term.",
995 args: ["term"]
996 }, function(data, chan) {
997 if (!data) {
998 return confetti.msg.bot("You need to give me a term!");
999 }
1000 return sys.webCall("http://api.urbandictionary.com/v0/define?term=" + (encodeURIComponent(data)), function(response) {
1001 var def, entry, ex, example, examples, json, list, _i, _len;
1002 if (!response) {
1003 return confetti.msg.bot("Couldn't load the definition - your internet might be down.", chan);
1004 }
1005 try {
1006 json = JSON.parse(response);
1007 } catch (_error) {
1008 ex = _error;
1009 return confetti.msg.bot("Couldn't load the definition - your internet might be down.", chan);
1010 }
1011 list = json.list;
1012 if (json.result_type === 'no_results') {
1013 return confetti.msg.bot("I couldn't find anything for " + data + "!");
1014 }
1015 entry = confetti.util.random(list);
1016 examples = entry.example.split('\n');
1017 def = entry.definition || '';
1018 if (def.trim()) {
1019 confetti.msg.bold(data, sys.htmlEscape(def), chan);
1020 }
1021 for (_i = 0, _len = examples.length; _i < _len; _i++) {
1022 example = examples[_i];
1023 if (example.trim()) {
1024 confetti.msg.html(" <b>•</b> " + (sys.htmlEscape(example)), chan);
1025 }
1026 }
1027 return null;
1028 });
1029 });
1030})();
1031
1032(function() {
1033 var chr, encool, encoolHandlers, encoolTypes, fullwidthChars, fullwidthConvert, fullwidthify, halfwidthChars, index, l33tify, natoTable, natoify, normalLetters, smallcapsConvert, smallcapsLetters, smallcapsify, val, _i, _j, _len, _len1;
1034 normalLetters = 'qwertyuiopasdfghjklzxcvbnm'.split('');
1035 smallcapsLetters = 'ǫᴡᴇʀᴛÊᴜɪá´á´˜á´€sᴅғɢʜᴊᴋʟᴢxᴄᴠʙɴá´'.split('');
1036 smallcapsConvert = {};
1037 for (index = _i = 0, _len = normalLetters.length; _i < _len; index = ++_i) {
1038 chr = normalLetters[index];
1039 smallcapsConvert[chr] = smallcapsConvert[chr.toUpperCase()] = smallcapsLetters[index];
1040 }
1041 halfwidthChars = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~'.split('');
1042 fullwidthChars = "ï¼ï¼‚#$%&'()*+,ï¼ï¼Žï¼ï¼ï¼‘23456789:;<ï¼ï¼žï¼Ÿï¼ ABCDEFGHIJKLï¼ï¼®ï¼¯ï¼°ï¼±ï¼²ï¼³ï¼´ï¼µï¼¶ï¼·ï¼¸ï¼¹ï¼ºï¼»ï¼¼ï¼½ï¼¾ï¼¿ï½€ï½ï½‚cdefghijklï½ï½Žï½ï½ï½‘rstuvwxyz{|ï½ï½ž".split('');
1043 fullwidthConvert = {};
1044 for (index = _j = 0, _len1 = halfwidthChars.length; _j < _len1; index = ++_j) {
1045 chr = halfwidthChars[index];
1046 fullwidthConvert[chr] = fullwidthChars[index];
1047 }
1048 natoTable = {
1049 a: "Alpha",
1050 b: "Bravo",
1051 c: "Charlie",
1052 d: "Delta",
1053 e: "Echo",
1054 f: "Foxtrot",
1055 g: "Golf",
1056 h: "Hotel",
1057 i: "India",
1058 j: "Juliet",
1059 k: "Kilo",
1060 l: "Lima",
1061 m: "Mike",
1062 n: "November",
1063 o: "Oscar",
1064 p: "Papa",
1065 q: "Quebec",
1066 r: "Romeo",
1067 s: "Sierra",
1068 t: "Tango",
1069 u: "Uniform",
1070 v: "Victor",
1071 w: "Whiskey",
1072 x: "Xray",
1073 y: "Yankee",
1074 z: "Zulu",
1075 0: "Zero",
1076 1: "One",
1077 2: "Two",
1078 3: "Three",
1079 4: "Four",
1080 5: "Five",
1081 6: "Six",
1082 7: "Seven",
1083 8: "Eight",
1084 9: "Niner"
1085 };
1086 for (chr in natoTable) {
1087 val = natoTable[chr];
1088 natoTable[chr.toUpperCase()] = val;
1089 }
1090 smallcapsify = function(msg) {
1091 var letter, str, _k, _len2;
1092 str = [];
1093 for (index = _k = 0, _len2 = msg.length; _k < _len2; index = ++_k) {
1094 letter = msg[index];
1095 str[index] = smallcapsConvert[letter] || letter;
1096 }
1097 return str.join('');
1098 };
1099 fullwidthify = function(msg) {
1100 var letter, str, _k, _len2;
1101 str = [];
1102 for (index = _k = 0, _len2 = msg.length; _k < _len2; index = ++_k) {
1103 letter = msg[index];
1104 str[index] = fullwidthConvert[letter] || letter;
1105 }
1106 return str.join('');
1107 };
1108 natoify = function(msg) {
1109 var letter, ntl, str, _k, _len2;
1110 msg = msg.replace(/\b(the|a(n)?|is|are)\b/gi, "");
1111 str = [];
1112 for (index = _k = 0, _len2 = msg.length; _k < _len2; index = ++_k) {
1113 letter = msg[index];
1114 ntl = natoTable[letter];
1115 if (ntl) {
1116 str.push(ntl);
1117 if (natoTable[msg[index + 1]]) {
1118 str.push("-");
1119 }
1120 } else {
1121 str.push(letter);
1122 }
1123 }
1124 return str.join('');
1125 };
1126 l33tify = function(msg) {
1127 return msg.replace(/\b(hacker|coder|programmer)(s|z)?\b/gi, 'haxor$2').replace(/\b(hack)(ed|s|z)?\b/gi, 'haxor$2').replace(/\b(thank you)\b/gi, 'TY').replace(/\b(luv|love|wuv|like)(s|z)?\b/gi, 'wub$2').replace(/\b(software)(s|z)?\b/gi, 'wares').replace(/\b((is|are|am) +(cool|wicked|awesome|great))\b/gi, 'rocks').replace(/\b((is|are|am) +(\w+) +(cool|wicked|awesome|great))\b/gi, '$3 rocks').replace(/\b(very|extremely)\b/gi, 'totally').replace(/\b(because)\b/gi, 'coz').replace(/\b(due to)\b/gi, 'coz of').replace(/\b(is|am)\b/gi, 'be').replace(/\b(are)\b/gi, 'is').replace(/\b(rock)(s|z)?\b/gi, 'roxor$2').replace(/\b(porn(o(graph(y|ic))?)?)\b/gi, 'pron').replace(/\b(lamer|dork|jerk|moron|idiot)\b/gi, 'loser').replace(/\b(an loser)\b/gi, 'a loser').replace(/\b(what('s)?)\b/gi, 'wot').replace(/\b(that)\b/gi, 'dat').replace(/\b(this)\b/gi, 'dis').replace(/\b(hooray|yippee|yay|yeah)\b/gi, 'woot').replace(/\b(win|own)(s|z)?\b/gi, 'pwn$2').replace(/\b(won|owned)\b/gi, 'pwnt').replace(/\b(suck)(ed|s|z)?\b/gi, 'suxor$2').replace(/\b(was|were|had been)/gi, 'wuz').replace(/\b(elite)/gi, 'leet').replace(/\byou\b/gi, 'joo').replace(/\b(man|dude|guy|boy)(s|z)?\b/gi, 'dood$2').replace(/\b(men)\b/gi, 'doods').replace(/\bstarbucks?\b/gi, 'bizzo').replace(/\b(the)\b/gi, 'teh').replace(/(ing)\b/gi, 'in\'').replace(/\b(stoked|happy|excited|thrilled|stimulated)\b/gi, 'geeked').replace(/\b(unhappy|depressed|miserable|sorry)\b/gi, 'bummed out').replace(/\b(and|an)\b/gi, 'n').replace(/\b(your|hey|hello|hi)\b/gi, 'yo').replace(/\b(might)\b/gi, 'gonna').replace(/\blater\b/gi, 'l8r').replace(/\bare\b/gi, 'R').replace(/\bbe\b/gi, 'b').replace(/\bto\b/gi, '2').replace(/\ba\b/gi, '@').replace(/(\S)l/g, '$1L').replace(/(\S)l/g, '$1L').replace(/a/gi, '4').replace(/\bfor\b/gi, '4').replace(/e/gi, '3').replace(/i/gi, '1').replace(/o/gi, '0').replace(/s\b/gi, 'z');
1128 };
1129 encoolHandlers = {
1130 none: function(msg) {
1131 return msg;
1132 },
1133 spaces: function(msg) {
1134 return msg.split('').join(' ');
1135 },
1136 smallcaps: function(msg) {
1137 return smallcapsify(msg);
1138 },
1139 fullwidth: function(msg) {
1140 return fullwidthify(msg);
1141 },
1142 nato: function(msg) {
1143 return natoify(msg);
1144 },
1145 leet: function(msg) {
1146 return l33tify(msg);
1147 },
1148 l33t: function(msg) {
1149 return l33tify(msg);
1150 },
1151 reverse: function(msg) {
1152 return msg.split('').reverse().join('');
1153 }
1154 };
1155 encool = function(msg, type) {
1156 if (type == null) {
1157 type = confetti.cache.read('encool');
1158 }
1159 return encoolHandlers[type || 'none'](msg);
1160 };
1161 encoolTypes = Object.keys(encoolHandlers);
1162 confetti.encool = encool;
1163 confetti._encool = {
1164 encoolHandlers: encoolHandlers,
1165 encoolTypes: encoolTypes
1166 };
1167 confetti.encool.register = function(type, handler) {
1168 encoolHandlers[type] = handler;
1169 return encoolTypes = Object.keys(encoolHandlers);
1170 };
1171 confetti.msg.notify = function(msg, chan) {
1172 if (typeof chan !== 'number' || !Client.hasChannel(chan)) {
1173 return;
1174 }
1175 return Network.sendChanMessage(chan, encool(msg));
1176 };
1177 confetti.command('encool', {
1178 help: function() {
1179 return "Changes your encool type to (" + (encoolTypes.join(', ')) + ").";
1180 },
1181 args: ["type"]
1182 }, function(data) {
1183 data = data.toLowerCase();
1184 if (!(__indexOf.call(encoolTypes, data) >= 0)) {
1185 confetti.msg.bot("That doesn't look right to me!");
1186 return confetti.msg.bot("Use one of the following types: " + (encoolTypes.join(', ')));
1187 }
1188 if (confetti.cache.read('encool') === data) {
1189 return confetti.msg.bot("Your encool type is already " + data + "!");
1190 }
1191 confetti.cache.store('encool', data).save();
1192 return confetti.msg.bot("Your encool type is now " + data + "!");
1193 });
1194 confetti.initFields({
1195 encool: 'none'
1196 });
1197 return confetti.hook('manipulateOwnMessage', function(message, chan, dirty) {
1198 var mess;
1199 mess = message;
1200 if (mess[0] !== '/') {
1201 mess = encool(message);
1202 dirty = true;
1203 }
1204 return [mess, chan, dirty];
1205 });
1206})();
1207
1208(function() {
1209 var classhilight, flashwordCategory;
1210 classhilight = "<span class='name-hilight'>$1</span><ping/>";
1211 flashwordCategory = function(word) {
1212 var flags, parts, regex;
1213 parts = word.split('/');
1214 if (parts.length < 3) {
1215 return {
1216 type: 'word',
1217 word: word
1218 };
1219 }
1220 flags = parts.pop();
1221 regex = parts.slice(1);
1222 return {
1223 type: 'regex',
1224 regex: regex,
1225 flags: flags
1226 };
1227 };
1228 confetti.command('flashwords', "Shows your flash words (sequences of characters that ping you when said).", function(_, chan) {
1229 var flashwords, html, index, numWords, word, _i, _len;
1230 flashwords = confetti.cache.get('flashwords');
1231 numWords = flashwords.length;
1232 if (numWords === 0) {
1233 return confetti.msg.bot("You have no flash words.");
1234 }
1235 confetti.msg.bold("Flash words <small>[" + numWords + "]</small>", '', chan);
1236 html = "";
1237 for (index = _i = 0, _len = flashwords.length; _i < _len; index = ++_i) {
1238 word = flashwords[index];
1239 html += confetti.msg.bullet + (" " + (flashwordCategory(word).type === 'word' ? 'Word' : 'Regex') + ": <b>" + (sys.htmlEscape(word)) + "</b> <small>[<a href='po:send/-removeflashword " + (confetti.util.stripquotes(word)) + "' style='text-decoration:none;color:black'>remove</a>]</small><br>");
1240 }
1241 return confetti.msg.html(html, chan);
1242 });
1243 confetti.alias('flashwordlist', 'flashwords');
1244 confetti.command('flashword', {
1245 help: "Adds [word] to your flash word list. [word] may also be a <a href='http://www.regexr.com/' title='Regexr'>regular expression</a>, prefix it with <b>/</b> like so: /(word)/i. The first capture group will be the flashword.",
1246 args: ["word"]
1247 }, function(data) {
1248 var flashwords, index;
1249 flashwords = confetti.cache.get('flashwords');
1250 if (!data) {
1251 return confetti.msg.bot("Specify the flashword!");
1252 }
1253 index = flashwords.indexOf(data);
1254 if (index !== -1) {
1255 return confetti.msg.bot("" + (sys.htmlEscape(data)) + " is already in your flashwords list!");
1256 }
1257 flashwords.push(data);
1258 confetti.cache.store('flashwords', flashwords).save();
1259 return confetti.msg.bot("<b>" + (sys.htmlEscape(data)) + "</b> will now ping you when said!");
1260 });
1261 confetti.alias('addflashword, stalkword, addstalkword', 'flashword');
1262 confetti.command('removeflashword', {
1263 help: "Removes [flashword] from your flashword list.",
1264 args: ["flashword"]
1265 }, function(data) {
1266 var flashwords, index;
1267 flashwords = confetti.cache.get('flashwords');
1268 if (!data) {
1269 return confetti.msg.bot("Specify the flash word!");
1270 }
1271 index = flashwords.indexOf(data);
1272 if (index === -1) {
1273 return confetti.msg.bot("" + (sys.htmlEscape(data)) + " is not in your flashwords list, check the spelling!");
1274 }
1275 flashwords.splice(index, 1);
1276 confetti.cache.store('flashwords', flashwords).save();
1277 return confetti.msg.bot("<b>" + (sys.htmlEscape(data)) + "</b> will no longer ping you!");
1278 });
1279 confetti.command('flashes', "Toggles whether if name flashes and flash words should be enabled.", function() {
1280 confetti.cache.store('flashes', !confetti.cache.read('flashes')).save();
1281 return confetti.msg.bot("Flashes are now " + (confetti.cache.read('flashes') ? 'on' : 'off') + ".");
1282 });
1283 confetti.alias('rmflashword, unflashword, removestalkword, rmstalkword, unstalkword', 'removeflashword');
1284 confetti.initFields({
1285 flashwords: []
1286 });
1287 return confetti.hook('manipulateChanPlayerMessage', function(from, fromId, message, playerMessage, _arg, chan, html, dirty) {
1288 var auth, authSymbol, cat, color, flashMessage, flashword, flashwords, _i, _len;
1289 color = _arg[0], auth = _arg[1], authSymbol = _arg[2];
1290 if (confetti.cache.get('flashes') === true) {
1291 flashwords = confetti.cache.get('flashwords');
1292 flashMessage = playerMessage;
1293 for (_i = 0, _len = flashwords.length; _i < _len; _i++) {
1294 flashword = flashwords[_i];
1295 cat = flashwordCategory(flashword);
1296 if (cat.type === 'word') {
1297 flashMessage = flashMessage.replace(new RegExp("\\b(" + (confetti.util.escapeRegex(cat.word)) + ")\\b(?![^\\s<]*>)", "gi"), classhilight);
1298 } else {
1299 flashMessage = flashMessage.replace(new RegExp(cat.regex, cat.flags), classhilight);
1300 }
1301 }
1302 if (flashMessage !== playerMessage) {
1303 playerMessage = flashMessage;
1304 dirty = true;
1305 }
1306 }
1307 return [from, fromId, message, playerMessage, [color, auth, authSymbol], chan, html, dirty];
1308 });
1309})();
1310
1311(function() {
1312 confetti.command('friends', "Displays your friends list.", function(_, chan) {
1313 var count, friend, friends, html, _i, _len;
1314 friends = confetti.util.sortOnlineOffline(confetti.cache.get('friends'));
1315 if (friends.length === 0) {
1316 return confetti.msg.bot("<span title='You have 0 friends.'>There is no one on your friend list.</span>");
1317 }
1318 confetti.msg.bold("Your friends <small>[" + friends.length + "]</small>", '', chan);
1319 html = "";
1320 count = 0;
1321 for (_i = 0, _len = friends.length; _i < _len; _i++) {
1322 friend = friends[_i];
1323 count += 1;
1324 html += "" + confetti.msg.bullet + " " + (confetti.player.fancyName(friend)) + " " + (confetti.player.status(friend));
1325 if (count % 3 === 0) {
1326 html += "<br>";
1327 }
1328 }
1329 return confetti.msg.html(html, chan);
1330 });
1331 confetti.command('friend', {
1332 help: "Adds [name] to your friend list.",
1333 args: ["name"]
1334 }, function(data) {
1335 var friends, name;
1336 name = confetti.player.name(data);
1337 data = data.toLowerCase();
1338 friends = confetti.cache.get('friends');
1339 if (!data) {
1340 return confetti.msg.bot("Specify a name!");
1341 }
1342 if (Client.ownName().toLowerCase() === data) {
1343 return confetti.msg.bot("You can't add yourself as a friend!");
1344 }
1345 if (__indexOf.call(friends, data) >= 0) {
1346 return confetti.msg.bot("" + name + " is already on your friends list!");
1347 }
1348 friends.push(data);
1349 confetti.cache.store('friends', friends).save();
1350 return confetti.msg.bot("" + (sys.htmlEscape(name)) + " is now on your friends list!");
1351 });
1352 confetti.command('unfriend', {
1353 help: "Removes [name] from your friend list.",
1354 args: ["name"]
1355 }, function(data) {
1356 var friends, name;
1357 data = data.toLowerCase();
1358 name = confetti.player.name(data);
1359 friends = confetti.cache.get('friends');
1360 if (__indexOf.call(friends, data) < 0) {
1361 return confetti.msg.bot("" + (sys.htmlEscape(name)) + " isn't on your friends list!");
1362 }
1363 friends.splice(friends.indexOf(data), 1);
1364 confetti.cache.store('friends', friends).save();
1365 return confetti.msg.bot("You removed " + (sys.htmlEscape(name)) + " from your friends list!");
1366 });
1367 confetti.command('friendnotifications', "Toggles whether if notifications specific to friends (logins, logouts) should be shown.", function() {
1368 confetti.cache.store('friendnotifications', !confetti.cache.read('friendnotifications')).save();
1369 return confetti.msg.bot("Friend notifications are now " + (confetti.cache.read('friendnotifications') ? 'on' : 'off') + ".");
1370 });
1371 confetti.initFields({
1372 friends: [],
1373 friendnotifications: true
1374 });
1375 confetti.hook('onPlayerReceived', function(id) {
1376 var friends, name, tracked, trackedName;
1377 if (confetti.loginTime === 0 || sys.time() <= confetti.loginTime + 4) {
1378 return;
1379 }
1380 if (confetti.cache.get('friendnotifications') === false) {
1381 return;
1382 }
1383 name = Client.name(id).toLowerCase();
1384 friends = confetti.cache.get('friends');
1385 trackedName = '';
1386 if (confetti.cache.get('trackingresolve')) {
1387 tracked = confetti.cache.get('tracked');
1388 trackedName = (tracked[name] || '').toLowerCase();
1389 }
1390 if (__indexOf.call(friends, name) >= 0 || (trackedName && __indexOf.call(friends, trackedName) >= 0)) {
1391 return confetti.msg.notification("" + (confetti.player.fancyName(id)) + " logged in.", "Friend joined");
1392 }
1393 });
1394 return confetti.hook('onPlayerRemoved', function(id) {
1395 var friends, name, tracked, trackedName;
1396 if (confetti.cache.get('friendnotifications') === false) {
1397 return;
1398 }
1399 name = Client.name(id).toLowerCase();
1400 friends = confetti.cache.get('friends');
1401 trackedName = '';
1402 if (confetti.cache.get('trackingresolve')) {
1403 tracked = confetti.cache.get('tracked');
1404 trackedName = (tracked[name] || '').toLowerCase();
1405 }
1406 if (__indexOf.call(friends, name) >= 0 || (trackedName && __indexOf.call(friends, trackedName) >= 0)) {
1407 return confetti.msg.notification("" + (confetti.player.fancyName(id, false)) + " logged out.", "Friend left");
1408 }
1409 });
1410})();
1411
1412(function() {
1413 confetti.command('commands', "Shows this command list.", function() {
1414 return new confetti.CommandList("Commands").group("Command Lists").cmds('commands scriptcommands plugincommands friendcommands blockcommands trackcommands flashcommands mapcommands configcommands').hooks('list').group("Player Symbols").cmds('authsymbols authsymbol').hooks('playersymbols').hooks('categories').whiteline().cmds('reconnect define translate news imp info chan idle pm flip myip teambuilder findbattle disconnect').hooks('misc').cmds('html eval').hooks('dev').render();
1415 });
1416 confetti.alias('commandlist', 'commands');
1417 confetti.command('configcommands', "Shows various commands that change your settings.", function() {
1418 return new confetti.CommandList("Configuration").cmds('botname botcolor encool notifications commandindicator autoreconnect ignorepms').hooks('config').whiteline().cmd('defaults').render();
1419 });
1420 confetti.command('blockcommands', "Shows commands related to blocking other players.", function() {
1421 return confetti.cmdlist("Blocking", 'block unblock blocked', 'block');
1422 });
1423 confetti.command('plugincommands', "Shows commands related to plugins.", function() {
1424 return confetti.cmdlist("Plugins", 'plugins addplugin removeplugin updateplugins', 'plugins');
1425 });
1426 confetti.command('scriptcommands', "Shows commands related to Confetti (the script).", function() {
1427 return confetti.cmdlist("Confetti", 'updatescript autoupdate changelog version', 'script');
1428 });
1429 confetti.command('trackcommands', "Shows commands related to tracking players (such as their aliases).", function() {
1430 return confetti.cmdlist("Tracking", 'track untrack tracked trackingresolve', 'track');
1431 });
1432 confetti.command('flashcommands', "Shows commands related to flashes and flashwords.", function() {
1433 return confetti.cmdlist("Flashes", 'flashword removeflashword flashwords flashes', 'flash');
1434 });
1435 confetti.command('mapcommands', "Shows commands related to message mapping", function() {
1436 return confetti.cmdlist("Message Mapping", 'map unmap maphelp mapindicator togglemaps', 'map');
1437 });
1438 return confetti.command('friendcommands', "Shows commands related to friends.", function() {
1439 return confetti.cmdlist("Friends", 'friend unfriend friends friendnotifications', 'friends');
1440 });
1441})();
1442
1443(function() {
1444 var executeMap, mapDataValidators, mapTypes;
1445 mapTypes = "command send".split(" ");
1446 mapDataValidators = {
1447 command: function(mapdata) {
1448 return mapdata.length > 0;
1449 },
1450 send: function(mapdata) {
1451 return mapdata.length > 0;
1452 }
1453 };
1454 executeMap = function(map, param, chan) {
1455 var data, line, _i, _len;
1456 if (chan == null) {
1457 chan = Client.currentChannel();
1458 }
1459 data = map.data.replace(/\$%/g, param).replace(/\$\\%/g, '$%').split('\\n');
1460 for (_i = 0, _len = data.length; _i < _len; _i++) {
1461 line = data[_i];
1462 switch (map.type) {
1463 case "command":
1464 confetti.runCommand(line, chan);
1465 break;
1466 case "send":
1467 confetti.msg.notify(line, chan);
1468 }
1469 }
1470 return true;
1471 };
1472 confetti.command('maphelp', "Displays help for message mapping.", function(_, chan) {
1473 var cin, min;
1474 cin = confetti.cache.get('commandindicator');
1475 min = confetti.cache.get('mapindicator');
1476 confetti.msg.bot("Message mapping (commonly known as binds) allows you to map a message (starting with your mapping indicator - which is currently <b><font size=4>" + cin + "</font></b>) to something else, specified by the mapping <b>type</b>. Its purpose is to expand something short, easily to type, into a longer piece of text which you have defined beforehand using the <b>map</b> command.");
1477 confetti.msg.bot("Maps take a type to indicate what to do. Here they are:");
1478 confetti.msg.html("" + confetti.msg.bullet + " <b>command</b>: Executes a Confetti command. Requires data: the command to execute. It doesn't have to start with your command indicator.", chan);
1479 confetti.msg.html("" + confetti.msg.bullet + " <b>send</b>: Sends a message in the channel you are in when you use the map. Requires data: the message to send. Can also be used to execute server commands.", chan);
1480 confetti.msg.html("", chan);
1481 confetti.msg.bot("For example:");
1482 confetti.msg.html("" + confetti.msg.bullet + " <b>Add a mapping</b>: <a href='po:send/-map pl:send:/players'>" + cin + "map pl:send:/players</a>", chan);
1483 confetti.msg.html("" + confetti.msg.bullet + " <b>Execute it</b>: <a href='po:send/" + min + "pl'>" + min + "pl</a>", chan);
1484 confetti.msg.html("" + confetti.msg.bullet + " <b>Add a multi map</b>: <a href='po:send/-map hi2:send:hi\\neveryone'>" + cin + "map hi2:send:hi\\neveryone</a> (executing it is the same process)", chan);
1485 confetti.msg.html("" + confetti.msg.bullet + " <b>Add a parameter map</b>: <a href='po:send/-map ch:command:chan $%'>" + cin + "map ch:send:chan $%</a>", chan);
1486 confetti.msg.html("" + confetti.msg.bullet + " <b>Execute it</b>: <a href='po:send/" + min + "ch Confetti'>" + min + "ch Confetti</a>", chan);
1487 confetti.msg.html("", chan);
1488 confetti.msg.bot("You can execute multiple commands in your mapping for a map by separating each command with the text \"\\n\". This is called a <b>multi map</b>.");
1489 confetti.msg.bot("If you want your map to take a parameter, you can do so by putting $% in your map (see below). If you need to have $% in your map, you can do $\\%. This is called a <b>parameter map</b>. Parameter maps and multi maps can be combined just fine.");
1490 confetti.msg.bot("To remove a mapping, use the <b>unmap</b> command. For a list of maps, use the <a href='po:send/-maps'><b>" + cin + "maps</b></a> command.");
1491 return confetti.msg.bot("You currently have maps " + (confetti.cache.get('mapsenabled') ? 'enabled' : 'disabled') + ". Toggle it with the <a href='po:send/-togglemaps'><b>" + cin + "togglemaps</b></a> command.");
1492 });
1493 confetti.command('maps', "Displays your message mappings.", function(_, chan) {
1494 var count, html, map, mapc, maps;
1495 maps = confetti.cache.get('maps');
1496 mapc = Object.keys(maps).length;
1497 if (mapc === 0) {
1498 return confetti.msg.bot("You have no message mappings.");
1499 }
1500 confetti.msg.bold("Your mappings <small>[" + mapc + "]</small>", '', chan);
1501 html = "";
1502 count = 0;
1503 for (_ in maps) {
1504 map = maps[_];
1505 count += 1;
1506 html += "" + confetti.msg.bullet + " <b>" + (sys.htmlEscape(map.msg)) + "</b>: " + map.type + " mapping" + (map.data ? ' (' + sys.htmlEscape(map.data) + ')' : '') + "<br>";
1507 }
1508 return confetti.msg.html(html, chan);
1509 });
1510 confetti.command('map', ['map [message]:[type]:[data...]', "Creates/overrides a message mapping for the message [message]. [type] is the map's type, [data] is any data to be supplied to the map. For more information (like what maps are, and the available mapping types), use the maphelp command.", 'send@maphelp'], function(data) {
1511 var mapdata, maps, mdata, msg, oldmap, type, validator, _ref;
1512 _ref = data.split(':'), msg = _ref[0], type = _ref[1], mapdata = 3 <= _ref.length ? __slice.call(_ref, 2) : [];
1513 if (type == null) {
1514 type = "";
1515 }
1516 type = type.toLowerCase();
1517 maps = confetti.cache.get('maps');
1518 if (!msg) {
1519 return confetti.msg.bot("Specify a mapping!");
1520 }
1521 if (msg.indexOf(' ') !== -1) {
1522 return confetti.msg.bot("Map names cannot contain spaces.");
1523 }
1524 if (!(__indexOf.call(mapTypes, type) >= 0)) {
1525 return confetti.msg.bot("" + type + " is not a valid map type. Use the maphelp command for more info.");
1526 }
1527 validator = mapDataValidators[type];
1528 if ((validator != null) && !validator(mapdata)) {
1529 return confetti.msg.bot("The validator for mapping type " + type + " didn't pass your map data. Use the maphelp command for more info.");
1530 }
1531 mdata = mapdata.join(':');
1532 if (maps[msg]) {
1533 oldmap = maps[msg];
1534 if (oldmap.type === type && oldmap.data === mdata) {
1535 return confetti.msg.bot("" + (confetti.cache.get('mapindicator')) + msg + " already maps to " + type + (mdata ? ' (' + mdata + ')' : '') + "!");
1536 }
1537 }
1538 maps[msg] = {
1539 msg: msg,
1540 type: type,
1541 data: mdata
1542 };
1543 confetti.cache.store('maps', maps).save();
1544 return confetti.msg.bot("" + (confetti.cache.get('mapindicator')) + (sys.htmlEscape(msg)) + " now maps to " + type + (mdata ? ' (' + sys.htmlEscape(mdata) + ')' : '') + "!");
1545 });
1546 confetti.command('unmap', {
1547 help: "Removes the mapping for the message [message].",
1548 args: ["message"]
1549 }, function(data) {
1550 var maps;
1551 maps = confetti.cache.get('maps');
1552 if (!maps.hasOwnProperty(data)) {
1553 return confetti.msg.bot("" + data + " isn't mapped to anything!");
1554 }
1555 delete maps[data];
1556 confetti.cache.store('maps', maps).save();
1557 return confetti.msg.bot("You removed " + (sys.htmlEscape(data)) + " from your message mappings!");
1558 });
1559 confetti.command('mapindicator', {
1560 help: "Changes your mapping indicator (to indicate usage of maps) to [symbol].",
1561 args: ["symbol"]
1562 }, function(data) {
1563 data = data.toLowerCase();
1564 if (data.length !== 1) {
1565 return confetti.msg.bot("Your mapping indicator has to be one character, nothing more, nothing less!");
1566 }
1567 if (data === '/' || data === '!') {
1568 return confetti.msg.bot("'!' and '/' are not allowed as command indicators because they are reserved for server scripts.");
1569 }
1570 if (confetti.cache.read('mapindicator') === data) {
1571 return confetti.msg.bot("Your mapping indicator is already " + (sys.htmlEscape(data)) + "!");
1572 }
1573 confetti.cache.store('mapindicator', data).save();
1574 return confetti.msg.bot("Your mapping indicator is now " + (sys.htmlEscape(data)) + "!");
1575 });
1576 confetti.command('togglemaps', "Toggles whether if message maps should be enabled.", function() {
1577 confetti.cache.store('mapsenabled', !confetti.cache.read('mapsenabled')).save();
1578 return confetti.msg.bot("Message mapping is now " + (confetti.cache.read('mapsenabled') ? 'enabled' : 'disabled') + ".");
1579 });
1580 confetti.initFields({
1581 maps: {},
1582 mapindicator: ':',
1583 mapsenabled: true
1584 });
1585 return confetti.hook('beforeSendMessage', function(message, chan, stop) {
1586 var mapmsg, mapparts, maps, params;
1587 if (confetti.cache.get('mapsenabled') === true && message[0] === confetti.cache.get('mapindicator')) {
1588 mapparts = message.substr(1).split(' ');
1589 mapmsg = mapparts[0];
1590 params = mapparts.slice(1);
1591 maps = confetti.cache.get('maps');
1592 if (maps.hasOwnProperty(mapmsg)) {
1593 executeMap(maps[mapmsg], params, chan);
1594 stop = true;
1595 }
1596 }
1597 return [message, chan, stop];
1598 });
1599})();
1600
1601(function() {
1602 confetti.command('eval', {
1603 help: "Evaluates a JavaScript Program.",
1604 args: ["code"]
1605 }, function(data, chan) {
1606 var ex, res;
1607 try {
1608 res = eval(data);
1609 return confetti.msg.bold("Eval returned", sys.htmlEscape(res), chan);
1610 } catch (_error) {
1611 ex = _error;
1612 confetti.msg.bold("Eval error", "" + ex + " on line " + ex.lineNumber, chan);
1613 if (ex.backtrace != null) {
1614 return confetti.msg.html(ex.backtrace.join('<br>'), chan);
1615 }
1616 }
1617 });
1618 confetti.command('evalp', 'eval');
1619 confetti.command('imp', {
1620 help: "Changes your name to [name]. If the name is deemed invalid, you will be kicked, so be careful!",
1621 args: ["name"]
1622 }, function(data) {
1623 if (!data) {
1624 return confetti.msg.bot("Specify a name!");
1625 } else if (data.length > 20) {
1626 return confetti.msg.bot("That name is too long or too short (max 20 characters)!");
1627 }
1628 Client.changeName(data);
1629 return confetti.msg.bot("You are now known as " + data + "!");
1630 });
1631 confetti.alias('changename', 'imp');
1632 confetti.command('flip', "Flips a coin in virtual life.", function() {
1633 return confetti.msg.bot("The coin landed " + (Math.random() > 0.5 ? 'heads' : 'tails') + "!");
1634 });
1635 confetti.alias('coin', 'flip');
1636 confetti.command('html', {
1637 help: "Displays some HTML [code] (for testing purposes).",
1638 args: ["code"]
1639 }, function(data, chan) {
1640 return confetti.msg.html(data, chan);
1641 });
1642 confetti.command('idle', "Toggles your idle status.", function() {
1643 var away;
1644 away = !Client.away();
1645 Client.goAway(away);
1646 return confetti.msg.bot("You are " + (away ? 'now idle' : 'no longer idle') + ".");
1647 });
1648 confetti.command('teambuilder', "Opens the teambuilder.", function() {
1649 return Client.openTeamBuilder();
1650 });
1651 confetti.alias('tb', 'teambuilder');
1652 confetti.command('findbattle', "Opens the find battle dialog.", function() {
1653 return Client.openBattleFinder();
1654 });
1655 confetti.alias('fb', 'findbattle');
1656 confetti.command('disconnect', "Disconnects you from the server and returns you to the server selection screen.", function() {
1657 return Client.done();
1658 });
1659 confetti.alias('dc', 'disconnect');
1660 confetti.command('chan', {
1661 help: "Joins, jumps to, or creates a channel.",
1662 args: ["name"]
1663 }, function(data) {
1664 var channelNames, cid, cname, exists, name;
1665 name = data;
1666 data = data.toLowerCase();
1667 channelNames = Client.channelNames();
1668 exists = false;
1669 for (cid in channelNames) {
1670 cname = channelNames[cid];
1671 if (cname.toLowerCase() === data) {
1672 name = cname;
1673 exists = true;
1674 break;
1675 }
1676 }
1677 if (exists) {
1678 cid = Client.channelId(name);
1679 if (Client.hasChannel(cid)) {
1680 return Client.activateChannel(name);
1681 } else {
1682 Client.join(name);
1683 return Client.activateChannel(name);
1684 }
1685 } else {
1686 Client.join(name);
1687 return sys.setTimer(function() {
1688 cid = Client.channelId(name);
1689 if (cid === 0) {
1690 return;
1691 }
1692 Client.activateChannel(name);
1693 return confetti.msg.bot("Channel " + name + " created.", cid);
1694 }, 500, false);
1695 }
1696 });
1697 confetti.alias('joinchan, channel, goto', 'chan');
1698 confetti.command('pm', {
1699 help: "Opens a PM session with [name].",
1700 args: ["name"]
1701 }, function(data) {
1702 var id;
1703 if (!data) {
1704 return confetti.msg.bot("Specify a name!");
1705 }
1706 id = Client.id(data);
1707 if (id === -1) {
1708 return confetti.msg.bot("" + (sys.htmlEscape(data)) + " is not online right now.");
1709 } else if (id === Client.ownId()) {
1710 return confetti.msg.bot("You can't PM yourself!");
1711 }
1712 return Client.startPM(id);
1713 });
1714 confetti.command('info', {
1715 help: "Shows some info (like id, color, auth level) for a given user. If you are a moderator, this will also open a control panel for the player and display additional information.",
1716 args: ["name"]
1717 }, function(data, chan) {
1718 var auth, bullet, color, hasAuth, id, name, showAvatar;
1719 id = Client.id(data);
1720 hasAuth = Client.ownAuth() >= 1;
1721 bullet = function(title, msg) {
1722 return confetti.msg.html("" + confetti.msg.bullet + " <b>" + title + "</b>: " + msg, chan);
1723 };
1724 showAvatar = function() {
1725 var avatar;
1726 if (id !== -1 && (Client.player != null)) {
1727 avatar = Client.player(id).avatar;
1728 return bullet("Avatar", "" + avatar + "<br>" + confetti.msg.indent + "<img src='trainer:" + avatar + "'>");
1729 }
1730 };
1731 if (hasAuth) {
1732 confetti.requestUserInfo(data, function(ui) {
1733 var FlagBanned, FlagMuted, FlagNonExistant, FlagOnline, FlagTempBanned, mode;
1734 FlagOnline = 1;
1735 FlagBanned = 2;
1736 FlagMuted = 4;
1737 FlagNonExistant = 8;
1738 FlagTempBanned = 16;
1739 if (ui.flags & FlagNonExistant) {
1740 return confetti.msg.bot("" + (sys.htmlEscape(data)) + " has not been on this server yet.", chan);
1741 }
1742 if (id === -1) {
1743 confetti.msg.html("<timestamp/><b>" + ui.name + "</b> (<b>" + (ui.flags & FlagOnline ? '<font color="green">Online</font>' : '<font color="red">Offline</font>') + "</b>)", chan);
1744 bullet("Auth", confetti.player.authToName(ui.auth) + (" (" + ui.auth + ")"));
1745 }
1746 bullet("IP", ui.ip);
1747 bullet("Last Online", ui.date.replace('T', ' at ') + " (GMT)");
1748 if (ui.os) {
1749 bullet("Operating System", ui.os);
1750 }
1751 mode = [];
1752 if (ui.flags & FlagBanned) {
1753 mode.push('Banned');
1754 }
1755 if (ui.flags & FlagMuted) {
1756 mode.push('Muted');
1757 }
1758 if (ui.flags & FlagTempBanned) {
1759 mode.push('Tempbanned');
1760 }
1761 if (mode.length) {
1762 confetti.msg.html("<timestamp/> <b>" + (mode.join('; ')) + "</b>");
1763 }
1764 return showAvatar();
1765 });
1766 Network.getBanList();
1767 Client.controlPanel(id);
1768 }
1769 if (id === -1) {
1770 if (!hasAuth) {
1771 confetti.msg.bot("" + (sys.htmlEscape(data)) + " is offline, I can't fetch any information about them.");
1772 }
1773 return;
1774 }
1775 name = confetti.player.fancyName(id);
1776 auth = Client.auth(id);
1777 color = Client.color(id);
1778 confetti.msg.html("<timestamp/>" + name + " " + (confetti.player.status(id)) + " <small>" + id + "</small>", chan);
1779 bullet("Auth", confetti.player.authToName(auth) + (" (" + auth + ")"));
1780 bullet("Color", "<b style='color:" + color + "'>" + color + "</b>");
1781 if (!hasAuth) {
1782 return showAvatar();
1783 }
1784 });
1785 confetti.alias('userinfo', 'info');
1786 confetti.alias('controlpanel', 'info');
1787 confetti.alias('cp', 'info');
1788 return confetti.command('myip', "Shows your IP address.", function() {
1789 return sys.webCall('http://bot.whatismyipaddress.com/', function(resp) {
1790 if (!resp) {
1791 return confetti.msg.bot("Couldn't obtain your IP address - check your internet connection.");
1792 }
1793 return confetti.msg.bot("Your IP address is <b>" + resp + "</b>.");
1794 });
1795 });
1796})();
1797
1798(function() {
1799 var newsurl;
1800 newsurl = 'https://ajax.googleapis.com/ajax/services/search/news?v=1.0&rsz=6&hl=';
1801 return confetti.command('news', ['news [language code?]:[topic?]', "Fetches the latest news, either the headlines or on a specific topic, from Google News, in an optional <a href='<a href='http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes#Partial_ISO_639_table'>[language]</a>.", 'send@news'], function(data, chan) {
1802 var lang, query, topic;
1803 data = data.split(':');
1804 lang = data[0].toLowerCase().trim();
1805 query = data.slice(1).join(':').trim();
1806 topic = '&topic=h';
1807 if (lang.length !== 2) {
1808 lang = 'en';
1809 }
1810 if (query) {
1811 topic = "&q=" + (encodeURIComponent(query.toLowerCase()));
1812 }
1813 return confetti.io.getRemoteJson("" + newsurl + (encodeURIComponent(lang)) + topic, ["A connection error occured while loading news.", chan], function(json) {
1814 var mess, res, stories, story, _i, _j, _len, _len1;
1815 stories = json.responseData.results;
1816 res = [];
1817 for (_i = 0, _len = stories.length; _i < _len; _i++) {
1818 story = stories[_i];
1819 res.push(("" + confetti.msg.bullet + " <b>") + story.titleNoFormatting.replace(/'/g, "'").replace(/`/g, "'").replace(/"/g, "\"") + ("</b><br>" + confetti.msg.indent + " → Read more: " + (sys.htmlEscape(story.unescapedUrl))));
1820 }
1821 if (res.length) {
1822 confetti.msg.bold("News " + (query ? 'on ' + query : 'Headlines'), '', chan);
1823 for (_j = 0, _len1 = res.length; _j < _len1; _j++) {
1824 mess = res[_j];
1825 confetti.msg.html(mess, chan);
1826 }
1827 }
1828 return null;
1829 });
1830 });
1831})();
1832
1833(function() {
1834 var findPlugin, getListing, getPluginFile, hasPlugin, pluginIndex, updatePlugins;
1835 pluginIndex = function(id, plugins) {
1836 var index, plugin, _i, _len;
1837 if (plugins == null) {
1838 plugins = confetti.cache.get('plugins');
1839 }
1840 id = id.toLowerCase();
1841 for (index = _i = 0, _len = plugins.length; _i < _len; index = ++_i) {
1842 plugin = plugins[index];
1843 if (plugin.id === id) {
1844 return index;
1845 }
1846 }
1847 return -1;
1848 };
1849 findPlugin = function(id, plugins) {
1850 var plugin, _i, _len;
1851 if (plugins == null) {
1852 plugins = confetti.cache.get('plugins');
1853 }
1854 id = id.toLowerCase();
1855 for (_i = 0, _len = plugins.length; _i < _len; _i++) {
1856 plugin = plugins[_i];
1857 if (plugin.id === id || plugin.name.toLowerCase() === id) {
1858 return plugin;
1859 }
1860 }
1861 return null;
1862 };
1863 hasPlugin = function(id, plugins) {
1864 return findPlugin(id, plugins) !== null;
1865 };
1866 getListing = function(chan, callback, verbose) {
1867 if (verbose == null) {
1868 verbose = true;
1869 }
1870 return confetti.io.getRemoteJson("" + confetti.pluginsUrl + "listing.json", [(verbose ? "An error occured whilst loading the plugin listing." : ""), chan], callback);
1871 };
1872 getPluginFile = function(pid, chan, callback, verbose) {
1873 if (verbose == null) {
1874 verbose = true;
1875 }
1876 return confetti.io.getRemoteFile("" + confetti.pluginsUrl + pid + "/" + pid + ".js", [(verbose ? "An error occured whilst loading the plugin source file of the plugin " + pid + "." : ""), chan], callback);
1877 };
1878 updatePlugins = function(verbose, chan) {
1879 if (verbose == null) {
1880 verbose = false;
1881 }
1882 return getListing(chan, function(json) {
1883 var done, plug, plugin, plugins, toUpdate, _i, _len;
1884 toUpdate = [];
1885 done = 0;
1886 plugins = confetti.cache.get('plugins');
1887 for (_i = 0, _len = plugins.length; _i < _len; _i++) {
1888 plugin = plugins[_i];
1889 plug = findPlugin(plugin.id, json);
1890 if (plug && plugin.version !== plug.version) {
1891 toUpdate.push([plugin, plug]);
1892 }
1893 }
1894 if (toUpdate.length) {
1895 return toUpdate.forEach(function(plugin) {
1896 var nplug, pid;
1897 nplug = plugin[1];
1898 pid = nplug.id;
1899 return getPluginFile(pid, chan, function(resp) {
1900 var p, pids, _j, _len1;
1901 confetti.io.writeLocal("plugin-" + pid + ".js", resp);
1902 plugins[pluginIndex(pid, plugins)] = nplug;
1903 done += 1;
1904 if (done === toUpdate.length) {
1905 pids = [];
1906 for (_j = 0, _len1 = toUpdate.length; _j < _len1; _j++) {
1907 p = toUpdate[_j];
1908 confetti.msg.bot("Plugin " + p[1].name + " updated to version " + p[1].version + "!", chan);
1909 pids.push(p[1].id);
1910 }
1911 confetti.cache.store('plugins', plugins).save();
1912 return confetti.initPlugins(pids);
1913 }
1914 }, verbose);
1915 });
1916 } else if (verbose) {
1917 return confetti.msg.bot("All plugins up to date.", chan);
1918 }
1919 }, verbose);
1920 };
1921 confetti.updatePlugins = updatePlugins;
1922 confetti._pluginAPI = {
1923 pluginIndex: pluginIndex,
1924 findPlugin: findPlugin,
1925 hasPlugin: hasPlugin,
1926 getListing: getListing,
1927 getPluginFile: getPluginFile,
1928 updatePlugins: updatePlugins
1929 };
1930 confetti.command('plugins', "Displays a list of enabled and available plugins.", function(_, chan) {
1931 var html, plugin, plugins, _i, _len;
1932 plugins = confetti.cache.get('plugins');
1933 if (plugins.length > 0) {
1934 confetti.msg.bold("Loaded Plugins <small>[" + plugins.length + "]</small>", '', chan);
1935 html = "";
1936 for (_i = 0, _len = plugins.length; _i < _len; _i++) {
1937 plugin = plugins[_i];
1938 html += "" + confetti.msg.bullet + " <b>" + plugin.name + "</b> (" + plugin.id + ") v" + plugin.version + " <small>[<a href='po:send/-removeplugin " + plugin.id + "' style='text-decoration:none;color:black'>remove</a>]</small><br>";
1939 }
1940 confetti.msg.html(html, chan);
1941 }
1942 return getListing(chan, function(json) {
1943 var addremove, len, pid, _j, _len1;
1944 len = json.length;
1945 if (!len) {
1946 return confetti.msg.bot("No plugins are available.", chan);
1947 }
1948 confetti.msg.bold("Available Plugins <small>[" + len + "]</small>", '', chan);
1949 html = "";
1950 for (_j = 0, _len1 = json.length; _j < _len1; _j++) {
1951 plugin = json[_j];
1952 addremove = "";
1953 pid = plugin.id;
1954 if (!hasPlugin(pid, plugins)) {
1955 addremove = "<small>[<a href='po:send/-addplugin " + pid + "' style='text-decoration:none;color:black'>add</a>]</small>";
1956 } else {
1957 addremove = "<small>[<a href='po:send/-removeplugin " + pid + "' style='text-decoration:none;color:black'>remove</a>]</small>";
1958 }
1959 html += "" + confetti.msg.bullet + " <b>" + plugin.name + "</b> (" + pid + ") v" + plugin.version + " " + addremove + "<br>";
1960 }
1961 return confetti.msg.html(html, chan);
1962 });
1963 });
1964 confetti.command('addplugin', {
1965 help: "Adds a plugin. The plugin's ID must be used (inside brackets).",
1966 args: ["id"]
1967 }, function(data, chan) {
1968 var name, plugins;
1969 plugins = confetti.cache.get('plugins');
1970 name = data;
1971 data = data.toLowerCase();
1972 if (!name) {
1973 return confetti.msg.bot("Specify a plugin!");
1974 } else if (hasPlugin(data, plugins)) {
1975 return confetti.msg.bot("" + name + " is already enabled as a plugin!");
1976 }
1977 return getListing(chan, function(json) {
1978 var pid, plugin;
1979 if (json.length === 0) {
1980 return confetti.msg.bot("No plugins are available.", chan);
1981 }
1982 plugin = findPlugin(data, json);
1983 if (plugin === null) {
1984 return confetti.msg.bot("That plugin is not available! Use the 'plugins' command to see a list of available plugins.", chan);
1985 }
1986 pid = plugin.id;
1987 return getPluginFile(pid, chan, function(file) {
1988 confetti.io.writeLocal("plugin-" + pid + ".js", file);
1989 plugins.push(plugin);
1990 confetti.cache.store('plugins', plugins).save();
1991 confetti.initPlugins(pid);
1992 return confetti.msg.bot("Plugin <b>" + plugin.name + "</b> added!", chan);
1993 });
1994 });
1995 });
1996 confetti.command('removeplugin', {
1997 help: "Removes a plugin. The plugin's ID must be used (inside brackets).",
1998 args: ["plugin"]
1999 }, function(data) {
2000 var name, plugin, plugins;
2001 name = data;
2002 data = data.toLowerCase();
2003 plugins = confetti.cache.get('plugins');
2004 plugin = findPlugin(data, plugins);
2005 if (plugin === null) {
2006 return confetti.msg.bot("" + name + " isn't an enabled plugin! Try to use its plugin id (in the plugins list, this is the name in brackets).");
2007 }
2008 plugins.splice(plugins.indexOf(plugin), 1);
2009 confetti.cache.store('plugins', plugins).save();
2010 confetti.io.deleteLocal("plugin-" + plugin.id + ".js");
2011 confetti.io.reloadScript();
2012 return confetti.msg.bot("Plugin <b>" + plugin.name + "</b> removed.");
2013 });
2014 return confetti.command('updateplugins', "Updates your plugins to their latest versions.", function(_, chan) {
2015 if (sys.isSafeScripts()) {
2016 return confetti.msg.bot("Please disable Safe Scripts before using this command.");
2017 }
2018 return updatePlugins(true, chan);
2019 });
2020})();
2021
2022(function() {
2023 var attemptToReconnect, attempts, autoReconnectTimer, failed, forceIgnore;
2024 autoReconnectTimer = -1;
2025 attempts = 0;
2026 forceIgnore = false;
2027 failed = false;
2028 attemptToReconnect = function() {
2029 if (attempts >= 3) {
2030 return false;
2031 }
2032 attempts += 1;
2033 return Client.reconnect();
2034 };
2035 Network.playerLogin.connect(function() {
2036 if (autoReconnectTimer !== -1) {
2037 confetti.msg.notification("Reconnected to server!");
2038 sys.unsetTimer(autoReconnectTimer);
2039 autoReconnectTimer = -1;
2040 attempts = 0;
2041 return failed = false;
2042 }
2043 });
2044 Network.disconnected.connect(function() {
2045 if (confetti.cache.get('autoreconnect') === true && autoReconnectTimer === -1 && !forceIgnore && !failed) {
2046 confetti.msg.bot("Attempting to reconnect...");
2047 confetti.msg.notification("Disconnection detected, attempting to reconnect.");
2048 autoReconnectTimer = sys.setTimer(function() {
2049 if (attemptToReconnect() === false) {
2050 confetti.msg.bot("Three attempts at reconnecting have failed, stopping.");
2051 confetti.msg.notification("Failed to reconnect.");
2052 sys.unsetTimer(autoReconnectTimer);
2053 autoReconnectTimer = -1;
2054 return failed = true;
2055 }
2056 }, 5000, true);
2057 }
2058 return forceIgnore = false;
2059 });
2060 confetti.command('reconnect', "Forces a reconnect to the server.", function() {
2061 confetti.msg.bot("Reconnecting to the server...");
2062 attempts = 0;
2063 forceIgnore = true;
2064 failed = false;
2065 return Client.reconnect();
2066 });
2067 confetti.command('autoreconnect', "Toggles whether if you should automatically reconnect to the server when detected you've disconnected.", function() {
2068 confetti.cache.store('autoreconnect', !confetti.cache.read('autoreconnect')).save();
2069 return confetti.msg.bot("Auto reconnect is now " + (confetti.cache.read('autoreconnect') ? 'on' : 'off') + ".");
2070 });
2071 return confetti.initFields({
2072 autoreconnect: true
2073 });
2074})();
2075
2076(function() {
2077 var autoUpdate, changelog, differentVersion, updateScript, versionFormat;
2078 changelog = {
2079 '2.0.0': 'Initial version of Confetti. Features encool, player blocking, friends, alias tracking, auto reconnect, plugins, and more.',
2080 '2.0.1': 'Improved news.',
2081 '2.0.2': 'Various usability improvements.',
2082 '2.0.3': 'Pokedex plugin, automatic updating.',
2083 '2.0.4': 'AoC Taunts plugin.',
2084 '2.0.5': 'Bug fixes for tracking and reconnect.',
2085 '2.0.6': 'More reconnect fixes, news and define improvements, removed dictionary.',
2086 '2.0.7': 'Emoji plugin.',
2087 '2.0.8': 'Plugin auto-updating and versions.',
2088 '2.0.9': 'Changelog, usability improvements, fullwidth encool, updated script urls.',
2089 '2.0.10': 'Pokémon Usage Statistics plugin, auth symbols, flashwords.',
2090 '2.1.0': 'Reworked command lists, pm utility command.',
2091 '2.1.1': 'Commands split into several new command lists, nato encool mode, idle utility command.',
2092 '2.1.2': 'Many important bug fixes, ignorepms, teambuilder & findbattle utility commands, improved info command.',
2093 '2.1.3': 'Message mapping, disconnect utility command, minor fix for info command.',
2094 '2.1.4': 'Parameter maps, improved maphelp, minor fixes, Ye Olde & Deladder plugins.'
2095 };
2096 autoUpdate = function() {
2097 var now;
2098 if (confetti.cache.get('autoupdate') === false) {
2099 return;
2100 }
2101 if (sys.isSafeScripts()) {
2102 return;
2103 }
2104 now = sys.time();
2105 if ((confetti.cache.get('lastupdatetime') + (6 * 60 * 60)) > now) {
2106 return;
2107 }
2108 confetti.cache.store('lastupdatetime', now).save();
2109 confetti.updatePlugins();
2110 return confetti.io.getRemoteJson("" + confetti.scriptUrl + "script/version.json", "", function(json) {
2111 if (differentVersion(confetti.version, json)) {
2112 return updateScript();
2113 }
2114 });
2115 };
2116 versionFormat = function(version) {
2117 return version.release + '.' + version.major + '.' + version.minor;
2118 };
2119 differentVersion = function(ov, nv) {
2120 return versionFormat(ov) !== versionFormat(nv);
2121 };
2122 updateScript = function() {
2123 return confetti.io.getRemoteFile("" + confetti.scriptUrl + "scripts.js", ["Couldn't load script, check your internet connection"], function(file) {
2124 confetti.io.write(sys.scriptsFolder + 'scripts.js', file);
2125 confetti.io.reloadScript(true);
2126 return confetti.msg.bot("Script updated!");
2127 });
2128 };
2129 sys.setTimer(autoUpdate, 15 * 1000, false);
2130 sys.setTimer(autoUpdate, 10 * 60 * 1000, true);
2131 confetti.changelog = changelog;
2132 confetti.autoUpdate = autoUpdate;
2133 confetti.updateScript = updateScript;
2134 confetti.command('updatescript', "Updates the script to the latest available version.", function() {
2135 if (sys.isSafeScripts()) {
2136 return confetti.msg.bot("Please disable Safe Scripts before using this command.");
2137 }
2138 confetti.msg.bot("Updating script...");
2139 return updateScript();
2140 });
2141 confetti.alias('updatescripts', 'updatescript');
2142 confetti.command('autoupdate', "Toggles whether if the script should automatically look for updates (every 6 hours).", function() {
2143 confetti.cache.store('autoupdate', !confetti.cache.read('autoupdate')).save();
2144 return confetti.msg.bot("Automatic updates are now " + (confetti.cache.read('autoupdate') ? 'enabled' : 'disabled') + ".");
2145 });
2146 confetti.command('version', "Shows the script's version.", function() {
2147 var vers;
2148 vers = versionFormat(confetti.version);
2149 confetti.msg.bot("Your copy of Confetti is currently on version " + vers + ".");
2150 if (changelog[vers]) {
2151 return confetti.msg.bot("What's new: " + changelog[vers]);
2152 }
2153 });
2154 confetti.command('changelog', "Shows a changelog containing the major changes in each version.", function() {
2155 var msg, ver, _results;
2156 _results = [];
2157 for (ver in changelog) {
2158 msg = changelog[ver];
2159 _results.push(confetti.msg.bot("" + ver + ": " + msg));
2160 }
2161 return _results;
2162 });
2163 return confetti.initFields({
2164 autoupdate: true,
2165 lastupdatetime: sys.time()
2166 });
2167})();
2168
2169(function() {
2170 confetti.command('notifications', "Toggles whether if notifications should be shown (tray messages).", function() {
2171 confetti.cache.store('notifications', !confetti.cache.read('notifications')).save();
2172 return confetti.msg.bot("Notifications are now " + (confetti.cache.read('notifications') ? 'on' : 'off') + ".");
2173 });
2174 confetti.command('ignorepms', "Toggles whether if PMs should be ignored. This feature is separate from the client's built-in (this one actually works). You can still send PMs, but no one will be able to send them to you and you won't receive notification of it (so be careful to leave this on).", function() {
2175 confetti.cache.store('ignorepms', !confetti.cache.read('ignorepms')).save();
2176 return confetti.msg.bot("PMs are now " + (confetti.cache.read('ignorepms') ? 'being ignored' : 'enabled') + ".");
2177 });
2178 confetti.command('botname', {
2179 help: "Changes the bot's name to [name].",
2180 args: ["name"]
2181 }, function(data) {
2182 if (data.length > 25) {
2183 return confetti.msg.bot("Uhh, that's too long, I think!");
2184 }
2185 if (confetti.cache.read('botname') === data) {
2186 return confetti.msg.bot("I'm already " + (sys.htmlEscape(data)) + "!");
2187 }
2188 confetti.cache.store('botname', data).save();
2189 return confetti.msg.bot("I'm now called " + (sys.htmlEscape(data)) + "!");
2190 });
2191 confetti.command('botcolor', {
2192 help: "Changes the bot's color to [color].",
2193 args: ["color"]
2194 }, function(data) {
2195 data = data.toLowerCase();
2196 if (!sys.validColor(data)) {
2197 return confetti.msg.bot("That doesn't look like a valid color to me!");
2198 }
2199 if (confetti.cache.read('botcolor') === data) {
2200 return confetti.msg.bot("My color is already " + data + "!");
2201 }
2202 confetti.cache.store('botcolor', data).save();
2203 return confetti.msg.bot("My color is now " + data + "!");
2204 });
2205 confetti.command('commandindicator', {
2206 help: "Changes your command indicator (to indicate usage of commands) to [symbol]. <b>-</b> will remain usable, in case you ever forget.",
2207 args: ["symbol"]
2208 }, function(data) {
2209 data = data.toLowerCase();
2210 if (data.length !== 1) {
2211 return confetti.msg.bot("Your command indicator has to be one character, nothing more, nothing less!");
2212 }
2213 if (data === '/' || data === '!') {
2214 return confetti.msg.bot("'!' and '/' are not allowed as command indicators because they are reserved for server scripts.");
2215 }
2216 if (confetti.cache.read('commandindicator') === data) {
2217 return confetti.msg.bot("Your command indicator is already " + (sys.htmlEscape(data)) + "!");
2218 }
2219 confetti.cache.store('commandindicator', data).save();
2220 return confetti.msg.bot("Your command indicator is now " + (sys.htmlEscape(data)) + "!");
2221 });
2222 return confetti.command('defaults', "Sets all settings back to their defaults. There may be some plugins which do not support this action, in which case they might break.", function(data) {
2223 if (data.toLowerCase() !== 'sure') {
2224 return confetti.msg.bot("<a href='po:send/-defaults sure' style='text-decoration: none; color: black;'>Are you sure that you want to reset your settings? There is no going back. Click this message to confirm (or type <small>" + (confetti.cache.get('commandindicator')) + "defaults sure</small>).</a>");
2225 }
2226 confetti.cache.wipe();
2227 confetti.initCache();
2228 confetti.io.reloadScript();
2229 return confetti.msg.bot("Your settings have been reset to their defaults!");
2230 });
2231})();
2232
2233(function() {
2234 confetti.command('tracked', "Displays a list of tracked players.", function(_, chan) {
2235 var alt, alts, html, name, names, numTracked, tracked, _i, _len;
2236 tracked = confetti.cache.get('tracked');
2237 numTracked = Object.keys(tracked).length;
2238 if (numTracked === 0) {
2239 return confetti.msg.bot("There is no one on your tracking list.");
2240 }
2241 confetti.msg.bold("Tracked players <small>[" + numTracked + "]</small>", '', chan);
2242 html = "";
2243 names = {};
2244 for (alt in tracked) {
2245 name = tracked[alt];
2246 if (names[name] == null) {
2247 names[name] = [];
2248 }
2249 names[name].push(alt);
2250 }
2251 for (name in names) {
2252 alts = names[name];
2253 html += "" + confetti.msg.bullet + " " + (confetti.player.fancyName(name, null, false)) + " " + (confetti.player.status(name, false)) + " as <small>[" + alts.length + "]</small><br>";
2254 alts = confetti.util.sortOnlineOffline(alts);
2255 for (_i = 0, _len = alts.length; _i < _len; _i++) {
2256 alt = alts[_i];
2257 html += " " + confetti.msg.bullet + " " + (confetti.player.fancyName(alt, null, false)) + " " + (confetti.player.status(alt, false)) + "<br>";
2258 }
2259 }
2260 return confetti.msg.html(html, chan);
2261 });
2262 confetti.alias('tracking, trackinglist', 'tracked');
2263 confetti.command('track', {
2264 help: "Adds [alias] as an alias of [name] to your tracking list.",
2265 args: ["alias", "name"]
2266 }, function(data) {
2267 var alt, altName, name, parts, tracked;
2268 parts = data.split(':');
2269 if (parts[1] == null) {
2270 parts[1] = '';
2271 }
2272 alt = parts[0], name = parts[1];
2273 alt = alt.toLowerCase().trim();
2274 name = name.trim();
2275 altName = confetti.player.name(alt, false);
2276 tracked = confetti.cache.get('tracked');
2277 if (!alt && !name) {
2278 return confetti.msg.bot("Specify both the alt and the name!");
2279 }
2280 if (tracked.hasOwnProperty(alt)) {
2281 return confetti.msg.bot("" + altName + " is already on your tracking list!");
2282 }
2283 tracked[alt] = name;
2284 confetti.cache.store('tracked', tracked).save();
2285 return confetti.msg.bot("" + altName + " is now on your tracking list as an alt of " + (confetti.player.name(name, false)) + "!");
2286 });
2287 confetti.command('untrack', {
2288 help: "Removes [alias] from your tracking list.",
2289 args: ["alias"]
2290 }, function(data) {
2291 var name, tracked;
2292 data = data.toLowerCase();
2293 name = confetti.player.name(data, false);
2294 tracked = confetti.cache.get('tracked');
2295 if (!tracked.hasOwnProperty(data)) {
2296 return confetti.msg.bot("" + name + " isn't on your tracking list!");
2297 }
2298 delete tracked[data];
2299 confetti.cache.store('tracked', tracked).save();
2300 return confetti.msg.bot("You removed " + name + " from your tracking list!");
2301 });
2302 confetti.command('trackingresolve', "Toggles whether if tracked names should resolve to their real name (in lists &c.). Does not affect chat name resolution.", function() {
2303 confetti.cache.store('trackingresolve', !confetti.cache.read('trackingresolve')).save();
2304 return confetti.msg.bot("Tracking name resolve is now " + (confetti.cache.read('trackingresolve') ? 'on' : 'off') + ".");
2305 });
2306 return confetti.hook('manipulateChanPlayerMessage', function(from, fromId, message, playerMessage, _arg, chan, html, dirty) {
2307 var auth, authSymbol, color, ownId, tracked, trackedName;
2308 color = _arg[0], auth = _arg[1], authSymbol = _arg[2];
2309 tracked = confetti.cache.get('tracked');
2310 trackedName = from.toLowerCase();
2311 ownId = Client.ownId();
2312 if (fromId !== ownId && tracked.hasOwnProperty(trackedName)) {
2313 from = "<span title='" + (confetti.util.stripquotes(from)) + "'>" + tracked[trackedName] + "</span>";
2314 dirty = true;
2315 }
2316 return [from, fromId, message, playerMessage, [color, auth, authSymbol], chan, html, dirty];
2317 });
2318})();
2319
2320(function() {
2321 var clearDuplicateCommas;
2322 clearDuplicateCommas = /,,/g;
2323 confetti.command('translate', ['translate [message]:[to language code]-[from language code]', "Translates a message from a language to another one. [from language code] is optional and might even be ignored, it's purely a hint (note the dash). Language codes are two letters, for example <b>en</b> (English), <b>es</b> (Spanish), <b>de</b> (German). A full list is available <a href='http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes#Partial_ISO_639_table'>here</a> (ISO 639-1 language codes).", 'setmsg@translate message:to-from'], function(data, chan) {
2324 var from, languageParts, message, parts, to, url;
2325 parts = data.split(':');
2326 message = parts[0];
2327 languageParts = (parts[1] || '').split('-');
2328 to = languageParts[0];
2329 from = languageParts[1] || '';
2330 if (!(message && to)) {
2331 return confetti.msg.bot("You have to specify a message and a language to translate to (message:es, for example).");
2332 }
2333 url = "http://translate.google.com/translate_a/t?client=t&text=" + (encodeURIComponent(message)) + "&hl=en&ie=UTF-8&oe=UTF-8&multires=1&otf=1&pc=1&trs=1&ssel=3&tsel=6&sc=1&tl=" + (encodeURIComponent(to));
2334 if (from) {
2335 url += "&sl=" + (encodeURIComponent(from));
2336 }
2337 return sys.webCall(url, function(response) {
2338 var ex, json;
2339 response = response.replace(clearDuplicateCommas, ',').replace(clearDuplicateCommas, ',');
2340 try {
2341 json = JSON.parse(response);
2342 } catch (_error) {
2343 ex = _error;
2344 return confetti.msg.bot("Failed to translate your message -- check your internet connection", chan);
2345 }
2346 return confetti.msg.bot("'" + (sys.htmlEscape(message)) + "' is '" + (sys.htmlEscape(json[0][0][0])) + "' in '" + (to.toUpperCase()) + "'.", chan);
2347 });
2348 });
2349 return confetti.alias('trans, tr', 'translate');
2350})();
2351
2352if (confetti.initialized && !confetti.silentReload) {
2353 print("Script Check: OK");
2354 if ((typeof script !== "undefined" && script !== null ? script.clientStartUp : void 0) != null) {
2355 script.clientStartUp();
2356 }
2357}
2358
2359if (!(confetti.initialized && (typeof confettiScript !== "undefined" && confettiScript !== null))) {
2360 sys.setTimer(function() {
2361 var chans, id, player, players;
2362 if (confetti.initialized) {
2363 return;
2364 }
2365 chans = confetti.channel.channelIds();
2366 players = ((function() {
2367 var _i, _len, _results;
2368 _results = [];
2369 for (_i = 0, _len = chans.length; _i < _len; _i++) {
2370 id = chans[_i];
2371 _results.push(confetti.channel.players(id).join(','));
2372 }
2373 return _results;
2374 })()).join(',').split(',');
2375 for (player in players) {
2376 if (!(player && confetti.players.hasOwnProperty(player))) {
2377 confetti.players[player] = confetti.player.create(player);
2378 }
2379 }
2380 return script.clientStartUp();
2381 }, 1, false);
2382}
2383
2384confetti.silentReload = false;
2385
2386confettiScript = {
2387 clientStartUp: function() {
2388 if (confetti.cache.initialized === false) {
2389 confetti.initCache();
2390 }
2391 confetti.initPlugins();
2392 if (!confetti.initialized) {
2393 if ((confetti.cache.get('lastuse') + (5 * 24 * 60 * 60)) < sys.time()) {
2394 confetti.msg.bot("Type <a href='po:send/-commands' style='text-decoration:none;color:green'><b>" + (confetti.cache.get('commandindicator')) + "commands</b></a> for a list of client commands.", -1);
2395 }
2396 confetti.cache.store('lastuse', sys.time()).save();
2397 if (confetti.cache.get('ignorepms') === true) {
2398 confetti.msg.bot("<b style='color:red'>PMs are currently being ignored. You can re-enable them with <a href='po:send/-ignorepms' style='text-decoration:none;color:green'><b>" + (confetti.cache.get('commandindicator')) + "ignorepms</b></a> (toggle command).", -1);
2399 }
2400 }
2401 if (sys.isSafeScripts()) {
2402 confetti.msg.bot("<b style='color:red'>Safe Scripts is enabled</b>. This will disable persistent data storage (your settings won't be saved) and limit other features.", -1);
2403 confetti.msg.bot("Disable it by unticking the \"<b>Safe Scripts</b>\" box in the <i>Script Window</i> [<i>Plugins->Script Window</i>] and clicking <b>Ok</b>.", -1);
2404 confetti.msg.bot("Afterwards, re-login to see the effects.", -1);
2405 }
2406 return confetti.initialized = true;
2407 },
2408 onPlayerReceived: function(id) {
2409 confetti.players[id] = confetti.player.create(id);
2410 return confetti.callHooks('onPlayerReceived', id);
2411 },
2412 onPlayerRemoved: function(id) {
2413 confetti.callHooks('onPlayerRemoved', id);
2414 return delete confetti.players[id];
2415 },
2416 beforePMSent: function(tar, message) {
2417 var dirty, _ref;
2418 dirty = false;
2419 _ref = confetti.callHooks('manipulateOwnPM', tar, message, dirty), tar = _ref[0], message = _ref[1], dirty = _ref[2];
2420 if (dirty) {
2421 sys.stopEvent();
2422 return Network.sendPM(tar, message);
2423 }
2424 },
2425 beforePMReceived: function(src, message) {
2426 if (confetti.cache.get('ignorepms') === true) {
2427 return sys.stopEvent();
2428 }
2429 },
2430 afterPMReceived: function(src, message) {
2431 return confetti.callHooks('pmReceived', src, message);
2432 },
2433 beforeSendMessage: function(message, chan) {
2434 var dirty, stop, _ref, _ref1;
2435 stop = false;
2436 _ref = confetti.callHooks('beforeSendMessage', message, chan, stop), message = _ref[0], chan = _ref[1], stop = _ref[2];
2437 if (stop) {
2438 sys.stopEvent();
2439 return;
2440 }
2441 if (confetti.isCommand(message)) {
2442 sys.stopEvent();
2443 confetti.runCommand(message, chan);
2444 return;
2445 }
2446 dirty = false;
2447 _ref1 = confetti.callHooks('manipulateOwnMessage', message, chan, dirty), message = _ref1[0], chan = _ref1[1], dirty = _ref1[2];
2448 if (dirty) {
2449 sys.stopEvent();
2450 return Network.sendChanMessage(chan, message);
2451 }
2452 },
2453 beforeChannelMessage: function(message, chan, html) {
2454 var auth, authSymbol, channel, color, dirty, finishedMessage, flashes, from, fromId, fromSrc, id, line, name, originalMessage, ownId, ownName, playerMessage, willFlash, _ref, _ref1, _ref2, _ref3;
2455 if (confetti.ignoreNextChanMessage) {
2456 confetti.ignoreNextChanMessage = false;
2457 return;
2458 }
2459 ownId = Client.ownId();
2460 if (ownId === -1) {
2461 return;
2462 }
2463 originalMessage = message;
2464 if (html) {
2465 message = confetti.util.stripHtml(message).trim();
2466 }
2467 from = fromSrc = message.substring(0, message.indexOf(":")).trim();
2468 fromId = Client.id(from);
2469 if (html && ((_ref = from.charAt(0)) === '~' || _ref === '+')) {
2470 from = from.substr(1).trim();
2471 fromId = Client.id(from);
2472 } else if (html && message.substr(0, 3).trim() === '***') {
2473 line = message.substr(3).trim();
2474 for (id in confetti.players) {
2475 name = Client.name(id);
2476 if (line.substring(0, name.length) === name) {
2477 from = name;
2478 fromId = id;
2479 break;
2480 }
2481 }
2482 }
2483 playerMessage = originalMessage.substring(originalMessage.indexOf(":") + 1).trim();
2484 if (html) {
2485 playerMessage = playerMessage.replace('</b>', '').replace('</i>', '').replace('</font>', '');
2486 }
2487 if (fromId === -1) {
2488 dirty = false;
2489 _ref1 = confetti.callHooks('manipulateChanBotMessage', fromSrc, message, playerMessage, chan, html, dirty), fromSrc = _ref1[0], message = _ref1[1], playerMessage = _ref1[2], chan = _ref1[3], html = _ref1[4], dirty = _ref1[5];
2490 if (dirty) {
2491 if (message) {
2492 Client.printChannelMessage(message, chan, html);
2493 }
2494 sys.stopEvent();
2495 }
2496 return;
2497 } else if (ownId !== fromId) {
2498 if (Client.isIgnored(fromId)) {
2499 sys.stopEvent();
2500 return;
2501 }
2502 }
2503 channel = Client.channel(chan);
2504 ownName = Client.ownName();
2505 willFlash = confetti.util.willFlash(playerMessage, ownName);
2506 flashes = confetti.cache.get('flashes') === true;
2507 dirty = !flashes && willFlash;
2508 color = Client.color(fromId);
2509 auth = Client.auth(fromId);
2510 authSymbol = [];
2511 if (auth > 4) {
2512 auth = 4;
2513 }
2514 if (!html) {
2515 playerMessage = sys.htmlEscape(playerMessage);
2516 playerMessage = Client.channel(chan).addChannelLinks(playerMessage);
2517 }
2518 _ref2 = confetti.callHooks('manipulateChanPlayerMessage', from, fromId, message, playerMessage, [color, auth, authSymbol], chan, html, dirty), from = _ref2[0], fromId = _ref2[1], message = _ref2[2], playerMessage = _ref2[3], (_ref3 = _ref2[4], color = _ref3[0], auth = _ref3[1], authSymbol = _ref3[2]), chan = _ref2[5], html = _ref2[6], dirty = _ref2[7];
2519 if (dirty) {
2520 if (authSymbol.length !== 2) {
2521 if ((4 > auth && auth > 0)) {
2522 authSymbol = ['+<i>', '</i>'];
2523 } else {
2524 authSymbol = ['', ''];
2525 }
2526 }
2527 if (flashes) {
2528 playerMessage = confetti.util.addNameHighlights(playerMessage, ownName);
2529 }
2530 finishedMessage = "<font color='" + color + "'><timestamp/>" + authSymbol[0] + "<b>" + from + ":</b>" + authSymbol[1] + "</font> " + playerMessage;
2531 sys.stopEvent();
2532 confetti.ignoreNextChanMessage = true;
2533 Client.printChannelMessage(finishedMessage, chan, true);
2534 if (flashes && playerMessage.indexOf('<ping/>') !== -1) {
2535 return confetti.msg.notification(confetti.util.stripHtml("" + from + ": " + playerMessage), "Ping in #" + (Client.channelName(chan)), false);
2536 }
2537 }
2538 }
2539};