!function(e){!function t(e,n,o){function i(s,a){if(!n[s]){if(!e[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(r)return r(s,!0);throw new Error("Cannot find module '"+s+"'")}var c=n[s]={exports:{}};e[s][0].call(c.exports,function(t){var n=e[s][1][t];return i(n?n:t)},c,c.exports,t,e,n,o)}return n[s].exports}for(var r="function"==typeof require&&require,s=0;se?this._legacy_add_donors(e):void 0):void 0})},n.prototype._legacy_parse_donors=function(e){var t=0;if(null!=e)for(var n=e.trim().split(/\W+/),o=0;o50)return"Each user you unmod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var o=t.length;t.length;){var i=t.shift();e.room.tmiRoom.sendMessage("/unmod "+i)}return"Sent unmod command for "+o+" users."},t.ffz_commands.massunmod.help="Usage: /ffz massunmod \nBroadcaster only. Unmod all the users in the provided list.",t.ffz_commands.massmod=function(e,t){if(t=t.join(" ").trim(),!t.length)return"You must provide a list of users to mod.";t=t.split(/\W*,\W*/);var n=this.get_user();if(!n||!n.login==e.id)return"You must be the broadcaster to use massmod.";if(t.length>50)return"Each user you mod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var o=t.length;t.length;){var i=t.shift();e.room.tmiRoom.sendMessage("/mod "+i)}return"Sent mod command for "+o+" users."},t.ffz_commands.massmod.help="Usage: /ffz massmod \nBroadcaster only. Mod all the users in the provided list."},{}],3:[function(e,t){var n='',o="true"==localStorage.ffzDebugMode&&document.body.classList.contains("ffz-dev");t.exports={DEBUG:o,SERVER:o?"//localhost:8000/":"//cdn.frankerfacez.com/",SVGPATH:n,ZREKNARF:''+n+"",CHAT_BUTTON:''+n+"",GEAR:'',HEART:'',EMOTE:''}},{}],4:[function(){var t=e.FrankerFaceZ;t.settings_info.developer_mode={type:"boolean",value:!1,storage_key:"ffzDebugMode",visible:function(){return this.settings.developer_mode||Date.now()-parseInt(localStorage.ffzLastDevMode||"0")<6048e5},category:"Debugging",name:"Developer Mode",help:"Load FrankerFaceZ from the local development server instead of the CDN. Please refresh after changing this setting.",on_update:function(){localStorage.ffzLastDevMode=Date.now()}},t.ffz_commands.developer_mode=function(e,t){var n,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?n=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(n=!1),void 0===n?"Developer Mode is currently "+(this.settings.developer_mode?"enabled.":"disabled."):(this.settings.set("developer_mode",n),"Developer Mode is now "+(n?"enabled":"disabled")+". Please refresh your browser.")},t.ffz_commands.developer_mode.help="Usage: /ffz developer_mode \nEnable or disable Developer Mode. When Developer Mode is enabled, the script will be reloaded from //localhost:8000/script.js instead of from the CDN."},{}],5:[function(){var t=e.FrankerFaceZ;t.prototype.setup_chatview=function(){this.log("Hooking the Ember Chat view.");var e=App.__container__.resolve("view:chat");this._modify_cview(e);try{e.create().destroy()}catch(t){}for(var n in Ember.View.views)if(Ember.View.views.hasOwnProperty(n)){var o=Ember.View.views[n];if(o instanceof e){this.log("Adding UI link manually to Chat view.",o);try{o.$(".textarea-contain").append(this.build_ui_link(o))}catch(t){this.error("setup: build_ui_link: "+t)}}}},t.prototype._modify_cview=function(e){var t=this;e.reopen({didInsertElement:function(){this._super();try{this.$()&&this.$(".textarea-contain").append(t.build_ui_link(this))}catch(e){t.error("didInsertElement: build_ui_link: "+e)}},willClearRender:function(){this._super();try{this.$(".ffz-ui-toggle").remove()}catch(e){t.error("willClearRender: remove ui link: "+e)}},ffzUpdateLink:Ember.observer("controller.currentRoom",function(){try{t.update_ui_link()}catch(e){t.error("ffzUpdateLink: update_ui_link: "+e)}})})}},{}],6:[function(t){var n=e.FrankerFaceZ,o=t("../utils"),i=function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},r="[\\s`~<>!-#%-\\x2A,-/:;\\x3F@\\x5B-\\x5D_\\x7B}\\u00A1\\u00A7\\u00AB\\u00B6\\u00B7\\u00BB\\u00BF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u0AF0\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E3B\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65]",s=new RegExp(r+"*,"+r+"*"),a=function(e){return(e+"").replace(/&/g,"&").replace(/'/g,"'").replace(/"/g,""").replace(//g,">")},l="http://static-cdn.jtvnw.net/emoticons/v1/",c=function(e){return l+e+"/1.0 1x, "+l+e+"/2.0 2x, "+l+e+"/3.0 4x"},u=function(e){var t="Emoticon"+e.code+"",n=e.set,o=e.set_type;return void 0===o&&(o="Channel"),n?(("00000turbo"==n||"turbo"==n)&&(n="Twitch Turbo",o=null),t+=o?""+o+""+n+"":''+n+"",''+t+"
"):e.code},d=function(e){{var t=this._twitch_emotes[e];t?t.set:null}return t?"string"==typeof t?t:t.tooltip?t.tooltip:t.tooltip=u(t):"???"},h=function(e,t,n,o){if(n){t&&(o.code=t),this._twitch_emotes[e]=o;for(var i=d.bind(this)(e),r=document.querySelectorAll('img[emote-id="'+e+'"]'),s=0;s-1&&(-1===t.indexOf("/")||t.indexOf("@")>16,t>>8&255,255&t],i=o.get_luminance(n),r="",s='span[style="color:'+e+'"]',a=!1;if(i>.3){a=!0;for(var l=255,c=n;l--&&(c=o.darken(c),!(o.get_luminance(c)<=.3)););r+=".ffz-chat-colors .ember-chat-container:not(.dark) .chat-line "+s+", .ffz-chat-colors .chat-container:not(.dark) .chat-line "+s+" { color: "+o.rgb_to_css(c)+" !important; }\n"}else r+=".ffz-chat-colors .ember-chat-container:not(.dark) .chat-line "+s+", .ffz-chat-colors .chat-container:not(.dark) .chat-line "+s+" { color: "+e+" !important; }\n";if(.1>i){a=!0;for(var l=255,c=n;l--&&(c=o.brighten(c),!(o.get_luminance(c)>=.1)););r+=".ffz-chat-colors .theatre .chat-container .chat-line "+s+", .ffz-chat-colors .chat-container.dark .chat-line "+s+", .ffz-chat-colors .ember-chat-container.dark .chat-line "+s+" { color: "+o.rgb_to_css(c)+" !important; }\n"}else r+=".ffz-chat-colors .theatre .chat-container .chat-line "+s+", .ffz-chat-colors .chat-container.dark .chat-line "+s+", .ffz-chat-colors .ember-chat-container.dark .chat-line "+s+" { color: "+e+" !important; }\n";a&&(this._fix_color_style.innerHTML+=r)}},n.capitalization={},n._cap_fetching=0,n.get_capitalization=function(t,o){if(e.BetterTTV&&BetterTTV.chat&&BetterTTV.chat.helpers.lookupDisplayName)return BetterTTV.chat.helpers.lookupDisplayName(t);if(!t)return t;if(t=t.toLowerCase(),"jtv"==t||"twitchnotify"==t)return t;var i=n.capitalization[t];return i&&Date.now()-i[1]<36e5?i[0]:(n._cap_fetching<25&&(n._cap_fetching++,n.get().ws_send("get_display_name",t,function(e,i){var r=e?i:t;n.capitalization[t]=[r,Date.now()],n._cap_fetching--,"function"==typeof o&&o(r)})),i?i[0]:t)},n.prototype.capitalize=function(e,t){var o=n.get_capitalization(t,this.capitalize.bind(this,e));o&&e&&e.$(".from").text(o)},n._regex_cache={},n._get_regex=function(e){return n._regex_cache[e]=n._regex_cache[e]||RegExp("\\b"+i(e)+"\\b","ig")},n._words_to_regex=function(e){var t=n._regex_cache[e];if(!t){for(var o="",s=0;s<banned link>',own:!0}:s)}return i},n.prototype._emoticonize=function(e,t){var n=e.get("parentController.model.id"),o=e.get("model.from"),i=this,r=this.getEmotes(o,n),s=[];return _.each(r,function(e){var n=i.emote_sets[e];n&&_.each(n.emotes,function(e){_.any(t,function(t){return _.isString(t)&&t.match(e.regex)})&&s.push(e)})}),s.length?("string"==typeof t&&(t=[t]),_.each(s,function(e){var n={isEmoticon:!0,cls:e.klass,emoticonSrc:e.url+'" data-ffz-emote="'+encodeURIComponent(JSON.stringify([e.id,e.set_id])),altText:e.hidden?"???":e.name};t=_.compact(_.flatten(_.map(t,function(t){if(_.isObject(t))return t;var o=t.split(e.regex),i=[];return o.forEach(function(e,t){i.push(e),t!==o.length-1&&i.push(n)}),i})))}),t):t}},{"../utils":26}],7:[function(t){var n=e.FrankerFaceZ,o=t("../utils"),i={ESC:27,P:80,B:66,T:84},r=[["5m",300],["10m",600],["1hr",3600],["12hr",43200],["24hr",86400]],s='',a='';n.settings_info.enhanced_moderation={type:"boolean",value:!1,visible:function(){return!this.has_bttv},category:"Chat",name:"Enhanced Moderation",help:"Use /p, /t, /u and /b in chat to moderate chat, or use hotkeys with moderation cards."},n.prototype.setup_mod_card=function(){this.log("Hooking the Ember Moderation Card view.");var e=App.__container__.resolve("view:moderation-card"),t=this;e.reopen({didInsertElement:function(){this._super();try{if(t.has_bttv||!t.settings.enhanced_moderation)return;var e=this.get("element"),n=this.get("context");if(e.classList.add("ffz-moderation-card"),n.get("parentController.model.isModeratorOrHigher")){e.classList.add("ffz-is-mod"),e.setAttribute("tabindex",1),e.addEventListener("keyup",function(e){var t=e.keyCode||e.which,o=n.get("model.user.id"),r=n.get("parentController.model");if(t==i.P)r.send("/timeout "+o+" 1");else if(t==i.B)r.send("/ban "+o);else if(t==i.T)r.send("/timeout "+o+" 600");else if(t!=i.ESC)return;n.send("hideModOverlay")});var l=document.createElement("div");l.className="interface clearfix";var c=function(e){var t=n.get("model.user.id"),o=n.get("parentController.model");o.send(-1===e?"/unban "+t:"/timeout "+t+" "+e)},u=function(e,t){var n=document.createElement("button");return n.className="button",n.innerHTML=e,n.title="Timeout User for "+o.number_commas(t)+" Second"+(1!=t?"s":""),600===t?n.title="(T)"+n.title.substr(1):1===t&&(n.title="(P)urge - "+n.title),jQuery(n).tipsy(),n.addEventListener("click",c.bind(this,t)),n};l.appendChild(u("Purge",1));var d=document.createElement("span");d.className="right",l.appendChild(d);for(var h=0;h button");v&&"button"==v.className&&(v.innerHTML=s,v.classList.add("glyph-only"),v.classList.add("message"),v.title="Message User",jQuery(v).tipsy()),this.$().draggable({start:function(){e.focus()}}),e.focus()}catch(b){try{t.error("ModerationCardView didInsertElement: "+b)}catch(b){}}}})},n.chat_commands.purge=n.chat_commands.p=function(e,t){if(!t||!t.length)return"Purge Usage: /p username [more usernames separated by spaces]";if(t.length>10)return"Please only purge up to 10 users at once.";for(var n=0;n10)return"Please only ban up to 10 users at once.";for(var n=0;n10)return"Please only unban up to 10 users at once.";for(var n=0;nn?this._legacy_add_room(e,t,n):void 0)})},n.prototype._legacy_load_room_css=function(e,t,n){var s=e,a=s.match(r); a&&a[1]&&(s=a[1]);var l={id:e,menu_sets:[s],sets:[s],moderator_badge:null,css:null};return n&&(n=n.replace(o,"").trim()),n&&(n=n.replace(i,function(e,t){return l.moderator_badge||"modicon.png"!==t.substr(-11)?e:(l.moderator_badge=t,"")})),l.css=n||null,this._load_room_json(e,t,l)}},{"../constants":3,"../utils":26}],9:[function(){var t=e.FrankerFaceZ;t.prototype.setup_viewers=function(){this.log("Hooking the Ember Viewers controller.");var e=App.__container__.resolve("controller:viewers");this._modify_viewers(e)},t.prototype._modify_viewers=function(e){var n=this;e.reopen({lines:function(){var e=this._super();try{var o=[],i={},r=null,s=App.__container__.lookup("controller:channel"),a=this.get("parentController.model.id"),l=s&&s.get("id");if(l){var c=s.get("display_name");c&&(t.capitalization[l]=[c,Date.now()])}a!=l&&(l=null);for(var u=0;un?this._legacy_load_set(e,t,n):"function"==typeof t&&t(!1))})},n.prototype._legacy_load_css=function(e,t,n){var r={},s={id:e,emotes:r,extra_css:null},a=this;n=n.replace(o,function(t,n,o,i,s,c,u,d){s=parseInt(s),c=parseInt(c),u=l(u,s);var h="."===i.substr(i.lastIndexOf("/")+1,1),m=++a._last_emote_id,p={id:m,set_id:e,hidden:h,name:o,height:s,width:c,url:i,margins:u,extra_css:d};return r[m]=p,""}).trim(),n&&n.replace(i,function(e,t){s.icon||"modicon.png"!==t.substr(-11)||(s.icon=t)}),this._load_set_json(e,t,s)}},{"./constants":3,"./utils":26}],11:[function(){var t=e.FrankerFaceZ,n=/(\sdata-sender="[^"]*"(?=>))/;t.prototype.find_bttv=function(t,n){return this.has_bttv=!1,e.BTTVLOADED?this.setup_bttv(n||0):void(n>=6e4?this.log("BetterTTV was not detected after 60 seconds."):setTimeout(this.find_bttv.bind(this,t,(n||0)+t),t))},t.prototype.setup_bttv=function(e){this.log("BetterTTV was detected after "+e+"ms. Hooking."),this.has_bttv=!0,document.body.classList.remove("ffz-dark"),this._dark_style&&(this._dark_style.parentElement.removeChild(this._dark_style),delete this._dark_style),document.body.classList.remove("ffz-chat-colors"),document.body.classList.remove("ffz-chat-background");var t=BetterTTV.chat.helpers.sendMessage,o=this;BetterTTV.chat.helpers.sendMessage=function(e){var n=e.split(" ",1)[0].toLowerCase();return"/ffz"!==n?t(e):void o.run_ffz_command(e.substr(5),BetterTTV.chat.store.currentRoom)};var i,r=BetterTTV.chat.handlers.privmsg;BetterTTV.chat.handlers.privmsg=function(e,t){i=e;var n=r(e,t);return i=null,n};var s=BetterTTV.chat.templates.privmsg;BetterTTV.chat.templates.privmsg=function(e,t,r,a,l){o.bttv_badges(l);var c=s(e,t,r,a,l);return c.replace(n,'$1 data-room="'+i+'"')};var a,l=BetterTTV.chat.templates.message;BetterTTV.chat.templates.message=function(e,t,n,o){a=e;var i=l(e,t,n,o);return a=null,i};var c=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(e,t){var n=c(e,t),r=o.getEmotes(a,i),t=[];return _.each(r,function(e){var i=o.emote_sets[e];i&&_.each(i.emotes,function(e){_.any(n,function(t){return _.isString(t)&&t.match(e.regex)})&&t.push(e)})}),t.length?(_.each(t,function(e){var t=[''+e.name+''],o=n;if(n=[],!o||!o.length)return n;for(var i=0;i=6e4?this.log("Emote Menu for Twitch was not detected after 60 seconds."):setTimeout(this.find_emote_menu.bind(this,t,(n||0)+t),t))},t.prototype.setup_emote_menu=function(e){this.log("Emote Menu for Twitch was detected after "+e+"ms. Registering emote enumerator."),emoteMenu.registerEmoteGetter("FrankerFaceZ",this._emote_menu_enumerator.bind(this))},t.prototype._emote_menu_enumerator=function(){for(var e=this.get_user(),n=e?e.login:null,o=App.__container__.lookup("controller:chat"),i=o?o.get("currentRoom.id"):null,r=this.getEmotes(n,i),s=[],a=0;a=6e4?this.log('Twitch application not detected in "'+location.toString()+'". Aborting.'):setTimeout(this.initialize.bind(this,t,(n||0)+t),t)))},n.prototype.setup_ember=function(t){var o=e.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch application after "+(t||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+n.version_info),this.users={},this.load_settings(),this.ws_create(),this.setup_emoticons(),this.setup_badges(),this.setup_room(),this.setup_line(),this.setup_chatview(),this.setup_viewers(),this.setup_mod_card(),this.setup_notifications(),this.setup_css(),this.setup_menu(),this.setup_my_emotes(),this.setup_races(),this.find_bttv(10),this.find_emote_menu(10),this.check_ff();var i=e.performance&&performance.now?performance.now():Date.now(),r=i-o;this.log("Initialization complete in "+r+"ms")}},{"./badges":1,"./commands":2,"./debug":4,"./ember/chatview":5,"./ember/line":6,"./ember/moderation-card":7,"./ember/room":8,"./ember/viewers":9,"./emoticons":10,"./ext/betterttv":11,"./ext/emote_menu":12,"./featurefriday":14,"./settings":15,"./shims":16,"./socket":17,"./ui/about_page":18,"./ui/menu":19,"./ui/menu_button":20,"./ui/my_emotes":21,"./ui/notifications":22,"./ui/races":23,"./ui/styles":24,"./ui/viewer_count":25}],14:[function(t){var n=e.FrankerFaceZ,o=t("./constants");n.prototype.feature_friday=null,n.prototype.check_ff=function(e){e||this.log("Checking for Feature Friday data..."),jQuery.ajax(o.SERVER+"script/event.json",{cache:!1,dataType:"json",context:this}).done(function(e){return this._load_ff(e)}).fail(function(t){return 404==t.status?this._load_ff(null):(e=e||0,e++,10>e?setTimeout(this.check_ff.bind(this,e),250):this._load_ff(null))})},n.ws_commands.reload_ff=function(){this.check_ff()},n.prototype._feature_friday_ui=function(e,t,n){if(this.feature_friday&&this.feature_friday.channel!=e){this._emotes_for_sets(t,n,[this.feature_friday.set],"Feature Friday");var o=App.__container__.lookup("controller:channel");if(!o||o.get("id")!=this.feature_friday.channel){var i=this.feature_friday,r=document.createElement("div"),s=document.createElement("a");r.className="chat-menu-content",r.style.textAlign="center";var a=i.display_name+(i.live?" is live now!":"");s.className="button primary",s.classList.toggle("live",i.live),s.classList.toggle("blue",this.has_bttv&&BetterTTV.settings.get("showBlueButtons")),s.href="http://www.twitch.tv/"+i.channel,s.title=a,s.target="_new",s.innerHTML=""+a+"",r.appendChild(s),t.appendChild(r)}}},n.prototype._load_ff=function(e){if(this.feature_friday){this.global_sets.removeObject(this.feature_friday.set);var t=this.emote_sets[this.feature_friday.set];t&&(t.global=!1),this.feature_friday=null,this.update_ui_link()}e&&e.set&&e.channel&&(this.feature_friday={set:e.set,channel:e.channel,live:!1,display_name:n.get_capitalization(e.channel,this._update_ff_name.bind(this))},this.global_sets.push(e.set),this.load_set(e.set,this._update_ff_set.bind(this)),this._update_ff_live())},n.prototype._update_ff_live=function(){if(this.feature_friday){var e=this;Twitch.api.get("streams/"+this.feature_friday.channel).done(function(t){e.feature_friday.live=null!=t.stream,e.update_ui_link()}).always(function(){e.feature_friday.timer=setTimeout(e._update_ff_live.bind(e),12e4)})}},n.prototype._update_ff_set=function(e,t){t&&(t.global=!0)},n.prototype._update_ff_name=function(e){this.feature_friday&&(this.feature_friday.display_name=e)}},{"./constants":3}],15:[function(t){var n=e.FrankerFaceZ,o=t("./constants");make_ls=function(e){return"ffz_setting_"+e},toggle_setting=function(e,t){var n=!this.settings.get(t);this.settings.set(t,n),e.classList.toggle("active",n)},n.settings_info={},n.prototype.load_settings=function(){this.log("Loading settings."),this.settings={};for(var t in n.settings_info)if(n.settings_info.hasOwnProperty(t)){var o=n.settings_info[t],i=o.storage_key||make_ls(t),r=o.hasOwnProperty("value")?o.value:void 0;if(localStorage.hasOwnProperty(i))try{r=JSON.parse(localStorage.getItem(i))}catch(s){this.log('Error loading value for "'+t+'": '+s)}this.settings[t]=r}this.settings.get=this._setting_get.bind(this),this.settings.set=this._setting_set.bind(this),this.settings.del=this._setting_del.bind(this),e.addEventListener("storage",this._setting_update.bind(this),!1)},n.menu_pages.settings={render:function(e,t){var o={},i=[];for(var r in n.settings_info)if(n.settings_info.hasOwnProperty(r)){var s=n.settings_info[r],a=s.category||"Miscellaneous",l=o[a];if(void 0!==s.visible&&null!==s.visible){var c=s.visible;if("function"==typeof s.visible&&(c=s.visible.bind(this)()),!c)continue}l||(i.push(a),l=o[a]=[]),l.push([r,s])}i.sort(function(e,t){var e=e.toLowerCase(),t=t.toLowerCase();return"Debugging"===e&&(e="zzz"+e),"Debugging"===t&&(t="zzz"+t),t>e?-1:e>t?1:0});for(var u=0;un?-1:n>o?1:r>i?-1:i>r?1:0});for(var f=0;f",b.className="switch-label",b.innerHTML=s.name,_.appendChild(v),_.appendChild(b),v.addEventListener("click",toggle_setting.bind(this,v,r))}else{_.classList.add("option");var y=document.createElement("a");y.innerHTML=s.name,y.href="#",_.appendChild(y),y.addEventListener("click",s.method.bind(this))}if(s.help){var w=document.createElement("span");w.className="help",w.innerHTML=s.help,_.appendChild(w)}m.appendChild(_)}t.appendChild(m)}},name:"Settings",icon:o.GEAR,sort_order:99999},n.prototype._setting_update=function(t){if(t||(t=e.event),this.log("Storage Event",t),t.key&&"ffz_setting_"===t.key.substr(0,12)){var o=t.key,i=o.substr(12),r=void 0,s=n.settings_info[i];if(!s){for(i in n.settings_info)if(n.settings_info.hasOwnProperty(i)&&(s=n.settings_info[i],s.storage_key==o))break;if(s.storage_key!=o)return}this.log("Updated Setting: "+i);try{r=JSON.parse(t.newValue)}catch(a){this.log('Error loading new value for "'+i+'": '+a),r=s.value||void 0}if(this.settings[i]=r,s.on_update)try{s.on_update.bind(this)(r,!1)}catch(a){this.log('Error running updater for setting "'+i+'": '+a)}}},n.prototype._setting_get=function(e){return this.settings[e]},n.prototype._setting_set=function(e,t){var o=n.settings_info[e],i=o.storage_key||make_ls(e),r=JSON.stringify(t);if(this.settings[e]=t,localStorage.setItem(i,r),this.log('Changed Setting "'+e+'" to: '+r),o.on_update)try{o.on_update.bind(this)(t,!0)}catch(s){this.log('Error running updater for setting "'+e+'": '+s)}},n.prototype._setting_del=function(e){var t=n.settings_info[e],o=t.storage_key||make_ls(e),i=void 0;if(localStorage.hasOwnProperty(o)&&localStorage.removeItem(o),delete this.settings[e],t&&(i=this.settings[e]=t.hasOwnProperty("value")?t.value:void 0),t.on_update)try{t.on_update.bind(this)(i,!0)}catch(r){this.log('Error running updater for setting "'+e+'": '+r)}}},{"./constants":3}],16:[function(){Array.prototype.equals=function(e){if(!e)return!1;if(this.length!=e.length)return!1;for(var t=0,n=this.length;n>t;t++)if(this[t]instanceof Array&&e[t]instanceof Array){if(!this[t].equals(e[t]))return!1}else if(this[t]!=e[t])return!1;return!0}},{}],17:[function(){var t=e.FrankerFaceZ;t.prototype._ws_open=!1,t.prototype._ws_delay=0,t.ws_commands={},t.ws_on_close=[],t.prototype.ws_create=function(){var e,n=this;this._ws_last_req=0,this._ws_callbacks={},this._ws_pending=this._ws_pending||[];try{e=this._ws_sock=new WebSocket("ws://ffz.stendec.me/")}catch(o){return this._ws_exists=!1,this.log("Error Creating WebSocket: "+o)}this._ws_exists=!0,e.onopen=function(){n._ws_open=!0,n._ws_delay=0,n.log("Socket connected.");var e=n.get_user();e&&n.ws_send("setuser",e.login);for(var t in n.rooms)n.rooms.hasOwnProperty(t)&&n.ws_send("sub",t);var o=n._ws_pending;n._ws_pending=[];for(var i=0;i0){i=!0;break}}var l=document.createElement("div"),c="";c+="

FrankerFaceZ

",c+='
new ways to woof
',l.className="chat-menu-content center",l.innerHTML=c,t.appendChild(l);var u=document.createElement("div"),d=document.createElement("a"),h="To use custom emoticons in "+(i?"this channel":"tons of channels")+", get FrankerFaceZ from http://www.frankerfacez.com";d.className="button primary",d.innerHTML="Advertise in Chat",d.addEventListener("click",this._add_emote.bind(this,e,h)),u.appendChild(d);var m=document.createElement("a");m.className="button ffz-donate",m.href="http://www.frankerfacez.com/donate.html",m.target="_new",m.innerHTML="Donate",u.appendChild(m),u.className="chat-menu-content center",t.appendChild(u);var p=document.createElement("div");c='',c+='',c+='',c+='',c+='',p.className="chat-menu-content center",p.innerHTML=c;var f=!1;p.querySelector("#ffz-debug-logs").addEventListener("click",function(){f||(f=!0,r._pastebin(r._log_data.join("\n"),function(e){f=!1,e?prompt("Your FrankerFaceZ logs have been uploaded to the URL:",e):alert("There was an error uploading the FrankerFaceZ logs.")}))}),t.appendChild(p)}}},{"../constants":3}],19:[function(t){var n=e.FrankerFaceZ,o=t("../constants");n.prototype.setup_menu=function(){this.log("Installing mouse-up event to auto-close menus.");var e=this;jQuery(document).mouseup(function(t){var n,o=e._popup;o&&(o=jQuery(o),n=o.parent(),n.is(t.target)||0!==n.has(t.target).length||(o.remove(),delete e._popup,e._popup_kill&&e._popup_kill(),delete e._popup_kill))})},n.menu_pages={},n.prototype.build_ui_popup=function(e){var t=this._popup;if(t)return t.parentElement.removeChild(t),delete this._popup,this._popup_kill&&this._popup_kill(),void delete this._popup_kill;var i=document.createElement("div"),r=document.createElement("div"),s=document.createElement("ul"),a=this.has_bttv?BetterTTV.settings.get("darkenedMode"):!1;i.className="emoticon-selector chat-menu ffz-ui-popup",r.className="emoticon-selector-box dropmenu",i.appendChild(r),i.classList.toggle("dark",a),s.className="menu clearfix",r.appendChild(s);var l=document.createElement("li");l.className="title",l.innerHTML=""+(o.DEBUG?"[DEV] ":"")+"FrankerFaceZ",s.appendChild(l);var c=document.createElement("div");c.className="ffz-ui-menu-page",r.appendChild(c);var u=[];for(var d in n.menu_pages)if(n.menu_pages.hasOwnProperty(d)){var h=n.menu_pages[d];h&&(!h.hasOwnProperty("visible")||h.visible&&("function"!=typeof h.visible||h.visible.bind(this)()))&&u.push([h.sort_order||0,d,h])}u.sort(function(e,t){if(e[0]t[0])return-1;var n=e[1].toLowerCase(),o=t[1].toLowerCase();return o>n?1:n>o?-1:0});for(var m=0;m0){i=!0;break}}e.classList.toggle("no-emotes",!i),e.classList.toggle("live",a),e.classList.toggle("dark",r),e.classList.toggle("blue",s)}}},{"../constants":3}],21:[function(t){var n=e.FrankerFaceZ,o=t("../constants"),i="http://static-cdn.jtvnw.net/emoticons/v1/",r={"00000turbo":!0},s=function(e){var t=App.__container__.lookup("controller:chat"),n=t.get("currentRoom.id"),o=e.rooms[n],i=o?o.room.tmiSession:null,r=i&&i._emotesParser&&i._emotesParser.emoticonSetIds||"0",s=e.get_user(),a=s&&e.users[s.login]&&e.users[s.login].sets||[];return r=r.split(",").removeObject("0"),[r,a]};n.prototype.setup_my_emotes=function(){if(this._twitch_emote_sets={},this._twitch_set_to_channel={},localStorage.ffzTwitchSets)try{this._twitch_set_to_channel=JSON.parse(localStorage.ffzTwitchSets)}catch(e){}},n.menu_pages.my_emotes={name:"My Emoticons",icon:o.EMOTE,visible:function(){var e=s(this);return e[0].length>0||e[1].length>0},render:function(e,t){var o=s(this),a=this;new RSVP.Promise(function(e){for(var t=[],i=0;i0?(a.ws_send("twitch_sets",t,function(e,n){if(t=[],e){for(var o in n)n.hasOwnProperty(o)&&(a._twitch_set_to_channel[o]=n[o],s(o,n[o]));localStorage.ffzTwitchSets=JSON.stringify(a._twitch_set_to_channel)}l()}),setTimeout(function(){t.length&&l()},5e3)):l()})]).then(function(){for(var t={},n=0;nt[0])return 1;var n=e[1].toLowerCase(),o=t[1].toLowerCase();return"twitch turbo"===n&&(n="zzz"+n),"twitch turbo"===o&&(o="zzz"+o),o>n?-1:n>o?1:0});for(var c=0;c'+l.source+""+n.get_capitalization(l.channel),l.badge&&(u.style.backgroundImage='url("'+l.badge+'")'),d.className="emoticon-grid",d.appendChild(u);for(var h=0;hSpeedRunsLive races under channels.',on_update:function(){this.rebuild_race_ui()}},n.ws_on_close.push(function(){var e=App.__container__.lookup("controller:channel"),t=e.get("id"),n=!1;for(var o in this.srl_races)delete this.srl_races[o],o==t&&(n=!0);n&&this.rebuild_race_ui()}),n.ws_commands.srl_race=function(e){for(var t=App.__container__.lookup("controller:channel"),n=t.get("id"),o=!1,i=0;i=300?"right":"left")+" share dropmenu",this._popup_kill=this._race_kill.bind(this),this._popup=e;var l="http://kadgar.net/live",c=!1;for(var u in s.entrants){var d=s.entrants[u].state;s.entrants.hasOwnProperty(u)&&s.entrants[u].channel&&("racing"==d||"entered"==d)&&(l+="/"+s.entrants[u].channel,c=!0)}var h=document.querySelector(".app-main.theatre")?document.body.clientHeight-300:t.parentElement.offsetTop-175,m=App.__container__.lookup("controller:channel"),p=m?m.get("display_name"):n.get_capitalization(r),f=encodeURIComponent("I'm watching "+p+" race "+s.goal+" in "+s.game+" on SpeedRunsLive!");a='
',a+='
Developers
Dan Salvato  
Stendec  
Version '+n.version_info+'Logs
',a+="
#Entrant Time
",a+='
',a+='',a+='

SRL',c&&(a+='   Multitwitch'),a+="

",e.innerHTML=a,t.appendChild(e),this._update_race(!0)}}},n.prototype._update_race=function(e){this._race_timer&&e&&(clearTimeout(this._race_timer),delete this._race_timer);var t=document.querySelector("#ffz-ui-race");if(t){var n=t.getAttribute("data-channel"),i=this.srl_races[n];if(!i)return t.parentElement.removeChild(t),this._popup_kill&&this._popup_kill(),void(this._popup&&(delete this._popup,delete this._popup_kill));var r=i.twitch_entrants[n],s=i.entrants[r],a=t.querySelector("#ffz-race-popup"),l=Date.now()/1e3,c=Math.floor(l-i.time);if(t.querySelector(".logo").innerHTML=o.placement(s),a){var u=a.querySelector("tbody"),d=a.querySelector(".heading span"),h=a.querySelector(".heading div");u.innerHTML="";var m=[],p=!0;for(var f in i.entrants)i.entrants.hasOwnProperty(f)&&("racing"==i.entrants[f].state&&(p=!1),m.push(i.entrants[f]));m.sort(function(e,t){var n=e.place||9999,o=t.place||9999,i=e.time||c,r=t.time||c;return("forfeit"==e.state||"dq"==e.state)&&(n=1e4),("forfeit"==t.state||"dq"==t.state)&&(o=1e4),o>n?-1:n>o?1:e.namet.name?1:r>i?-1:i>r?1:void 0});for(var _=0;_'+f.display_name+"",v=f.channel?'':"",b=f.hitbox?'':"",y=c?o.time_to_string(f.time||c):"",w=o.place_string(f.place),F=f.comment?o.sanitize(f.comment):"";u.innerHTML+="'+w+""+g+""+v+b+''+("forfeit"==f.state?"Forfeit":y)+""}if(this._race_game!=i.game||this._race_goal!=i.goal){this._race_game=i.game,this._race_goal=i.goal;var k=o.sanitize(i.game),E=o.sanitize(i.goal);h.innerHTML='

'+k+"

Goal: "+E}c?p?d.innerHTML="Done":(d.innerHTML=o.time_to_string(c),this._race_timer=setTimeout(this._update_race.bind(this),1e3)):d.innerHTML="Entry Open"}}}},{"../utils":26}],24:[function(t){var n=e.FrankerFaceZ,o=t("../constants");n.prototype.setup_css=function(){this.log("Injecting main FrankerFaceZ CSS.");var e=this._main_style=document.createElement("link");e.id="ffz-ui-css",e.setAttribute("rel","stylesheet"),e.setAttribute("href",o.SERVER+"script/style.css?_="+Date.now()),document.head.appendChild(e),jQuery.noty.themes.ffzTheme={name:"ffzTheme",style:function(){this.$bar.removeClass().addClass("noty_bar").addClass("ffz-noty").addClass(this.options.type)},callback:{onShow:function(){},onClose:function(){}}}}},{"../constants":3}],25:[function(t){var n=e.FrankerFaceZ,o=t("../constants"),i=t("../utils");n.ws_commands.viewers=function(e){var t=e[0],n=e[1],r=App.__container__.lookup("controller:channel"),s=r&&r.get&&r.get("id");if(s===t){var a=document.querySelector(".channel-stats .ffz.stat"),l=o.ZREKNARF+" "+i.number_commas(n);if(a)a.innerHTML=l;else{var c=document.querySelector(".channel-stats");if(!c)return;a=document.createElement("span"),a.className="ffz stat",a.title="Viewers with FrankerFaceZ",a.innerHTML=l,c.appendChild(a),jQuery(a).tipsy()}}}},{"../constants":3,"../utils":26}],26:[function(t,n){var o=(e.FrankerFaceZ,t("./constants"),{}),i=document.createElement("span"),r=function(e){return 1==e?"1st":2==e?"2nd":3==e?"3rd":null==e?"---":e+"th"},s=function(e,t){t=0===t?0:t||1,t=Math.round(255*-(t/100));var n=Math.max(0,Math.min(255,e[0]-t)),o=Math.max(0,Math.min(255,e[1]-t)),i=Math.max(0,Math.min(255,e[2]-t));return[n,o,i]},a=function(e){return"rgb("+e[0]+", "+e[1]+", "+e[2]+")"},l=function(e,t){return t=0===t?0:t||1,s(e,-t)},c=function(e){e=[e[0]/255,e[1]/255,e[2]/255];for(var t=0;ts;(l||n)&&(l&&(o=o.substr(0,s)+o.substr(a+r.length)),n&&(o+=i+n+r),e.innerHTML=o)},get_luminance:c,brighten:s,darken:l,rgb_to_css:a,number_commas:function(e){var t=e.toString().split(".");return t[0]=t[0].replace(/\B(?=(\d{3})+(?!\d))/g,","),t.join(".")},place_string:r,placement:function(e){return"forfeit"==e.state?"Forfeit":"dq"==e.state?"DQed":e.place?r(e.place):""},sanitize:function(e){var t=o[e];return t||(i.textContent=e,t=o[e]=i.innerHTML,i.innerHTML=""),t},time_to_string:function(e){var t=e%60,n=Math.floor(e/60),o=Math.floor(n/60);return n%=60,(10>o?"0":"")+o+":"+(10>n?"0":"")+n+":"+(10>t?"0":"")+t}}},{"./constants":3}]},{},[13]),e.ffz=new FrankerFaceZ}(window);