// Generated by CoffeeScript 1.6.2 (function() {   var Command, RoomHelper, User, addCommand, afkCheck, afksCommand, allAfksCommand, announceCurate, antispam, apiHooks, avgVoteRatioCommand, chatCommandDispatcher, chatUniversals, cmds, data, dieCommand, disconnectLookupCommand, fans, handleNewSong, handleUserJoin, handleUserLeave, handleVote, hook, initEnvironment, initHooks, initialize, lockCommand, lockskipCommand, msToStr, newSongsCommand, newsCommand, populateUserData, promoCommand, pupOnline, reloadCommand, removeCommand, roomHelpCommand, rulesCommand, settings, skipCommand, staffCommand, statusCommand, themeCommand, undoHooks, unhook, unlockCommand, updateVotes, versionCommand, voteRatioCommand, _ref, _ref1, _ref10, _ref11, _ref12, _ref13, _ref14, _ref15, _ref16, _ref17, _ref18, _ref19, _ref2, _ref20, _ref21, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8, _ref9,     __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },     __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; },     __hasProp = {}.hasOwnProperty,     __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };    settings = (function() {     function settings() {       this.implode = __bind(this.implode, this);       this.intervalMessages = __bind(this.intervalMessages, this);       this.startAfkInterval = __bind(this.startAfkInterval, this);       this.setInternalWaitlist = __bind(this.setInternalWaitlist, this);       this.userJoin = __bind(this.userJoin, this);       this.getRoomUrlPath = __bind(this.getRoomUrlPath, this);       this.startup = __bind(this.startup, this);     }      settings.prototype.currentsong = {};      settings.prototype.users = {};      settings.prototype.djs = [];      settings.prototype.mods = [];      settings.prototype.host = [];      settings.prototype.hasWarned = false;      settings.prototype.currentwoots = 0;      settings.prototype.currentmehs = 0;      settings.prototype.currentcurates = 0;      settings.prototype.roomUrlPath = null;      settings.prototype.internalWaitlist = [];      settings.prototype.userDisconnectLog = [];      settings.prototype.voteLog = {};      settings.prototype.seshOn = false;      settings.prototype.forceSkip = false;      settings.prototype.seshMembers = [];      settings.prototype.launchTime = null;      settings.prototype.totalVotingData = {       woots: 0,       mehs: 0,       curates: 0     };      settings.prototype.pupScriptUrl = 'https://dl.dropbox.com/u/21023321/TastycatBot.js';      settings.prototype.afkTime = 60 * 60 * 1000;      settings.prototype.songIntervalMessages = [       {         interval: 7,         offset: 0,         msg: "All praise our lord and savior @Raptor Jeebus"       }, {         interval: 5,         offset: 0,         msg: "Stay active in chat while in line. We remove AFK DJ's at the booth!"       }     ];      settings.prototype.songCount = 0;      settings.prototype.startup = function() {       this.launchTime = new Date();       return this.roomUrlPath = this.getRoomUrlPath();     };      settings.prototype.getRoomUrlPath = function() {       return window.location.pathname.replace(/\//g, '');     };      settings.prototype.newSong = function() {       this.totalVotingData.woots += this.currentwoots;       this.totalVotingData.mehs += this.currentmehs;       this.totalVotingData.curates += this.currentcurates;       this.setInternalWaitlist();       this.currentsong = API.getMedia();       if (this.currentsong !== null) {         return this.currentsong;       } else {         return false;       }     };      settings.prototype.userJoin = function(u) {       var userIds, _ref;        userIds = Object.keys(this.users);       if (_ref = u.id, __indexOf.call(userIds, _ref) >= 0) {         return this.users[u.id].inRoom(true);       } else {         this.users[u.id] = new User(u);         return this.voteLog[u.id] = {};       }     };      settings.prototype.setInternalWaitlist = function() {       var boothWaitlist, fullWaitList, lineWaitList;        boothWaitlist = API.getDJs().slice(1);       lineWaitList = API.getWaitList();       fullWaitList = boothWaitlist.concat(lineWaitList);       return this.internalWaitlist = fullWaitList;     };      settings.prototype.activity = function(obj) {       if (obj.type === 'message') {         return this.users[obj.fromID].updateActivity();       }     };      settings.prototype.startAfkInterval = function() {       return this.afkInterval = setInterval(afkCheck, 2000);     };      settings.prototype.intervalMessages = function() {       var msg, _i, _len, _ref, _results;        this.songCount++;       _ref = this.songIntervalMessages;       _results = [];       for (_i = 0, _len = _ref.length; _i < _len; _i++) {         msg = _ref[_i];         if (((this.songCount + msg['offset']) % msg['interval']) === 0) {           _results.push(API.sendChat(msg['msg']));         } else {           _results.push(void 0);         }       }       return _results;     };      settings.prototype.implode = function() {       var item, val;        for (item in this) {         val = this[item];         if (typeof this[item] === 'object') {           delete this[item];         }       }       return clearInterval(this.afkInterval);     };      settings.prototype.lockBooth = function(callback) {       if (callback == null) {         callback = null;       }       return $.ajax({         url: "http://plug.dj/_/gateway/room.update_options",         type: 'POST',         data: JSON.stringify({           service: "room.update_options",           body: [             this.roomUrlPath, {               "boothLocked": true,               "waitListEnabled": true,               "maxPlays": 1,               "maxDJs": 5             }           ]         }),         async: this.async,         dataType: 'json',         contentType: 'application/json'       }).done(function() {         if (callback != null) {           return callback();         }       });     };      settings.prototype.unlockBooth = function(callback) {       if (callback == null) {         callback = null;       }       return $.ajax({         url: "http://plug.dj/_/gateway/room.update_options",         type: 'POST',         data: JSON.stringify({           service: "room.update_options",           body: [             this.roomUrlPath, {               "boothLocked": false,               "waitListEnabled": true,               "maxPlays": 1,               "maxDJs": 5             }           ]         }),         async: this.async,         dataType: 'json',         contentType: 'application/json'       }).done(function() {         if (callback != null) {           return callback();         }       });     };      return settings;    })();    data = new settings();    User = (function() {     User.prototype.afkWarningCount = 0;      User.prototype.lastWarning = null;      User.prototype["protected"] = false;      User.prototype.isInRoom = true;      function User(user) {       this.user = user;       this.updateVote = __bind(this.updateVote, this);       this.inRoom = __bind(this.inRoom, this);       this.notDj = __bind(this.notDj, this);       this.warn = __bind(this.warn, this);       this.getIsDj = __bind(this.getIsDj, this);       this.getWarningCount = __bind(this.getWarningCount, this);       this.getUser = __bind(this.getUser, this);       this.getLastWarning = __bind(this.getLastWarning, this);       this.getLastActivity = __bind(this.getLastActivity, this);       this.getLastDrinkTime = __bind(this.getLastDrinkTime, this);       this.updateDrinkTime = __bind(this.updateDrinkTime, this);       this.updateActivity = __bind(this.updateActivity, this);       this.init = __bind(this.init, this);       this.init();     }      User.prototype.init = function() {       this.lastActivity = new Date();       return this.drinkTime = new Date();     };      User.prototype.updateActivity = function() {       this.lastActivity = new Date();       this.afkWarningCount = 0;       return this.lastWarning = null;     };      User.prototype.updateDrinkTime = function() {       return this.drinkTime = new Date();     };      User.prototype.getLastDrinkTime = function() {       return this.drinkTime;     };      User.prototype.getLastActivity = function() {       return this.lastActivity;     };      User.prototype.getLastWarning = function() {       if (this.lastWarning === null) {         return false;       } else {         return this.lastWarning;       }     };      User.prototype.getUser = function() {       return this.user;     };      User.prototype.getWarningCount = function() {       return this.afkWarningCount;     };      User.prototype.getIsDj = function() {       var DJs, dj, _i, _len;        DJs = API.getDJs();       for (_i = 0, _len = DJs.length; _i < _len; _i++) {         dj = DJs[_i];         if (this.user.id === dj.id) {           return true;         }       }       return false;     };      User.prototype.warn = function() {       this.afkWarningCount++;       return this.lastWarning = new Date();     };      User.prototype.notDj = function() {       this.afkWarningCount = 0;       return this.lastWarning = null;     };      User.prototype.inRoom = function(online) {       return this.isInRoom = online;     };      User.prototype.updateVote = function(v) {       if (this.isInRoom) {         return data.voteLog[this.user.id][data.currentsong.id] = v;       }     };      return User;    })();    RoomHelper = (function() {     function RoomHelper() {}      RoomHelper.prototype.lookupUser = function(username) {       var id, u, _ref;        _ref = data.users;       for (id in _ref) {         u = _ref[id];         if (u.getUser().username === username) {           return u.getUser();         }       }       return false;     };      RoomHelper.prototype.userVoteRatio = function(user) {       var songId, songVotes, vote, votes;        songVotes = data.voteLog[user.id];       votes = {         'woot': 0,         'meh': 0       };       for (songId in songVotes) {         vote = songVotes[songId];         if (vote === 1) {           votes['woot']++;         } else if (vote === -1) {           votes['meh']++;         }       }       votes['positiveRatio'] = (votes['woot'] / (votes['woot'] + votes['meh'])).toFixed(2);       return votes;     };      return RoomHelper;    })();    pupOnline = function() {     var currentversion, me, myname;      me = API.getSelf();     myname = me.username;     currentversion = "1.1.0";     log("TastycatBOT version " + currentversion + " started");     return API.sendChat("Have no fear, " + myname + " is here!");   };    populateUserData = function() {     var u, users, _i, _len;      users = API.getUsers();     for (_i = 0, _len = users.length; _i < _len; _i++) {       u = users[_i];       data.users[u.id] = new User(u);       data.voteLog[u.id] = {};     }   };    initEnvironment = function() {     document.getElementById("button-vote-positive").click();     document.getElementById("button-sound").click();     Playback.streamDisabled = true;     return Playback.stop();   };    initialize = function() {     pupOnline();     populateUserData();     initEnvironment();     initHooks();     data.startup();     data.newSong();     return data.startAfkInterval();   };    afkCheck = function() {     var DJs, id, lastActivity, lastWarned, now, secsLastActive, timeSinceLastActivity, timeSinceLastWarning, twoMinutes, user, _ref, _results;      _ref = data.users;     _results = [];     for (id in _ref) {       user = _ref[id];       now = new Date();       lastActivity = user.getLastActivity();       timeSinceLastActivity = now.getTime() - lastActivity.getTime();       if (timeSinceLastActivity > data.afkTime) {         if (user.getIsDj()) {           secsLastActive = timeSinceLastActivity / 1000;           if (user.getWarningCount() === 0) {             user.warn();             _results.push(API.sendChat("@" + user.getUser().username + ", I haven't seen you chat in 1 hour. Are you AFK?  If you don't show activity in 4 minutes I will remove you from the booth."));           } else if (user.getWarningCount() === 1) {             lastWarned = user.getLastWarning();             timeSinceLastWarning = now.getTime() - lastWarned.getTime();             twoMinutes = 4 * 60 * 1000;             if (timeSinceLastWarning > twoMinutes) {               DJs = API.getDJs();               if (DJs.length > 0 && DJs[0].id !== user.getUser().id) {                 API.sendChat("@" + user.getUser().username + ", you had 1 warning. Please stay active by chatting.");                 API.moderateRemoveDJ(id);                 _results.push(user.warn());               } else {                 _results.push(void 0);               }             } else {               _results.push(void 0);             }           } else {             _results.push(void 0);           }         } else {           _results.push(user.notDj());         }       } else {         _results.push(void 0);       }     }     return _results;   };    msToStr = function(msTime) {     var ms, msg, timeAway;      msg = '';     timeAway = {       'days': 0,       'hours': 0,       'minutes': 0,       'seconds': 0     };     ms = {       'day': 24 * 60 * 60 * 1000,       'hour': 60 * 60 * 1000,       'minute': 60 * 1000,       'second': 1000     };     if (msTime > ms['day']) {       timeAway['days'] = Math.floor(msTime / ms['day']);       msTime = msTime % ms['day'];     }     if (msTime > ms['hour']) {       timeAway['hours'] = Math.floor(msTime / ms['hour']);       msTime = msTime % ms['hour'];     }     if (msTime > ms['minute']) {       timeAway['minutes'] = Math.floor(msTime / ms['minute']);       msTime = msTime % ms['minute'];     }     if (msTime > ms['second']) {       timeAway['seconds'] = Math.floor(msTime / ms['second']);     }     if (timeAway['days'] !== 0) {       msg += timeAway['days'].toString() + 'd';     }     if (timeAway['hours'] !== 0) {       msg += timeAway['hours'].toString() + 'h';     }     if (timeAway['minutes'] !== 0) {       msg += timeAway['minutes'].toString() + 'm';     }     if (timeAway['seconds'] !== 0) {       msg += timeAway['seconds'].toString() + 's';     }     if (msg !== '') {       return msg;     } else {       return false;     }   };    Command = (function() {     function Command(msgData) {       this.msgData = msgData;       this.init();     }      Command.prototype.init = function() {       this.parseType = null;       this.command = null;       return this.rankPrivelege = null;     };      Command.prototype.functionality = function(data) {};      Command.prototype.hasPrivelege = function() {       var user;        user = data.users[this.msgData.fromID].getUser();       switch (this.rankPrivelege) {         case 'host':           return user.permission >= 5;         case 'cohost':           return user.permission >= 4;         case 'mod':           return user.permission >= 3;         case 'manager':           return user.permission >= 3;         case 'bouncer':           return user.permission >= 2;         case 'featured':           return user.permission >= 1;         default:           return true;       }     };      Command.prototype.commandMatch = function() {       var command, msg, _i, _len, _ref;        msg = this.msgData.message;       if (typeof this.command === 'string') {         if (this.parseType === 'exact') {           if (msg === this.command) {             return true;           } else {             return false;           }         } else if (this.parseType === 'startsWith') {           if (msg.substr(0, this.command.length) === this.command) {             return true;           } else {             return false;           }         } else if (this.parseType === 'contains') {           if (msg.indexOf(this.command) !== -1) {             return true;           } else {             return false;           }         }       } else if (typeof this.command === 'object') {         _ref = this.command;         for (_i = 0, _len = _ref.length; _i < _len; _i++) {           command = _ref[_i];           if (this.parseType === 'exact') {             if (msg === command) {               return true;             }           } else if (this.parseType === 'startsWith') {             if (msg.substr(0, command.length) === command) {               return true;             }           } else if (this.parseType === 'contains') {             if (msg.indexOf(command) !== -1) {               return true;             }           }         }         return false;       }     };      Command.prototype.evalMsg = function() {       if (this.commandMatch() && this.hasPrivelege()) {         this.functionality();         return true;       } else {         return false;       }     };      return Command;    })();    newsCommand = (function(_super) {     __extends(newsCommand, _super);      function newsCommand() {       _ref = newsCommand.__super__.constructor.apply(this, arguments);       return _ref;     }      newsCommand.prototype.init = function() {       this.command = '/news';       this.parseType = 'startsWith';       return this.rankPrivelege = 'bouncer';     };      newsCommand.prototype.functionality = function() {       var msg;        msg = "No news at this moment in time. ";       return API.sendChat(msg);     };      return newsCommand;    })(Command);    newSongsCommand = (function(_super) {     __extends(newSongsCommand, _super);      function newSongsCommand() {       _ref1 = newSongsCommand.__super__.constructor.apply(this, arguments);       return _ref1;     }      newSongsCommand.prototype.init = function() {       this.command = '/newsongs';       this.parseType = 'startsWith';       return this.rankPrivelege = 'featured';     };      newSongsCommand.prototype.functionality = function() {       var arts, cMedia, chans, chooseRandom, mChans, msg, selections, u, _ref2;        mChans = this.memberChannels.slice(0);       chans = this.channels.slice(0);       arts = this.artists.slice(0);       chooseRandom = function(list) {         var l, r;          l = list.length;         r = Math.floor(Math.random() * l);         return list.splice(r, 1);       };       selections = {         channels: [],         artist: ''       };       u = data.users[this.msgData.fromID].getUser().username;       if (u.indexOf("MistaDubstep") !== -1) {         selections['channels'].push('MistaDubstep');       } else if (u.indexOf("Underground Promotions") !== -1) {         selections['channels'].push('UndergroundDubstep');       } else {         selections['channels'].push(chooseRandom(mChans));       }       selections['channels'].push(chooseRandom(chans));       selections['channels'].push(chooseRandom(chans));       cMedia = API.getMedia();       if (_ref2 = cMedia.author, __indexOf.call(arts, _ref2) >= 0) {         selections['artist'] = cMedia.author;       } else {         selections['artist'] = chooseRandom(arts);       }       msg = "Everyone's heard that " + selections['artist'] + " track! Get new music from http://youtube.com/" + selections['channels'][0] + " http://youtube.com/" + selections['channels'][1] + " or http://youtube.com/" + selections['channels'][2];       return API.sendChat(msg);     };      newSongsCommand.prototype.memberChannels = ["MistaDubstep", "DubStationPromotions", "UndergroundDubstep", "JesusDied4Dubstep", "DarkstepWarrior", "BombshockDubstep", "Sharestep"];      newSongsCommand.prototype.channels = ["BassRape", "MonstercatMedia", "UKFdubstep", "DropThatBassline", "VitalDubstep", "AirwaveDubstepTV", "InspectorDubplate", "TehDubstepChannel", "UNITEDubstep", "LuminantNetwork", "TheSoundIsle", "PandoraMuslc", "MrSuicideSheep", "HearTheSensation", "bassoutletpromos", "MistaDubstep", "DubStationPromotions", "UndergroundDubstep", "JesusDied4Dubstep", "DarkstepWarrior", "BombshockDubstep", "Sharestep"];      newSongsCommand.prototype.artists = ["Doctor P", "Excision", "Flux Pavilion", "Knife Party", "Rusko", "Bassnectar", "Nero", "Deadmau5", "Borgore", "Zomboy"];      return newSongsCommand;    })(Command);    themeCommand = (function(_super) {     __extends(themeCommand, _super);      function themeCommand() {       _ref2 = themeCommand.__super__.constructor.apply(this, arguments);       return _ref2;     }      themeCommand.prototype.init = function() {       this.command = '/theme';       this.parseType = 'startsWith';       return this.rankPrivelege = 'featured';     };      themeCommand.prototype.functionality = function() {       var msg;        msg = "Any type of Bass Music is allowed here. Including Dubstep, Complextro, Drum and Bass, Glitch-Hop, Trap, ";       msg += "Garage, Breakbeat, Hardstyle, Moombahton, HEAVY EDM, House, Electro, and Trance!!";       return API.sendChat(msg);     };      return themeCommand;    })(Command);    rulesCommand = (function(_super) {     __extends(rulesCommand, _super);      function rulesCommand() {       _ref3 = rulesCommand.__super__.constructor.apply(this, arguments);       return _ref3;     }      rulesCommand.prototype.init = function() {       this.command = '/rules';       this.parseType = 'startsWith';       return this.rankPrivelege = 'featured';     };      rulesCommand.prototype.functionality = function() {       var msg1, msg2;        msg1 = "1) Don't complain! we are all here to have fun!. ";       msg1 += "2) Tastycat DJ's have  priority!. ";       msg1 += "3) The bot will remove you from the booth if you are AFK for 1 hour. ";       msg1 += "4) skips will be decided by staff. ";       msg1 += "5) Do not play mixes. ";       msg2 = "6) Do not use the /em or /me commands( yellow text ) ...using this twice will get you kicked from the room. ";       msg2 += "7) Do not ask for fans. ";       API.sendChat(msg1);       return setTimeout((function() {         return API.sendChat(msg2);       }), 750);     };      return rulesCommand;    })(Command);    roomHelpCommand = (function(_super) {     __extends(roomHelpCommand, _super);      function roomHelpCommand() {       _ref4 = roomHelpCommand.__super__.constructor.apply(this, arguments);       return _ref4;     }      roomHelpCommand.prototype.init = function() {       this.command = '/roomhelp';       this.parseType = 'startsWith';       return this.rankPrivelege = 'featured';     };      roomHelpCommand.prototype.functionality = function() {       var msg1, msg2;        msg1 = "Welcome to #TASTYCAT! Create a playlist and populate it with songs from either YouTube or Soundcloud.  ";       msg1 += "Click the 'Join Waitlist' button and wait your turn to play music. All forms of EDM are allowed.";       msg2 = "Play good quality music.  ";       msg2 += "Ask staff if you're unsure about your song choice";       API.sendChat(msg1);       return setTimeout((function() {         return API.sendChat(msg2);       }), 750);     };      return roomHelpCommand;    })(Command);    afksCommand = (function(_super) {     __extends(afksCommand, _super);      function afksCommand() {       _ref5 = afksCommand.__super__.constructor.apply(this, arguments);       return _ref5;     }      afksCommand.prototype.init = function() {       this.command = '/afks';       this.parseType = 'exact';       return this.rankPrivelege = 'mod';     };      afksCommand.prototype.functionality = function() {       var dj, djAfk, djs, msg, now, _i, _len;        msg = '';       djs = API.getDJs();       for (_i = 0, _len = djs.length; _i < _len; _i++) {         dj = djs[_i];         now = new Date();         djAfk = now.getTime() - data.users[dj.id].getLastActivity().getTime();         if (djAfk > (5 * 60 * 1000)) {           if (msToStr(djAfk) !== false) {             msg += dj.username + ' - ' + msToStr(djAfk);             msg += '. ';           }         }       }       if (msg === '') {         return API.sendChat("No one is AFK");       } else {         return API.sendChat('AFKs: ' + msg);       }     };      return afksCommand;    })(Command);    allAfksCommand = (function(_super) {     __extends(allAfksCommand, _super);      function allAfksCommand() {       _ref6 = allAfksCommand.__super__.constructor.apply(this, arguments);       return _ref6;     }      allAfksCommand.prototype.init = function() {       this.command = '/allafks';       this.parseType = 'exact';       return this.rankPrivelege = 'mod';     };      allAfksCommand.prototype.functionality = function() {       var msg, now, u, uAfk, usrs, _i, _len;        msg = '';       usrs = API.getUsers();       for (_i = 0, _len = usrs.length; _i < _len; _i++) {         u = usrs[_i];         now = new Date();         uAfk = now.getTime() - data.users[u.id].getLastActivity().getTime();         if (uAfk > (10 * 60 * 1000)) {           if (msToStr(uAfk) !== false) {             msg += u.username + ' - ' + msToStr(uAfk);             msg += '. ';           }         }       }       if (msg === '') {         return API.sendChat("No one is AFK");       } else {         return API.sendChat('AFKs: ' + msg);       }     };      return allAfksCommand;    })(Command);    statusCommand = (function(_super) {     __extends(statusCommand, _super);      function statusCommand() {       _ref7 = statusCommand.__super__.constructor.apply(this, arguments);       return _ref7;     }      statusCommand.prototype.init = function() {       this.command = '/status';       this.parseType = 'exact';       return this.rankPrivelege = 'bouncer';     };      statusCommand.prototype.functionality = function() {       var day, hour, launch, lt, meridian, min, month, msg, t, totals;        lt = data.launchTime;       month = lt.getMonth() + 1;       day = lt.getDate();       hour = lt.getHours();       meridian = hour % 12 === hour ? 'AM' : 'PM';       min = lt.getMinutes();       min = min < 10 ? '0' + min : min;       t = data.totalVotingData;       t['songs'] = data.songCount;       launch = 'Initiated ' + month + '/' + day + ' ' + hour + ':' + min + ' ' + meridian + '. ';       totals = '' + t.songs + ' songs have been played, accumulating ' + t.woots + ' woots, ' + t.mehs + ' mehs, and ' + t.curates + ' queues.';       msg = launch + totals;       return API.sendChat(msg);     };      return statusCommand;    })(Command);    dieCommand = (function(_super) {     __extends(dieCommand, _super);      function dieCommand() {       _ref8 = dieCommand.__super__.constructor.apply(this, arguments);       return _ref8;     }      dieCommand.prototype.init = function() {       this.command = '/die';       this.parseType = 'exact';       return this.rankPrivelege = 'mod';     };      dieCommand.prototype.functionality = function() {       API.sendChat("Noooo, don't kill me!");       undoHooks();       API.sendChat("Arrggh");       data.implode();       return API.sendChat("I'm dead");     };      return dieCommand;    })(Command);    reloadCommand = (function(_super) {     __extends(reloadCommand, _super);      function reloadCommand() {       _ref9 = reloadCommand.__super__.constructor.apply(this, arguments);       return _ref9;     }      reloadCommand.prototype.init = function() {       this.command = '/reload';       this.parseType = 'exact';       return this.rankPrivelege = 'manager';     };      reloadCommand.prototype.functionality = function() {       var pupSrc;        API.sendChat('brb');       undoHooks();       pupSrc = data.pupScriptUrl;       data.implode();       return $.getScript(pupSrc);     };      return reloadCommand;    })(Command);    lockCommand = (function(_super) {     __extends(lockCommand, _super);      function lockCommand() {       _ref10 = lockCommand.__super__.constructor.apply(this, arguments);       return _ref10;     }      lockCommand.prototype.init = function() {       this.command = '/lock';       this.parseType = 'exact';       return this.rankPrivelege = 'mod';     };      lockCommand.prototype.functionality = function() {       return data.lockBooth();     };      return lockCommand;    })(Command);    unlockCommand = (function(_super) {     __extends(unlockCommand, _super);      function unlockCommand() {       _ref11 = unlockCommand.__super__.constructor.apply(this, arguments);       return _ref11;     }      unlockCommand.prototype.init = function() {       this.command = '/unlock';       this.parseType = 'exact';       return this.rankPrivelege = 'bouncer';     };      unlockCommand.prototype.functionality = function() {       return data.unlockBooth();     };      return unlockCommand;    })(Command);    removeCommand = (function(_super) {     __extends(removeCommand, _super);      function removeCommand() {       _ref12 = removeCommand.__super__.constructor.apply(this, arguments);       return _ref12;     }      removeCommand.prototype.init = function() {       this.command = '/remove';       this.parseType = 'startsWith';       return this.rankPrivelege = 'bouncer';     };      removeCommand.prototype.functionality = function() {       var djs, popDj;        djs = API.getDJs();       popDj = djs[djs.length - 1];       return API.moderateRemoveDJ(popDj.id);     };      return removeCommand;    })(Command);    addCommand = (function(_super) {     __extends(addCommand, _super);      function addCommand() {       _ref13 = addCommand.__super__.constructor.apply(this, arguments);       return _ref13;     }      addCommand.prototype.init = function() {       this.command = '/add';       this.parseType = 'startsWith';       return this.rankPrivelege = 'bouncer';     };      addCommand.prototype.functionality = function() {       var msg, name, r, user;        msg = this.msgData.message;       if (msg.length > this.command.length + 2) {         name = msg.substr(this.command.length + 2);         r = new RoomHelper();         user = r.lookupUser(name);         if (user !== false) {           API.moderateAddDJ(user.id);           return setTimeout((function() {             return data.unlockBooth();           }), 5000);         }       }     };      return addCommand;    })(Command);    skipCommand = (function(_super) {     __extends(skipCommand, _super);      function skipCommand() {       _ref14 = skipCommand.__super__.constructor.apply(this, arguments);       return _ref14;     }      skipCommand.prototype.init = function() {       this.command = '/skip';       this.parseType = 'exact';       this.rankPrivelege = 'bouncer';       return window.lastSkipTime;     };      skipCommand.prototype.functionality = function() {       var currentTime, millisecondsPassed;        currentTime = new Date();       if (!window.lastSkipTime) {         API.moderateForceSkip();         return window.lastSkipTime = currentTime;       } else {         millisecondsPassed = Math.round(currentTime.getTime() - window.lastSkipTime.getTime());         if (millisecondsPassed > 10000) {           window.lastSkipTime = currentTime;           return API.moderateForceSkip();         }       }     };      return skipCommand;    })(Command);    disconnectLookupCommand = (function(_super) {     __extends(disconnectLookupCommand, _super);      function disconnectLookupCommand() {       _ref15 = disconnectLookupCommand.__super__.constructor.apply(this, arguments);       return _ref15;     }      disconnectLookupCommand.prototype.init = function() {       this.command = '/dclookup';       this.parseType = 'startsWith';       return this.rankPrivelege = 'bouncer';     };      disconnectLookupCommand.prototype.functionality = function() {       var cmd, dcHour, dcLookupId, dcMeridian, dcMins, dcSongsAgo, dcTimeStr, dcUser, disconnectInstances, givenName, id, recentDisconnect, resp, u, _i, _len, _ref16, _ref17;        cmd = this.msgData.message;       if (cmd.length > 11) {         givenName = cmd.slice(11);         _ref16 = data.users;         for (id in _ref16) {           u = _ref16[id];           if (u.getUser().username === givenName) {             dcLookupId = id;             disconnectInstances = [];             _ref17 = data.userDisconnectLog;             for (_i = 0, _len = _ref17.length; _i < _len; _i++) {               dcUser = _ref17[_i];               if (dcUser.id === dcLookupId) {                 disconnectInstances.push(dcUser);               }             }             if (disconnectInstances.length > 0) {               resp = u.getUser().username + ' has disconnected ' + disconnectInstances.length.toString() + ' time';               if (disconnectInstances.length === 1) {                 resp += '. ';               } else {                 resp += 's. ';               }               recentDisconnect = disconnectInstances.pop();               dcHour = recentDisconnect.time.getHours();               dcMins = recentDisconnect.time.getMinutes();               if (dcMins < 10) {                 dcMins = '0' + dcMins.toString();               }               dcMeridian = dcHour % 12 === dcHour ? 'AM' : 'PM';               dcTimeStr = '' + dcHour + ':' + dcMins + ' ' + dcMeridian;               dcSongsAgo = data.songCount - recentDisconnect.songCount;               resp += 'Their most recent disconnect was at ' + dcTimeStr + ' (' + dcSongsAgo + ' songs ago). ';               if (recentDisconnect.waitlistPosition !== void 0) {                 resp += 'They were ' + recentDisconnect.waitlistPosition + ' song';                 if (recentDisconnect.waitlistPosition > 1) {                   resp += 's';                 }                 resp += ' away from the DJ booth.';               } else {                 resp += 'They were not on the waitlist.';               }               API.sendChat(resp);               return;             } else {               API.sendChat("I haven't seen " + u.getUser().username + " disconnect.");               return;             }           }         }         return API.sendChat("I don't see a user in the room named '" + givenName + "'.");       }     };      return disconnectLookupCommand;    })(Command);    voteRatioCommand = (function(_super) {     __extends(voteRatioCommand, _super);      function voteRatioCommand() {       _ref16 = voteRatioCommand.__super__.constructor.apply(this, arguments);       return _ref16;     }      voteRatioCommand.prototype.init = function() {       this.command = '/voteratio';       this.parseType = 'startsWith';       return this.rankPrivelege = 'bouncer';     };      voteRatioCommand.prototype.functionality = function() {       var msg, name, r, u, votes;        r = new RoomHelper();       msg = this.msgData.message;       if (msg.length > 12) {         name = msg.substr(12);         u = r.lookupUser(name);         if (u !== false) {           votes = r.userVoteRatio(u);           msg = u.username + " has wooted " + votes['woot'].toString() + " time";           if (votes['woot'] === 1) {             msg += ', ';           } else {             msg += 's, ';           }           msg += "and meh'd " + votes['meh'].toString() + " time";           if (votes['meh'] === 1) {             msg += '. ';           } else {             msg += 's. ';           }           msg += "Their woot:vote ratio is " + votes['positiveRatio'].toString() + ".";           return API.sendChat(msg);         } else {           return API.sendChat("I don't recognize a user named '" + name + "'");         }       } else {         return API.sendChat("I'm not sure what you want from me...");       }     };      return voteRatioCommand;    })(Command);    avgVoteRatioCommand = (function(_super) {     __extends(avgVoteRatioCommand, _super);      function avgVoteRatioCommand() {       _ref17 = avgVoteRatioCommand.__super__.constructor.apply(this, arguments);       return _ref17;     }      avgVoteRatioCommand.prototype.init = function() {       this.command = '/avgvoteratio';       this.parseType = 'exact';       return this.rankPrivelege = 'mod';     };      avgVoteRatioCommand.prototype.functionality = function() {       var averageRatio, msg, r, ratio, roomRatios, uid, user, userRatio, votes, _i, _len, _ref18;        roomRatios = [];       r = new RoomHelper();       _ref18 = data.voteLog;       for (uid in _ref18) {         votes = _ref18[uid];         user = data.users[uid].getUser();         userRatio = r.userVoteRatio(user);         roomRatios.push(userRatio['positiveRatio']);       }       averageRatio = 0.0;       for (_i = 0, _len = roomRatios.length; _i < _len; _i++) {         ratio = roomRatios[_i];         averageRatio += ratio;       }       averageRatio = averageRatio / roomRatios.length;       msg = "Accounting for " + roomRatios.length.toString() + " user ratios, the average room ratio is " + averageRatio.toFixed(2).toString() + ".";       return API.sendChat(msg);     };      return avgVoteRatioCommand;    })(Command);    staffCommand = (function(_super) {     __extends(staffCommand, _super);      function staffCommand() {       _ref18 = staffCommand.__super__.constructor.apply(this, arguments);       return _ref18;     }      staffCommand.prototype.init = function() {       this.command = '/staff';       this.parseType = 'exact';       this.rankPrivelege = 'user';       return window.lastActiveStaffTime;     };      staffCommand.prototype.staff = function() {       var now, staff, staffAfk, stringstaff, user, _i, _len;        staff = API.getStaff();       now = new Date();       stringstaff = "";       for (_i = 0, _len = staff.length; _i < _len; _i++) {         user = staff[_i];         if (user.permission > 2) {           staffAfk = now.getTime() - data.users[user.id].getLastActivity().getTime();           if (staffAfk < (20 * 60 * 1000)) {             stringstaff += "@" + user.username + " ";           }         }       }       if (stringstaff.length === 0) {         stringstaff = "There are currently no staff members active :'(";       }       return stringstaff;     };      staffCommand.prototype.functionality = function() {       var currentTime, millisecondsPassed, thestaff;        thestaff = this.staff();       currentTime = new Date();       if (!window.lastActiveStaffTime) {         API.sendChat(thestaff);         return window.lastActiveStaffTime = currentTime;       } else {         millisecondsPassed = currentTime.getTime() - window.lastActiveStaffTime.getTime();         if (millisecondsPassed > 10000) {           window.lastActiveStaffTime = currentTime;           return API.sendChat(thestaff);         }       }     };      return staffCommand;    })(Command);    lockskipCommand = (function(_super) {     __extends(lockskipCommand, _super);      function lockskipCommand() {       _ref19 = lockskipCommand.__super__.constructor.apply(this, arguments);       return _ref19;     }      lockskipCommand.prototype.init = function() {       this.command = '/lockskip';       this.parseType = 'startsWith';       return this.rankPrivelege = 'bouncer';     };      lockskipCommand.prototype.functionality = function() {       return data.lockBooth(function() {         return setTimeout(function() {}, API.moderateForceSkip(), setTimeout(function() {           return data.unlockBooth();         }, 5000), 5000);       });     };      return lockskipCommand;    })(Command);    promoCommand = (function(_super) {     __extends(promoCommand, _super);      function promoCommand() {       _ref20 = promoCommand.__super__.constructor.apply(this, arguments);       return _ref20;     }      promoCommand.prototype.init = function() {       this.command = '/tastycat';       this.parseType = 'startsWith';       return this.rankPrivelege = 'featured';     };      promoCommand.prototype.functionality = function() {       return API.sendChat("/em: " + "Promo code = tastycat " + "http://community.edmspotlight.com/forum.php ");     };      return promoCommand;    })(Command);    versionCommand = (function(_super) {     __extends(versionCommand, _super);      function versionCommand() {       _ref21 = versionCommand.__super__.constructor.apply(this, arguments);       return _ref21;     }      versionCommand.prototype.init = function() {       this.command = '/version';       this.parseType = 'exact';       return this.rankPrivelege = 'mod';     };      versionCommand.prototype.functionality = function() {       return API.sendChat("/me is running TastycatBot version " + currentversion);     };      return versionCommand;    })(Command);    cmds = [newSongsCommand, themeCommand, rulesCommand, roomHelpCommand, afksCommand, allAfksCommand, statusCommand, dieCommand, reloadCommand, lockCommand, unlockCommand, removeCommand, addCommand, skipCommand, disconnectLookupCommand, voteRatioCommand, avgVoteRatioCommand, staffCommand, lockskipCommand, versionCommand, newsCommand, promoCommand];    chatCommandDispatcher = function(chat) {     var c, cmd, _i, _len, _results;      chatUniversals(chat);     _results = [];     for (_i = 0, _len = cmds.length; _i < _len; _i++) {       cmd = cmds[_i];       c = new cmd(chat);       if (c.evalMsg()) {         break;       } else {         _results.push(void 0);       }     }     return _results;   };    updateVotes = function(obj) {     data.currentwoots = obj.positive;     data.currentmehs = obj.negative;     return data.currentcurates = obj.curates;   };    announceCurate = function(obj) {     return APIsendChat("/em: " + obj.user.username + " loves this song!");   };    handleUserJoin = function(user) {     data.userJoin(user);     return data.users[user.id].updateActivity();   };    handleNewSong = function(obj) {     var songId;      data.intervalMessages();     if (data.currentsong === null) {       data.newSong();     } else {       API.sendChat("/em: " + data.currentsong.title + " by " + data.currentsong.author + ". Stats: Woots: " + data.currentwoots + ", Mehs: " + data.currentmehs + ", Loves: " + data.currentcurates + ".");       data.newSong();       document.getElementById("button-vote-positive").click();     }     if (data.forceSkip) {       songId = obj.media.id;       return setTimeout(function() {         var cMedia;          cMedia = API.getMedia();         if (cMedia.id === songId) {           return API.moderateForceSkip();         }       }, obj.media.duration * 1000);     }   };    handleVote = function(obj) {     return data.users[obj.user.id].updateVote(obj.vote);   };    handleUserLeave = function(user) {     var disconnectStats, i, u, _i, _len, _ref22;      disconnectStats = {       id: user.id,       time: new Date(),       songCount: data.songCount     };     i = 0;     _ref22 = data.internalWaitlist;     for (_i = 0, _len = _ref22.length; _i < _len; _i++) {       u = _ref22[_i];       if (u.id === user.id) {         disconnectStats['waitlistPosition'] = i - 1;         data.setInternalWaitlist();         break;       } else {         i++;       }     }     data.userDisconnectLog.push(disconnectStats);     return data.users[user.id].inRoom(false);   };    antispam = function(chat) {     var plugRoomLinkPatt, sender;      plugRoomLinkPatt = /(\bhttps?:\/\/(www.)?plug\.dj[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;     if (plugRoomLinkPatt.exec(chat.message)) {       sender = API.getUser(chat.fromID);       if (!sender.ambassador && !sender.moderator && !sender.owner && !sender.superuser) {         if (!data.users[chat.fromID]["protected"]) {           API.sendChat("Don't spam room links you ass clown");           return API.moderateDeleteChat(chat.chatID);         } else {           return API.sendChat("I'm supposed to kick you, but you're just too darn pretty.");         }       }     }   };    fans = function(chat) {     var msg;      msg = chat.message.toLowerCase();     if (msg.indexOf('fan me') !== -1 || msg.indexOf('fan for fan') !== -1 || msg.indexOf('fan pls') !== -1 || msg.indexOf('fan4fan') !== -1 || msg.indexOf('add me to fan') !== -1 || msg.indexOf('autowoot:') !== -1) {       return API.moderateDeleteChat(chat.chatID);     }   };    chatUniversals = function(chat) {     data.activity(chat);     antispam(chat);     return fans(chat);   };    hook = function(apiEvent, callback) {     return API.addEventListener(apiEvent, callback);   };    unhook = function(apiEvent, callback) {     return API.removeEventListener(apiEvent, callback);   };    apiHooks = [     {       'event': API.ROOM_SCORE_UPDATE,       'callback': updateVotes     }, {       'event': API.CURATE_UPDATE,       'callback': announceCurate     }, {       'event': API.USER_JOIN,       'callback': handleUserJoin     }, {       'event': API.DJ_ADVANCE,       'callback': handleNewSong     }, {       'event': API.VOTE_UPDATE,       'callback': handleVote     }, {       'event': API.CHAT,       'callback': chatCommandDispatcher     }, {       'event': API.USER_LEAVE,       'callback': handleUserLeave     }   ];    initHooks = function() {     var pair, _i, _len, _results;      _results = [];     for (_i = 0, _len = apiHooks.length; _i < _len; _i++) {       pair = apiHooks[_i];       _results.push(hook(pair['event'], pair['callback']));     }     return _results;   };    undoHooks = function() {     var pair, _i, _len, _results;      _results = [];     for (_i = 0, _len = apiHooks.length; _i < _len; _i++) {       pair = apiHooks[_i];       _results.push(unhook(pair['event'], pair['callback']));     }     return _results;   };    initialize();  }).call(this);