=6e4?this.log("BetterTTV was not detected after 60 seconds."):setTimeout(this.find_bttv.bind(this,e,(s||0)+e),e))},s.prototype.setup_bttv=function(t){this.log("BetterTTV was detected after "+t+"ms. Hooking."),this.has_bttv=!0,document.body.classList.remove("ffz-dark"),this._dark_style&&(this._dark_style.parentElement.removeChild(this._dark_style),this._dark_style=void 0),this._layout_style&&(this._layout_style.parentElement.removeChild(this._layout_style),this._layout_style=void 0),this._chat_style&&(n.update_css(this._chat_style,"chat_font_size",""),n.update_css(this._chat_style,"chat_ts_font_size","")),this.settings.group_tabs&&this._chatv&&this._chatv.ffzDisableTabs(),this._roomv&&(this.settings.chat_hover_pause&&this._roomv.ffzDisableFreeze(),this.settings.room_status&&this._roomv.ffzUpdateStatus()),document.body.classList.remove("ffz-chat-colors"),document.body.classList.remove("ffz-chat-colors-gray"),document.body.classList.remove("ffz-chat-background"),document.body.classList.remove("ffz-chat-padding"),document.body.classList.remove("ffz-chat-separator"),document.body.classList.remove("ffz-chat-separator-3d"),document.body.classList.remove("ffz-sidebar-swap"),document.body.classList.remove("ffz-transparent-badges"),document.body.classList.remove("ffz-high-contrast-chat-text"),document.body.classList.remove("ffz-high-contrast-chat-bg"),document.body.classList.remove("ffz-high-contrast-chat-bold"),this.settings.following_count&&(this._schedule_following_count(),this._draw_following_count(),this._draw_following_channels()),this.is_dashboard&&this._update_subscribers(),document.body.classList.add("ffz-bttv");var e=BetterTTV.chat.helpers.sendMessage,s=this;BetterTTV.chat.helpers.sendMessage=function(t){var n=t.split(" ",1)[0].toLowerCase();return"/ffz"!==n?e(t):void s.run_ffz_command(t.substr(5),BetterTTV.chat.store.currentRoom)};var i,o=BetterTTV.chat.handlers.onPrivmsg;BetterTTV.chat.handlers.onPrivmsg=function(t,e){i=t;var s=o(t,e);return i=null,s};var a=BetterTTV.chat.templates.privmsg;BetterTTV.chat.templates.privmsg=function(t,e,n,o,r){try{return s.bttv_badges(r),''+BetterTTV.chat.templates.timestamp(r.time)+" "+(o?BetterTTV.chat.templates.modicons():"")+" "+BetterTTV.chat.templates.badges(r.badges)+BetterTTV.chat.templates.from(r.nickname,r.color)+BetterTTV.chat.templates.message(r.sender,r.message,r.emotes,e?r.color:!1)+"
"}catch(d){return s.log("Error: ",d),a(t,e,n,o,r)}};var r=BetterTTV.chat.templates.whisper;BetterTTV.chat.templates.whisper=function(t){try{return s.bttv_badges(t),''+BetterTTV.chat.templates.timestamp(t.time)+" "+(t.badges&&t.badges.length?BetterTTV.chat.templates.badges(t.badges):"")+BetterTTV.chat.templates.whisperName(t.sender,t.receiver,t.from,t.to,t.fromColor,t.toColor)+BetterTTV.chat.templates.message(t.sender,t.message,t.emotes,!1)+"
"}catch(e){return s.log("Error: ",e),r(t)}};var d,u=BetterTTV.chat.templates.message;BetterTTV.chat.templates.message=function(t,e,n,i){try{i=i||!1;var o=encodeURIComponent(e);if("jtv"!==t){d=t;var a=BetterTTV.chat.templates.emoticonize(e,n);d=null;for(var r=0;r'+e+""}catch(c){return s.log("Error: ",c),u(t,e,n,i)}};var c=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(t,e){var n=c(t,e),o=i||BetterTTV.getChannel(),a=o&&o.toLowerCase(),r=d&&d.toLowerCase(),u=s.getEmotes(r,a),e=[],l=s.get_user(),h=l&&l.login===r;return _.each(u,function(t){var i=s.emote_sets[t];i&&_.each(i.emoticons,function(t){_.any(n,function(e){return _.isString(e)&&e.match(t.regex)})&&e.push(t)})}),e.length&&_.each(e,function(t){var e=s._emote_tooltip(t),i=['
'],o=n;n=[];for(var r=0;r=6e4?this.log("Emote Menu for Twitch was not detected after 60 seconds."):setTimeout(this.find_emote_menu.bind(this,e,(s||0)+e),e))},e.prototype.setup_emote_menu=function(t){this.log("Emote Menu for Twitch was detected after "+t+"ms. Registering emote enumerator."),emoteMenu.registerEmoteGetter("FrankerFaceZ",this._emote_menu_enumerator.bind(this))},e.prototype._emote_menu_enumerator=function(){for(var t=this.get_user(),e=t?t.login:null,s=App.__container__.lookup("controller:chat"),n=s?s.get("currentRoom.id"):null,i=this.getEmotes(e,n),o=[],a=0;a=6e4?this.log('Twitch application not detected in "'+location.toString()+'". Aborting.'):setTimeout(this.initialize.bind(this,e,(s||0)+e),e)))}},s.prototype.init_player=function(e){var n=t.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch Player after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!1;try{this.embed_in_dash=t.top!==t&&/\/[^\/]+\/dashboard/.test(t.top.location.pathname)&&!/bookmarks$/.test(t.top.location.pathname)}catch(i){this.embed_in_dash=!1}this.load_settings(),this.setup_dark();var o=t.performance&&performance.now?performance.now():Date.now(),a=o-n;this.log("Initialization complete in "+a+"ms")},s.prototype.init_normal=function(e,n){var i=t.performance&&performance.now?performance.now():Date.now();this.log("Found non-Ember Twitch after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!1;try{this.embed_in_dash=t.top!==t&&/\/[^\/]+\/dashboard/.test(t.top.location.pathname)&&!/bookmarks$/.test(t.top.location.pathname)}catch(o){this.embed_in_dash=!1}this.load_settings(),this.setup_dark(),n||this.ws_create(),this.setup_colors(),this.setup_emoticons(),this.setup_badges(),this.setup_notifications(),this.setup_following_count(!1),this.setup_css(),this.setup_menu(),this.find_bttv(10);var a=t.performance&&performance.now?performance.now():Date.now(),r=a-i;this.log("Initialization complete in "+r+"ms")},s.prototype.is_dashboard=!1,s.prototype.init_dashboard=function(e){var n=t.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch Dashboard after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!0,this.embed_in_dash=!1,this.load_settings(),this.setup_dark(),this.ws_create(),this.setup_colors(),this.setup_emoticons(),this.setup_badges(),this.setup_tokenization(),this.setup_notifications(),this.setup_css(),this._update_subscribers(),this.setup_message_event(),this.find_bttv(10);var i=t.performance&&performance.now?performance.now():Date.now(),o=i-n;this.log("Initialization complete in "+o+"ms")},s.prototype.init_ember=function(e){var n=t.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch application after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!1;try{this.embed_in_dash=t.top!==t&&/\/[^\/]+\/dashboard/.test(t.top.location.pathname)&&!/bookmarks$/.test(t.top.location.pathname)}catch(i){this.embed_in_dash=!1}this.load_settings(),this.setup_dark(),this.ws_create(),this.setup_emoticons(),this.setup_badges(),this.setup_colors(),this.setup_tokenization(),this.setup_channel(),this.setup_room(),this.setup_line(),this.setup_layout(),this.setup_chatview(),this.setup_viewers(),this.setup_mod_card(),this.setup_chat_input(),this.setup_notifications(),this.setup_css(),this.setup_menu(),this.setup_my_emotes(),this.setup_following(),this.setup_following_count(!0),this.setup_races(),this.connect_extra_chat(),this.find_bttv(10),this.find_emote_menu(10),this.check_ff();var o=t.performance&&performance.now?performance.now():Date.now(),a=o-n;this.log("Initialization complete in "+a+"ms")},s.prototype.setup_message_event=function(){this.log("Listening for Window Messages."),t.addEventListener("message",this._on_window_message.bind(this),!1)},s.prototype._on_window_message=function(t){if(t.data&&t.data.from_ffz){t.data}}},{"./badges":2,"./colors":3,"./commands":4,"./debug":6,"./ember/channel":7,"./ember/chat-input":8,"./ember/chatview":9,"./ember/layout":10,"./ember/line":11,"./ember/moderation-card":12,"./ember/room":13,"./ember/viewers":14,"./emoticons":15,"./ext/betterttv":16,"./ext/emote_menu":17,"./featurefriday":19,"./settings":20,"./socket":21,"./tokenize":22,"./ui/about_page":23,"./ui/dark":24,"./ui/following":26,"./ui/following-count":25,"./ui/menu":27,"./ui/menu_button":28,"./ui/my_emotes":29,"./ui/notifications":30,"./ui/races":31,"./ui/styles":32,"./ui/sub_count":33,"./ui/viewer_count":34}],19:[function(e){var s=t.FrankerFaceZ,n=e("./constants");s.prototype.feature_friday=null,s.prototype.check_ff=function(t){t||this.log("Checking for Feature Friday data..."),jQuery.ajax(n.SERVER+"script/event.json",{cache:!1,dataType:"json",context:this}).done(function(t){return this._load_ff(t)}).fail(function(e){return 404==e.status?this._load_ff(null):(t=t||0,t++,10>t?setTimeout(this.check_ff.bind(this,t),250):this._load_ff(null))})},s.ws_commands.reload_ff=function(){this.check_ff()},s.prototype._feature_friday_ui=function(t,e,s){if(this.feature_friday&&this.feature_friday.channel!=t){this._emotes_for_sets(e,s,[this.feature_friday.set],this.feature_friday.title,this.feature_friday.icon,"FrankerFaceZ");var n=App.__container__.lookup("controller:channel");if(!n||n.get("id")!=this.feature_friday.channel){var i=this.feature_friday,o=document.createElement("div"),a=document.createElement("a");o.className="chat-menu-content",o.style.textAlign="center";var r=i.display_name+(i.live?" is live now!":"");a.className="button primary",a.classList.toggle("live",i.live),a.classList.toggle("blue",this.has_bttv&&BetterTTV.settings.get("showBlueButtons")),a.href="http://www.twitch.tv/"+i.channel,a.title=r,a.target="_new",a.innerHTML=""+r+"",o.appendChild(a),e.appendChild(o)}}},s.prototype._load_ff=function(t){this.feature_friday&&(this.global_sets.removeObject(this.feature_friday.set),this.default_sets.removeObject(this.feature_friday.set),this.feature_friday=null,this.update_ui_link()),t&&t.set&&t.channel&&(this.feature_friday={set:t.set,channel:t.channel,live:!1,title:t.title||"Feature Friday",display_name:s.get_capitalization(t.channel,this._update_ff_name.bind(this))},this.global_sets.push(t.set),this.default_sets.push(t.set),this.load_set(t.set),this._update_ff_live())},s.prototype._update_ff_live=function(){if(this.feature_friday){var t=this;Twitch.api.get("streams/"+this.feature_friday.channel).done(function(e){t.feature_friday.live=null!=e.stream,t.update_ui_link()}).always(function(){t.feature_friday.timer=setTimeout(t._update_ff_live.bind(t),12e4)})}},s.prototype._update_ff_name=function(t){this.feature_friday&&(this.feature_friday.display_name=t)}},{"./constants":5}],20:[function(e){var s=t.FrankerFaceZ,n=e("./constants"),i=e("./FileSaver");make_ls=function(t){return"ffz_setting_"+t},toggle_setting=function(t,e){var s=!this.settings.get(e);this.settings.set(e,s),t.classList.toggle("active",s)},option_setting=function(t,e){this.settings.set(e,JSON.parse(t.options[t.selectedIndex].value))},toggle_basic_setting=function(t,e){var n=s.basic_settings[e].get,i=!("function"==typeof n?n.bind(this)():this.settings.get(n)),o=s.basic_settings[e].set;"function"==typeof o?o.bind(this)(i):this.settings.set(o,i),t.classList.toggle("active",i)},option_basic_setting=function(t,e){s.basic_settings[e].set.bind(this)(JSON.parse(t.options[t.selectedIndex].value))},s.settings_info={advanced_settings:{value:!1,visible:!1}},s.basic_settings={},s.prototype.load_settings=function(){this.log("Loading settings."),this.settings={};for(var e in s.settings_info)if(s.settings_info.hasOwnProperty(e)){var n=s.settings_info[e],i=n.storage_key||make_ls(e),o=n.hasOwnProperty("value")?n.value:void 0;if(localStorage.hasOwnProperty(i))try{o=JSON.parse(localStorage.getItem(i))}catch(a){this.log('Error loading value for "'+e+'": '+a)}n.process_value&&(o=n.process_value.bind(this)(o)),this.settings[e]=o}this.settings.get=this._setting_get.bind(this),this.settings.set=this._setting_set.bind(this),this.settings.del=this._setting_del.bind(this),t.addEventListener("storage",this._setting_update.bind(this),!1)},s.prototype.save_settings_file=function(){var t={version:1,script_version:s.version_info+"",aliases:this.aliases,settings:{}};for(var e in s.settings_info)if(s.settings_info.hasOwnProperty(e)){var n=s.settings_info[e],o=n.storage_key||make_ls(e);localStorage.hasOwnProperty(o)&&(t.settings[e]=this.settings[e])}var a=new Blob([JSON.stringify(t,null,4)],{type:"application/json;charset=utf-8"});i.saveAs(a,"ffz-settings.json")},s.prototype.load_settings_file=function(t){if("string"==typeof t)this._load_settings_file(t);else{var e=new FileReader,s=this;e.onload=function(t){s._load_settings_file(t.target.result)},e.readAsText(t)}},s.prototype._load_settings_file=function(t){try{t=JSON.parse(t)}catch(e){return this.error("Error Loading Settings: "+e),alert("There was an error attempting to read the provided settings data.")}this.log("Loading Settings Data",t);var n=[],i=[];if(t.settings)for(var o in t.settings)if(s.settings_info.hasOwnProperty(o)){var a=s.settings_info[o],r=t.settings[o];a.process_value&&(r=a.process_value.bind(this)(r)),r!==this.settings.get(o)&&this.settings.set(o,r),i.push(o)}else n.push(o);setTimeout(function(){alert("Successfully loaded "+i.length+" settings and skipped "+n.length+" settings.")})},s.menu_pages.settings={render:function(t,e){var n=document.createElement("ul"),i=document.createElement("div"),o=document.createElement("li"),a=document.createElement("a"),r=document.createElement("li"),d=document.createElement("a"),u=document.createElement("li"),c=document.createElement("a"),l=parseInt(e.style.maxHeight||"0");l||(l=Math.max(200,t.$().height()-172)),l&&0/0!==l&&(l-=37,i.style.maxHeight=l+"px"),i.className="ffz-ui-sub-menu-page",n.className="menu sub-menu clearfix",o.className="item",o.id="ffz-settings-page-basic",a.innerHTML="Basic",o.appendChild(a),r.className="item",r.id="ffz-settings-page-advanced",d.innerHTML="Advanced",r.appendChild(d),u.className="item",u.id="ffz-settings-page-save",c.textContent="Backup & Restore",u.appendChild(c),n.appendChild(o),n.appendChild(r),n.appendChild(u);var h=s.menu_pages.settings.change_page;a.addEventListener("click",h.bind(this,t,e,n,i,"basic")),d.addEventListener("click",h.bind(this,t,e,n,i,"advanced")),c.addEventListener("click",h.bind(this,t,e,n,i,"save")),this.settings.advanced_settings?d.click():a.click(),e.appendChild(i),e.appendChild(n)},change_page:function(t,e,n,i,o){i.innerHTML="",i.setAttribute("data-page",o);for(var a=n.querySelectorAll("li.active"),r=0,d=a.length;d>r;r++)a[r].classList.remove("active");var u=n.querySelector("#ffz-settings-page-"+o);u&&u.classList.add("active"),s.menu_pages.settings["render_"+o].bind(this)(t,i),"advanced"===o?this.settings.set("advanced_settings",!0):"basic"===o&&this.settings.set("advanced_settings",!1)},render_save:function(t,e){var s=document.createElement("div"),n=document.createElement("div"),i=document.createElement("div"),o=document.createElement("div"),a=document.createElement("p"),r=document.createElement("a"),d=document.createElement("span"),u=document.createElement("p"),c=document.createElement("input"),l=document.createElement("a"),h=document.createElement("span"),f=this;i.className="chat-menu-content",s.className="heading",s.innerHTML="Backup Settings",i.appendChild(s),a.className="clearfix option",r.href="#",r.innerHTML="Save to File",r.addEventListener("click",this.save_settings_file.bind(this)),d.className="help",d.innerHTML="This generates a JSON file containing all of your settings and prompts you to save it.",a.appendChild(r),a.appendChild(d),i.appendChild(a),o.className="chat-menu-content",n.className="heading",n.innerHTML="Restore Settings",o.appendChild(n),u.className="clearfix option",c.type="file",c.addEventListener("change",function(){f.load_settings_file(this.files[0])}),l.href="#",l.innerHTML="Restore from File",l.addEventListener("click",function(t){t.preventDefault(),c.click()}),h.className="help",h.innerHTML="This loads settings from a previously generated JSON file.",u.appendChild(l),u.appendChild(h),o.appendChild(u),e.appendChild(i),e.appendChild(o)},render_basic:function(t,e){var n={},i=[],o=-1!==navigator.userAgent.indexOf("Android");for(var a in s.basic_settings)if(s.basic_settings.hasOwnProperty(a)){var r=s.basic_settings[a],d=r.category||"Miscellaneous",u=n[d];if(void 0!==r.visible&&null!==r.visible){var c=r.visible;if("function"==typeof r.visible&&(c=r.visible.bind(this)()),!c)continue}o&&r.no_mobile||(u||(i.push(d),u=n[d]=[]),u.push([a,r]))}i.sort(function(t,e){var t=t.toLowerCase(),e=e.toLowerCase();return"debugging"===t&&(t="zzz"+t),"debugging"===e&&(e="zzz"+e),e>t?-1:t>e?1:0});for(var l=(this._ffz_basic_settings_page||i[0],0);ls?-1:s>n?1:o>i?-1:i>o?1:0});for(var p=0;p",b.className="switch-label",b.innerHTML=r.name,g.appendChild(w),g.appendChild(b),w.addEventListener("click",toggle_basic_setting.bind(this,w,a))}else if("select"===r.type){var z=document.createElement("select"),b=document.createElement("span");b.className="option-label",b.innerHTML=r.name;for(var k in r.options){var E=document.createElement("option");E.value=JSON.stringify(k),v===k&&E.setAttribute("selected",!0),E.innerHTML=r.options[k],z.appendChild(E)}z.addEventListener("change",option_basic_setting.bind(this,z,a)),g.appendChild(b),g.appendChild(z)}else{g.classList.add("option");var C=document.createElement("a");C.innerHTML=r.name,C.href="#",g.appendChild(C),C.addEventListener("click",r.method.bind(this))}if(r.help){var y=document.createElement("span");y.className="help",y.innerHTML=r.help,g.appendChild(y)}}m.appendChild(g)}e.appendChild(m)}},render_advanced:function(t,e){var n={},i=[],o=-1!==navigator.userAgent.indexOf("Android");for(var a in s.settings_info)if(s.settings_info.hasOwnProperty(a)){var r=s.settings_info[a],d=r.category||"Miscellaneous",u=n[d];if(void 0!==r.visible&&null!==r.visible){var c=r.visible;if("function"==typeof r.visible&&(c=r.visible.bind(this)()),!c)continue}o&&r.no_mobile||(u||(i.push(d),u=n[d]=[]),u.push([a,r]))}i.sort(function(t,e){var t=t.toLowerCase(),e=e.toLowerCase();return"debugging"===t&&(t="zzz"+t),"debugging"===e&&(e="zzz"+e),e>t?-1:t>e?1:0});for(var l=this,h=this._ffz_settings_page||i[0],f=0;fs?-1:s>n?1:o>i?-1:i>o?1:0});for(var v=0;v<_.length;v++){var a=_[v][0],r=_[v][1],b=document.createElement("p"),y=this.settings.get(a);if(b.className="clearfix",this.has_bttv&&r.no_bttv){var w=document.createElement("span"),z=document.createElement("span");w.className="switch-label",w.innerHTML=r.name,z=document.createElement("span"),z.className="help",z.innerHTML="Disabled due to incompatibility with BetterTTV.",b.classList.add("disabled"),b.appendChild(w),b.appendChild(z)}else{if("boolean"==r.type){var k=document.createElement("a"),w=document.createElement("span");k.className="switch",k.classList.toggle("active",y),k.innerHTML="",w.className="switch-label",w.innerHTML=r.name,b.appendChild(k),b.appendChild(w),k.addEventListener("click",toggle_setting.bind(this,k,a))}else if("select"===r.type){var E=document.createElement("select"),w=document.createElement("span");w.className="option-label",w.innerHTML=r.name;for(var C in r.options){var x=document.createElement("option");x.value=JSON.stringify(C),y===C&&x.setAttribute("selected",!0),x.innerHTML=r.options[C],E.appendChild(x)}E.addEventListener("change",option_setting.bind(this,E,a)),b.appendChild(w),b.appendChild(E)}else{b.classList.add("option");var T=document.createElement("a");T.innerHTML=r.name,T.href="#",b.appendChild(T),T.addEventListener("click",r.method.bind(this))}if(r.help){var z=document.createElement("span");z.className="help",z.innerHTML=r.help,b.appendChild(z)}}p.appendChild(b)}e.appendChild(p)}},name:"Settings",icon:n.GEAR,sort_order:99999,wide:!0,sub_menu:!0},s.prototype._setting_update=function(e){if(e||(e=t.event),e.key&&"ffz_setting_"===e.key.substr(0,12)){var n=e.key,i=n.substr(12),o=void 0,a=s.settings_info[i];if(!a){for(i in s.settings_info)if(s.settings_info.hasOwnProperty(i)&&(a=s.settings_info[i],a.storage_key==n))break;if(a.storage_key!=n)return}this.log("Updated Setting: "+i);try{o=JSON.parse(e.newValue)}catch(r){this.log('Error loading new value for "'+i+'": '+r),o=a.value||void 0}if(this.settings[i]=o,a.on_update)try{a.on_update.bind(this)(o,!1)}catch(r){this.log('Error running updater for setting "'+i+'": '+r)}}},s.prototype._setting_get=function(t){return this.settings[t]},s.prototype._setting_set=function(t,e){var n=s.settings_info[t],i=n.storage_key||make_ls(t),o=JSON.stringify(e);if(this.settings[t]=e,localStorage.setItem(i,o),this.log('Changed Setting "'+t+'" to: '+o),n.on_update)try{n.on_update.bind(this)(e,!0)}catch(a){this.log('Error running updater for setting "'+t+'": '+a)}},s.prototype._setting_del=function(t){var e=s.settings_info[t],n=e.storage_key||make_ls(t),i=void 0;if(localStorage.hasOwnProperty(n)&&localStorage.removeItem(n),delete this.settings[t],e&&(i=this.settings[t]=e.hasOwnProperty("value")?e.value:void 0),e.on_update)try{e.on_update.bind(this)(i,!0)}catch(o){this.log('Error running updater for setting "'+t+'": '+o)}}},{"./FileSaver":1,"./constants":5}],21:[function(){var e=t.FrankerFaceZ;
+return 65536>e?String.fromCharCode(e):(e-=65536,String.fromCharCode(55296+(e>>10),56320+(1023&e)))};s.prototype.setup_emoticons=function(){this.log("Preparing emoticon system."),this.emoji_data={},this.emoji_names={},this.emote_sets={},this.global_sets=[],this.default_sets=[],this._last_emote_id=0,this.emote_usage={},this.log("Creating emoticon style element.");var t=this._emote_style=document.createElement("style");t.id="ffz-emoticon-css",document.head.appendChild(t),this.log("Loading global emote sets."),this.load_global_sets(),this.log("Loading emoji data."),this.load_emoji_data(),this.log("Watching Twitch emoticon parser to ensure it loads."),this._twitch_emote_check=setTimeout(this.check_twitch_emotes.bind(this),1e4)},s.prototype.add_usage=function(t,e,s){var n=this.emote_usage[e]=this.emote_usage[e]||{};n[t]=(n[t]||0)+(s||1),this._emote_report_scheduled||(this._emote_report_scheduled=setTimeout(this._report_emotes.bind(this),3e4))},s.prototype._report_emotes=function(){this._emote_report_scheduled&&delete this._emote_report_scheduled;var t=this.emote_usage;this.emote_usage={},this.ws_send("emoticon_uses",[t],function(){},!0)},s.prototype.check_twitch_emotes=function(){this._twitch_emote_check&&(clearTimeout(this._twitch_emote_check),delete this._twitch_emote_check);var t;if(this.rooms)for(var e in this.rooms)if(this.rooms.hasOwnProperty(e)){t=this.rooms[e];break}if(!t||!t.room||!t.room.tmiSession)return void(this._twitch_emote_check=setTimeout(this.check_twitch_emotes.bind(this),1e4));var s=t.room.tmiSession._emotesParser,n=Object.keys(s.emoticonRegexToIds).length;if(!(n>0)){var i=s.emoticonSetIds;s.emoticonSetIds="",s.updateEmoticons(i),this._twitch_emote_check=setTimeout(this.check_twitch_emotes.bind(this),1e4)}},s.prototype.getEmotes=function(t,e){var s=this.users&&this.users[t],n=this.rooms&&this.rooms[e];return _.union(s&&s.sets||[],n&&n.set&&[n.set]||[],n&&n.extra_sets||[],this.default_sets)},s.ws_commands.reload_set=function(t){this.emote_sets.hasOwnProperty(t)&&this.load_set(t)},s.ws_commands.load_set=function(t){this.load_set(t)},s.prototype._emote_tooltip=function(t){if(!t)return null;if(t._tooltip)return t._tooltip;var e=this.emote_sets[t.set_id],s=t.owner,n=e&&e.title||"Global";return t._tooltip="Emoticon: "+(t.hidden?"???":t.name)+"\nFFZ "+n+(s?"\nBy: "+s.display_name:""),t._tooltip},s.prototype.load_emoji_data=function(t,e){var s=this;jQuery.getJSON(n.SERVER+"emoji/emoji.json").done(function(e){var i={},o={};for(var a in e){var r=e[a];a=a.toLowerCase(),r.code=a,i[a]=r,o[r.short_name]=a,r.raw=_.map(r.code.split("-"),d).join(""),r.src=n.SERVER+"emoji/"+a+"-1x.png",r.srcSet=r.src+" 1x, "+n.SERVER+"emoji/"+a+"-2x.png 2x, "+n.SERVER+"emoji/"+a+"-4x.png 4x",r.token={srcSet:r.srcSet,emoticonSrc:r.src,ffzEmoji:a,altText:r.raw}}s.emoji_data=i,s.emoji_names=o,s.log("Loaded data on "+Object.keys(i).length+" emoji."),"function"==typeof t&&t(!0,e)}).fail(function(n){return 404===n.status?"function"==typeof t&&t(!1):(e=(e||0)+1,50>e?s.load_emoji(t,e):"function"==typeof t&&t(!1))})},s.prototype.load_global_sets=function(t,e){var s=this;jQuery.getJSON(((e||0)%2===0?n.API_SERVER:n.API_SERVER_2)+"v1/set/global").done(function(t){s.default_sets=t.default_sets;var e=s.global_sets=[],n=t.sets||{};s.feature_friday&&s.feature_friday.set&&(-1===s.global_sets.indexOf(s.feature_friday.set)&&s.global_sets.push(s.feature_friday.set),-1===s.default_sets.indexOf(s.feature_friday.set)&&s.default_sets.push(s.feature_friday.set));for(var i in n)if(n.hasOwnProperty(i)){var o=n[i];e.push(i),s._load_set_json(i,void 0,o)}}).fail(function(n){return 404==n.status?"function"==typeof t&&t(!1):(e=e||0,e++,50>e?s.load_global_sets(t,e):"function"==typeof t&&t(!1))})},s.prototype.load_set=function(t,e,s){var i=this;jQuery.getJSON(((s||0)%2===0?n.API_SERVER:n.API_SERVER_2)+"v1/set/"+t).done(function(s){i._load_set_json(t,e,s&&s.set)}).fail(function(n){return 404==n.status?"function"==typeof e&&e(!1):(s=s||0,s++,10>s?i.load_set(t,e,s):"function"==typeof e&&e(!1))})},s.prototype.unload_set=function(t){var e=this.emote_sets[t];e&&(this.log("Unloading emoticons for set: "+t),i.update_css(this._emote_style,t,null),delete this.emote_sets[t])},s.prototype._load_set_json=function(t,e,s){if(!s)return"function"==typeof e&&e(!1);var n=this.emote_sets[t]&&this.emote_sets[t].users||[];this.emote_sets[t]=s,s.users=n,s.count=0;var o="",a=s.emoticons;s.emoticons={};for(var d=0;d=6e4?this.log("BetterTTV was not detected after 60 seconds."):setTimeout(this.find_bttv.bind(this,e,(s||0)+e),e))},s.prototype.setup_bttv=function(t){this.log("BetterTTV was detected after "+t+"ms. Hooking."),this.has_bttv=!0,document.body.classList.remove("ffz-dark"),this._dark_style&&(this._dark_style.parentElement.removeChild(this._dark_style),this._dark_style=void 0),this._layout_style&&(this._layout_style.parentElement.removeChild(this._layout_style),this._layout_style=void 0),this._chat_style&&(n.update_css(this._chat_style,"chat_font_size",""),n.update_css(this._chat_style,"chat_ts_font_size","")),this.settings.group_tabs&&this._chatv&&this._chatv.ffzDisableTabs(),this._roomv&&(this.settings.chat_hover_pause&&this._roomv.ffzDisableFreeze(),this.settings.room_status&&this._roomv.ffzUpdateStatus()),document.body.classList.remove("ffz-chat-colors"),document.body.classList.remove("ffz-chat-colors-gray"),document.body.classList.remove("ffz-chat-background"),document.body.classList.remove("ffz-chat-padding"),document.body.classList.remove("ffz-chat-separator"),document.body.classList.remove("ffz-chat-separator-3d"),document.body.classList.remove("ffz-sidebar-swap"),document.body.classList.remove("ffz-transparent-badges"),document.body.classList.remove("ffz-high-contrast-chat-text"),document.body.classList.remove("ffz-high-contrast-chat-bg"),document.body.classList.remove("ffz-high-contrast-chat-bold"),this.settings.following_count&&(this._schedule_following_count(),this._draw_following_count(),this._draw_following_channels()),this.is_dashboard&&this._update_subscribers(),document.body.classList.add("ffz-bttv");var e=BetterTTV.chat.helpers.sendMessage,s=this;BetterTTV.chat.helpers.sendMessage=function(t){var n=t.split(" ",1)[0].toLowerCase();return"/ffz"!==n?e(t):void s.run_ffz_command(t.substr(5),BetterTTV.chat.store.currentRoom)};var i,o=BetterTTV.chat.handlers.onPrivmsg;BetterTTV.chat.handlers.onPrivmsg=function(t,e){i=t;var s=o(t,e);return i=null,s};var a=BetterTTV.chat.templates.privmsg;BetterTTV.chat.templates.privmsg=function(t,e,n,o,r){try{return s.bttv_badges(r),''+BetterTTV.chat.templates.timestamp(r.time)+" "+(o?BetterTTV.chat.templates.modicons():"")+" "+BetterTTV.chat.templates.badges(r.badges)+BetterTTV.chat.templates.from(r.nickname,r.color)+BetterTTV.chat.templates.message(r.sender,r.message,r.emotes,e?r.color:!1)+"
"}catch(d){return s.log("Error: ",d),a(t,e,n,o,r)}};var r=BetterTTV.chat.templates.whisper;BetterTTV.chat.templates.whisper=function(t){try{return s.bttv_badges(t),''+BetterTTV.chat.templates.timestamp(t.time)+" "+(t.badges&&t.badges.length?BetterTTV.chat.templates.badges(t.badges):"")+BetterTTV.chat.templates.whisperName(t.sender,t.receiver,t.from,t.to,t.fromColor,t.toColor)+BetterTTV.chat.templates.message(t.sender,t.message,t.emotes,!1)+"
"}catch(e){return s.log("Error: ",e),r(t)}};var d,u=BetterTTV.chat.templates.message;BetterTTV.chat.templates.message=function(t,e,n,i){try{i=i||!1;var o=encodeURIComponent(e);if("jtv"!==t){d=t;var a=BetterTTV.chat.templates.emoticonize(e,n);d=null;for(var r=0;r'+e+""}catch(c){return s.log("Error: ",c),u(t,e,n,i)}};var c=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(t,e){var n=c(t,e),o=i||BetterTTV.getChannel(),a=o&&o.toLowerCase(),r=d&&d.toLowerCase(),u=s.getEmotes(r,a),e=[],l=s.get_user(),h=l&&l.login===r;return _.each(u,function(t){var i=s.emote_sets[t];i&&_.each(i.emoticons,function(t){_.any(n,function(e){return _.isString(e)&&e.match(t.regex)})&&e.push(t)})}),e.length&&_.each(e,function(t){var e=s._emote_tooltip(t),i=['
'],o=n;n=[];for(var r=0;r=6e4?this.log("Emote Menu for Twitch was not detected after 60 seconds."):setTimeout(this.find_emote_menu.bind(this,e,(s||0)+e),e))},e.prototype.setup_emote_menu=function(t){this.log("Emote Menu for Twitch was detected after "+t+"ms. Registering emote enumerator."),emoteMenu.registerEmoteGetter("FrankerFaceZ",this._emote_menu_enumerator.bind(this))},e.prototype._emote_menu_enumerator=function(){for(var t=this.get_user(),e=t?t.login:null,s=App.__container__.lookup("controller:chat"),n=s?s.get("currentRoom.id"):null,i=this.getEmotes(e,n),o=[],a=0;a=6e4?this.log('Twitch application not detected in "'+location.toString()+'". Aborting.'):setTimeout(this.initialize.bind(this,e,(s||0)+e),e)))}},s.prototype.init_player=function(e){var n=t.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch Player after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!1;try{this.embed_in_dash=t.top!==t&&/\/[^\/]+\/dashboard/.test(t.top.location.pathname)&&!/bookmarks$/.test(t.top.location.pathname)}catch(i){this.embed_in_dash=!1}this.load_settings(),this.setup_dark();var o=t.performance&&performance.now?performance.now():Date.now(),a=o-n;this.log("Initialization complete in "+a+"ms")},s.prototype.init_normal=function(e,n){var i=t.performance&&performance.now?performance.now():Date.now();this.log("Found non-Ember Twitch after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!1;try{this.embed_in_dash=t.top!==t&&/\/[^\/]+\/dashboard/.test(t.top.location.pathname)&&!/bookmarks$/.test(t.top.location.pathname)}catch(o){this.embed_in_dash=!1}this.load_settings(),this.setup_dark(),n||this.ws_create(),this.setup_colors(),this.setup_emoticons(),this.setup_badges(),this.setup_notifications(),this.setup_following_count(!1),this.setup_css(),this.setup_menu(),this.find_bttv(10);var a=t.performance&&performance.now?performance.now():Date.now(),r=a-i;this.log("Initialization complete in "+r+"ms")},s.prototype.is_dashboard=!1,s.prototype.init_dashboard=function(e){var n=t.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch Dashboard after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!0,this.embed_in_dash=!1,this.load_settings(),this.setup_dark(),this.ws_create(),this.setup_colors(),this.setup_emoticons(),this.setup_badges(),this.setup_tokenization(),this.setup_notifications(),this.setup_css(),this._update_subscribers(),this.setup_message_event(),this.find_bttv(10);var i=t.performance&&performance.now?performance.now():Date.now(),o=i-n;this.log("Initialization complete in "+o+"ms")},s.prototype.init_ember=function(e){var n=t.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch application after "+(e||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+s.version_info),this.users={},this.is_dashboard=!1;try{this.embed_in_dash=t.top!==t&&/\/[^\/]+\/dashboard/.test(t.top.location.pathname)&&!/bookmarks$/.test(t.top.location.pathname)}catch(i){this.embed_in_dash=!1}this.load_settings(),this.setup_dark(),this.ws_create(),this.setup_emoticons(),this.setup_badges(),this.setup_colors(),this.setup_tokenization(),this.setup_channel(),this.setup_room(),this.setup_line(),this.setup_layout(),this.setup_chatview(),this.setup_viewers(),this.setup_mod_card(),this.setup_chat_input(),this.setup_notifications(),this.setup_css(),this.setup_menu(),this.setup_my_emotes(),this.setup_following(),this.setup_following_count(!0),this.setup_races(),this.connect_extra_chat(),this.find_bttv(10),this.find_emote_menu(10),this.check_ff();var o=t.performance&&performance.now?performance.now():Date.now(),a=o-n;this.log("Initialization complete in "+a+"ms")},s.prototype.setup_message_event=function(){this.log("Listening for Window Messages."),t.addEventListener("message",this._on_window_message.bind(this),!1)},s.prototype._on_window_message=function(t){if(t.data&&t.data.from_ffz){t.data}}},{"./badges":2,"./colors":3,"./commands":4,"./debug":6,"./ember/channel":7,"./ember/chat-input":8,"./ember/chatview":9,"./ember/layout":10,"./ember/line":11,"./ember/moderation-card":12,"./ember/room":13,"./ember/viewers":14,"./emoticons":15,"./ext/betterttv":16,"./ext/emote_menu":17,"./featurefriday":19,"./settings":20,"./socket":21,"./tokenize":22,"./ui/about_page":23,"./ui/dark":24,"./ui/following":26,"./ui/following-count":25,"./ui/menu":27,"./ui/menu_button":28,"./ui/my_emotes":29,"./ui/notifications":30,"./ui/races":31,"./ui/styles":32,"./ui/sub_count":33,"./ui/viewer_count":34}],19:[function(e){var s=t.FrankerFaceZ,n=e("./constants");s.prototype.feature_friday=null,s.prototype.check_ff=function(t){t||this.log("Checking for Feature Friday data..."),jQuery.ajax(n.SERVER+"script/event.json",{cache:!1,dataType:"json",context:this}).done(function(t){return this._load_ff(t)}).fail(function(e){return 404==e.status?this._load_ff(null):(t=t||0,t++,10>t?setTimeout(this.check_ff.bind(this,t),250):this._load_ff(null))})},s.ws_commands.reload_ff=function(){this.check_ff()},s.prototype._feature_friday_ui=function(t,e,s){if(this.feature_friday&&this.feature_friday.channel!=t){this._emotes_for_sets(e,s,[this.feature_friday.set],this.feature_friday.title,this.feature_friday.icon,"FrankerFaceZ");var n=App.__container__.lookup("controller:channel");if(!n||n.get("id")!=this.feature_friday.channel){var i=this.feature_friday,o=document.createElement("div"),a=document.createElement("a");o.className="chat-menu-content",o.style.textAlign="center";var r=i.display_name+(i.live?" is live now!":"");a.className="button primary",a.classList.toggle("live",i.live),a.classList.toggle("blue",this.has_bttv&&BetterTTV.settings.get("showBlueButtons")),a.href="http://www.twitch.tv/"+i.channel,a.title=r,a.target="_new",a.innerHTML=""+r+"",o.appendChild(a),e.appendChild(o)}}},s.prototype._load_ff=function(t){this.feature_friday&&(this.global_sets.removeObject(this.feature_friday.set),this.default_sets.removeObject(this.feature_friday.set),this.feature_friday=null,this.update_ui_link()),t&&t.set&&t.channel&&(this.feature_friday={set:t.set,channel:t.channel,live:!1,title:t.title||"Feature Friday",display_name:s.get_capitalization(t.channel,this._update_ff_name.bind(this))},this.global_sets.push(t.set),this.default_sets.push(t.set),this.load_set(t.set),this._update_ff_live())},s.prototype._update_ff_live=function(){if(this.feature_friday){var t=this;Twitch.api.get("streams/"+this.feature_friday.channel).done(function(e){t.feature_friday.live=null!=e.stream,t.update_ui_link()}).always(function(){t.feature_friday.timer=setTimeout(t._update_ff_live.bind(t),12e4)})}},s.prototype._update_ff_name=function(t){this.feature_friday&&(this.feature_friday.display_name=t)}},{"./constants":5}],20:[function(e){var s=t.FrankerFaceZ,n=e("./constants"),i=e("./FileSaver");make_ls=function(t){return"ffz_setting_"+t},toggle_setting=function(t,e){var s=!this.settings.get(e);this.settings.set(e,s),t.classList.toggle("active",s)},option_setting=function(t,e){this.settings.set(e,JSON.parse(t.options[t.selectedIndex].value))},toggle_basic_setting=function(t,e){var n=s.basic_settings[e].get,i=!("function"==typeof n?n.bind(this)():this.settings.get(n)),o=s.basic_settings[e].set;"function"==typeof o?o.bind(this)(i):this.settings.set(o,i),t.classList.toggle("active",i)},option_basic_setting=function(t,e){s.basic_settings[e].set.bind(this)(JSON.parse(t.options[t.selectedIndex].value))},s.settings_info={advanced_settings:{value:!1,visible:!1}},s.basic_settings={},s.prototype.load_settings=function(){this.log("Loading settings."),this.settings={};for(var e in s.settings_info)if(s.settings_info.hasOwnProperty(e)){var n=s.settings_info[e],i=n.storage_key||make_ls(e),o=n.hasOwnProperty("value")?n.value:void 0;if(localStorage.hasOwnProperty(i))try{o=JSON.parse(localStorage.getItem(i))}catch(a){this.log('Error loading value for "'+e+'": '+a)}n.process_value&&(o=n.process_value.bind(this)(o)),this.settings[e]=o}this.settings.get=this._setting_get.bind(this),this.settings.set=this._setting_set.bind(this),this.settings.del=this._setting_del.bind(this),t.addEventListener("storage",this._setting_update.bind(this),!1)},s.prototype.save_settings_file=function(){var t={version:1,script_version:s.version_info+"",aliases:this.aliases,settings:{}};for(var e in s.settings_info)if(s.settings_info.hasOwnProperty(e)){var n=s.settings_info[e],o=n.storage_key||make_ls(e);localStorage.hasOwnProperty(o)&&(t.settings[e]=this.settings[e])}var a=new Blob([JSON.stringify(t,null,4)],{type:"application/json;charset=utf-8"});i.saveAs(a,"ffz-settings.json")},s.prototype.load_settings_file=function(t){if("string"==typeof t)this._load_settings_file(t);else{var e=new FileReader,s=this;e.onload=function(t){s._load_settings_file(t.target.result)},e.readAsText(t)}},s.prototype._load_settings_file=function(t){try{t=JSON.parse(t)}catch(e){return this.error("Error Loading Settings: "+e),alert("There was an error attempting to read the provided settings data.")}this.log("Loading Settings Data",t);var n=[],i=[];if(t.settings)for(var o in t.settings)if(s.settings_info.hasOwnProperty(o)){var a=s.settings_info[o],r=t.settings[o];a.process_value&&(r=a.process_value.bind(this)(r)),r!==this.settings.get(o)&&this.settings.set(o,r),i.push(o)}else n.push(o);setTimeout(function(){alert("Successfully loaded "+i.length+" settings and skipped "+n.length+" settings.")})},s.menu_pages.settings={render:function(t,e){var n=document.createElement("ul"),i=document.createElement("div"),o=document.createElement("li"),a=document.createElement("a"),r=document.createElement("li"),d=document.createElement("a"),u=document.createElement("li"),c=document.createElement("a"),l=parseInt(e.style.maxHeight||"0");l||(l=Math.max(200,t.$().height()-172)),l&&0/0!==l&&(l-=37,i.style.maxHeight=l+"px"),i.className="ffz-ui-sub-menu-page",n.className="menu sub-menu clearfix",o.className="item",o.id="ffz-settings-page-basic",a.innerHTML="Basic",o.appendChild(a),r.className="item",r.id="ffz-settings-page-advanced",d.innerHTML="Advanced",r.appendChild(d),u.className="item",u.id="ffz-settings-page-save",c.textContent="Backup & Restore",u.appendChild(c),n.appendChild(o),n.appendChild(r),n.appendChild(u);var h=s.menu_pages.settings.change_page;a.addEventListener("click",h.bind(this,t,e,n,i,"basic")),d.addEventListener("click",h.bind(this,t,e,n,i,"advanced")),c.addEventListener("click",h.bind(this,t,e,n,i,"save")),this.settings.advanced_settings?d.click():a.click(),e.appendChild(i),e.appendChild(n)},change_page:function(t,e,n,i,o){i.innerHTML="",i.setAttribute("data-page",o);for(var a=n.querySelectorAll("li.active"),r=0,d=a.length;d>r;r++)a[r].classList.remove("active");var u=n.querySelector("#ffz-settings-page-"+o);u&&u.classList.add("active"),s.menu_pages.settings["render_"+o].bind(this)(t,i),"advanced"===o?this.settings.set("advanced_settings",!0):"basic"===o&&this.settings.set("advanced_settings",!1)},render_save:function(t,e){var s=document.createElement("div"),n=document.createElement("div"),i=document.createElement("div"),o=document.createElement("div"),a=document.createElement("p"),r=document.createElement("a"),d=document.createElement("span"),u=document.createElement("p"),c=document.createElement("input"),l=document.createElement("a"),h=document.createElement("span"),f=this;i.className="chat-menu-content",s.className="heading",s.innerHTML="Backup Settings",i.appendChild(s),a.className="clearfix option",r.href="#",r.innerHTML="Save to File",r.addEventListener("click",this.save_settings_file.bind(this)),d.className="help",d.innerHTML="This generates a JSON file containing all of your settings and prompts you to save it.",a.appendChild(r),a.appendChild(d),i.appendChild(a),o.className="chat-menu-content",n.className="heading",n.innerHTML="Restore Settings",o.appendChild(n),u.className="clearfix option",c.type="file",c.addEventListener("change",function(){f.load_settings_file(this.files[0])}),l.href="#",l.innerHTML="Restore from File",l.addEventListener("click",function(t){t.preventDefault(),c.click()}),h.className="help",h.innerHTML="This loads settings from a previously generated JSON file.",u.appendChild(l),u.appendChild(h),o.appendChild(u),e.appendChild(i),e.appendChild(o)},render_basic:function(t,e){var n={},i=[],o=-1!==navigator.userAgent.indexOf("Android");for(var a in s.basic_settings)if(s.basic_settings.hasOwnProperty(a)){var r=s.basic_settings[a],d=r.category||"Miscellaneous",u=n[d];if(void 0!==r.visible&&null!==r.visible){var c=r.visible;if("function"==typeof r.visible&&(c=r.visible.bind(this)()),!c)continue}o&&r.no_mobile||(u||(i.push(d),u=n[d]=[]),u.push([a,r]))}i.sort(function(t,e){var t=t.toLowerCase(),e=e.toLowerCase();return"debugging"===t&&(t="zzz"+t),"debugging"===e&&(e="zzz"+e),e>t?-1:t>e?1:0});for(var l=(this._ffz_basic_settings_page||i[0],0);ls?-1:s>n?1:o>i?-1:i>o?1:0});for(var p=0;p",b.className="switch-label",b.innerHTML=r.name,g.appendChild(w),g.appendChild(b),w.addEventListener("click",toggle_basic_setting.bind(this,w,a))}else if("select"===r.type){var z=document.createElement("select"),b=document.createElement("span");b.className="option-label",b.innerHTML=r.name;for(var k in r.options){var E=document.createElement("option");E.value=JSON.stringify(k),v===k&&E.setAttribute("selected",!0),E.innerHTML=r.options[k],z.appendChild(E)}z.addEventListener("change",option_basic_setting.bind(this,z,a)),g.appendChild(b),g.appendChild(z)}else{g.classList.add("option");var C=document.createElement("a");C.innerHTML=r.name,C.href="#",g.appendChild(C),C.addEventListener("click",r.method.bind(this))}if(r.help){var y=document.createElement("span");y.className="help",y.innerHTML=r.help,g.appendChild(y)}}m.appendChild(g)}e.appendChild(m)}},render_advanced:function(t,e){var n={},i=[],o=-1!==navigator.userAgent.indexOf("Android");for(var a in s.settings_info)if(s.settings_info.hasOwnProperty(a)){var r=s.settings_info[a],d=r.category||"Miscellaneous",u=n[d];if(void 0!==r.visible&&null!==r.visible){var c=r.visible;if("function"==typeof r.visible&&(c=r.visible.bind(this)()),!c)continue}o&&r.no_mobile||(u||(i.push(d),u=n[d]=[]),u.push([a,r]))}i.sort(function(t,e){var t=t.toLowerCase(),e=e.toLowerCase();return"debugging"===t&&(t="zzz"+t),"debugging"===e&&(e="zzz"+e),e>t?-1:t>e?1:0});for(var l=this,h=this._ffz_settings_page||i[0],f=0;fs?-1:s>n?1:o>i?-1:i>o?1:0});for(var v=0;v<_.length;v++){var a=_[v][0],r=_[v][1],b=document.createElement("p"),y=this.settings.get(a);if(b.className="clearfix",this.has_bttv&&r.no_bttv){var w=document.createElement("span"),z=document.createElement("span");w.className="switch-label",w.innerHTML=r.name,z=document.createElement("span"),z.className="help",z.innerHTML="Disabled due to incompatibility with BetterTTV.",b.classList.add("disabled"),b.appendChild(w),b.appendChild(z)}else{if("boolean"==r.type){var k=document.createElement("a"),w=document.createElement("span");k.className="switch",k.classList.toggle("active",y),k.innerHTML="",w.className="switch-label",w.innerHTML=r.name,b.appendChild(k),b.appendChild(w),k.addEventListener("click",toggle_setting.bind(this,k,a))}else if("select"===r.type){var E=document.createElement("select"),w=document.createElement("span");w.className="option-label",w.innerHTML=r.name;for(var C in r.options){var x=document.createElement("option");x.value=JSON.stringify(C),y===C&&x.setAttribute("selected",!0),x.innerHTML=r.options[C],E.appendChild(x)}E.addEventListener("change",option_setting.bind(this,E,a)),b.appendChild(w),b.appendChild(E)}else{b.classList.add("option");var T=document.createElement("a");T.innerHTML=r.name,T.href="#",b.appendChild(T),T.addEventListener("click",r.method.bind(this))}if(r.help){var z=document.createElement("span");z.className="help",z.innerHTML=r.help,b.appendChild(z)}}p.appendChild(b)}e.appendChild(p)}},name:"Settings",icon:n.GEAR,sort_order:99999,wide:!0,sub_menu:!0},s.prototype._setting_update=function(e){if(e||(e=t.event),e.key&&"ffz_setting_"===e.key.substr(0,12)){var n=e.key,i=n.substr(12),o=void 0,a=s.settings_info[i];if(!a){for(i in s.settings_info)if(s.settings_info.hasOwnProperty(i)&&(a=s.settings_info[i],a.storage_key==n))break;if(a.storage_key!=n)return}this.log("Updated Setting: "+i);try{o=JSON.parse(e.newValue)}catch(r){this.log('Error loading new value for "'+i+'": '+r),o=a.value||void 0}if(this.settings[i]=o,a.on_update)try{a.on_update.bind(this)(o,!1)}catch(r){this.log('Error running updater for setting "'+i+'": '+r)}}},s.prototype._setting_get=function(t){return this.settings[t]},s.prototype._setting_set=function(t,e){var n=s.settings_info[t],i=n.storage_key||make_ls(t),o=JSON.stringify(e);if(this.settings[t]=e,localStorage.setItem(i,o),this.log('Changed Setting "'+t+'" to: '+o),n.on_update)try{n.on_update.bind(this)(e,!0)}catch(a){this.log('Error running updater for setting "'+t+'": '+a)}},s.prototype._setting_del=function(t){var e=s.settings_info[t],n=e.storage_key||make_ls(t),i=void 0;if(localStorage.hasOwnProperty(n)&&localStorage.removeItem(n),delete this.settings[t],e&&(i=this.settings[t]=e.hasOwnProperty("value")?e.value:void 0),e.on_update)try{e.on_update.bind(this)(i,!0)}catch(o){this.log('Error running updater for setting "'+t+'": '+o)}}},{"./FileSaver":1,"./constants":5}],21:[function(){var e=t.FrankerFaceZ;
e.prototype._ws_open=!1,e.prototype._ws_delay=0,e.prototype._ws_last_iframe=0,e.ws_commands={},e.ws_on_close=[],e.prototype.ws_iframe=function(){this._ws_last_iframe=Date.now();var t=document.createElement("iframe"),e=this;t.src="http://catbag.frankerfacez.com",t.style.visibility="hidden",document.body.appendChild(t),setTimeout(function(){document.body.removeChild(t),e._ws_open||e.ws_create()},2e3)},e.prototype.ws_create=function(){var s,n=this;this._ws_last_req=0,this._ws_callbacks={},this._ws_pending=this._ws_pending||[];try{s=this._ws_sock=new WebSocket("ws://catbag.frankerfacez.com/")}catch(i){return this._ws_exists=!1,this.log("Error Creating WebSocket: "+i)}this._ws_exists=!0,s.onopen=function(){n._ws_open=!0,n._ws_delay=0,n._ws_last_iframe=Date.now(),n.log("Socket connected.");var s=t.RequestFileSystem||t.webkitRequestFileSystem;s?s(t.TEMPORARY,100,n.ws_send.bind(n,"hello",["ffz_"+e.version_info,localStorage.ffzClientId],n._ws_on_hello.bind(n)),n.log.bind(n,"Operating in Incognito Mode.")):n.ws_send("hello",["ffz_"+e.version_info,localStorage.ffzClientId],n._ws_on_hello.bind(n));var i=n.get_user();if(i&&n.ws_send("setuser",i.login),n.is_dashboard){var o=location.pathname.match(/\/([^\/]+)/);o&&(n.ws_send("sub",o[1]),n.ws_send("sub_channel",o[1]))}for(var a in n.rooms)n.rooms.hasOwnProperty(a)&&n.rooms[a]&&(n.ws_send("sub",a),n.rooms[a].needs_history&&(n.rooms[a].needs_history=!1,!n.has_bttv&&n.settings.chat_history&&n.ws_send("chat_history",[a,25],n._load_history.bind(n,a))));if(n._cindex){var r=n._cindex.get("controller.id"),d=n._cindex.get("controller.hostModeTarget.id");r&&n.ws_send("sub_channel",r),d&&n.ws_send("sub_channel",d)}var u=n._ws_pending;n._ws_pending=[];for(var c=0;c1e4){var o=navigator.userAgent.toLowerCase();if(Date.now()-n._ws_last_iframe>18e5&&(-1!==o.indexOf("chrome")||-1===o.indexOf("safari")))return n.ws_iframe()}n._ws_delay<6e4?n._ws_delay+=1e3*(Math.floor(10*Math.random())+5):n._ws_delay=1e3*(Math.floor(60*Math.random())+30),setTimeout(n.ws_create.bind(n),n._ws_delay)},s.onmessage=function(t){var s,i,o=t.data.indexOf(" "),a=t.data.substr(o+1),r=parseInt(t.data.slice(0,o));if(o=a.indexOf(" "),-1===o&&(o=a.length),s=a.slice(0,o),a=a.substr(o+1),a&&(i=JSON.parse(a)),-1===r){var d=e.ws_commands[s];d?d.bind(n)(i):n.log("Invalid command: "+s,i,!1,!0)}else{var u="True"===s,c="function"==typeof n._ws_callbacks[r];if(c){try{n._ws_callbacks[r](u,i)}catch(l){n.error("Callback for "+r+": "+l)}n._ws_callbacks[r]=void 0}else n.log("Socket Reply to "+r+" - "+(u?"SUCCESS":"FAIL"),i,!1,!0)}}},e.prototype.ws_send=function(t,e,s,n){if(!this._ws_open){if(n){var i=this._ws_pending=this._ws_pending||[];return i.push([t,e,s]),!0}return!1}var o=++this._ws_last_req;e=void 0!==e?" "+JSON.stringify(e):"",s&&(this._ws_callbacks[o]=s);try{this._ws_sock.send(o+" "+t+e)}catch(a){return this.log("Socket Send Error: "+a),!1}return o},e.prototype._ws_on_hello=function(t,s){if(!t)return this.log("Error Saying Hello: "+s);localStorage.ffzClientId=s,this.log("Client ID: "+s);var n={},i=n.settings={};for(var o in e.settings_info)i[o]=this.settings[o];i.keywords=this.settings.keywords.length,i.banned_words=this.settings.banned_words.length,n.bttv=this.has_bttv||!!document.head.querySelector('script[src*="betterttv"]'),n["user-agent"]=navigator.userAgent,n.screen=[screen.width,screen.height],n.language=navigator.language,n.platform=navigator.platform,this.ws_send("survey",[n])},e.ws_commands.do_authorize=function(t){var s;for(var n in this.rooms)if(this.rooms.hasOwnProperty(n)){var i=this.rooms[n];if(i&&i.room&&!i.room.get("roomProperties.eventchat")&&!i.room.get("isGroupRoom")&&i.room.tmiRoom){var o=i.room.tmiRoom._getConnection();if(o.isConnected){s=o;break}}}s?s._send("PRIVMSG #frankerfacezauthorizer :AUTH "+t):setTimeout(e.ws_commands.do_authorize.bind(this,t),5e3)}},{}],22:[function(e){var s,n=t.FrankerFaceZ,i=e("./utils"),o=e("./constants"),a="http://static-cdn.jtvnw.net/emoticons/v1/",r={};build_srcset=function(t){if(r[t])return r[t];var e=r[t]=a+t+"/1.0 1x, "+a+t+"/2.0 2x, "+a+t+"/3.0 4x";return e},data_to_tooltip=function(t){var e=t.set,s=t.set_type,n=t.owner;return void 0===s&&(s="Channel"),e?("--global--"===e?(e="Twitch Global",s=null):("--twitch-turbo--"==e||"turbo"==e||"--turbo-faces--"==e)&&(e="Twitch Turbo",s=null),"Emoticon: "+t.code+"\n"+(s?s+": ":"")+e+(n?"\nBy: "+n.display_name:"")):t.code},build_tooltip=function(t){{var e=this._twitch_emotes[t];e?e.set:null}return e?"string"==typeof e?e:e.tooltip?e.tooltip:e.tooltip=data_to_tooltip(e):"???"},load_emote_data=function(t,e,s,n){if(!s)return e;e&&(n.code=e),this._twitch_emotes[t]=n;for(var i=build_tooltip.bind(this)(t),o=document.querySelectorAll('img[data-emote="'+t+'"]'),a=0;a!-#%-\\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]",SPLITTER=new RegExp(SEPARATORS+"*,"+SEPARATORS+"*"),LINK_SPLIT=/^(?:(https?):\/\/)?(?:(.*?)@)?([^\/:]+)(?::(\d+))?(.*?)(?:\?(.*?))?(?:\#(.*?))?$/,YOUTUBE_CHECK=/^(?:https?:\/\/)?(?:m\.|www\.)?youtu(?:be\.com|\.be)\/(?:v\/|watch\/|.*?(?:embed|watch).*?v=)?([a-zA-Z0-9\-_]+)$/,IMGUR_PATH=/^\/(?:gallery\/)?[A-Za-z0-9]+(?:\.(?:png|jpg|jpeg|gif|gifv|bmp))?$/,IMAGE_EXT=/\.(?:png|jpg|jpeg|gif|bmp)$/i,IMAGE_DOMAINS=[],is_image=function(t,e){var s=t.match(LINK_SPLIT);if(s){var n=s[3].toLowerCase(),i=s[4],o=s[5];return i&&"80"!==i&&"443"!==i?!1:"i.imgur.com"===n||"imgur.com"===n||"www.imgur.com"===n||"m.imgur.com"===n?IMGUR_PATH.test(o):e?IMAGE_EXT.test(o):-1!==IMAGE_DOMAINS.indexOf(n)}},image_iframe=function(t,e){return''},build_link_tooltip=function(t){var e,s=this._link_data[t];if(!s)return"";if(s.tooltip)return s.tooltip;if("youtube"==s.type)e=this.settings.link_image_hover?image_iframe(s.full||t,"ffz-yt-thumb"):"",e+="YouTube: "+i.sanitize(s.title)+"
",e+="Channel: "+i.sanitize(s.channel)+" | "+i.time_to_string(s.duration)+"
",e+=i.number_commas(s.views||0)+" Views | 👍 "+i.number_commas(s.likes||0)+" 👎 "+i.number_commas(s.dislikes||0);else if("strawpoll"==s.type){e="Strawpoll: "+i.sanitize(s.title)+"
";for(var n in s.items){{var o=s.items[n];Math.floor(o/s.total*100)}e+=''+i.sanitize(n)+' | '+i.number_commas(o)+" |
"}e+="
Total: "+i.number_commas(s.total);var a=i.parse_date(s.fetched);if(a){var r=Math.floor((a.getTime()-Date.now())/1e3);r>60&&(e+="
Data was cached "+i.time_to_string(r)+" ago.")}}else if("twitch"==s.type){e="Twitch: "+i.sanitize(s.display_name)+"
";var d=i.parse_date(s.since);d&&(e+="Member Since: "+i.date_string(d)+"
"),e+="Views: "+i.number_commas(s.views)+" | Followers: "+i.number_commas(s.followers)+""}else if("twitch_vod"==s.type)e="Twitch "+("highlight"==s.broadcast_type?"Highlight":"Broadcast")+": "+i.sanitize(s.title)+"
",e+="By: "+i.sanitize(s.display_name)+(s.game?" | Playing: "+i.sanitize(s.game):" | Not Playing")+"
",e+="Views: "+i.number_commas(s.views)+" | "+i.time_to_string(s.length);else if("twitter"==s.type)e="Tweet By: "+i.sanitize(s.user)+"
",e+=i.sanitize(s.tweet);else if("reputation"==s.type){if(e=this.settings.link_image_hover&&is_image(s.full||t,this.settings.image_hover_all_domains)?image_iframe(s.full||t):"",e+=''+i.sanitize(s.full.toLowerCase())+"",s.trust<50||s.safety<50||s.tags&&s.tags.length>0){e+="
";var u=!1;(s.trust<50||s.safety<50)&&(s.unsafe=!0,e+="Potentially Unsafe Link
",e+="Trust: "+s.trust+"% | Child Safety: "+s.safety+"%",u=!0),s.tags&&s.tags.length>0&&(e+=(u?"
":"")+"Tags: "+s.tags.join(", ")),e+="
Data Source: WOT"}}else s.full&&(e=this.settings.link_image_hover&&is_image(s.full||t,this.settings.image_hover_all_domains)?image_iframe(s.full||t):"",e+=''+i.sanitize(s.full.toLowerCase())+"");return e||(e=''+i.sanitize(t.toLowerCase())+""),s.tooltip=e,e},load_link_data=function(t,e,s){if(e){this._link_data[t]=s,s.unsafe=!1;var n,i=build_link_tooltip.bind(this)(t),o="/"==t.charAt(t.length-1)?t.substr(0,t.length-1):null;if(n=document.querySelectorAll(o?'span.message a[href="'+t+'"], span.message a[href="'+o+'"], span.message a[data-url="'+t+'"], span.message a[data-url="'+o+'"]':'span.message a[href="'+t+'"], span.message a[data-url="'+t+'"]'),this.settings.link_info)for(var a=0;a12&&!e.settings.twenty_four_timestamps?s-=12:0!==s||e.settings.twenty_four_timestamps||(s=12),s+":"+(10>n?"0":"")+n},s.linkifyMessage=function(t,s){var n=e.settings.show_deleted_links;return _.chain(t).map(function(t){if(!_.isString(t))return t;var e=t.match(LINK);return e&&e.length?_.zip(t.split(LINK),_.map(e,function(t){var e=t.length>255;return n||!s&&!e?{isLink:!0,href:t}:{isLink:!0,isDeleted:!0,isLong:e,href:t}})):[t]}).flatten().compact().value()}},n.prototype.load_twitch_emote_data=function(t){jQuery.ajax(o.SERVER+"script/twitch_emotes.json",{cache:!1,context:this}).done(function(t){for(var e in t){var s=t[e];if(s){this._twitch_set_to_channel[e]=s.name;for(var n=0,i=s.emotes.length;i>n;n++)this._twitch_emote_to_set[s.emotes[n]]=e}}this._twitch_set_to_channel[0]="--global--",this._twitch_set_to_channel[33]="--turbo-faces--",this._twitch_set_to_channel[42]="--turbo-faces--"}).fail(function(e){404!==e.status&&(t=(t||0)+1,10>t&&setTimeout(this.load_twitch_emote_data.bind(this,t),1e3))})},n.prototype.tokenize_chat_line=function(e,i,o){if(e.cachedTokens)return e.cachedTokens;var a=e.message,r=this.get_user(),d=e.room,u=r&&e.from===r.login,c=e.tags&&e.tags.emotes,l=[a];if(s&&s.linkifyMessage){var h=a.labels||[],f=-1!==h.indexOf("owner")||-1!==h.indexOf("staff")||-1!==h.indexOf("admin")||-1!==h.indexOf("global_mod")||-1!==h.indexOf("mod")||"admin"===a.style;l=s.linkifyMessage(l,o&&!f)}r&&r.login&&s&&s.mentionizeMessage&&(l=s.mentionizeMessage(l,r.login,u)),s&&s.emoticonizeMessage&&(l=s.emoticonizeMessage(l,c)),this.settings.replace_bad_emotes&&(l=this.tokenize_replace_emotes(l)),l=this._remove_banned(l),l=this.tokenize_emotes(e.from,d,l,u),this.settings.parse_emoji&&(l=this.tokenize_emoji(l));var m=e.tags&&e.tags["display-name"];if(m&&m.length&&(n.capitalization[e.from]=[m.trim(),Date.now()]),!u){l=this.tokenize_mentions(l);for(var p=0;p'}if(t.isLink){var g=t.title||t.isLong&&""||t.isDeleted&&""||t.href;if(!e&&void 0!==e)return i.sanitize(g);var a,v=t.href,b="",y=v.indexOf("@"),w=v.indexOf("/");if(-1!==y&&(-1===w||w>y))b="email-link",s.settings.link_info&&(b+=" tooltip",a="E-Mail "+v),v="mailto:"+v;else if(v.match(/^https?:\/\//)||(v="http://"+v),s.settings.link_info){b="html-tooltip";var m=s._link_data&&s._link_data[v];m?(a=m.tooltip,m.unsafe&&(b+=" unsafe-link")):(s._link_data=s._link_data||{},s._link_data[v]=!0,s.ws_send("get_link",v,load_link_data.bind(s,v)),s.settings.link_image_hover&&is_image(v,s.settings.image_hover_all_domains)&&(a=image_iframe(v)))}else s.settings.link_image_hover&&(b="html-tooltip",is_image(v,s.settings.image_hover_all_domains)&&(a=image_iframe(v)));var z=v;return t.isDeleted&&(b="deleted-link "+b,a=i.sanitize(t.censoredHref||t.href),v="#"),''+i.sanitize(g)+""}return t.mentionedUser?''+i.sanitize(t.mentionedUser)+"":i.sanitize(t.deletedLink?t.text:t)}).join("")},n.prototype.tokenize_replace_emotes=function(t){_.isString(t)&&(t=[t]);for(var e=0;e-1&&(-1===e.indexOf("/")||e.indexOf("@")FrankerFaceZchange log
',jQuery.ajax(n.SERVER+"script/changelog.html",{cache:!1,context:this}).done(function(t){e.appendChild(s),e.innerHTML+=t}).fail(function(){var t=document.createElement("div");t.className="chat-menu-content menu-side-padding",t.textContent="There was an error loading the change log from the server.",e.appendChild(s),e.appendChild(t)})}},s.menu_pages.about={name:"About",icon:n.HEART,sort_order:1e5,render:function(t,e,n,i){var o=this.rooms[t.get("context.currentRoom.id")],a=!1,r=this;if(o&&o.set){var d=this.emote_sets[o.set];d&&d.count>0&&(a=!0)}var u=document.createElement("div"),c="";c+="FrankerFaceZ
",c+='new ways to woof
',u.className="chat-menu-content center",u.innerHTML=c,e.appendChild(u);var l=0,h=u.querySelector("h1");h&&h.addEventListener("click",function(){if(h.style.cursor="pointer",l++,l>=3){l=0;var t=document.querySelector(".app-main")||document.querySelector(".ember-chat-container");t&&t.classList.toggle("ffz-flip")}setTimeout(function(){l=0,h.style.cursor=""},2e3)});var f=document.createElement("div"),m=document.createElement("a"),_="To use custom emoticons in "+(a?"this channel":"tons of channels")+", get FrankerFaceZ from http://www.frankerfacez.com";m.className="button primary",m.innerHTML="Advertise in Chat",m.addEventListener("click",this._add_emote.bind(this,t,_)),f.appendChild(m);var p=document.createElement("a");p.className="button ffz-donate",p.href="https://www.frankerfacez.com/donate",p.target="_new",p.innerHTML="Donate",f.appendChild(p),f.className="chat-menu-content center",e.appendChild(f);var g=document.createElement("div");c='',c+='Developers |
',c+='Dan Salvato | | | |
',c+='Stendec | | | |
',c+='Version '+s.version_info+' | Logs |
',g.className="chat-menu-content center",g.innerHTML=c,g.querySelector("#ffz-changelog").addEventListener("click",function(){r._ui_change_page(t,n,i,e,"about_changelog")});var v=!1;g.querySelector("#ffz-debug-logs").addEventListener("click",function(){v||(v=!0,r._pastebin(r._log_data.join("\n"),function(t){v=!1,t?prompt("Your FrankerFaceZ logs have been uploaded to the URL:",t):alert("There was an error uploading the FrankerFaceZ logs.")}))}),e.appendChild(g)}}},{"../constants":5}],24:[function(e){var s=t.FrankerFaceZ,n=e("../constants");s.basic_settings.dark_twitch={type:"boolean",no_bttv:!0,category:"General",name:"Dark Twitch",help:"Apply a dark background to channels and other related pages for easier viewing.",get:function(){return this.settings.dark_twitch},set:function(t){this.settings.set("dark_twitch",t),this.settings.set("dark_no_blue",t)}},s.basic_settings.separated_chat={type:"boolean",no_bttv:!0,category:"Chat",name:"Separated Lines",help:"Use alternating rows and thin lines to visually separate chat messages for easier reading.",get:function(){return this.settings.chat_rows&&"0"!==this.settings.chat_separators},set:function(t){this.settings.set("chat_rows",t),this.settings.set("chat_separators",t?"2":"0")}},s.basic_settings.minimalistic_chat={type:"boolean",category:"Chat",name:"Minimalistic UI",help:"Hide all of chat except messages and the input box and reduce chat margins.",get:function(){return this.settings.minimal_chat&&this.settings.chat_padding},set:function(t){this.settings.set("minimal_chat",t),this.settings.set("chat_padding",t)}},s.basic_settings.high_contrast={type:"boolean",category:"Chat",no_bttv:!0,name:"High Contrast",help:"Display chat using white and black for maximum contrast. This is suitable for capturing and chroma keying chat to display on stream.",get:function(){return"222"!==this.settings.high_contrast_chat},set:function(t){this.settings.set("high_contrast_chat",t?"111":"222")}},s.basic_settings.keywords={type:"button",category:"Chat",no_bttv:!0,name:"Highlight Keywords",help:"Set additional keywords that will be highlighted in chat.",method:function(){s.settings_info.keywords.method.bind(this)()}},s.basic_settings.banned_words={type:"button",category:"Chat",no_bttv:!0,name:"Banned Keywords",help:"Set a list of words that will be removed from chat messages, locally.",method:function(){s.settings_info.banned_words.method.bind(this)()}},s.settings_info.twitch_chat_dark={type:"boolean",value:!1,visible:!1},s.settings_info.dark_twitch={type:"boolean",value:!1,no_bttv:!0,category:"Appearance",name:"Dark Twitch",help:"Apply a dark background to channels and other related pages for easier viewing.",on_update:function(e){var s=document.querySelector("input.ffz-setting-dark-twitch");if(s&&(s.checked=e),!this.has_bttv){document.body.classList.toggle("ffz-dark",e);var n=t.App?App.__container__.lookup("controller:settings").get("model"):void 0;e?(this._load_dark_css(),n&&this.settings.set("twitch_chat_dark",n.get("darkMode")),n&&n.set("darkMode",!0)):n&&n.set("darkMode",this.settings.twitch_chat_dark)}}},s.settings_info.dark_no_blue={type:"boolean",value:!1,category:"Appearance",name:"Gray Chat (no blue)",help:"Make the dark theme for chat and a few other places on Twitch a bit darker and not at all blue.",on_update:function(t){document.body.classList.toggle("ffz-no-blue",t)}},s.settings_info.hide_recent_past_broadcast={type:"boolean",value:!1,no_mobile:!0,category:"Channel Metadata",name:'Hide "Watch Last Broadcast"',help:'Hide the "Watch Last Broadcast" banner at the top of offline Twitch channels.',on_update:function(t){document.body.classList.toggle("ffz-hide-recent-past-broadcast",t)}},s.prototype.setup_dark=function(){document.body.classList.toggle("ffz-hide-recent-past-broadcast",this.settings.hide_recent_past_broadcast),document.body.classList.toggle("ffz-no-blue",this.settings.dark_no_blue),this.has_bttv||(document.body.classList.toggle("ffz-dark",this.settings.dark_twitch),this.settings.dark_twitch&&(t.App&&App.__container__.lookup("controller:settings").set("model.darkMode",!0),this._load_dark_css()))},s.prototype._load_dark_css=function(){if(!this._dark_style){this.log("Injecting FrankerFaceZ Dark Twitch CSS.");var t=this._dark_style=document.createElement("link");t.id="ffz-dark-css",t.setAttribute("rel","stylesheet"),t.setAttribute("href",n.SERVER+"script/dark.css?_="+(n.DEBUG?Date.now():s.version_info)),document.head.appendChild(t)}}},{"../constants":5}],25:[function(e){var s=t.FrankerFaceZ,n=e("../utils"),i=e("../constants"),o=function(t,e){return(t.settings.following_count&&"following"===e.parentElement.getAttribute("data-name")?"n":"")+(t.settings.swap_sidebars?"e":"w")},a=function(t,e){return!t.settings.following_count||"header_following"!==e.id&&"following"!==e.parentElement.getAttribute("data-name")?"":"ffz-wide-tip"};s.settings_info.following_count={type:"boolean",value:!0,no_mobile:!0,category:"Appearance",name:"Sidebar Following Data",help:"Display the number of live channels you're following on the sidebar, and list the channels in a tooltip.",on_update:function(){this._schedule_following_count();var e=t.App&&App.__container__.resolve("model:stream"),s=e&&e.find("live");if(s){var n=s.get("total")||0;this._draw_following_count(n),this._draw_following_channels(s.get("content"),n)}else this._update_following_count(),this._draw_following_channels()}},s.prototype.setup_following_count=function(e){if(this.settings.following_count&&this._schedule_following_count(),this._install_following_tooltips(),!e)return this._update_following_count();this.log("Connecting to Live Streams model.");var s=t.App&&App.__container__.resolve("model:stream");if(!s)return this.log("Unable to find Stream model.");var n=s.find("live"),i=this;if(!n)return this.log("Unable to find Live Streams collection.");n.addObserver("total",function(){i._draw_following_count(this.get("total"))}),n.addObserver("content.length",function(){i._draw_following_channels(this.get("content"),this.get("total"))}),n.load();var o=n.get("total"),a=n.get("content");"number"==typeof o&&(this._draw_following_count(o),a&&a.length&&this._draw_following_channels(a,o))},s.prototype._schedule_following_count=function(){return this.settings.following_count?void(this._following_count_timer||(this._following_count_timer=setTimeout(this._update_following_count.bind(this),55e3+1e4*Math.random()))):void(this._following_count_timer&&(clearTimeout(this._following_count_timer),this._following_count_timer=void 0))},s.prototype._update_following_count=function(){if(!this.settings.following_count)return void(this._following_count_timer&&(clearTimeout(this._following_count_timer),this._following_count_timer=void 0));this._following_count_timer=setTimeout(this._update_following_count.bind(this),55e3+1e4*Math.random());var e=t.App&&App.__container__.resolve("model:stream"),s=e&&e.find("live"),n=this;s?s.load():Twitch.api&&Twitch.api.get("streams/followed",{limit:5,offset:0},{version:3}).done(function(t){n._draw_following_count(t._total),n._draw_following_channels(t.streams,t._total)}).fail(function(){n._draw_following_count(),n._draw_following_channels()})},s.prototype._build_following_tooltip=function(t){if("header_following"!==t.id&&"following"!==t.parentElement.getAttribute("data-name"))return t.getAttribute("original-title");if(!this.settings.following_count)return"Following";var e=(this.has_bttv?'FrankerFaceZ':"")+"Following",s=t.getBoundingClientRect(),o=document.body.clientHeight-(s.bottom+54),a=Math.max(Math.floor(o/36)-1,2),r=this._tooltip_streams,d=this._tooltip_total||r&&r.length||0;
if(r&&r.length)for(var u=0,c=0,l=r.length;l>c;c++){var h=r[c];if(h&&h.channel){if(u+=1,u>a){e+="
And "+n.number_commas(d-a)+" more...";break}var f=this.settings.stream_uptime&&h.created_at&&n.parse_date(h.created_at),m=f&&Math.floor((Date.now()-f.getTime())/1e3)||0,_=Math.floor(m/60)%60,p=Math.floor(m/3600);e+=(0===c?"
":"")+(m>0?''+i.CLOCK+" "+(p>0?p+"h":"")+_+"m":"")+''+i.LIVE+" "+n.number_commas(h.viewers)+""+n.sanitize(h.channel.display_name||h.channel.name)+'
'+(h.channel.game?"Playing "+n.sanitize(h.channel.game):"Not Playing")+""}}else e+="
No one you're following is online.";return setTimeout(function(){var t=document.querySelector(".tipsy"),e=t.getBoundingClientRect(),s=parseInt(t.style.left||"0"),n=e.left+t.scrollWidth;e.left<5?t.style.left=s-e.left+5+"px":n>document.body.clientWidth-5&&(t.style.left=s-(5+n-document.body.clientWidth)+"px")}),e},s.prototype._install_following_tooltips=function(){var t=this,e={html:!0,className:function(){return a(t,this)},title:function(){return t._build_following_tooltip(this)}},s=jQuery('#small_nav ul.game_filters li[data-name="following"] a');if(s&&s.length){var n=s.data("tipsy");n&&n.options?(n.options=_.extend(n.options,e),n.options.gravity=function(){return o(t,this)}):s.tipsy(_.extend({gravity:function(){return o(t,this)}},e))}var i=jQuery('#large_nav #nav_personal li[data-name="following"] a');if(i&&i.length){var n=i.data("tipsy");n&&n.options?n.options=_.extend(n.options,e):i.tipsy(e)}var r=jQuery("#header_actions #header_following");if(r&&r.length){var n=r.data("tipsy");n&&n.options?n.options=_.extend(n.options,e):r.tipsy(e)}},s.prototype._draw_following_channels=function(t,e){this._tooltip_streams=t,this._tooltip_total=e},s.prototype._draw_following_count=function(t){var e=document.querySelector('#small_nav ul.game_filters li[data-name="following"] a');if(e){var s=e.querySelector(".ffz-follow-count");this.has_bttv||!this.settings.following_count?s&&s.parentElement.removeChild(s):(s||(s=document.createElement("span"),s.className="ffz-follow-count",e.appendChild(s)),s.innerHTML=t?n.format_unread(t):"")}var i=document.querySelector('#large_nav #nav_personal li[data-name="following"] a');if(i){var s=i.querySelector(".ffz-follow-count");this.has_bttv||!this.settings.following_count?s&&s.parentElement.removeChild(s):(s||(s=document.createElement("span"),s.className="ffz-follow-count",i.appendChild(s)),s.innerHTML=t?n.format_unread(t):"")}var o=document.querySelector("#header_actions #header_following");if(o){var s=o.querySelector(".ffz-follow-count");this.has_bttv||!this.settings.following_count?s&&s.parentElement.removeChild(s):(s||(s=document.createElement("span"),s.className="ffz-follow-count",o.appendChild(s)),s.innerHTML=t?n.format_unread(t):"")}}},{"../constants":5,"../utils":35}],26:[function(e){var s=t.FrankerFaceZ,n=e("../utils"),i=/^[A-Za-z0-9_]+$/,o=/^(?:https?:\/\/)?(?:www\.)?twitch\.tv\/([A-Za-z0-9_]+)/i;s.prototype.setup_following=function(){this.log("Initializing following support."),this.follow_data={},this.follow_sets={}},s.settings_info.follow_buttons={type:"boolean",value:!0,no_mobile:!0,category:"Channel Metadata",name:"Relevant Follow Buttons",help:"Display additional Follow buttons for channels relevant to the stream, such as people participating in co-operative gameplay.",on_update:function(){this.rebuild_following_ui()}},s.ffz_commands.following=function(t,e){e=e.join(" ").trim().toLowerCase().split(/[ ,]+/);for(var s=[],n=0,i=e.length;i>n;n++){var a=e[n],r=a.match(o);r&&(a=r[1]),""!==a&&-1===s.indexOf(a)&&s.push(a)}var d=this.get_user(),u=this;return!d||d.login!==t.id&&"sirstendec"!==d.login&&"dansalvato"!==d.login?"You must be logged in as the broadcaster to use this command.":this.ws_send("update_follow_buttons",[t.id,s],function(e,s){return e?void(s?u.room_message(t,"The following buttons have been updated."):u.room_message(t,"The following buttons have been disabled.")):void u.room_message(t,"There was an error updating the following buttons.")})?void 0:"There was an error communicating with the server."},s.ws_on_close.push(function(){var e=t.App&&App.__container__.lookup("controller:channel"),s=e&&e.get("id"),n=e&&e.get("hostModeTarget.id"),i=!1;if(this.follow_sets={},e){for(var o in this.follow_data)if(delete this.follow_data[o],(o===s||o===n)&&(i=!0),this.rooms&&this.rooms[o]&&this.rooms[o].extra_sets){var a=this.rooms[o].extra_sets;delete this.rooms[o].extra_sets;for(var r=0;r span")}catch(d){r=void 0}r?o.insertBefore(a,r):o.appendChild(a)}for(var u=[e],c=0;cc;c++){var l=n[c];-1===u.indexOf(l)&&(this._build_following_button(a,l),u.push(l))}}else a&&a.parentElement.removeChild(a)}if(s){var n=this.follow_data&&this.follow_data[s],i=this._cindex.get("element"),o=i&&i.querySelector("#hostmode .channel-actions"),a=o&&o.querySelector("#ffz-ui-following");if(o&&this.settings.follow_buttons&&n&&n.length){if(a)a.innerHTML="";else{a=document.createElement("span"),a.id="ffz-ui-following";var r;try{r=o.querySelector(":scope > span")}catch(d){r=void 0}r?o.insertBefore(a,r):o.appendChild(a)}for(var u=[s],c=0;cc;c++){var l=n[c];-1===u.indexOf(l)&&(this._build_following_button(a,l),u.push(l))}}else a&&a.parentElement.removeChild(a)}}},s.prototype._build_following_button=function(e,o){if(!i.test(o))return this.log("Ignoring Invalid Channel: "+n.sanitize(o));var a,r=document.createElement("a"),d=this,u=document.createElement("div"),c=document.createElement("a"),l=document.createElement("div"),h=!1,f=!1,m=function(){u.classList.toggle("is-following",h),r.title=(h?"Unf":"F")+"ollow "+n.sanitize(a),r.innerHTML=(h?"":"Follow ")+n.sanitize(a),l.classList.toggle("hidden",!h)},_=function(){var t=d.get_user();return t&&t.login?void Twitch.api.get("users/"+t.login+"/follows/channels/"+o).done(function(t){h=!0,f=t.notifications,u.classList.add("is-initialized"),m()}).fail(function(){h=!1,f=!1,u.classList.add("is-initialized"),m()}):(h=!1,notification=!1,u.classList.add("is-initialized"),m())},p=function(t){t!==!1&&(t=!0);var e=d.get_user();return e&&e.login?(f=t,Twitch.api.put("users/:login/follows/channels/"+o,{notifications:f}).fail(_)):null},g=function(t){a=t||o,m()};u.className="ember-follow follow-button",u.appendChild(r),c.className="toggle-notification-menu js-toggle-notification-menu",c.href="#",l.className="notification-controls v2 hidden",l.appendChild(c),r.addEventListener("click",function(){var t=d.get_user();return t&&t.login?(h=!h,m(),d.ws_send("track_follow",[o,h]),h?p():Twitch.api.del("users/:login/follows/channels/"+o).done(_),!1):Ember.$.login({mpSourceAction:"follow-button",follow:o})}),r.addEventListener("mousedown",function(e){1===e.button&&(e.preventDefault(),t.open(Twitch.uri.profile(o)))}),c.addEventListener("click",function(){var t=d._build_following_popup(l,o,f);return t&&t.addEventListener("click",function(){var e=!f;return t.classList.toggle("active",e),p(e),!1}),!1}),a=s.get_capitalization(o,g),m(),setTimeout(_,5e3*Math.random()),e.appendChild(u),e.appendChild(l)},s.prototype._build_following_popup=function(t,e,n){var i=this._popup,o="",a=t.offsetLeft+t.offsetWidth;return i&&(i.parentElement.removeChild(i),delete this._popup,this._popup_kill&&this._popup_kill(),delete this._popup_kill,"ffz-following-popup"==i.id&&i.getAttribute("data-channel")===e)?null:(i=this._popup=document.createElement("div"),i.id="ffz-following-popup",i.setAttribute("data-channel",e),i.className=(a>=300?"right":"left")+" dropmenu notify-menu js-notify",o='",o+='',o+='',o+='Notify me when the broadcaster goes live',o+="
",i.innerHTML=o,t.appendChild(i),i.querySelector("a.switch"))}},{"../utils":35}],27:[function(e){var s=t.FrankerFaceZ,n=e("../constants"),i=e("../utils"),o="http://static-cdn.jtvnw.net/emoticons/v1/",a=function(t){var e=document.body.classList.contains("ffz-sidebar-swap"),s=t.getBoundingClientRect(),n=parseInt(t.style.left||"0"),i=s.left+t.scrollWidth,o=!!t.style.left;e?s.left<20?(t.style.left="",o=!1):i>document.body.clientWidth&&(t.style.left=n-(i-document.body.clientWidth)+"px"):s.left<0?t.style.left=n-s.left+"px":i>document.body.clientWidth-20&&(t.style.left="",o=!1),t.classList.toggle("ui-moved",o)};s.prototype.setup_menu=function(){this.log("Installing mouse-up event to auto-close menus.");var e=this;jQuery(document).mouseup(function(t){var s,n=e._popup;n&&("ffz-chat-menu"===n.id&&n.style&&n.style.left||(n=jQuery(n),s=n.parent(),s.is(t.target)||0!==s.has(t.target).length||(n.remove(),delete e._popup,e._popup_kill&&e._popup_kill(),delete e._popup_kill)))}),document.body.classList.toggle("ffz-menu-replace",this.settings.replace_twitch_menu),this.log("Hooking the Ember Chat Settings view.");var s=t.App&&App.__container__.resolve("view:settings");if(s){s.reopen({didInsertElement:function(){this._super();try{this.ffzInit()}catch(t){e.error("ChatSettings didInsertElement: "+t)}},willClearRender:function(){try{this.ffzTeardown()}catch(t){e.error("ChatSettings willClearRender: "+t)}this._super()},ffzInit:function(){var t=this,s=this.get("element"),n=s&&s.querySelector(".dropmenu");if(n){var i,o,a,r=document.createElement("div"),d=document.createElement("div");r.className="list-header",r.innerHTML="FrankerFaceZ",d.className="chat-menu-content",i=document.createElement("p"),i.className="no-bttv",o=document.createElement("input"),o.type="checkbox",o.className="ember-checkbox ffz-setting-dark-twitch",o.checked=e.settings.dark_twitch,i.appendChild(o),i.appendChild(document.createTextNode("Dark Twitch")),d.appendChild(i),o.addEventListener("change",function(){e.settings.set("dark_twitch",this.checked)}),i=document.createElement("p"),o=document.createElement("input"),o.type="checkbox",o.className="ember-checkbox ffz-setting-hosted-channels",o.checked=e.settings.hosted_channels,i.appendChild(o),i.appendChild(document.createTextNode("Channel Hosting")),d.appendChild(i),o.addEventListener("change",function(){e.settings.set("hosted_channels",this.checked)}),i=document.createElement("p"),a=document.createElement("a"),a.href="#",a.innerHTML="More Settings",i.appendChild(a),d.appendChild(i),a.addEventListener("click",function(s){return t.set("controller.model.hidden",!0),e._last_page="settings",e.build_ui_popup(e._chatv),s.stopPropagation(),!1}),n.appendChild(r),n.appendChild(d)}},ffzTeardown:function(){}});try{s.create().destroy()}catch(n){}for(var i in Ember.View.views)if(Ember.View.views.hasOwnProperty(i)){var o=Ember.View.views[i];if(o instanceof s){this.log("Manually updating existing Chat Settings view.",o);try{o.ffzInit()}catch(n){this.error("setup: ChatSettings ffzInit: "+n)}}}}},s.menu_pages={},s.prototype._fix_menu_position=function(){var t=document.querySelector("#ffz-chat-menu");t&&a(t)},s.prototype.build_ui_popup=function(t){var e=this._popup;if(e)return e.parentElement.removeChild(e),delete this._popup,this._popup_kill&&this._popup_kill(),void delete this._popup_kill;var i=document.createElement("div"),o=document.createElement("div"),r=document.createElement("ul"),d=this.has_bttv?BetterTTV.settings.get("darkenedMode"):!1;i.className="emoticon-selector chat-menu ffz-ui-popup",i.id="ffz-chat-menu",o.className="emoticon-selector-box dropmenu",i.appendChild(o),i.classList.toggle("dark",d);var u=document.createElement("div");u.className="ffz-ui-menu-page",o.appendChild(u),r.className="menu clearfix",o.appendChild(r);var c=document.createElement("li");c.className="title",c.innerHTML='Franker'+(n.DEBUG?"Dev":"Face")+"Z";var l=document.createElement("span"),h=this;l.className="ffz-handle ffz-close-button",c.insertBefore(l,c.firstChild);var f=!1;l.addEventListener("mousedown",function(){var t=h._popup;f=t&&"ffz-chat-menu"===t.id&&t.style.left}),l.addEventListener("click",function(){var t=h._popup;f&&t&&(t.parentElement.removeChild(t),delete h._popup,h._popup_kill&&h._popup_kill(),delete h._popup_kill)}),r.appendChild(c),jQuery(i).draggable({handle:r,cancel:"li.item",axis:"x",stop:function(){a(this)}}),i.style.position="";var m=[];for(var _ in s.menu_pages)if(s.menu_pages.hasOwnProperty(_)){var p=s.menu_pages[_];try{if(!p||p.hasOwnProperty("visible")&&(!p.visible||"function"==typeof p.visible&&!p.visible.bind(this)(t)))continue}catch(g){this.error("menu_pages "+_+" visible: "+g);continue}m.push([p.sort_order||0,_,p])}m.sort(function(t,e){if(t[0]e[0])return-1;var s=t[1].toLowerCase(),n=e[1].toLowerCase();return n>s?1:s>n?-1:0});for(var v=0;v0,!l||h||f||(l.addObserver("isLoaded",function(){setTimeout(function(){"channel"===n.getAttribute("data-page")&&(n.innerHTML="",s.menu_pages.channel.render.bind(u)(e,n))},0)}),l.load()),_.className="emoticon-grid",p.className="heading",m&&(p.style.backgroundImage='url("'+m+'")'),p.innerHTML='TwitchSubscriber Emoticons',_.appendChild(p);for(var v=c.get("emoticons")||[],b=0;b0&&n.appendChild(_),g>0&&!h){var E=document.createElement("div"),C=document.createElement("div"),x=document.createElement("span"),T=document.createElement("a");E.className="subscribe-message",C.className="non-subscriber-message",E.appendChild(C),x.className="unlock-text",x.innerHTML="Subscribe to unlock Emoticons",C.appendChild(x),T.className="action subscribe-button button primary",T.href=c.get("product_url"),T.innerHTML='Subscribe'+c.get("price")+"",C.appendChild(T),n.appendChild(E)}else if(g>0){var L=l.get("content");if(L=L.length>0?L[L.length-1]:void 0,L&&L.purchase_profile&&!L.purchase_profile.will_renew){var M=i.parse_date(L.access_end||"");E=document.createElement("div"),C=document.createElement("div"),x=document.createElement("span"),end_time=M?Math.floor((M.getTime()-Date.now())/1e3):null,E.className="subscribe-message",C.className="non-subscriber-message",E.appendChild(C),x.className="unlock-text",x.innerHTML="Subscription expires in "+i.time_to_string(end_time,!0,!0),C.appendChild(x),n.appendChild(E)}}}}var S=r&&r.extra_sets||[];this._emotes_for_sets(n,e,r&&r.set&&[r.set]||[],this.feature_friday||d||S.length?"Channel Emoticons":null,"http://cdn.frankerfacez.com/script/devicon.png","FrankerFaceZ");for(var b=0;bs?-1:s>n?1:0});for(var f=0;f0&&(o=!0)}e.classList.toggle("no-emotes",!o),e.classList.toggle("live",d),e.classList.toggle("dark",a),e.classList.toggle("blue",r)}}},{"../constants":5}],29:[function(e){var s=t.FrankerFaceZ,n=e("../constants"),i=e("../utils"),o="http://static-cdn.jtvnw.net/emoticons/v1/";s.basic_settings.replace_twitch_menu={type:"boolean",category:"Chat",name:"Unified Emoticons Menu",help:"Completely replace the default Twitch emoticon menu and display global emoticons in the My Emoticons menu.",get:function(){return this.settings.replace_twitch_menu&&this.settings.global_emotes_in_menu&&this.settings.emoji_in_menu},set:function(t){this.settings.set("replace_twitch_menu",t),this.settings.set("global_emotes_in_menu",t),this.settings.set("emoji_in_menu",t)}},s.settings_info.replace_twitch_menu={type:"boolean",value:!1,category:"Chat Input",name:"Replace Twitch Emoticon Menu",help:"Completely replace the default Twitch emoticon menu.",on_update:function(t){document.body.classList.toggle("ffz-menu-replace",t)}},s.settings_info.global_emotes_in_menu={type:"boolean",value:!1,category:"Chat Input",name:"Display Global Emotes in My Emotes",help:"Display the global Twitch emotes in the My Emoticons menu."},s.settings_info.emoji_in_menu={type:"boolean",value:!1,category:"Chat Input",name:"Display Emoji in My Emotes",help:"Display the supported emoji images in the My Emoticons menu."},s.settings_info.emote_menu_collapsed={value:[],visible:!1},s.prototype.setup_my_emotes=function(){this._twitch_badges={},this._twitch_badges["--global--"]="//cdn.frankerfacez.com/script/twitch_logo.png",this._twitch_badges["--turbo-faces--"]=this._twitch_badges.turbo="//cdn.frankerfacez.com/script/turbo_badge.png"},s.menu_pages.myemotes={name:"My Emoticons",icon:n.EMOTE,visible:function(t){var e=this.get_user(),s=t.get("controller.currentRoom.tmiSession"),n=e&&this.users[e.login]&&this.users[e.login].sets||[],i=(s&&s.getEmotes()||{emoticon_sets:{}}).emoticon_sets;return n.length||i&&Object.keys(i).length},render:function(t,e){var n=t.get("controller.currentRoom.tmiSession"),i=(n&&n.getEmotes()||{emoticon_sets:{}}).emoticon_sets;return s.menu_pages.myemotes.draw_menu.bind(this)(t,e,i)},toggle_section:function(t){var e=t.parentElement,s=e.getAttribute("data-set"),n=this.settings.emote_menu_collapsed,i=-1!==n.indexOf(s);i?n.removeObject(s):n.push(s),this.settings.set("emote_menu_collapsed",n),e.classList.toggle("collapsed",!i)},draw_emoji:function(t){var e=document.createElement("div"),i=document.createElement("div"),o=this;e.className="heading",e.innerHTML='FrankerFaceZEmoji',e.style.backgroundImage='url("'+n.SERVER+'/emoji/1f4af-1x.png")',i.className="emoticon-grid collapsable",i.appendChild(e),i.setAttribute("data-set","emoji"),i.classList.toggle("collapsed",-1!==this.settings.emote_menu_collapsed.indexOf("emoji")),e.addEventListener("click",function(){s.menu_pages.myemotes.toggle_section.bind(o)(this)});var a=[];for(var r in this.emoji_data)a.push(this.emoji_data[r]);a.sort(function(t,e){var s=t.short_name.toLowerCase(),n=e.short_name.toLowerCase();return n>s?-1:s>n?1:t.rawe.raw?1:0});for(var d=0;dTwitch'+i.sanitize(t)}),u.className="heading",u.innerHTML='Twitch'+i.sanitize(d),this._twitch_badges[h])u.style.backgroundImage='url("'+this._twitch_badges[h]+'")';else{var l=this;Twitch.api.get("chat/"+h+"/badges",null,{version:3}).done(function(t){t.subscriber&&t.subscriber.image&&(l._twitch_badges[h]=t.subscriber.image,localStorage.ffzTwitchBadges=JSON.stringify(l._twitch_badges),u.style.backgroundImage='url("'+t.subscriber.image+'")')})}c.className="emoticon-grid collapsable",c.appendChild(u),c.setAttribute("data-set","twitch-"+a),c.classList.toggle("collapsed",-1!==this.settings.emote_menu_collapsed.indexOf("twitch-"+a)),u.addEventListener("click",function(){s.menu_pages.myemotes.toggle_section.bind(l)(this)}),r.sort(function(t,e){var s=t.code.toLowerCase(),n=e.code.toLowerCase();return n>s?-1:s>n?1:t.ide.id?1:0});for(var f=0;fFrankerFaceZ'+n.title,i.style.backgroundImage='url("'+(n.icon||"//cdn.frankerfacez.com/script/devicon.png")+'")',o.className="emoticon-grid collapsable",o.appendChild(i),o.setAttribute("data-set","ffz-"+n.id),o.classList.toggle("collapsed",-1!==this.settings.emote_menu_collapsed.indexOf("ffz-"+n.id)),i.addEventListener("click",function(){s.menu_pages.myemotes.toggle_section.bind(a)(this)});for(var d in n.emoticons)n.emoticons.hasOwnProperty(d)&&!n.emoticons[d].hidden&&r.push(n.emoticons[d]);r.sort(function(t,e){var s=t.name.toLowerCase(),n=e.name.toLowerCase();return n>s?-1:s>n?1:t.ide.id?1:0});for(var u=0;us?-1:s>n?1:0});for(var u=0;us)&&(s=60),this.settings.set("notification_timeout",s)}}},e.ws_commands.message=function(t){this.show_message(t)},e._notifications={},e._last_notification=0,e.prototype.clear_notifications=function(){for(var t in e._notifications){var s=e._notifications[t];if(s)try{s.close()}catch(n){}}e._notifications={},e._last_notification=0},e.prototype.show_notification=function(t,s,n,i,o,a){var r=Notification.permission;if("denied "===r)return!1;if("granted"===r){s=s||"FrankerFaceZ",i=i||1e3*this.settings.notification_timeout;
var d={lang:"en-US",dir:"ltr",body:t,tag:n||"FrankerFaceZ",icon:"http://cdn.frankerfacez.com/icon32.png"},u=this,c=new Notification(s,d),l=e._last_notification++;return e._notifications[l]=c,c.addEventListener("click",function(){delete e._notifications[l],o&&o.bind(u)()}),c.addEventListener("close",function(){delete e._notifications[l],a&&a.bind(u)()}),void("number"==typeof i&&c.addEventListener("show",function(){setTimeout(function(){delete e._notifications[l],c.close()},i)}))}var u=this;Notification.requestPermission(function(){u.show_notification(t,s,n)})},e.prototype.show_message=function(e){t.noty({text:e,theme:"ffzTheme",layout:"bottomCenter",closeWith:["button"]}).show()}},{}],31:[function(e){var s=t.FrankerFaceZ,n=e("../utils");s.prototype.setup_races=function(){this.log("Initializing race support."),this.srl_races={}},s.settings_info.srl_races={type:"boolean",value:!0,no_mobile:!0,category:"Channel Metadata",name:"SRL Race Information",help:'Display information about SpeedRunsLive races under channels.',on_update:function(){this.rebuild_race_ui()}},s.ws_on_close.push(function(){var e=t.App&&App.__container__.lookup("controller:channel"),s=e&&e.get("id"),n=e&&e.get("hostModeTarget.id"),i=!1;if(e){for(var o in this.srl_races)delete this.srl_races[o],(o===s||o===n)&&(i=!0);i&&this.rebuild_race_ui()}}),s.ws_commands.srl_race=function(t){var e=App.__container__.lookup("controller:channel"),s=e&&e.get("id"),n=e&&e.get("hostModeTarget.id"),i=!1;this.srl_races=this.srl_races||{};for(var o=0;o',r.addEventListener("click",this._build_race_popup.bind(this,a,e)),a.appendChild(r),o.appendChild(a)}this._update_race(a,!0)}else a&&a.parentElement.removeChild(a)}if(s){var n=this.srl_races&&this.srl_races[s],i=this._cindex.get("element"),o=i&&i.querySelector("#hostmode .channel-actions"),a=o&&o.querySelector("#ffz-ui-race");if(o&&this.settings.srl_races&&n){if(!a){a=document.createElement("span"),a.id="ffz-ui-race",a.setAttribute("data-channel",s);var r=document.createElement("span");r.className="button drop action",r.title="SpeedRunsLive Race",r.innerHTML='',r.addEventListener("click",this._build_race_popup.bind(this,a,s)),a.appendChild(r),o.appendChild(a)}this._update_race(a,!0)}else a&&a.parentElement.removeChild(a)}}},s.prototype._race_kill=function(){this._race_timer&&(clearTimeout(this._race_timer),delete this._race_timer),delete this._race_game,delete this._race_goal},s.prototype._build_race_popup=function(t,e){var n=this._popup;if((!n||(n.parentElement.removeChild(n),delete this._popup,this._popup_kill&&this._popup_kill(),delete this._popup_kill,"ffz-race-popup"!==n.id||n.getAttribute("data-channel")!==e))&&t){var i=t.querySelector(".button"),o=i.offsetLeft+i.offsetWidth,a=this.srl_races[e],n=document.createElement("div"),r="";n.id="ffz-race-popup",n.setAttribute("data-channel",e),n.className=(o>=300?"right":"left")+" share dropmenu",this._popup_kill=this._race_kill.bind(this),this._popup=n;var d="http://kadgar.net/live",u=!1;for(var c in a.entrants){var l=a.entrants[c].state;a.entrants.hasOwnProperty(c)&&a.entrants[c].channel&&("racing"==l||"entered"==l)&&(d+="/"+a.entrants[c].channel,u=!0)}var h=document.querySelector(".app-main.theatre")?document.body.clientHeight-300:t.parentElement.offsetTop-175,f=App.__container__.lookup("controller:channel"),m=f?f.get("display_name"):s.get_capitalization(e),_=encodeURIComponent("I'm watching "+m+" race "+a.goal+" in "+a.game+" on SpeedRunsLive!");r='',r+='",r+='',r+='',r+='SRL',u&&(r+=' Multitwitch'),r+="
",n.innerHTML=r,t.appendChild(n),this._update_race(t,!0)}},s.prototype._update_race=function(t,e){if(this._race_timer&&e&&(clearTimeout(this._race_timer),delete this._race_timer),t){var s=t.getAttribute("data-channel"),i=this.srl_races[s];if(!i)return t.parentElement.removeChild(t),void(this._popup&&"ffz-race-popup"===this._popup.id&&this._popup.getAttribute("data-channel")===s&&(this._popup_kill&&this._popup_kill(),this._popup&&(delete this._popup,delete this._popup_kill)));var o=i.twitch_entrants[s],a=i.entrants[o],r=t.querySelector("#ffz-race-popup"),d=Date.now()/1e3,u=Math.floor(d-i.time);if(t.querySelector(".logo").innerHTML=n.placement(a),r){var c=r.querySelector("tbody"),l=r.querySelector(".heading span"),h=r.querySelector(".heading div");c.innerHTML="";var f=[],m=!0;for(var _ in i.entrants)i.entrants.hasOwnProperty(_)&&("racing"==i.entrants[_].state&&(m=!1),f.push(i.entrants[_]));f.sort(function(t,e){var s=t.place||9999,n=e.place||9999,i=t.time||u,o=e.time||u;return("forfeit"==t.state||"dq"==t.state)&&(s=1e4),("forfeit"==e.state||"dq"==e.state)&&(n=1e4),n>s?-1:s>n?1:t.namee.name?1:o>i?-1:i>o?1:void 0});for(var p=0;p'+_.display_name+"",v=_.channel?'':"",b=_.hitbox?'':"",y=u?n.time_to_string(_.time||u):"",w=n.place_string(_.place),z=_.comment?n.sanitize(_.comment):"";c.innerHTML+="'+w+" | "+g+" | "+v+b+' | '+("forfeit"==_.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=n.sanitize(i.game),E=n.sanitize(i.goal);h.innerHTML=''+k+"
Goal: "+E}u?m?l.innerHTML="Done":(l.innerHTML=n.time_to_string(u),this._race_timer=setTimeout(this._update_race.bind(this,t),1e3)):l.innerHTML="Entry Open"}}}},{"../utils":35}],32:[function(e){var s=t.FrankerFaceZ,n=e("../constants");s.prototype.setup_css=function(){this.log("Injecting main FrankerFaceZ CSS.");var t=this._main_style=document.createElement("link");t.id="ffz-ui-css",t.setAttribute("rel","stylesheet"),t.setAttribute("href",n.SERVER+"script/style.css?_="+(n.DEBUG?Date.now():s.version_info)),document.head.appendChild(t),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":5}],33:[function(e){{var s=t.FrankerFaceZ,n=e("../constants");e("../utils")}s.prototype._update_subscribers=function(){this._update_subscribers_timer&&(clearTimeout(this._update_subscribers_timer),delete this._update_subscribers_timer),this._update_subscribers_timer=setTimeout(this._update_subscribers.bind(this),6e4);var t=this.get_user(),e=this,s=this.is_dashboard?location.pathname.match(/\/([^\/]+)/):void 0,i=this.is_dashboard&&s&&s[1];if(this.has_bttv||!i||i!==t.login){var o=document.querySelector("#ffz-sub-display");return void(o&&o.parentElement.removeChild(o))}jQuery.ajax({url:"/broadcast/dashboard/partnership"}).done(function(t){try{var s,o=document.createElement("span");o.innerHTML=t,s=o.querySelector("#dash_main");var a=s&&s.textContent.match(/([\d,\.]+) total active subscribers/),r=a&&a[1];if(!r){var d=document.querySelector("#ffz-sub-display");return d&&d.parentElement.removeChild(d),void(e._update_subscribers_timer&&(clearTimeout(e._update_subscribers_timer),delete e._update_subscribers_timer))}var d=document.querySelector("#ffz-sub-display span");if(!d){var u=document.querySelector(e.is_dashboard?"#stats":"#channel .stats-and-actions .channel-stats");if(!u)return;var c=document.createElement("span");c.className="ffz stat",c.id="ffz-sub-display",c.title="Active Channel Subscribers",c.innerHTML=n.STAR+" ",d=document.createElement("span"),c.appendChild(d),Twitch.api.get("chat/"+i+"/badges",null,{version:3}).done(function(t){t.subscriber&&t.subscriber.image&&(c.innerHTML="",c.appendChild(d),c.style.backgroundImage='url("'+t.subscriber.image+'")',c.style.backgroundRepeat="no-repeat",c.style.paddingLeft="23px",c.style.backgroundPosition="0 50%")}),u.appendChild(c),jQuery(c).tipsy(e.is_dashboard?{gravity:"s"}:void 0)}d.innerHTML=r}catch(l){e.error("_update_subscribers: "+l)}}).fail(function(){var t=document.querySelector("#ffz-sub-display");t&&t.parentElement.removeChild(t)})}},{"../constants":5,"../utils":35}],34:[function(e){var s=t.FrankerFaceZ,n=e("../constants"),i=e("../utils");s.ws_commands.chatters=function(e){{var s=e[0],n=e[1],i=t.App&&App.__container__.lookup("controller:channel"),o=this.is_dashboard?location.pathname.match(/\/([^\/]+)/):void 0;this.is_dashboard?o&&o[1]:i&&i.get&&i.get("id")}if(!this.is_dashboard){var a=this.rooms&&this.rooms[s];return void(a&&(a.ffz_chatters=n,this._cindex&&this._cindex.ffzUpdateChatters()))}this._dash_chatters=n},s.ws_commands.viewers=function(e){var s=e[0],o=e[1],a=t.App&&App.__container__.lookup("controller:channel"),r=this.is_dashboard?location.pathname.match(/\/([^\/]+)/):void 0,d=this.is_dashboard?r&&r[1]:a&&a.get&&a.get("id");if(!this.is_dashboard){var u=this.rooms&&this.rooms[s];return void(u&&(u.ffz_viewers=o,this._cindex&&this._cindex.ffzUpdateChatters()))}if(this._dash_viewers=o,this.settings.chatter_count&&d===s){var c=document.querySelector("#ffz-ffzchatter-display"),l=n.ZREKNARF+" "+i.number_commas(o)+("number"==typeof this._dash_chatters?" ("+i.number_commas(this._dash_chatters)+")":"");if(c)c.innerHTML=l;else{var h=document.querySelector("#stats");if(!h)return;c=document.createElement("span"),c.id="ffz-ffzchatter-display",c.className="ffz stat",c.title="Viewers (In Chat) with FrankerFaceZ",c.innerHTML=l,h.appendChild(c),jQuery(c).tipsy(this.is_dashboard?{gravity:"s"}:void 0)}}}},{"../constants":5,"../utils":35}],35:[function(e,s){var n=(t.FrankerFaceZ,e("./constants"),document.createElement("span")),i=function(t){return n.textContent=t,n.innerHTML},o=/"/g,a=/'/g,r=/&/g,d=//g,c=function(t){return t.replace(r,"&").replace(o,""").replace(a,"'").replace(d,"<").replace(u,">")},l=function(t,e,s){return s=s||"s",e=e||"",1===t?e:s},h=function(t){return 1==t?"1st":2==t?"2nd":3==t?"3rd":null==t?"---":t+"th"},f=/^(\d{4}|\+\d{6})(?:-?(\d{2})(?:-?(\d{2})(?:T(\d{2})(?::?(\d{2})(?::?(\d{2})(?:(?:\.|,)(\d{1,}))?)?)?(Z|([\-+])(\d{2})(?::?(\d{2}))?)?)?)?)?$/,m=function(t){var e=t.match(f);if(!e)return null;e[7]=e[7]&&e[7].length?e[7].substr(0,3):0;var s=Date.UTC(e[1],e[2]-1,e[3],e[4],e[5],e[6],e[7]);if(e[9]){var n=6e4*("-"==e[9]?1:-1)*(60*e[10]+1*e[11]);s+=n}return new Date(s)},_=function(t){t=$.trim(t);var e={raw:t},s=-1;"@"===t.charAt(0)&&(s=t.indexOf(" "),e.tags=t.substr(1,s-1));var n=s+1,i=-1;":"===t.charAt(n)&&(i=t.indexOf(" ",n),e.prefix=t.substr(n+1,i-(n+1)));var o=t.indexOf(" :",n);o>=0?e.trailing=t.substr(o+2):o=t.length;var a=t.substr(i+1,o-i-1).split(" ");return e.command=a[0],a.length>1&&(e.params=a.slice(1)),e},p={":":";",s:" ",r:"\r",n:"\n","\\":"\\"},g=function(t){for(var e="",s=0;s=55296&&56319>=i?o=i:n.push(i.toString(16));var r=y[t]=y[t]||{},d=r[e]=n.join("-");return d};s.exports={update_css:function(t,e,s){var n=t.innerHTML,i="/*BEGIN "+e+"*/",o="/*END "+e+"*/",a=n.indexOf(i),r=n.indexOf(o),d=-1!==a&&-1!==r&&r>a;(d||s)&&(d&&(n=n.substr(0,a)+n.substr(r+o.length)),s&&(n+=i+s+o),t.innerHTML=n)},splitIRCMessage:_,parseIRCTags:b,emoji_to_codepoint:w,parse_date:m,number_commas:function(t){var e=t.toString().split(".");return e[0]=e[0].replace(/\B(?=(\d{3})+(?!\d))/g,","),e.join(".")},place_string:h,placement:function(t){return"forfeit"==t.state?"Forfeit":"dq"==t.state?"DQed":t.place?h(t.place):""},sanitize:i,quote_attr:c,date_string:function(t){return t.getFullYear()+"-"+(t.getMonth()+1)+"-"+t.getDate()},pluralize:l,human_time:function(t,e){e=e||1,t=Math.floor(t);var s=Math.floor(t*e/31536e3)/e;if(s>=1)return s+" year"+l(s);var n=Math.floor((t%=31536e3)/86400);if(n>=1)return n+" day"+l(n);var i=Math.floor((t%=86400)/3600);if(i>=1)return i+" hour"+l(i);var o=Math.floor((t%=3600)/60);if(o>=1)return o+" minute"+l(o);var a=t%60;return a>=1?a+" second"+l(a):"less than a second"},time_to_string:function(t,e,s,n){var i=t%60,o=Math.floor(t/60),a=Math.floor(o/60),r="";if(o%=60,e){if(r=Math.floor(a/24),a%=24,s&&r>0)return r+" days";r=r>0?r+" days, ":""}return r+(!n||r||a?(10>a?"0":"")+a+":":"")+(10>o?"0":"")+o+":"+(10>i?"0":"")+i},format_unread:function(t){return 1>t?"":t>=99?"99+":""+t}}},{"./constants":5}]},{},[18]),t.ffz=new FrankerFaceZ}(window);
\ No newline at end of file
diff --git a/src/ember/line.js b/src/ember/line.js
index 1c7529ef..678544cf 100644
--- a/src/ember/line.js
+++ b/src/ember/line.js
@@ -824,7 +824,7 @@ FFZ.get_capitalization = function(name, callback) {
// ---------------------
FFZ.prototype._remove_banned = function(tokens) {
- var banned_words = this.settings.banned_words;
+ var banned_words = _.union(['j.mp', 'bit.ly'], this.settings.banned_words);
if ( ! banned_words || ! banned_words.length )
return tokens;
@@ -847,10 +847,6 @@ FFZ.prototype._remove_banned = function(tokens) {
isLong: false,
censoredHref: token.href.replace(regex, "$1***")
});
- /*{
- mentionedUser: '<banned link>',
- own: true
- });*/
else
new_tokens.push(token);
diff --git a/src/main.js b/src/main.js
index b6187c0c..a5de7ec3 100644
--- a/src/main.js
+++ b/src/main.js
@@ -21,7 +21,7 @@ FFZ.get = function() { return FFZ.instance; }
// Version
var VER = FFZ.version_info = {
- major: 3, minor: 5, revision: 12,
+ major: 3, minor: 5, revision: 13,
toString: function() {
return [VER.major, VER.minor, VER.revision].join(".") + (VER.extra || "");
}
diff --git a/style.css b/style.css
index f0a4fd33..dc5eb719 100644
--- a/style.css
+++ b/style.css
@@ -556,6 +556,9 @@ body:not(.ffz-minimal-chat):not(.ffz-menu-replace) .emoticon-selector-toggle + s
list-style-type: none;
border-top: 1px solid rgba(0,0,0,0.2);
background-color: #eee;
+}
+
+.ffz-ui-popup ul.menu:not(.sub-menu) {
cursor: ew-resize;
}