!function(e){!function t(e,n,i){function o(r,a){if(!n[r]){if(!e[r]){var c="function"==typeof require&&require;if(!a&&c)return c(r,!0);if(s)return s(r,!0);throw new Error("Cannot find module '"+r+"'")}var l=n[r]={exports:{}};e[r][0].call(l.exports,function(t){var n=e[r][1][t];return o(n?n:t)},l,l.exports,t,e,n,i)}return n[r].exports}for(var s="function"==typeof require&&require,r=0;re?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+/),i=0;i50)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 i=t.length;t.length;){var o=t.shift();e.room.tmiRoom.sendMessage("/unmod "+o)}return"Sent unmod command for "+i+" 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 i=t.length;t.length;){var o=t.shift();e.room.tmiRoom.sendMessage("/mod "+o)}return"Sent mod command for "+i+" 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='',i="true"==localStorage.ffzDebugMode&&document.body.classList.contains("ffz-dev");t.exports={DEBUG:i,SERVER:i?"//localhost:8000/":"//cdn.frankerfacez.com/",SVGPATH:n,ZREKNARF:''+n+"",CHAT_BUTTON:''+n+"",GEAR:'',HEART:''}},{}],4:[function(){var t=e.FrankerFaceZ;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 "+("true"==localStorage.ffzDebugMode?"enabled.":"disabled."):(localStorage.ffzDebugMode=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),e.create().destroy();for(var t in Ember.View.views)if(Ember.View.views.hasOwnProperty(t)){var n=Ember.View.views[t];if(n instanceof e){this.log("Adding UI link manually to Chat view.",n);try{n.$(".textarea-contain").append(this.build_ui_link(n))}catch(i){this.error("setup: build_ui_link: "+i)}}}},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,i=t("../utils"),o=function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")};n.settings_info.capitalize={type:"boolean",value:!0,category:"Chat",visible:function(){return!this.has_bttv},name:"Username Capitalization",help:"Display names in chat with proper capitalization."},n.settings_info.keywords={type:"button",value:[],category:"Chat",visible:function(){return!this.has_bttv},name:"Highlight Keywords",help:"Set additional keywords that will be highlighted in chat.",method:function(){var e=this.settings.keywords.join(", "),t=prompt("Highlight Keywords\n\nPlease enter a comma-separated list of words that you would like to be highlighted in chat.",e);null!==t&&void 0!==t&&(t=t.trim().split(/\W*,\W*/),1!=t.length||""!=t[0]&&"disable"!=t[0]||(t=[]),this.settings.set("keywords",t))}},n.settings_info.fix_color={type:"boolean",value:!1,category:"Chat",visible:function(){return!this.has_bttv},name:"Adjust Username Colors",help:"Ensure that username colors contrast with the background enough to be readable.",on_update:function(e){this.has_bttv||document.body.classList.toggle("ffz-chat-colors",e)}},n.settings_info.chat_rows={type:"boolean",value:!1,category:"Chat",visible:function(){return!this.has_bttv},name:"Chat Line Backgrounds",help:"Display alternating background colors for lines in chat.",on_update:function(e){this.has_bttv||document.body.classList.toggle("ffz-chat-background",e)}},n.prototype.setup_line=function(){document.body.classList.toggle("ffz-chat-colors",!this.has_bttv&&this.settings.fix_color),document.body.classList.toggle("ffz-chat-background",!this.has_bttv&&this.settings.chat_rows),this._colors={},this._last_row={};var t=this._fix_color_style=document.createElement("style");t.id="ffz-style-username-colors",t.type="text/css",document.head.appendChild(t),this.log("Hooking the Ember Line controller.");var i=App.__container__.resolve("controller:line"),o=this;i.reopen({tokenizedMessage:function(){var e=this._super();try{e=o._emoticonize(this,e);var t=o.get_user();t&&this.get("model.from")==t.login||(e=o._mentionize(this,e))}catch(n){try{o.error("LineController tokenizedMessage: "+n)}catch(n){}}return e}.property("model.message","isModeratorOrHigher")}),this.log("Hooking the Ember Line view.");var i=App.__container__.resolve("view:line");i.reopen({didInsertElement:function(){this._super();try{var t=this.get("element"),i=this.get("context.model.from"),s=this.get("context.parentController.content.id"),r=this.get("context.model.color"),a=this.get("context.model.ffz_alternate");r&&o._handle_color(r),void 0===a&&(a=o._last_row[s]=o._last_row.hasOwnProperty(s)?!o._last_row[s]:!1,this.set("context.model.ffz_alternate",a)),t.classList.toggle("ffz-alternate",a),t.setAttribute("data-room",s),t.setAttribute("data-sender",i),o.render_badge(this),o.settings.capitalize&&o.capitalize(this,i);var c=t.querySelector("span.mentioned");if(c&&(t.classList.add("ffz-mentioned"),!document.hasFocus()&&!this.get("context.model.ffz_notified")&&o.settings.highlight_notifications)){var l=n.get_capitalization(s),d=n.get_capitalization(i),u=l,h=this.get("context.model.message");this.get("context.parentController.content.isGroupRoom")&&(u=this.get("context.parentController.content.tmiRoom.displayName")),h="action"==this.get("context.model.style")?"* "+d+" "+h:d+": "+h,o.show_notification(h,"Twitch Chat Mention in "+u,l,6e4,e.focus.bind(e))}this.set("context.model.ffz_notified",!0)}catch(p){try{o.error("LineView didInsertElement: "+p)}catch(p){}}}});var s=this.get_user();s&&s.name&&(n.capitalization[s.login]=[s.name,Date.now()])},n.prototype._handle_color=function(e){if(e&&!this._colors[e]){this._colors[e]=!0;var t=parseInt(e.substr(1),16),n=[t>>16,t>>8&255,255&t],o=i.get_luminance(n),s="",r='span[style="color:'+e+'"]',a=!1;if(o>.3){a=!0;for(var c=255,l=n;c--&&(l=i.darken(l),!(i.get_luminance(l)<=.3)););s+=".ffz-chat-colors .ember-chat-container:not(.dark) .chat-line "+r+", .ffz-chat-colors .chat-container:not(.dark) .chat-line "+r+" { color: "+i.rgb_to_css(l)+" !important; }\n"}else s+=".ffz-chat-colors .ember-chat-container:not(.dark) .chat-line "+r+", .ffz-chat-colors .chat-container:not(.dark) .chat-line "+r+" { color: "+e+" !important; }\n";if(.1>o){a=!0;for(var c=255,l=n;c--&&(l=i.brighten(l),!(i.get_luminance(l)>=.1)););s+=".ffz-chat-colors .theatre .chat-container .chat-line "+r+", .ffz-chat-colors .chat-container.dark .chat-line "+r+", .ffz-chat-colors .ember-chat-container.dark .chat-line "+r+" { color: "+i.rgb_to_css(l)+" !important; }\n"}else s+=".ffz-chat-colors .theatre .chat-container .chat-line "+r+", .ffz-chat-colors .chat-container.dark .chat-line "+r+", .ffz-chat-colors .ember-chat-container.dark .chat-line "+r+" { color: "+e+" !important; }\n";a&&(this._fix_color_style.innerHTML+=s)}},n.capitalization={},n._cap_fetching=0,n.get_capitalization=function(t,i){if(e.BetterTTV)return BetterTTV.chat.helpers.lookupDisplayName(t);if(!t)return t;if(t=t.toLowerCase(),"jtv"==t||"twitchnotify"==t)return t;var o=n.capitalization[t];return o&&Date.now()-o[1]<36e5?o[0]:(n._cap_fetching<5&&(n._cap_fetching++,Twitch.api.get("users/"+t).always(function(e){var o=e.display_name||t;n.capitalization[t]=[o,Date.now()],n._cap_fetching--,"function"==typeof i&&i(o)})),o?o[0]:t)},n.prototype.capitalize=function(e,t){var i=n.get_capitalization(t,this.capitalize.bind(this,e));i&&e.$(".from").text(i)},n._regex_cache={},n._get_regex=function(e){return n._regex_cache[e]=n._regex_cache[e]||RegExp("\\b"+o(e)+"\\b","ig")},n._mentions_to_regex=function(e){return n._regex_cache[e]=n._regex_cache[e]||RegExp("\\b(?:"+_.chain(e).map(o).value().join("|")+")\\b","ig")},n.prototype._mentionize=function(e,t){var i=this.settings.keywords;if(!i||!i.length)return t;"string"==typeof t&&(t=[t]);var o=n._mentions_to_regex(i);return _.chain(t).map(function(e){return _.isString(e)?e.match(o)?_.zip(_.map(e.split(o),_.identity),_.map(e.match(o),function(e){return{mentionedUser:e,own:!1}})):[e]:e}).flatten().compact().value()},n.prototype._emoticonize=function(e,t){var n=e.get("parentController.model.id"),i=e.get("model.from"),o=this,s=this.getEmotes(i,n),r=[];return _.each(s,function(e){var n=o.emote_sets[e];n&&_.each(n.emotes,function(e){_.any(t,function(t){return _.isString(t)&&t.match(e.regex)})&&r.push(e)})}),r.length?("string"==typeof t&&(t=[t]),_.each(r,function(e){var n={isEmoticon:!0,cls:e.klass,emoticonSrc:e.url,altText:e.hidden?"???":e.name};t=_.compact(_.flatten(_.map(t,function(t){if(_.isObject(t))return t;var i=t.split(e.regex),o=[];return i.forEach(function(e,t){o.push(e),t!==i.length-1&&o.push(n)}),o})))}),t):t}},{"../utils":24}],7:[function(t){var n=e.FrankerFaceZ,i=t("../utils"),o={ESC:27,P:80,B:66,T:84},s=[["5m",300],["10m",600],["1hr",3600],["12hr",43200],["24hr",86400]],r='';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 moderator, 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.settings.enhanced_moderation)return;var e=this.get("element"),n=this.get("context");if(n.get("parentController.model.isModeratorOrHigher")){e.classList.add("ffz-moderation-card"),e.setAttribute("tabindex",1),e.addEventListener("keyup",function(e){var t=e.keyCode||e.which,i=n.get("model.user.id"),s=n.get("parentController.model");if(t==o.P)s.send("/timeout "+i+" 1");else if(t==o.B)s.send("/ban "+i);else if(t==o.T)s.send("/timeout "+i+" 600");else if(t!=o.ESC)return;n.send("hideModOverlay")});var a=document.createElement("div");a.className="interface clearfix";var c=function(e){var t=n.get("model.user.id"),i=n.get("parentController.model");i.send(-1===e?"/unban "+t:"/timeout "+t+" "+e)},l=function(e,t){var n=document.createElement("button");return n.className="button",n.innerHTML=e,n.title="Timeout User for "+i.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};a.appendChild(l("Purge",1));var d=document.createElement("span");d.className="right",a.appendChild(d);for(var u=0;u button");g&&"button"==g.className&&(g.innerHTML=r,g.classList.add("glyph-only"),g.classList.add("message"),g.title="Message User",jQuery(g).tipsy()),this.$().draggable({start:function(){e.focus()}}),e.focus()}catch(v){try{t.error("ModerationCardView didInsertElement: "+v)}catch(v){}}}})},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 r=e,a=r.match(s);a&&a[1]&&(r=a[1]);var c={id:e,menu_sets:[r],sets:[r],moderator_badge:null,css:null};return n&&(n=n.replace(i,"").trim()),n&&(n=n.replace(o,function(e,t){return c.moderator_badge||"modicon.png"!==t.substr(-11)?e:(c.moderator_badge=t,"")})),c.css=n||null,this._load_room_json(e,t,c)}},{"../constants":3,"../utils":24}],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 i=[],o={},s=null,r=App.__container__.lookup("controller:channel"),a=this.get("parentController.model.id"),c=r&&r.get("id");if(c){var l=r.get("display_name");l&&(t.capitalization[c]=[l,Date.now()])}a!=c&&(c=null);for(var d=0;dn?this._legacy_load_set(e,t,n):"function"==typeof t&&t(!1))})},n.prototype._legacy_load_css=function(e,t,n){var s={},r={id:e,emotes:s,extra_css:null},a=this;n=n.replace(i,function(e,t,n,i,o,r,l,d){o=parseInt(o),r=parseInt(r),l=c(l,o);var u="."===i.substr(i.lastIndexOf("/")+1,1),h=++a._last_emote_id,p={id:h,hidden:u,name:n,height:o,width:r,url:i,margins:l,extra_css:d};return s[h]=p,""}).trim(),n&&n.replace(o,function(e,t){r.icon||"modicon.png"!==t.substr(-11)||(r.icon=t)}),this._load_set_json(e,t,r)}},{"./constants":3,"./utils":24}],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,i=this;BetterTTV.chat.helpers.sendMessage=function(e){var n=e.split(" ",1)[0].toLowerCase();return"/ffz"!==n?t(e):void i.run_ffz_command(e.substr(5),BetterTTV.chat.store.currentRoom)};var o,s=BetterTTV.chat.handlers.privmsg;BetterTTV.chat.handlers.privmsg=function(e,t){o=e;var n=s(e,t);return o=null,n};var r=BetterTTV.chat.templates.privmsg;BetterTTV.chat.templates.privmsg=function(e,t,s,a,c){i.bttv_badges(c);var l=r(e,t,s,a,c);return l.replace(n,'$1 data-room="'+o+'"')};var a,c=BetterTTV.chat.templates.message;BetterTTV.chat.templates.message=function(e,t,n,i){a=e;var o=c(e,t,n,i);return a=null,o};var l=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(e,t){var n=l(e,t),s=i.getEmotes(a,o),t=[];return _.each(s,function(e){var o=i.emote_sets[e];o&&_.each(o.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+''],i=n;if(n=[],!i||!i.length)return n;for(var o=0;o=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,i=App.__container__.lookup("controller:chat"),o=i?i.get("currentRoom.id"):null,s=this.getEmotes(n,o),r=[],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 i=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_races(),this.find_bttv(10),this.find_emote_menu(10),this.check_ff();var o=e.performance&&performance.now?performance.now():Date.now(),s=o-i;this.log("Initialization complete in "+s+"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/menu":18,"./ui/menu_button":19,"./ui/notifications":20,"./ui/races":21,"./ui/styles":22,"./ui/viewer_count":23}],14:[function(t){var n=e.FrankerFaceZ,i=t("./constants");n.prototype.feature_friday=null,n.prototype.check_ff=function(e){e||this.log("Checking for Feature Friday data..."),jQuery.ajax(i.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 i=App.__container__.lookup("controller:channel");if(!i||i.get("id")!=this.feature_friday.channel){var o=this.feature_friday,s=document.createElement("div"),r=document.createElement("a");s.className="chat-menu-content",s.style.textAlign="center";var a=o.display_name+(o.live?" is live now!":"");r.className="button primary",r.classList.toggle("live",o.live),r.classList.toggle("blue",this.has_bttv&&BetterTTV.settings.get("showBlueButtons")),r.href="http://www.twitch.tv/"+o.channel,r.title=a,r.target="_new",r.innerHTML=""+a+"",s.appendChild(r),t.appendChild(s)}}},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(){var t=e.FrankerFaceZ,n=function(e){return"ffz_setting_"+e};t.settings_info={},t.prototype.load_settings=function(){this.log("Loading settings."),this.settings={};for(var i in t.settings_info){var o=n(i),s=t.settings_info[i],r=s.hasOwnProperty("value")?s.value:void 0;if(localStorage.hasOwnProperty(o))try{r=JSON.parse(localStorage.getItem(o))}catch(a){this.log('Error loading value for "'+i+'": '+a)}this.settings[i]=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))},t.prototype._setting_update=function(n){if(n||(n=e.event),this.log("Storage Event",n),n.key&&"ffz_setting_"===n.key.substr(0,12)){var i=n.key,o=i.substr(12),s=void 0,r=t.settings_info[o];this.log("Updated Setting: "+o);try{s=JSON.parse(n.newValue)}catch(a){this.log('Error loading new value for "'+o+'": '+a),s=r.value||void 0}if(this.settings[o]=s,r.on_update)try{r.on_update.bind(this)(s,!1)}catch(a){this.log('Error running updater for setting "'+o+'": '+a)}}},t.prototype._setting_get=function(e){return this.settings[e]},t.prototype._setting_set=function(e,i){var o=n(e),s=t.settings_info[e],r=JSON.stringify(i);if(this.settings[e]=i,localStorage.setItem(o,r),this.log('Changed Setting "'+e+'" to: '+r),s.on_update)try{s.on_update.bind(this)(i,!0)}catch(a){this.log('Error running updater for setting "'+e+'": '+a)}},t.prototype._setting_del=function(e){var i=n(e),o=t.settings_info[e],s=void 0;if(localStorage.hasOwnProperty(i)&&localStorage.removeItem(i),delete this.settings[e],o&&(s=this.settings[e]=o.hasOwnProperty("value")?o.value:void 0),o.on_update)try{o.on_update.bind(this)(s,!0)}catch(r){this.log('Error running updater for setting "'+e+'": '+r)}}},{}],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(i){return this._ws_exists=!1,this.log("Error Creating WebSocket: "+i)}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.ws_send("sub",t);var i=n._ws_pending;n._ws_pending=[];for(var o=0;oFrankerFaceZ",s.appendChild(a),a.addEventListener("click",this._add_emote.bind(this,e,"To use custom emoticons in tons of channels, get FrankerFaceZ from http://www.frankerfacez.com"));var c=document.createElement("div");c.className="ffz-ui-menu-page",o.appendChild(c);for(var l in n.menu_pages){var d=n.menu_pages[l];if(d&&(!d.hasOwnProperty("visible")||d.visible&&("function"!=typeof d.visible||d.visible.bind(this)()))){var a=document.createElement("li"),u=document.createElement("a");a.className="item",a.id="ffz-menu-page-"+l,u.title=d.name,u.innerHTML=d.icon,u.addEventListener("click",this._ui_change_page.bind(this,e,s,c,l)),a.appendChild(u),s.appendChild(a)}}this._ui_change_page(e,s,c,this._last_page||"channel"),this._popup=i,c.style.maxHeight=Math.max(100,e.$().height()-162)+"px",e.$(".chat-interface").append(i)},n.prototype._ui_change_page=function(e,t,i,o){this._last_page=o,i.innerHTML="";for(var s=t.querySelectorAll("li.active"),r=0;re?-1:e>t?1:0});for(var d=0;do?-1:o>s?1:0});for(var f=0;f",b.className="switch-label",b.innerHTML=r.name,m.appendChild(v),m.appendChild(b),v.addEventListener("click",this._ui_toggle_setting.bind(this,v,s))}else{m.classList.add("option");var y=document.createElement("a");y.innerHTML=r.name,y.href="#",m.appendChild(y),y.addEventListener("click",r.method.bind(this))}if(r.help){var w=document.createElement("span");w.className="help",w.innerHTML=r.help,m.appendChild(w)}p.appendChild(m)}t.appendChild(p)}},name:"Settings",icon:i.GEAR},n.prototype._ui_toggle_setting=function(e,t){var n=!this.settings.get(t);this.settings.set(t,n),e.classList.toggle("active",n)},n.menu_pages.channel={render:function(e,t){{var n=e.get("controller.currentRoom.id"),i=this.rooms[n];this._emotes_for_sets(t,e,i&&i.menu_sets||[])}this._feature_friday_ui(n,t,e)},name:"Channel",icon:i.ZREKNARF},n.prototype._emotes_for_sets=function(e,t,n,i,o){if(null!=i){var s=document.createElement("div");s.className="list-header",s.appendChild(document.createTextNode(i)),o&&s.appendChild(o),e.appendChild(s)}var r=document.createElement("div"),a=0;r.className="emoticon-grid";for(var c=0;c0){o=!0;break}}e.classList.toggle("no-emotes",!o),e.classList.toggle("live",a),e.classList.toggle("dark",s),e.classList.toggle("blue",r)}}},{"../constants":3}],20:[function(){var t=e.FrankerFaceZ;t.prototype.setup_notifications=function(){this.log("Adding event handler for window focus."),e.addEventListener("focus",this.clear_notifications.bind(this))},t.settings_info.highlight_notifications={type:"boolean",value:!1,category:"Chat",visible:function(){return!this.has_bttv},name:"Highlight Notifications",help:"Display notifications when a highlighted word appears in chat in an unfocused tab.",on_update:function(e,t){if(e&&t){if("denied"===Notification.permission)return this.log("Notifications have been denied by the user."),void this.settings.set("highlight_notifications",!1);if("granted"!==Notification.permission){var n=this;Notification.requestPermission(function(e){"denied"===e&&(n.log("Notifications have been denied by the user."),n.settings.set("highlight_notifications",!1))})}}}},t.ws_commands.message=function(e){this.show_message(e)},t._notifications={},t._last_notification=0,t.prototype.clear_notifications=function(){for(var e in t._notifications){var n=t._notifications[e];if(n)try{n.close()}catch(i){}}t._notifications={},t._last_notification=0},t.prototype.show_notification=function(e,n,i,o,s,r){var a=Notification.permission;if("denied "===a)return!1;if("granted"===a){n=n||"FrankerFaceZ",o=o||1e4;var c={lang:"en-US",dir:"ltr",body:e,tag:i||"FrankerFaceZ",icon:"http://cdn.frankerfacez.com/icon32.png"},l=this,d=new Notification(n,c),u=t._last_notification++;return t._notifications[u]=d,d.addEventListener("click",function(){delete t._notifications[u],s&&s.bind(l)()}),d.addEventListener("close",function(){delete t._notifications[u],r&&r.bind(l)()}),void("number"==typeof o&&d.addEventListener("show",function(){setTimeout(function(){delete t._notifications[u],d.close()},o)}))}var l=this;Notification.requestPermission(function(){l.show_notification(e,n,i)})},t.prototype.show_message=function(t){e.noty({text:t,theme:"ffzTheme",layout:"bottomCenter",closeWith:["button"]}).show()}},{}],21:[function(t){var n=e.FrankerFaceZ,i=t("../utils");n.prototype.setup_races=function(){this.log("Initializing race support."),this.srl_races={}},n.settings_info.srl_races={type:"boolean",value:!0,category:"Channel Metadata",name:"SRL Race Information",help:'Display information about SpeedRunsLive 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 i in this.srl_races)delete this.srl_races[i],i==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"),i=!1,o=0;o=300?"right":"left")+" share dropmenu",this._popup_kill=this._race_kill.bind(this),this._popup=e;var c="http://kadgar.net/live",l=!1;for(var d in r.entrants){var u=r.entrants[d].state;r.entrants.hasOwnProperty(d)&&r.entrants[d].channel&&("racing"==u||"entered"==u)&&(c+="/"+r.entrants[d].channel,l=!0)}var h=document.querySelector(".app-main.theatre")?document.body.clientHeight-300:t.parentElement.offsetTop-175,p=App.__container__.lookup("controller:channel"),_=p?p.get("display_name"):n.get_capitalization(s),f=encodeURIComponent("I'm watching "+_+" race "+r.goal+" in "+r.game+" on SpeedRunsLive!");a='
',a+='
',a+="
#Entrant Time
",a+='
',a+='',a+='

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

'+x+"

Goal: "+z}l?_?u.innerHTML="Done":(u.innerHTML=i.time_to_string(l),this._race_timer=setTimeout(this._update_race.bind(this),1e3)):u.innerHTML="Entry Open"}}}},{"../utils":24}],22:[function(t){var n=e.FrankerFaceZ,i=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",i.SERVER+"script/style.css"),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}],23:[function(t){var n=e.FrankerFaceZ,i=t("../constants"),o=t("../utils");n.ws_commands.viewers=function(e){var t=e[0],n=e[1],s=App.__container__.lookup("controller:channel"),r=s&&s.get&&s.get("id");if(r===t){var a=document.querySelector(".channel-stats .ffz.stat"),c=i.ZREKNARF+" "+o.number_commas(n);if(a)a.innerHTML=c;else{var l=document.querySelector(".channel-stats");if(!l)return;a=document.createElement("span"),a.className="ffz stat",a.title="Viewers with FrankerFaceZ",a.innerHTML=c,l.appendChild(a),jQuery(a).tipsy()}}}},{"../constants":3,"../utils":24}],24:[function(t,n){var i=(e.FrankerFaceZ,t("./constants"),{}),o=document.createElement("span"),s=function(e){return 1==e?"1st":2==e?"2nd":3==e?"3rd":null==e?"---":e+"th"},r=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)),i=Math.max(0,Math.min(255,e[1]-t)),o=Math.max(0,Math.min(255,e[2]-t));return[n,i,o]},a=function(e){return"rgb("+e[0]+", "+e[1]+", "+e[2]+")"},c=function(e,t){return t=0===t?0:t||1,r(e,-t)},l=function(e){e=[e[0]/255,e[1]/255,e[2]/255];for(var t=0;tr;(c||n)&&(c&&(i=i.substr(0,r)+i.substr(a+s.length)),n&&(i+=o+n+s),e.innerHTML=i)},get_luminance:l,brighten:r,darken:c,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:s,placement:function(e){return"forfeit"==e.state?"Forfeit":"dq"==e.state?"DQed":e.place?s(e.place):""},sanitize:function(e){var t=i[e];return t||(o.textContent=e,t=i[e]=o.innerHTML,o.innerHTML=""),t},time_to_string:function(e){var t=e%60,n=Math.floor(e/60),i=Math.floor(n/60);return n%=60,(10>i?"0":"")+i+":"+(10>n?"0":"")+n+":"+(10>t?"0":"")+t}}},{"./constants":3}]},{},[13]),e.ffz=new FrankerFaceZ}(window);