}}},{"../constants":3,"../utils":30}],6:[function(t){vars=e.FrankerFaceZ,o=t("../utils"),n=t("../constants"),i=function(e){return1>e?"":e>=99?"99+":""+e};s.settings_info.minimal_chat={type:"boolean",value:!1,category:"Chat",name:"Minimalistic Chat",help:"Hide all of the chat user interface, only showing messages and an input box.",on_update:function(e){if(document.body.classList.toggle("ffz-minimal-chat",e),this.settings.group_tabs&&this._chatv&&this._chatv._ffz_tabs){vart=this;setTimeout(function(){t._chatv&&t._chatv.$(".chat-room").css("top",t._chatv._ffz_tabs.offsetHeight+"px")},0)}}},s.settings_info.prevent_clear={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Show Deleted Messages",help:"Fade deleted messages instead of replacing them, and prevent chat from being cleared.",on_update:function(e){if(!this.has_bttv&&this.rooms)for(vartinthis.rooms){vars=this.rooms[t],o=s&&s.room;o&&o.get("messages").forEach(function(t,s){e&&!t.ffz_deleted&&t.deleted?o.set("messages."+s+".deleted",!1):!t.ffz_deleted||e||t.deleted||o.set("messages."+s+".deleted",!0)})}}},s.settings_info.chat_history={type:"boolean",value:!0,visible:!1,category:"Chat",name:"Chat History <span>Alpha</span>",help:"Load previous chat messages when loading a chat room so you can see what people have been talking about. <b>This currently only works in a handful of channels due to server capacity.</b>"},s.settings_info.group_tabs={type:"boolean",value:!1,no_bttv:!0,category:"Chat",name:"Chat Room Tabs <span>Beta</span>",help:"Enhanced UI for switching the current chat room and noticing new messages.",on_update:function(e){vart=!this.has_bttv&&e;this._chatv&&t!==this._group_tabs_state&&(t?this._chatv.ffzEnableTabs():this._chatv.ffzDisableTabs())}},s.settings_info.pinned_rooms={type:"button",value:[],category:"Chat",visible:!1,name:"Pinned Chat Rooms",help:"Set a list of channels that should always be available in chat."},s.prototype.setup_chatview=function(){document.body.classList.toggle("ffz-minimal-chat",this.settings.minimal_chat),this.log("Hooking the Ember Chat controller.");vare=App.__container__.lookup("controller:chat"),t=this;e&&e.reopen({ffzUpdateChannels:function(){t.settings.group_tabs&&t._chatv&&t._chatv.ffzRebuildTabs()}.observes("currentChannelRoom","connectedPrivateGroupRooms"),removeCurrentChannelRoom:function(){if(!t.settings.group_tabs||t.has_bttv)returnthis._super();vare=this.get("currentChannelRoom"),s=e&&e.get("id");t.settings.pinned_rooms&&-1!==t.settings.pinned_rooms.indexOf(s)||(e===this.get("currentRoom")&&this.blurRoom(),e&&e.destroy()),this.set("currentChannelRoom",void0)}}),this.log("Hooking the Ember Chat view.");vare=App.__container__.resolve("view:chat");this._modify_cview(e);try{e.create().destroy()}catch(s){}for(varoinEmber.View.views)if(Ember.View.views.hasOwnProperty(o)){varn=Ember.View.views[o];if(ninstanceofe){this.log("Manually updating existing Chat view.",n);try{n.ffzInit()}catch(s){this.error("setup: build_ui_link: "+s)}}}this.log("Hooking the Ember Layout controller.");vari=App.__container__.lookup("controller:layout");if(i){i.reopen({ffzFixTabs:function(){t.settings.group_tabs&&t._chatv&&t._chatv._ffz_tabs&&setTimeout(function(){t._chatv&&t._chatv.$(".chat-room").css("top",t._chatv._ffz_tabs.offsetHeight+"px")},0)}.observes("isRightColumnClosed")}),this.log("Hooking the Ember 'Right Column' controller. Seriously...");vara=App.__container__.lookup("controller:right-column");a&&a.reopen({ffzFixTabs:function(){t.settings.group_tabs&&t._chatv&&t._chatv._ffz_tabs&&setTimeout(function(){t._chatv&&t._chatv.$(".chat-room").css("top",t._chatv._ffz_tabs.offsetHeight+"px")},0)}.observes("firstTabSelected")})}},s.prototype._modify_cview=function(e){vart=this;e.reopen({didInsertElement:function(){this._super();try{this.ffzInit()}catch(e){t.error("ChatView didInsertElement: "+e)}},willClearRender:function(){try{this.ffzTeardown()}catch(e){t.error("ChatView willClearRender: "+e)}this._super()},ffzInit:function(){t._chatv=this,this.$(".textarea-contain").append(t.build_ui_link(this)),!t.has
varf=document.createElement("span");f.className="right",h.appendChild(f);for(var_=0;_<d.settings.mod_card_durations.length;_++)f.appendChild(l(d.settings.mod_card_durations[_]));t.appendChild(h),this.$("button.timeout").remove()}varm=t.querySelector("button.ban");d.settings.mod_card_hotkeys&&m.setAttribute("title","(B)an User");varp=document.createElement("button");p.className="unban button glyph-only light",p.innerHTML=r,p.title=(d.settings.mod_card_hotkeys?"(U)":"U")+"nban User",jQuery(p).tipsy(),p.addEventListener("click",c.bind(this,-1)),jQuery(m).after(p)}varg=t.querySelector("button.mod");if(g){varv=o.get("cardInfo.isChannelOwner"),b=ffz.get_user();can_op=v||b&&b.is_admin||b&&b.is_staff,can_op||g.parentElement.removeChild(g)}vary=t.querySelector(".interface > button");if(y&&y.classList.contains("message-button")&&(y.innerHTML=a,y.classList.add("glyph-only"),y.classList.add("message"),y.title="Whisper User",jQuery(y).tipsy()),d.settings.mod_card_history){varw=App.__container__.lookup("controller:chat"),z=w&&w.get("currentRoom"),k=z&&d.rooms&&d.rooms[z.get("id")],C=k&&k.user_history&&k.user_history[o.get("cardInfo.user.id")];if(C&&C.length){varE=document.createElement("ul"),T=!1;E.className="interface clearfix chat-history";for(var_=0;_<C.length;_++){varh=C[_],F=document.createElement("li");F.className="message-line chat-line",F.classList.toggle("ffz-alternate",T),T=!T,h.style&&F.classList.add(h.style),F.innerHTML=(s?'<span class="timestamp float-left">'+s.getTime(h.date)+"</span> ":"")+'<span class="message">'+("action"===h.style?"*"+h.from+" ":"")+d.render_tokens(h.cachedTokens)+"</span>";for(varx=F.querySelectorAll("a.deleted-link"),S=0;S<x.length;S++)x[S].addEventListener("click",d._deleted_link_click);jQuery("a",F).tipsy({html:!0}),E.appendChild(F)}t.appendChild(E),E.scrollTop=E.scrollHeight}}this.$().draggable({start:function(){t.focus()}}),t.focus()}catch(L){try{d.error("ModerationCardView didInsertElement: "+L)}catch(L){}}}})},o.chat_commands.purge=function(e,t){if(!t||!t.length)return"Purge Usage: /p username [more usernames separated by spaces]";if(t.length>10)return"Please only purge up to 10 users at once.";for(vars=0;s<t.length;s++){varo=t[s];o&&e.room.send("/timeout "+o+" 1")}},o.chat_commands.p=function(e,t){returno.chat_commands.purge.bind(this)(e,t)},o.chat_commands.p.enabled=function(){returnthis.settings.short_commands},o.chat_commands.t=function(e,t){returnt&&t.length?voide.room.send("/timeout "+t.join(" ")):"Timeout Usage: /t username [duration]"},o.chat_commands.t.enabled=function(){returnthis.settings.short_commands},o.chat_commands.b=function(e,t){if(!t||!t.length)return"Ban Usage: /b username [more usernames separated by spaces]";if(t.length>10)return"Please only ban up to 10 users at once.";for(vars=0;s<t.length;s++){varo=t[s];o&&e.room.send("/ban "+o)}},o.chat_commands.b.enabled=function(){returnthis.settings.short_commands},o.chat_commands.u=function(e,t){if(!t||!t.length)return"Unban Usage: /u username [more usernames separated by spaces]";if(t.length>10)return"Please only unban up to 10 users at once.";for(vars=0;s<t.length;s++){varo=t[s];o&&e.room.send("/unban "+o)}},o.chat_commands.u.enabled=function(){returnthis.settings.short_commands}},{"../utils":30}],9:[function(t){vars=e.FrankerFaceZ,o=t("../constants"),n=t("../utils"),i=function(e){returne.moderator_badge?'.chat-line[data-room="'+e.id+'"] .badges .moderator:not(.ffz-badge-replacement) { background-image:url("'+e.moderator_badge+'") !important; }':""};s.prototype.setup_room=function(){this.rooms={},this.log("Creating room style element.");vare=this._room_style=document.createElement("style");e.id="ffz-room-css",document.head.appendChild(e),this.log("Hooking the Ember Room controller.");vart=App.__container__.lookup("controller:room");if(t){vars=t._actions.banUser,o=t._actions.timeoutUser;t._actions.banUser=function(e){s.bind(this)(e),this.get("model").clearMessages(e.user)},t._actions.timeoutUser=function(e){o.bind(this)(e),this.get("model").clearMessages(e.user)},t._actions.purgeUser=function(e){th
t=a.join(" ")}return'<span class="message" '+(n?'style="color: '+n+'" ':"")+'data-raw="'+i+'" data-emotes="'+(o?encodeURIComponent(JSON.stringify(o)):"false")+'">'+t+"</span>"}catch(d){returns.log("Error: ",d),c(e,t,o,n)}};varl=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(e,t){vara=l(e,t),r=i||BetterTTV.getChannel(),d=r&&r.toLowerCase(),c=u&&u.toLowerCase(),h=s.getEmotes(c,d),t=[],f=s.get_user(),m=f&&f.login===c;if(_.each(h,function(e){varo=s.emote_sets[e];o&&_.each(o.emoticons,function(e){_.any(a,function(t){return_.isString(t)&&t.match(e.regex)})&&t.push(e)})}),t.length&&_.each(t,function(e){vart=s._emote_tooltip(e),o=['<img class="emoticon" srcset="'+(e.srcSet||"")+'" src="'+e.urls[1]+'" alt="'+t+'" title="'+t+'" />'],n=a;a=[];for(vari=0;i<n.length;i++){varr=n[i];if("string"==typeofr)for(varu=r.split(e.regex);u.length;){varc=u.shift();u.length?(c+=u.shift(),c&&a.push(c),u.shift(),a.push(o),m&&d&&s.add_usage(d,e.id)):a.push(c)}elsea.push(r)}}),s.settings.parse_emoji&&s.emoji_data){varp=a;a=[];for(varg=0;g<p.length;g++){varv=p[g];if("string"==typeofv)for(varb=v.split(o.EMOJI_REGEX);b.length;){vary=b.shift();if(y&&a.push(y),b.length){varw=b.shift(),z=b.shift();if("︎"===z)bits.push(w);else{vark=n.emoji_to_codepoint(w,z),C=s.emoji_data[k],E=w+(z||"");a.push(C?['<img class="emoticon" height="18px" srcset="'+(C.srcSet||"")+'" src="'+C.src+'" alt="'+E+'" title="Emoji: '+E+"\nName: "+C.short_name+'">']:w+(z||""))}}}elsea.push(v)}}returna},this.update_ui_link()}},{"../constants":3,"../utils":30}],13:[function(){vart=e.FrankerFaceZ;t.prototype.find_emote_menu=function(t,s){returnthis.has_emote_menu=!1,e.emoteMenu&&emoteMenu.registerEmoteGetter?this.setup_emote_menu(s||0):void(s>=6e4?this.log("Emote Menu for Twitch was not detected after 60 seconds."):setTimeout(this.find_emote_menu.bind(this,t,(s||0)+t),t))},t.prototype.setup_emote_menu=function(e){this.log("Emote Menu for Twitch was detected after "+e+"ms. Registering emote enumerator."),emoteMenu.registerEmoteGetter("FrankerFaceZ",this._emote_menu_enumerator.bind(this))},t.prototype._emote_menu_enumerator=function(){for(vare=this.get_user(),s=e?e.login:null,o=App.__container__.lookup("controller:chat"),n=o?o.get("currentRoom.id"):null,i=this.getEmotes(s,n),a=[],r=0;r<i.length;r++){vard=this.emote_sets[i[r]];if(d&&d.emoticons)for(varuind.emoticons)if(d.emoticons.hasOwnProperty(u)){varc=d.emoticons[u];if(!c.hidden){varl=d.title,h=d.icon||null;l=l?"FrankerFaceZ: "+l:"global"==d.id?"FrankerFaceZ Global Emotes":"globalevent"==d.id?"FrankerFaceZ Event Emotes":this.feature_friday&&d.id==this.feature_friday.set?"FrankerFaceZ "+this.feature_friday.title+": "+this.feature_friday.display_name:"FrankerFaceZ Set: "+t.get_capitalization(d.id),a.push({text:c.name,url:c.urls[1],hidden:!1,channel:l,badge:h})}}}returna}},{}],14:[function(t){vars=e.FrankerFaceZ=function(){s.instance=this,this._log_data=[],this.initialize()};s.get=function(){returns.instance};varo=s.version_info={major:3,minor:4,revision:10,toString:function(){return[o.major,o.minor,o.revision].join(".")+(o.extra||"")}};s.prototype.log=function(e,t,s,o){e="FFZ: "+e+(s?" -- "+JSON.stringify(t):""),this._log_data.push(e+(!s&&o?" -- "+JSON.stringify(t):"")),void0!==t&&console.groupCollapsed&&console.dir?(console.groupCollapsed(e),-1!==navigator.userAgent.indexOf("Firefox/")?console.log(t):console.dir(t),console.groupEnd(e)):console.log(e)},s.prototype.error=function(e,t,s){e="FFZ Error: "+e+(s?" -- "+JSON.stringify(t):""),this._log_data.push(e),void0!==t&&console.groupCollapsed&&console.dir?(console.groupCollapsed(e),-1!==navigator.userAgent.indexOf("Firefox/")?console.log(t):console.dir(t),console.groupEnd(e)):console.assert(!1,e)},s.prototype.paste_logs=function(){this._pastebin(this._log_data.join("\n"),function(e){returne?voidconsole.log("FFZ: Your FrankerFaceZ log has been pasted to: "+e):console.log("FFZ Error: Unable to upload log to pastebin.")})},s.prototype._pastebin=function(e,t){jQuery.ajax({url:"http://putco.de/",type:"PUT",data:e,context:th
})?void0:"There was an error communicating with the server."},s.ws_on_close.push(function(){vart=e.App&&App.__container__.lookup("controller:channel"),s=t&&t.get("id"),o=t&&t.get("hostModeTarget.id"),n=!1;if(this.follow_sets={},t){for(variinthis.follow_data)if(deletethis.follow_data[i],(i===s||i===o)&&(n=!0),this.rooms&&this.rooms[i]&&this.rooms[i].extra_sets){vara=this.rooms[i].extra_sets;deletethis.rooms[i].extra_sets;for(varr=0;r<a.length;r++){vard=this.emote_sets[a[r]];d&&(d.users.removeObject(i),this.global_sets.contains(a[r])||d.users.length||this.unload_set(a[r]))}}n&&this.rebuild_following_ui()}}),s.ws_commands.follow_buttons=function(t){vars=e.App&&App.__container__.lookup("controller:channel"),o=s&&s.get("id"),n=s&&s.get("hostModeTarget.id"),i=!1;this.follow_data=this.follow_data||{};for(varaint)this.follow_data[a]=t[a],(a===o||a===n)&&(i=!0);i&&this.rebuild_following_ui()},s.ws_commands.follow_sets=function(e){{vart=App.__container__.lookup("controller:channel");t&&t.get("id"),t&&t.get("hostModeTarget.id")}this.follow_sets=this.follow_sets||{};for(varsine)if(this.rooms&&this.rooms.hasOwnProperty(s)){for(varo=this.rooms[s].extra_sets||[],n=this.rooms[s].extra_sets=e[s],i=0;i<o.length;i++){vara=o[i];if(-1===n.indexOf(a)){varr=this.emote_sets&&this.emote_sets[a];r&&(r.users.removeObject(s),this.global_sets.contains(a)||r.users.length||this.unload_set(a))}}for(vari=0;i<n.length;i++){vara=n[i],r=this.emote_sets&&this.emote_sets[a];r?-1===r.users.indexOf(s)&&r.users.push(s):this.load_set(a,function(e,t){e&&t.users.push(s)})}}elsethis.follow_sets[s]=e[s]},s.prototype.rebuild_following_ui=function(){vare=App.__container__.lookup("controller:channel"),t=e&&e.get("id"),s=e&&e.get("hostModeTarget.id");if(this._cindex){if(t){varo=this.follow_data&&this.follow_data[t],n=this._cindex.get("element"),i=n&&n.querySelector(".stats-and-actions .channel-actions"),a=i&&i.querySelector("#ffz-ui-following");if(i&&this.settings.follow_buttons&&o&&o.length){if(a)a.innerHTML="";else{a=document.createElement("span"),a.id="ffz-ui-following";varr=i.querySelector(":scope > span");r?i.insertBefore(a,r):i.appendChild(a)}for(vard=0;d<o.length;d++)this._build_following_button(a,o[d])}elsea&&a.parentElement.removeChild(a)}if(s){varo=this.follow_data&&this.follow_data[s],n=this._cindex.get("element"),i=n&&n.querySelector("#hostmode .channel-actions"),a=i&&i.querySelector("#ffz-ui-following");if(i&&this.settings.follow_buttons&&o&&o.length){if(a)a.innerHTML="";else{a=document.createElement("span"),a.id="ffz-ui-following";varr=i.querySelector(":scope > span");r?i.insertBefore(a,r):i.appendChild(a)}for(vard=0;d<o.length;d++)this._build_following_button(a,o[d])}elsea&&a.parentElement.removeChild(a)}}},s.prototype._build_following_button=function(e,t){varo,n=document.createElement("a"),i=this,a=document.createElement("div"),r=document.createElement("a"),d=document.createElement("div"),u=!1,c=!1,l=function(){a.classList.toggle("is-following",u),n.title=(u?"Unf":"F")+"ollow "+o,n.innerHTML=(u?"":"Follow ")+o,d.classList.toggle("hidden",!u)},h=function(){vare=i.get_user();returne&&e.login?voidTwitch.api.get("users/"+e.login+"/follows/channels/"+t).done(function(e){u=!0,c=e.notifications,a.classList.add("is-initialized"),l()}).fail(function(){u=!1,c=!1,a.classList.add("is-initialized"),l()}):(u=!1,notification=!1,a.classList.add("is-initialized"),l())},f=function(e){e!==!1&&(e=!0);vars=i.get_user();returns&&s.login?(c=e,Twitch.api.put("users/:login/follows/channels/"+t,{notifications:c}).fail(h)):null},_=function(e){o=e||t,l()};a.className="ember-follow follow-button",a.appendChild(n),r.className="toggle-notification-menu js-toggle-notification-menu",r.href="#",d.className="notification-controls v2 hidden",d.appendChild(r),n.addEventListener("click",function(){vare=i.get_user();returne&&e.login?(u=!u,l(),i.ws_send("track_follow",[t,u]),u?f():Twitch.api.del("users/:login/follows/channels/"+t).done(h),!1):Ember.$.login({mpSourceAction:"follow-button",follow:t})}),r.addEventListener("click",function(){vare=i._build