1
0
Fork 0
mirror of https://github.com/FrankerFaceZ/FrankerFaceZ.git synced 2025-06-28 15:27:43 +00:00
FrankerFaceZ/script.min.js

2 lines
No EOL
52 KiB
JavaScript

!function(e){!function t(e,n,i){function s(a,r){if(!n[a]){if(!e[a]){var l="function"==typeof require&&require;if(!r&&l)return l(a,!0);if(o)return o(a,!0);throw new Error("Cannot find module '"+a+"'")}var c=n[a]={exports:{}};e[a][0].call(c.exports,function(t){var n=e[a][1][t];return s(n?n:t)},c,c.exports,t,e,n,i)}return n[a].exports}for(var o="function"==typeof require&&require,a=0;a<i.length;a++)s(i[a]);return s}({1:[function(t){var n=e.FrankerFaceZ,i=t("./constants"),s=t("./utils");n.prototype.setup_badges=function(){this.log("Preparing badge system."),this.badges={},this.log("Creating badge style element.");var e=this._badge_style=document.createElement("style");e.id="ffz-badge-css",document.head.appendChild(e),this.log("Adding legacy donor badges."),this._legacy_add_donors()};var o=function(e){return".badges .ffz-badge-"+e.id+" { background-color: "+e.color+'; background-image: url("'+e.image+'"); '+(e.extra_css||"")+"}"};n.prototype.bttv_badges=function(e){var t=e.sender,n=this.users[t],i=[],s=-1;if(n&&n.badges){for(var o=0;o<e.badges.length;o++){var a=e.badges[o];if("subscriber"==a.type||"turbo"==a.type){s=o;break}}for(var r in n.badges)if(n.badges.hasOwnProperty(r)){var a=n.badges[r],l=this.badges[a.id]||{},c=a.title||l.title,h="",u=BetterTTV.settings.get("alphaTags");a.image&&(h+='background-image: url(\\"'+a.image+'\\"); '),a.color&&!u&&(h+="background-color: "+a.color+"; "),a.extra_css&&(h+=a.extra_css),h&&(c+='" style="'+h),i.push([(-1==s?1:-1)*r,{type:"ffz-badge-"+a.id+(u?" alpha":""),name:"",description:c}])}if(i.sort(function(e,t){return e[0]-t[0]}),-1==s)for(;i.length;)e.badges.push(i.shift()[1]);else for(;i.length;)e.badges.insertAt(s,i.shift()[1])}},n.prototype.render_badge=function(e){var t=e.get("context.model.from"),n=(e.get("context.parentController.content.id"),e.$(".badges")),i=this.users[t];if(i&&i.badges){var s=n.find(".badge").filter(function(){var e=this.title.toLowerCase();return"subscriber"==e||"turbo"==e}).first(),o=[],a=!!s.length;for(var r in i.badges)if(i.badges.hasOwnProperty(r)){var l=i.badges[r],c=this.badges[l.id]||{},h=document.createElement("div");h.className="badge float-left tooltip ffz-badge-"+l.id,h.setAttribute("title",l.title||c.title),l.image&&(h.style.backgroundImage='url("'+l.image+'")'),l.color&&(h.style.backgroundColor=l.color),l.extra_css&&(h.style.cssText+=l.extra_css),o.push([(a?1:-1)*r,h])}if(o.sort(function(e,t){return e[0]-t[0]}),a)for(;o.length;)s.before(o.shift()[1]);else for(;o.length;)n.append(o.shift()[1])}},n.prototype._legacy_add_donors=function(e){this.badges[1]={id:1,title:"FFZ Donor",color:"#755000",image:"//cdn.frankerfacez.com/channel/global/donoricon.png"},s.update_css(this._badge_style,1,o(this.badges[1])),this.badges[0]={id:0,title:"FFZ Developer",color:"#FAAF19",image:"//cdn.frankerfacez.com/channel/global/devicon.png"},s.update_css(this._badge_style,0,o(this.badges[0])),this.users.sirstendec={badges:{0:{id:0}}},jQuery.ajax(i.SERVER+"script/donors.txt",{cache:!1,context:this}).done(function(e){this._legacy_parse_donors(e)}).fail(function(t){return 404!=t.status?(e=(e||0)+1,10>e?this._legacy_add_donors(e):void 0):void 0})},n.prototype._legacy_parse_donors=function(e){var t=0;if(null!=e)for(var n=e.trim().split(/\W+/),i=0;i<n.length;i++){var o=n[i],a=this.users[o]=this.users[o]||{},r=a.badges=a.badges||{};r[0]||(r[0]={id:1},t+=1)}this.log("Added donor badge to "+s.number_commas(t)+" users.")}},{"./constants":3,"./utils":25}],2:[function(){var t=e.FrankerFaceZ;t.chat_commands.massunmod=function(e,t){if(t=t.join(" ").trim(),!t.length)return"You must provide a list of users to unmod.";t=t.split(/\W*,\W*/);var n=this.get_user();if(!n||!n.login==e.id)return"You must be the broadcaster to use massunmod.";if(t.length>50)return"Each user you unmod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var i=t.length;t.length;){var s=t.shift();e.room.tmiRoom.sendMessage("/unmod "+s)}return"Sent unmod command for "+i+" users."},t.chat_commands.massunmod.help="Usage: /ffz massunmod <list, of, users>\nBroadcaster only. Unmod all the users in the provided list.",t.chat_commands.massmod=function(e,t){if(t=t.join(" ").trim(),!t.length)return"You must provide a list of users to mod.";t=t.split(/\W*,\W*/);var n=this.get_user();if(!n||!n.login==e.id)return"You must be the broadcaster to use massmod.";if(t.length>50)return"Each user you mod counts as a single message. To avoid being globally banned, please limit yourself to 50 at a time and wait between uses.";for(var i=t.length;t.length;){var s=t.shift();e.room.tmiRoom.sendMessage("/mod "+s)}return"Sent mod command for "+i+" users."},t.chat_commands.massmod.help="Usage: /ffz massmod <list, of, users>\nBroadcaster only. Mod all the users in the provided list."},{}],3:[function(e,t){var n='<path d="m120.95 1.74c4.08-0.09 8.33-0.84 12.21 0.82 3.61 1.8 7 4.16 11.01 5.05 2.08 3.61 6.12 5.46 8.19 9.07 3.6 5.67 7.09 11.66 8.28 18.36 1.61 9.51 7.07 17.72 12.69 25.35 3.43 7.74 1.97 16.49 3.6 24.62 2.23 5.11 4.09 10.39 6.76 15.31 1.16 2 4.38 0.63 4.77-1.32 1.2-7.1-2.39-13.94-1.97-21.03 0.38-3.64-0.91-7.48 0.25-10.99 2.74-3.74 4.57-8.05 7.47-11.67 3.55-5.47 10.31-8.34 16.73-7.64 2.26 2.89 5.13 5.21 7.58 7.92 2.88 4.3 6.52 8.01 9.83 11.97 1.89 2.61 3.06 5.64 4.48 8.52 2.81 4.9 4 10.5 6.63 15.49 2.16 6.04 5.56 11.92 5.37 18.5 0.65 1.95 0.78 4 0.98 6.03 1.01 3.95 2.84 8.55 0.63 12.42-2.4 5.23-7.03 8.97-11.55 12.33-6.06 4.66-11.62 10.05-18.37 13.75-4.06 2.65-8.24 5.17-12.71 7.08-3.59 1.57-6.06 4.94-9.85 6.09-2.29 1.71-3.98 4.51-6.97 5.02-4.56 1.35-8.98-3.72-13.5-1.25-2.99 1.83-6.19 3.21-9.39 4.6-8.5 5.61-18.13 9.48-28.06 11.62-8.36-0.2-16.69 0.62-25.05 0.47-3.5-1.87-7.67-1.08-11.22-2.83-6.19-1.52-10.93-6.01-16.62-8.61-2.87-1.39-5.53-3.16-8.11-4.99-2.58-1.88-4.17-4.85-6.98-6.44-3.83-0.11-6.54 3.42-10.24 3.92-2.31 0.28-4.64 0.32-6.96 0.31-3.5-3.65-5.69-8.74-10.59-10.77-5.01-3.68-10.57-6.67-14.84-11.25-2.52-2.55-5.22-4.87-8.24-6.8-4.73-4.07-7.93-9.51-11.41-14.62-3.08-4.41-5.22-9.73-4.6-15.19 0.65-8.01 0.62-16.18 2.55-24.02 4.06-10.46 11.15-19.34 18.05-28.06 3.71-5.31 9.91-10.21 16.8-8.39 3.25 1.61 5.74 4.56 7.14 7.89 1.19 2.7 3.49 4.93 3.87 7.96 0.97 5.85 1.6 11.86 0.74 17.77-1.7 6.12-2.98 12.53-2.32 18.9 0.01 2.92 2.9 5.36 5.78 4.57 3.06-0.68 3.99-4.07 5.32-6.48 1.67-4.06 4.18-7.66 6.69-11.23 3.61-5.28 5.09-11.57 7.63-17.37 2.07-4.56 1.7-9.64 2.56-14.46 0.78-7.65-0.62-15.44 0.7-23.04 1.32-3.78 1.79-7.89 3.8-11.4 3.01-3.66 6.78-6.63 9.85-10.26 1.72-2.12 4.21-3.32 6.55-4.6 7.89-2.71 15.56-6.75 24.06-7z"/>',i="true"==localStorage.ffzDebugMode&&document.body.classList.contains("ffz-dev");t.exports={DEBUG:i,SERVER:i?"//localhost:8000/":"//cdn.frankerfacez.com/",SVGPATH:n,ZREKNARF:'<svg style="padding:1.75px 0" class="svg-glyph_views" width="16px" viewBox="0 0 249 195" version="1.1" height="12.5px">'+n+"</svg>",CHAT_BUTTON:'<svg class="svg-emoticons ffz-svg" height="18px" width="24px" viewBox="0 0 249 195" version="1.1">'+n+"</svg>",GEAR:'<svg class="svg-gear" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M15,7v2h-2.115c-0.125,0.615-0.354,1.215-0.713,1.758l1.484,1.484l-1.414,1.414l-1.484-1.484C10.215,12.531,9.615,12.76,9,12.885V15H7v-2.12c-0.614-0.126-1.21-0.356-1.751-0.714l-1.491,1.49l-1.414-1.414l1.491-1.49C3.477,10.211,3.247,9.613,3.12,9H1V7h2.116C3.24,6.384,3.469,5.785,3.829,5.242L2.343,3.757l1.414-1.414l1.485,1.485C5.785,3.469,6.384,3.24,7,3.115V1h2v2.12c0.613,0.126,1.211,0.356,1.752,0.714l1.49-1.491l1.414,1.414l-1.49,1.492C12.523,5.79,12.754,6.387,12.88,7H15z M8,6C6.896,6,6,6.896,6,8s0.896,2,2,2s2-0.896,2-2S9.104,6,8,6z" fill-rule="evenodd"></path></svg>',HEART:'<svg class="svg-heart" height="16px" version="1.1" viewBox="0 0 16 16" width="16px" x="0px" y="0px"><path clip-rule="evenodd" d="M8,13.5L1.5,7V4l2-2h3L8,3.5L9.5,2h3l2,2v3L8,13.5z" fill-rule="evenodd"></path></svg>'}},{}],4:[function(){var t=e.FrankerFaceZ;t.chat_commands.developer_mode=function(e,t){var n,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?n=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(n=!1),void 0===n?"Developer Mode is currently "+("true"==localStorage.ffzDebugMode?"enabled.":"disabled."):(localStorage.ffzDebugMode=n,"Developer Mode is now "+(n?"enabled":"disabled")+". Please refresh your browser.")},t.chat_commands.developer_mode.help="Usage: /ffz developer_mode <on|off>\nEnable or disable Developer Mode. When Developer Mode is enabled, the script will be reloaded from //localhost:8000/script.js instead of from the CDN."},{}],5:[function(){var t=e.FrankerFaceZ;t.prototype.setup_chatview=function(){this.log("Hooking the Ember Chat view.");var e=App.__container__.resolve("view:chat");this._modify_cview(e),e.create().destroy();for(var t in Ember.View.views)if(Ember.View.views.hasOwnProperty(t)){var n=Ember.View.views[t];n instanceof e&&(this.log("Adding UI link manually to Chat view.",n),n.$(".textarea-contain").append(this.build_ui_link(n)))}},t.prototype._modify_cview=function(e){var t=this;e.reopen({didInsertElement:function(){this._super(),this.$()&&this.$(".textarea-contain").append(t.build_ui_link(this))},willClearRender:function(){this._super(),this.$(".ffz-ui-toggle").remove()},ffzUpdateLink:Ember.observer("controller.currentRoom",function(){t.update_ui_link()})})}},{}],6:[function(){var t=e.FrankerFaceZ,n=function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")};t.settings_info.capitalize={type:"boolean",value:!0,visible:function(){return!this.has_bttv},name:"Username Capitalization",help:"Display names in chat with proper capitalization."},t.settings_info.keywords={type:"button",value:[],visible:function(){return!this.has_bttv},name:"Highlight Keywords",help:"Set additional keywords that will be highlighted in chat.",method:function(){var e=this.settings.keywords.join(", "),t=prompt("Highlight Keywords\n\nPlease enter a comma-separated list of words that you would like to be highlighted in chat.",e);t&&(t=t.trim().split(/\W*,\W*/),1!=t.length||""!=t[0]&&"disable"!=t[0]||(t=[]),this.settings.set("keywords",t))}},t.settings_info.chat_rows={type:"boolean",value:!1,visible:function(){return!this.has_bttv},name:"Chat Line Backgrounds",help:"Display alternating background colors for lines in chat.",on_update:function(e){document.querySelector(".app-main").classList.toggle("ffz-chat-background",e)}},t.prototype.setup_line=function(){document.querySelector(".app-main").classList.toggle("ffz-chat-background",this.settings.chat_rows),this._last_row={},this.log("Hooking the Ember Line controller.");var n=App.__container__.resolve("controller:line"),i=this;n.reopen({tokenizedMessage:function(){var e=i._emoticonize(this,this._super()),t=i.get_user();return t&&this.get("model.from")==t.login||(e=i._mentionize(this,e)),e}.property("model.message","isModeratorOrHigher")}),this.log("Hooking the Ember Line view.");var n=App.__container__.resolve("view:line");n.reopen({didInsertElement:function(){this._super();var n=this.get("element"),s=this.get("context.model.from"),o=this.get("context.parentController.content.id"),a=this.get("context.model.ffzAlternate");void 0===a&&(a=i._last_row[o]=i._last_row.hasOwnProperty(o)?!i._last_row[o]:!1,this.set("context.model.ffzAlternate",a)),n.classList.toggle("ffz-alternate",a),n.setAttribute("data-room",o),n.setAttribute("data-sender",s),i.render_badge(this),i.settings.capitalize&&i.capitalize(this,s);var r=n.querySelector("span.mentioned");if(r&&(n.classList.add("ffz-mentioned"),!document.hasFocus()&&!this.get("context.model.ffzNotified")&&i.settings.highlight_notifications)){var l=t.get_capitalization(o),c=t.get_capitalization(s),h=l,u=this.get("context.model.message");this.get("context.parentController.content.isGroupRoom")&&(h=this.get("context.parentController.content.tmiRoom.displayName")),u="action"==this.get("context.model.style")?"* "+c+" "+u:c+": "+u,i.show_notification(u,"Twitch Chat Mention in "+h,l,6e4,e.focus.bind(e))}this.set("context.model.ffzNotified",!0)}});var s=this.get_user();s&&s.name&&(t.capitalization[s.login]=[s.name,Date.now()])},t.capitalization={},t._cap_fetching=0,t.get_capitalization=function(n,i){if(e.BetterTTV)return BetterTTV.chat.helpers.lookupDisplayName(n);if(n=n.toLowerCase(),"jtv"==n||"twitchnotify"==n)return n;var s=t.capitalization[n];return s&&Date.now()-s[1]<36e5?s[0]:(t._cap_fetching<5&&(t._cap_fetching++,Twitch.api.get("users/"+n).always(function(e){var s=e.display_name||n;t.capitalization[n]=[s,Date.now()],t._cap_fetching--,"function"==typeof i&&i(s)})),s?s[0]:n)},t.prototype.capitalize=function(e,n){var i=t.get_capitalization(n,this.capitalize.bind(this,e));i&&e.$(".from").text(i)},t.chat_commands.capitalization=function(e,t){var n,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?n=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(n=!1),void 0===n?"Chat Name Capitalization is currently "+(this.settings.capitalize?"enabled.":"disabled."):(this.settings.set("capitalize",n),"Chat Name Capitalization is now "+(n?"enabled.":"disabled."))},t.chat_commands.capitalization.help="Usage: /ffz capitalization <on|off>\nEnable or disable Chat Name Capitalization. This setting does not work with BetterTTV.",t._regex_cache={},t._get_rex=function(e){return t._regex_cache[e]=t._regex_cache[e]||RegExp("\\b"+n(e)+"\\b","ig")},t._mentions_to_regex=function(e){return t._regex_cache[e]=t._regex_cache[e]||RegExp("\\b(?:"+_.chain(e).map(n).value().join("|")+")\\b","ig")},t.prototype._mentionize=function(e,n){var i=this.settings.keywords;if(!i)return n;"string"==typeof n&&(n=[n]);var s=t._mentions_to_regex(i);return _.chain(n).map(function(e){return _.isString(e)?e.match(s)?_.zip(_.map(e.split(s),_.identity),_.map(e.match(s),function(e){return{mentionedUser:e,own:!1}})):[e]:e}).flatten().compact().value()},t.chat_commands.mentionize=function(e,t){if(t&&t.length){var n=t.join(" ").trim().split(/\W*,\W*/);1==n.length&&"disable"==n[0]&&(n=[]),this.settings.set("keywords",n)}var n=this.settings.keywords;return n.length?"The following words will be highlighted: "+n.join(", "):"There are no words set that will be highlighted."},t.chat_commands.mentionize.help="Usage: /ffz mentionize <comma, separated, word, list|disable>\nSet a list of words that will also be highlighted in chat.",t.prototype._emoticonize=function(e,t){var n=e.get("parentController.model.id"),i=e.get("model.from"),s=this,o=this.getEmotes(i,n),a=[];return _.each(o,function(e){var n=s.emote_sets[e];n&&_.each(n.emotes,function(e){_.any(t,function(t){return _.isString(t)&&t.match(e.regex)})&&a.push(e)})}),a.length?("string"==typeof t&&(t=[t]),_.each(a,function(e){var n={isEmoticon:!0,cls:e.klass,emoticonSrc:e.url,altText:e.hidden?"???":e.name};t=_.compact(_.flatten(_.map(t,function(t){if(_.isObject(t))return t;var i=t.split(e.regex),s=[];return i.forEach(function(e,t){s.push(e),t!==i.length-1&&s.push(n)}),s})))}),t):t}},{}],7:[function(t){var n=e.FrankerFaceZ,i=/\.([\w\-_]+)\s*?\{content:\s*?"([^"]+)";\s*?background-image:\s*?url\("([^"]+)"\);\s*?height:\s*?(\d+)px;\s*?width:\s*?(\d+)px;\s*?margin:([^;}]+);?([^}]*)\}/gm,s=/[^\n}]*\.badges\s+\.moderator\s*{\s*background-image:\s*url\(\s*['"]([^'"]+)['"][^}]+(?:}|$)/,o=/^_([^_]+)_\d+$/,a=t("../constants"),r=t("../utils"),l=function(e){return e.moderator_badge?'.chat-line[data-room="'+e.id+'"] .badges .moderator { background-image:url("'+e.moderator_badge+'") !important; }':""};n.prototype.setup_room=function(){this.rooms={},this.log("Creating room style element.");var e=this._room_style=document.createElement("style");e.id="ffz-room-css",document.head.appendChild(e),this.log("Hooking the Ember Room model.");var t=App.__container__.resolve("model:room");this._modify_room(t);var n=t.instances;for(var i in n)if(n.hasOwnProperty(i)){var s=n[i];this.add_room(s.id,s),this._modify_room(s)}},n.chat_commands={},n.prototype.room_message=function(e,t){var n=t.split("\n");if(this.has_bttv)for(var i=0;i<n.length;i++)BetterTTV.chat.handlers.onPrivmsg(e.id,{style:"admin",date:new Date,from:"jtv",message:n[i]});else for(var i=0;i<n.length;i++)e.room.addMessage({style:"ffz admin",date:new Date,from:"FFZ",message:n[i]})},n.prototype.run_command=function(e,t){var i=this.rooms[t];if(i&&i.room){if(!e){var s=document.querySelector("a.ffz-ui-toggle");if(s)return s.click();e="help"}var o=e.split(" "),a=o.shift().toLowerCase();this.log("Received Command: "+a,o,!0);var r,l=n.chat_commands[a];if(l)try{r=l.bind(this)(i,o)}catch(c){this.log("Error Running Command - "+a+": "+c,i),r="There was an error running the command."}else r='There is no "'+a+'" command.';r&&this.room_message(i,r)}},n.chat_commands.help=function(e,t){if(t&&t.length){var i=n.chat_commands[t[0].toLowerCase()];return i?i.help?i.help:'No help is available for the command "'+t[0]+'".':'There is no "'+t[0]+'" command.'}var s=[];for(var o in n.chat_commands)n.chat_commands.hasOwnProperty(o)&&s.push(o);return"The available commands are: "+s.join(", ")},n.chat_commands.help.help="Usage: /ffz help [command]\nList available commands, or show help for a specific command.",n.prototype.add_room=function(e,t){return this.rooms[e]?this.log("Tried to add existing room: "+e):(this.log("Adding Room: "+e),this.rooms[e]={id:e,room:t,menu_sets:[],sets:[],css:null},this.ws_send("sub",e),void this._legacy_add_room(e))},n.prototype.remove_room=function(e){var t=this.rooms[e];if(t){this.log("Removing Room: "+e),(t.css||t.moderator_badge)&&r.update_css(this._room_style,e,null),this.ws_send("unsub",e),delete this.rooms[e];for(var n=0;n<t.sets.length;n++){var i=t.sets[n],s=this.emote_sets[i];s&&(s.users.removeObject(e),s.global||s.users.length||this.unload_set(i))}}},n.prototype.load_room=function(e,t){return this._legacy_load_room(e,t)},n.prototype._load_room_json=function(e,t,n){this.rooms[e]&&(n.room=this.rooms[e].room),this.rooms[e]=n,(n.css||n.moderator_badge)&&r.update_css(this._room_style,e,l(n)+(n.css||""));for(var i=0;i<n.sets.length;i++){var s=n.sets[i];this.emote_sets.hasOwnProperty(s)||this.load_set(s)}this.update_ui_link(),t&&t(!0,n)},n.prototype._modify_room=function(e){var t=this;e.reopen({init:function(){this._super(),t.add_room(this.id,this)},willDestroy:function(){this._super(),t.remove_room(this.id)},getSuggestions:function(){var e=this._super();return this.settings.capitalize&&(e=_.map(e,n.get_capitalization)),e},send:function(e){var n=e.split(" ",1)[0].toLowerCase();return"/ffz"!==n?this._super(e):(this.set("messageToSend",""),void t.run_command(e.substr(5),this.get("id")))}})},n.prototype._legacy_add_room=function(e,t,n){jQuery.ajax(a.SERVER+"channel/"+e+".css",{cache:!1,context:this}).done(function(n){this._legacy_load_room_css(e,t,n)}).fail(function(i){return 404==i.status?this._legacy_load_room_css(e,t,null):(n=n||0,n++,10>n?this._legacy_add_room(e,t,n):void 0)})},n.prototype._legacy_load_room_css=function(e,t,n){var a=e,r=a.match(o);r&&r[1]&&(a=r[1]);var l={id:e,menu_sets:[a],sets:[a],moderator_badge:null,css:null};return n&&(n=n.replace(i,"").trim()),n&&(n=n.replace(s,function(e,t){return l.moderator_badge||"modicon.png"!==t.substr(-11)?e:(l.moderator_badge=t,"")})),l.css=n||null,this._load_room_json(e,t,l)}},{"../constants":3,"../utils":25}],8:[function(){var t=e.FrankerFaceZ;t.prototype.setup_router=function(){this.log("Hooking the Ember router.");var e=this;App.__container__.lookup("router:main").reopen({ffzTransition:function(){e.track_page()}.on("didTransition")})}},{}],9:[function(){var t=e.FrankerFaceZ;t.prototype.setup_viewers=function(){this.log("Hooking the Ember Viewers controller.");var e=App.__container__.resolve("controller:viewers");this._modify_viewers(e)},t.prototype._modify_viewers=function(e){e.reopen({lines:function(){var e=this._super(),n=[],i={},s=null,o=App.__container__.lookup("controller:channel"),a=this.get("parentController.model.id"),r=o&&o.get("id");if(r){var l=o.get("display_name");l&&(t.capitalization[r]=[l,Date.now()])}a!=r&&(r=null);for(var c=0;c<e.length;c++){var h=e[c];if(h.category)s=h.category,n.push(s),i[s]=[];else{var u=h.chatter.toLowerCase();if(!u)continue;u==r?(n.unshift("Broadcaster"),i.Broadcaster=[u]):i.hasOwnProperty(s)&&i[s].push(u)}}e=[];for(var c=0;c<n.length;c++){var d=n[c],p=i[d];if(p&&p.length)for(e.push({category:d}),e.push({chatter:""}),p.sort();p.length;){var u=p.shift();u=t.get_capitalization(u),e.push({chatter:u})}}return e}.property("content.chatters")})}},{}],10:[function(t){var n=e.FrankerFaceZ,i=/\.([\w\-_]+)\s*?\{content:\s*?"([^"]+)";\s*?background-image:\s*?url\("([^"]+)"\);\s*?height:\s*?(\d+)px;\s*?width:\s*?(\d+)px;\s*?margin:([^;}]+);?([^}]*)\}/gm,s=/[^\n}]*\.badges\s+\.moderator\s*{\s*background-image:\s*url\(\s*['"]([^'"]+)['"][^}]+(?:}|$)/,o=t("./constants"),a=t("./utils"),r=function(e,t,n){t&&(n.global=!0,this.global_sets.push(e))},l=function(e,t){var n=e.split(/ +/);return 2!=n.length?e:(n[0]=parseFloat(n[0]),n[1]=parseFloat(n[1]),n[0]==(t-18)/-2&&0==n[1]?null:e)},c=function(e){var t=e.margins;return t||(t=(e.height-18)/-2+"px 0"),".ffz-emote-"+e.id+' { background-image: url("'+e.url+'"); height: '+e.height+"px; width: "+e.width+"px; margin: "+t+(e.extra_css?"; "+e.extra_css:"")+"}\n"},h=function(e){return e.margins||e.extra_css?c(e)+'img[src="'+e.url+'"] { '+(e.margins?"margin: "+e.margins+";":"")+(e.extra_css||"")+" }\n":c(e)},u=h;n.prototype.setup_emoticons=function(){this.log("Preparing emoticon system."),this.emote_sets={},this.global_sets=[],this._last_emote_id=0,this.log("Creating emoticon style element.");var e=this._emote_style=document.createElement("style");e.id="ffz-emoticon-css",document.head.appendChild(e),this.log("Loading global emote set."),this.load_set("global",r.bind(this,"global"))},n.prototype.getEmotes=function(e,t){var n=this.users[e],i=this.rooms[t];return _.union(n&&n.sets||[],i&&i.sets||[],this.global_sets)},n.ws_commands.reload_set=function(e){this.load_set(e)},n.prototype.load_set=function(e,t){return this._legacy_load_set(e,t)},n.prototype.unload_set=function(e){var t=this.emote_sets[e];if(t){this.log("Unloading emoticons for set: "+e),a.update_css(this._emote_style,e,null),delete this.emote_sets[e];for(var n=0;n<t.users.length;n++){var i=this.rooms[t.users[n]];i&&i.sets.removeObject(e)}}},n.prototype._load_set_json=function(e,t,n){this.emote_sets[e]=n,n.users=[],n.global=!1,n.count=0;var i="";for(var s in n.emotes)if(n.emotes.hasOwnProperty(s)){var o=n.emotes[s];o.klass="ffz-emote-"+o.id,o.regex="!"===o.name[o.name.length-1]?new RegExp("\\b"+o.name+"(?=\\W|$)","g"):new RegExp("\\b"+o.name+"\\b","g"),i+=u(o),n.count++}a.update_css(this._emote_style,e,i+(n.extra_css||"")),this.log("Updated emoticons for set: "+e,n),this.update_ui_link(),t&&t(!0,n)},n.prototype._legacy_load_set=function(e,t,n){jQuery.ajax(o.SERVER+"channel/"+e+".css",{cache:!1,context:this}).done(function(n){this._legacy_load_css(e,t,n)}).fail(function(i){return 404==i.status?"function"==typeof t&&t(!1):(n=n||0,n++,10>n?this._legacy_load_set(e,t,n):"function"==typeof t&&t(!1))})},n.prototype._legacy_load_css=function(e,t,n){var o={},a={id:e,emotes:o,extra_css:null},r=this;n=n.replace(i,function(e,t,n,i,s,a,c,h){s=parseInt(s),a=parseInt(a),c=l(c,s);var u="."===i.substr(i.lastIndexOf("/")+1,1),d=++r._last_emote_id,p={id:d,hidden:u,name:n,height:s,width:a,url:i,margins:c,extra_css:h};return o[d]=p,""}).trim(),n&&n.replace(s,function(e,t){a.icon||"modicon.png"!==t.substr(-11)||(a.icon=t)}),this._load_set_json(e,t,a)}},{"./constants":3,"./utils":25}],11:[function(){var t=e.FrankerFaceZ,n=/(\sdata-sender="[^"]*"(?=>))/;t.prototype.find_bttv=function(t,n){return this.has_bttv=!1,e.BTTVLOADED?this.setup_bttv(n||0):void(n>=6e4?this.log("BetterTTV was not detected after 60 seconds."):setTimeout(this.find_bttv.bind(this,t,(n||0)+t),t))},t.prototype.setup_bttv=function(e){this.log("BetterTTV was detected after "+e+"ms. Hooking."),this.has_bttv=!0,this.track("setCustomVariable","3","BetterTTV",BetterTTV.info.versionString());var t=BetterTTV.chat.helpers.sendMessage,i=this;BetterTTV.chat.helpers.sendMessage=function(e){var n=e.split(" ",1)[0].toLowerCase();return"/ffz"!==n?t(e):void i.run_command(e.substr(5),BetterTTV.chat.store.currentRoom)};var s,o=BetterTTV.chat.handlers.privmsg;BetterTTV.chat.handlers.privmsg=function(e,t){s=e;var n=o(e,t);return s=null,n};var a=BetterTTV.chat.templates.privmsg;BetterTTV.chat.templates.privmsg=function(e,t,o,r,l){i.bttv_badges(l);var c=a(e,t,o,r,l);return c.replace(n,'$1 data-room="'+s+'"')};var r,l=BetterTTV.chat.templates.message;BetterTTV.chat.templates.message=function(e,t,n,i){r=e;var s=l(e,t,n,i);return r=null,s};var c=BetterTTV.chat.templates.emoticonize;BetterTTV.chat.templates.emoticonize=function(e,t){var n=c(e,t),o=i.getEmotes(r,s),t=[];return _.each(o,function(e){var s=i.emote_sets[e];s&&_.each(s.emotes,function(e){_.any(n,function(t){return _.isString(t)&&t.match(e.regex)})&&t.push(e)})}),t.length?(_.each(t,function(e){var t=['<img class="emoticon" src="'+e.url+(e.hidden?"":'" alt="'+e.name+'" title="'+e.name)+'" />'],i=n;if(n=[],!i||!i.length)return n;for(var s=0;s<i.length;s++){var o=i[s];if("string"==typeof o){var a=o.split(e.regex);a.forEach(function(e,i){e&&e.length&&n.push(e),i!==a.length-1&&n.push(t)})}else n.push(o)}}),n):n},this.update_ui_link()}},{}],12:[function(){var t=e.FrankerFaceZ;t.prototype.find_emote_menu=function(t,n){return this.has_emote_menu=!1,e.emoteMenu&&emoteMenu.registerEmoteGetter?this.setup_emote_menu(n||0):void(n>=6e4?this.log("Emote Menu for Twitch was not detected after 60 seconds."):setTimeout(this.find_emote_menu.bind(this,t,(n||0)+t),t))},t.prototype.setup_emote_menu=function(e){this.log("Emote Menu for Twitch was detected after "+e+"ms. Registering emote enumerator."),emoteMenu.registerEmoteGetter("FrankerFaceZ",this._emote_menu_enumerator.bind(this))},t.prototype._emote_menu_enumerator=function(){for(var e=this.get_user(),n=e?e.login:null,i=App.__container__.lookup("controller:chat"),s=i?i.get("currentRoom.id"):null,o=this.getEmotes(n,s),a=[],r=0;r<o.length;r++){var l=this.emote_sets[o[r]];if(l&&l.emotes)for(var c in l.emotes)if(l.emotes.hasOwnProperty(c)){var h=l.emotes[c];if(!h.hidden){var u=l.title,d=l.icon||null;u||(u="global"==l.id?"FrankerFaceZ Global Emotes":"globalevent"==l.id?"FrankerFaceZ Event Emotes":this.feature_friday&&l.id==this.feature_friday.set?"FrankerFaceZ Feature Friday: "+this.feature_friday.channel:"FrankerFaceZ Set: "+t.get_capitalization(l.id)),a.push({text:h.name,url:h.url,hidden:!1,channel:u,badge:d})}}}return a}},{}],13:[function(t){t("./shims");var n=e.FrankerFaceZ=function(){n.instance=this,this.initialize()};n.get=function(){return n.instance};var i=n.version_info={major:3,minor:0,revision:0,toString:function(){return[i.major,i.minor,i.revision].join(".")+(i.extra||"")}};n.prototype.log=function(e,t,n){e="FFZ: "+e+(n?" -- "+JSON.stringify(t):""),void 0!==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)},n.prototype.get_user=function(){if(e.PP&&PP.login)return PP;if(e.App){var t=App.__container__.lookup("controller:navigation");return t?t.get("userData"):void 0}},t("./settings"),t("./socket"),t("./emoticons"),t("./badges"),t("./ember/router"),t("./ember/room"),t("./ember/line"),t("./ember/chatview"),t("./ember/viewers"),t("./tracking"),t("./debug"),t("./ext/betterttv"),t("./ext/emote_menu"),t("./featurefriday"),t("./ui/styles"),t("./ui/notifications"),t("./ui/viewer_count"),t("./ui/menu_button"),t("./ui/menu"),t("./ui/races"),t("./commands"),n.prototype.initialize=function(t,n){var i=void 0!=e.App&&void 0!=App.__container__&&void 0!=App.__container__.resolve("model:room");return i?void this.setup_ember(n):(t=t||10,void(n>=6e4?this.log('Twitch application not detected in "'+location.toString()+'". Aborting.'):setTimeout(this.initialize.bind(this,t,(n||0)+t),t)))},n.prototype.setup_ember=function(t){var i=e.performance&&performance.now?performance.now():Date.now();this.log("Found Twitch application after "+(t||0)+' ms in "'+location+'". Initializing FrankerFaceZ version '+n.version_info),this.users={},this.load_settings(),this.ws_create(),this.setup_emoticons(),this.setup_badges(),this.setup_piwik(),this.setup_router(),this.setup_room(),this.setup_line(),this.setup_chatview(),this.setup_viewers(),this.setup_notifications(),this.setup_css(),this.setup_menu(),this.setup_races(),this.find_bttv(10),this.find_emote_menu(10),this.check_ff();var s=e.performance&&performance.now?performance.now():Date.now(),o=s-i;this.log("Initialization complete in "+o+"ms")}},{"./badges":1,"./commands":2,"./debug":4,"./ember/chatview":5,"./ember/line":6,"./ember/room":7,"./ember/router":8,"./ember/viewers":9,"./emoticons":10,"./ext/betterttv":11,"./ext/emote_menu":12,"./featurefriday":14,"./settings":15,"./shims":16,"./socket":17,"./tracking":18,"./ui/menu":19,"./ui/menu_button":20,"./ui/notifications":21,"./ui/races":22,"./ui/styles":23,"./ui/viewer_count":24}],14:[function(t){var n=e.FrankerFaceZ,i=t("./constants");n.prototype.feature_friday=null,n.prototype.check_ff=function(e){e||this.log("Checking for Feature Friday data..."),jQuery.ajax(i.SERVER+"script/event.json",{cache:!1,dataType:"json",context:this}).done(function(e){return this._load_ff(e)}).fail(function(t){return 404==t.status?this._load_ff(null):(e=e||0,e++,10>e?setTimeout(this.check_ff.bind(this,e),250):this._load_ff(null))})},n.ws_commands.reload_ff=function(){this.check_ff()},n.prototype._feature_friday_ui=function(e,t,n){if(this.feature_friday&&this.feature_friday.channel!=e){this._emotes_for_sets(t,n,[this.feature_friday.set],"Feature Friday");var i=App.__container__.lookup("controller:channel");if(!i||i.get("id")!=this.feature_friday.channel){var s=this.feature_friday,o=this,a=document.createElement("div"),r=document.createElement("a");a.className="chat-menu-content",a.style.textAlign="center";var l=s.display_name+(s.live?" is live now!":"");r.className="button primary",r.classList.toggle("live",s.live),r.classList.toggle("blue",this.has_bttv&&BetterTTV.settings.get("showBlueButtons")),r.href="http://www.twitch.tv/"+s.channel,r.title=l,r.target="_new",r.innerHTML="<span>"+l+"</span>",r.addEventListener("click",function(){o.track("trackLink",this.href,"link")}),a.appendChild(r),t.appendChild(a)}}},n.prototype._load_ff=function(e){if(this.feature_friday){this.global_sets.removeObject(this.feature_friday.set);var t=this.emote_sets[this.feature_friday.set];t&&(t.global=!1),this.feature_friday=null,this.update_ui_link()}e&&e.set&&e.channel&&(this.feature_friday={set:e.set,channel:e.channel,live:!1,display_name:n.get_capitalization(e.channel,this._update_ff_name.bind(this))},this.global_sets.push(e.set),this.load_set(e.set,this._update_ff_set.bind(this)),this._update_ff_live())},n.prototype._update_ff_live=function(){if(this.feature_friday){var e=this;Twitch.api.get("streams/"+this.feature_friday.channel).done(function(t){e.feature_friday.live=null!=t.stream,e.update_ui_link()}).always(function(){e.feature_friday.timer=setTimeout(e._update_ff_live.bind(e),12e4)})}},n.prototype._update_ff_set=function(e,t){t&&(t.global=!0)},n.prototype._update_ff_name=function(e){this.feature_friday&&(this.feature_friday.display_name=e)}},{"./constants":3}],15:[function(){var t=e.FrankerFaceZ,n=function(e){return"ffz_setting_"+e};t.settings_info={},t.prototype.load_settings=function(){this.log("Loading settings."),this.settings={};for(var i in t.settings_info){var s=n(i),o=t.settings_info[i],a=o.hasOwnProperty("value")?o.value:void 0;if(localStorage.hasOwnProperty(s))try{a=JSON.parse(localStorage.getItem(s))}catch(r){this.log('Error loading value for "'+i+'": '+r)}this.settings[i]=a}this.settings.get=this._setting_get.bind(this),this.settings.set=this._setting_set.bind(this),this.settings.del=this._setting_del.bind(this),e.addEventListener("storage",this._setting_update.bind(this))},t.prototype._setting_update=function(n){if(n||(n=e.event),this.log("Storage Event",n),n.key&&"ffz_setting_"===n.key.substr(0,12)){var i=n.key,s=i.substr(12),o=void 0,a=t.settings_info[s];
this.log("Updated Setting: "+s);try{o=JSON.parse(n.newValue)}catch(r){this.log('Error loading new value for "'+s+'": '+r),o=a.value||void 0}if(this.settings[s]=o,a.on_update)try{a.on_update.bind(this)(o,!1)}catch(r){this.log('Error running updater for setting "'+s+'": '+r)}}},t.prototype._setting_get=function(e){return this.settings[e]},t.prototype._setting_set=function(e,i){var s=n(e),o=t.settings_info[e],a=JSON.stringify(i);if(this.settings[e]=i,localStorage.setItem(s,a),this.log('Changed Setting "'+e+'" to: '+a),o.on_update)try{o.on_update.bind(this)(i,!0)}catch(r){this.log('Error running updater for setting "'+e+'": '+r)}},t.prototype._setting_del=function(e){var i=n(e),s=t.settings_info[e],o=void 0;if(localStorage.hasOwnProperty(i)&&localStorage.removeItem(i),delete this.settings[e],s&&(o=this.settings[e]=s.hasOwnProperty("value")?s.value:void 0),s.on_update)try{s.on_update.bind(this)(o,!0)}catch(a){this.log('Error running updater for setting "'+e+'": '+a)}}},{}],16:[function(){Array.prototype.equals=function(e){if(!e)return!1;if(this.length!=e.length)return!1;for(var t=0,n=this.length;n>t;t++)if(this[t]instanceof Array&&e[t]instanceof Array){if(!this[t].equals(e[t]))return!1}else if(this[t]!=e[t])return!1;return!0}},{}],17:[function(){var t=e.FrankerFaceZ;t.prototype._ws_open=!1,t.prototype._ws_delay=0,t.ws_commands={},t.ws_on_close=[],t.prototype.ws_create=function(){var e,n=this;this._ws_last_req=0,this._ws_callbacks={},this._ws_pending=this._ws_pending||[];try{e=this._ws_sock=new WebSocket("ws://ffz.stendec.me/")}catch(i){return this._ws_exists=!1,this.log("Error Creating WebSocket: "+i)}this._ws_exists=!0,e.onopen=function(){n._ws_open=!0,n._ws_delay=0,n.log("Socket connected.");var e=n.get_user();e&&n.ws_send("setuser",e.login);for(var t in n.rooms)n.ws_send("sub",t);var i=n._ws_pending;n._ws_pending=[];for(var s=0;s<i.length;s++){var o=i[s];n.ws_send(o[0],o[1],o[2])}},e.onclose=function(){n.log("Socket closed."),n._ws_open=!1;for(var e=0;e<t.ws_on_close.length;e++)try{t.ws_on_close[e].bind(n)()}catch(i){n.log("Error on Socket Close Callback: "+i)}n._ws_delay<3e4&&(n._ws_delay+=5e3),setTimeout(n.ws_create.bind(n),n._ws_delay)},e.onmessage=function(e){var i,s,o=e.data.indexOf(" "),a=e.data.substr(o+1),r=parseInt(e.data.slice(0,o));if(o=a.indexOf(" "),-1===o&&(o=a.length),i=a.slice(0,o),a=a.substr(o+1),a&&(s=JSON.parse(a)),-1===r){var l=t.ws_commands[i];l?l.bind(n)(s):n.log("Invalid command: "+i,s)}else{var c="True"===i,h=n._ws_callbacks[r];n.log("Socket Reply to "+r+" - "+(c?"SUCCESS":"FAIL"),s),h&&(delete n._ws_callbacks[r],h(c,s))}}},t.prototype.ws_send=function(e,t,n,i){if(!this._ws_open){if(i){var s=this._ws_pending=this._ws_pending||[];return s.push([e,t,n]),!0}return!1}var o=++this._ws_last_req;return t=void 0!==t?" "+JSON.stringify(t):"",n&&(this._ws_callbacks[o]=n),this._ws_sock.send(o+" "+e+t),o}},{}],18:[function(t){var n=e.FrankerFaceZ,i=(t("./constants"),("https:"==document.location.protocol?"https:":"http:")+"//sir.stendec.me/ffz_piwik/");n.prototype.setup_piwik=function(){if(void 0!=e._paq)return this.log("Piwik is already present. Disabling analytics."),void(this._tracking=!1);if("false"==localStorage.ffzTracking)return this.log("The user has opted out of tracking. Disabling analytics."),void(this._tracking=!1);this.log("Initializing Piwik."),this._tracking=!0;var t=e._paq=[];t.push(["setSiteId",1]),t.push(["setTrackerUrl",i+"piwik.php"]),this.has_bttv&&t.push(["setCustomVariable","3","BetterTTV",BetterTTV.info.versionString()]);var n=this.get_user(),s=this;n?(t.push(["setCustomVariable","1","Partnered",n.is_partner?"Yes":"No"]),t.push(["setCustomVariable","2","User Type",n.is_staff?"Staff":n.is_admin?"Admin":"User"]),t.push(["setUserId",n.login]),Twitch.api.get("channels/"+n.login).done(function(e){e.logo&&s.track("setCustomVariable","4","Avatar",e.logo)}).always(function(){s.track_page()})):this.track_page(),"true"==localStorage.ffzTracking&&(this.track("trackEvent","Analytics","Enable"),localStorage.removeItem("ffzTracking"));var o=document.createElement("script");o.type="text/javascript",o.defer=!0,o.async=!0,o.src=i+"piwik.js",document.head.appendChild(o)},n.chat_commands.analytics=function(e,t){var n,t=t&&t.length?t[0].toLowerCase():null;return"y"==t||"yes"==t||"true"==t||"on"==t?n=!0:("n"==t||"no"==t||"false"==t||"off"==t)&&(n=!1),void 0===n?"Analytics are currently "+("false"!=localStorage.ffzTracking?"enabled.":"disabled."):(this._tracking&&!n&&"false"!=localStorage.ffzTracking&&this.track("trackEvent","Analytics","Disable"),localStorage.ffzTracking=n,"Analytics are now "+(n?"enabled":"disabled")+". Please refresh your browser.")},n.chat_commands.analytics.help="Usage: /ffz analytics <on|off>\nEnable or disable FrankerFaceZ analytics. We collect some data about your browser and how you use FrankerFaceZ to help us improve the script. Turn off analytics if you'd rather we not.",n.prototype.track=function(){this._tracking&&e._paq&&_paq.push(Array.prototype.slice.call(arguments))},n.prototype.track_page=function(){if(this._tracking){this._old_url&&this.track("setReferrerUrl",this._old_url),this._old_url=document.location.toString(),this.track("setCustomUrl",this._old_url),this.track("deleteCustomVariable","1","page"),this.track("deleteCustomVariable","3","page");var e=App.__container__.resolve("router:main").router.currentHandlerInfos;if(e&&0!=e.length){var t=e[e.length-1];if("channel.index"==t.name&&t.context){var n=t.context.get("isFollowing.isFollowing");void 0!==n&&null!==n&&this.track("setCustomVariable","1","Following",n?"Yes":"No","page");var i=t.context.get("game");i&&this.track("setCustomVariable","3","Game",i,"page"),this.track("trackPageView",document.title)}}}}},{"./constants":3}],19:[function(t){var n=e.FrankerFaceZ,i=t("../constants");n.prototype.setup_menu=function(){this.log("Installing mouse-up event to auto-close menus.");var e=this;jQuery(document).mouseup(function(t){var n,i=e._popup;i&&(i=jQuery(i),n=i.parent(),n.is(t.target)||0!==n.has(t.target).length||(i.remove(),delete e._popup,e._popup_kill&&e._popup_kill(),delete e._popup_kill))})},n.menu_pages={},n.prototype.build_ui_popup=function(e){var t=this._popup;if(t)return t.parentElement.removeChild(t),delete this._popup,this._popup_kill&&this._popup_kill(),void delete this._popup_kill;var i=document.createElement("div"),s=document.createElement("div"),o=document.createElement("ul"),a=this.has_bttv?BetterTTV.settings.get("darkenedMode"):!1;i.className="emoticon-selector chat-menu ffz-ui-popup",s.className="emoticon-selector-box dropmenu",i.appendChild(s),i.classList.toggle("dark",a),o.className="menu clearfix",s.appendChild(o);var r=document.createElement("li");r.className="title",r.innerHTML="<span>FrankerFaceZ</span>",o.appendChild(r),r.addEventListener("click",this._add_emote.bind(this,e,"To use custom emoticons in tons of channels, get FrankerFaceZ from http://www.frankerfacez.com"));var l=document.createElement("div");l.className="ffz-ui-menu-page",s.appendChild(l);for(var c in n.menu_pages){var h=n.menu_pages[c];if(h&&(!h.hasOwnProperty("visible")||h.visible&&("function"!=typeof h.visible||h.visible.bind(this)()))){var r=document.createElement("li"),u=document.createElement("a");r.className="item",r.id="ffz-menu-page-"+c,u.title=h.name,u.innerHTML=h.icon,u.addEventListener("click",this._ui_change_page.bind(this,e,o,l,c)),r.appendChild(u),o.appendChild(r)}}this._ui_change_page(e,o,l,this._last_page||"channel"),this._popup=i,l.style.maxHeight=Math.max(300,e.$().height()-212)+"px",e.$(".chat-interface").append(i)},n.prototype._ui_change_page=function(e,t,i,s){this._last_page=s,i.innerHTML="";for(var o=t.querySelectorAll("li.active"),a=0;a<o.length;a++)o[a].classList.remove("active");var r=t.querySelector("#ffz-menu-page-"+s);r?r.classList.add("active"):this.log("No matching page: "+s),n.menu_pages[s].render.bind(this)(e,i)},n.menu_pages.settings={render:function(e,t){var i=document.createElement("div");i.className="chat-menu-content";var s=[];for(var o in n.settings_info)s.push([o,n.settings_info[o]]);s.sort(function(e,t){var n=e[1],i=t[1],s=n.name.toLowerCase(),o=i.name.toLowerCase();return o>s?-1:s>o?1:0});for(var a=0;a<s.length;a++){var o=s[a][0],r=s[a][1],l=document.createElement("p"),c=this.settings.get(o);if(void 0!==r.visible&&null!==r.visible){var h=r.visible;if("function"==typeof r.visible&&(h=r.visible.bind(this)()),!h)continue}if(l.className="clearfix","boolean"==r.type){var u=document.createElement("a"),d=document.createElement("span");u.className="switch",u.classList.toggle("active",c),u.innerHTML="<span></span>",d.className="switch-label",d.innerHTML=r.name,l.appendChild(u),l.appendChild(d),u.addEventListener("click",this._ui_toggle_setting.bind(this,u,o))}else{l.classList.add("option");var p=document.createElement("a");p.innerHTML=r.name,p.href="#",l.appendChild(p),p.addEventListener("click",r.method.bind(this))}if(r.help){var _=document.createElement("span");_.className="help",_.innerHTML=r.help,l.appendChild(_)}i.appendChild(l)}t.appendChild(i)},name:"Settings",icon:i.GEAR},n.prototype._ui_toggle_setting=function(e,t){var n=!this.settings.get(t);this.settings.set(t,n),e.classList.toggle("active",n)},n.menu_pages.channel={render:function(e,t){var n=e.get("controller.currentRoom.id"),i=this.rooms[n];this.log("Menu for Room: "+n,i),this.track("trackEvent","Menu","Open",n);this._emotes_for_sets(t,e,i&&i.menu_sets||[]);this._feature_friday_ui(n,t,e)},name:"Channel",icon:i.ZREKNARF},n.prototype._emotes_for_sets=function(e,t,n,i,s){if(null!=i){var o=document.createElement("div");o.className="list-header",o.appendChild(document.createTextNode(i)),s&&o.appendChild(s),e.appendChild(o)}var a=document.createElement("div"),r=0;a.className="emoticon-grid";for(var l=0;l<n.length;l++){var c=this.emote_sets[n[l]];if(c&&c.emotes)for(var h in c.emotes){var u=c.emotes[h];if(c.emotes.hasOwnProperty(h)&&!u.hidden){r++;var d=document.createElement("span");d.className="emoticon tooltip",d.style.backgroundImage='url("'+u.url+'")',d.style.width=u.width+"px",d.style.height=u.height+"px",d.title=u.name,d.addEventListener("click",this._add_emote.bind(this,t,u.name)),a.appendChild(d)}}}r||(a.innerHTML="This channel has no emoticons.",a.className="chat-menu-content ffz-no-emotes center"),e.appendChild(a)},n.prototype._add_emote=function(e,t){var n=e.get("controller.currentRoom"),i=n.get("messageToSend")||"";i&&" "!==i.substr(-1)&&(i+=" "),n.set("messageToSend",i+(t.name||t))}},{"../constants":3}],20:[function(t){var n=e.FrankerFaceZ,i=t("../constants");n.prototype.build_ui_link=function(e){var t=document.createElement("a");return t.className="ffz-ui-toggle",t.innerHTML=i.CHAT_BUTTON,t.addEventListener("click",this.build_ui_popup.bind(this,e)),this.update_ui_link(t),t},n.prototype.update_ui_link=function(e){var t=App.__container__.lookup("controller:chat");if(e=e||document.querySelector("a.ffz-ui-toggle"),e&&t){var n=t.get("currentRoom.id"),i=this.rooms[n],s=!1,o=this.has_bttv?BetterTTV.settings.get("darkenedMode"):!1,a=this.has_bttv?BetterTTV.settings.get("showBlueButtons"):!1,r=this.feature_friday&&this.feature_friday.live;if(i&&i.sets.length)for(var l=0;l<i.sets.length;l++){var c=this.emote_sets[i.sets[l]];if(c&&c.count>0){s=!0;break}}e.classList.toggle("no-emotes",!s),e.classList.toggle("live",r),e.classList.toggle("dark",o),e.classList.toggle("blue",a)}}},{"../constants":3}],21:[function(){var t=e.FrankerFaceZ;t.prototype.setup_notifications=function(){this.log("Adding event handler for window focus."),e.addEventListener("focus",this.clear_notifications.bind(this))},t.settings_info.highlight_notifications={type:"boolean",value:!1,visible:function(){return!this.has_bttv},name:"Highlight Notifications",help:"Display notifications when a highlighted word appears in chat in an unfocused tab.",on_update:function(e,t){if(e&&t){if("denied"===Notification.permission)return this.log("Notifications have been denied by the user."),void this.settings.set("highlight_notifications",!1);if("granted"!==Notification.permission){var n=this;Notification.requestPermission(function(e){"denied"===e&&(n.log("Notifications have been denied by the user."),n.settings.set("highlight_notifications",!1))})}}}},t.ws_commands.message=function(e){this.show_mesage(e)},t._notifications={},t._last_notification=0,t.prototype.clear_notifications=function(){for(var e in t._notifications){var n=t._notifications[e];if(n)try{n.close()}catch(i){}}t._notifications={},t._last_notification=0},t.prototype.show_notification=function(e,n,i,s,o,a){var r=Notification.permission;if("denied "===r)return!1;if("granted"===r){n=n||"FrankerFaceZ",s=s||1e4;var l={lang:"en-US",dir:"ltr",body:e,tag:i||"FrankerFaceZ",icon:"http://cdn.frankerfacez.com/icon32.png"},c=this,h=new Notification(n,l),u=t._last_notification++;return t._notifications[u]=h,h.addEventListener("click",function(){delete t._notifications[u],o&&o.bind(c)()}),h.addEventListener("close",function(){delete t._notifications[u],a&&a.bind(c)()}),void("number"==typeof s&&h.addEventListener("show",function(){setTimeout(function(){delete t._notifications[u],h.close()},s)}))}var c=this;Notification.requestPermission(function(){c.show_notification(e,n,i)})},t.prototype.show_message=function(t){e.noty({text:t,theme:"ffzTheme",layout:"bottomCenter",closeWith:["button"]}).show()}},{}],22:[function(t){var n=e.FrankerFaceZ,i=t("../utils");n.prototype.setup_races=function(){this.log("Initializing race support."),this.srl_races={}},n.settings_info.srl_races={type:"boolean",value:!0,name:"SRL Race Information",help:'Display information about <a href="http://www.speedrunslive.com/" target="_new">SpeedRunsLive</a> races under channels.',on_update:function(){this.rebuild_race_ui()}},n.ws_on_close.push(function(){var e=App.__container__.lookup("controller:channel"),t=e.get("id"),n=!1;for(var i in this.srl_races)delete this.srl_races[i],i==t&&(n=!0);n&&this.rebuild_race_ui()}),n.ws_commands.srl_race=function(e){for(var t=App.__container__.lookup("controller:channel"),n=t.get("id"),i=!1,s=0;s<e[0].length;s++){var o=e[0][s];this.srl_races[o]=e[1],o==n&&(i=!0)}if(e[1]){var a=e[1],r=a.twitch_entrants={};for(var l in a.entrants)a.entrants.hasOwnProperty(l)&&(a.entrants[l].channel&&(r[a.entrants[l].channel]=l),a.entrants[l].name=l)}i&&this.rebuild_race_ui()},n.prototype.rebuild_race_ui=function(){var e=App.__container__.lookup("controller:channel"),t=e.get("id"),n=this.srl_races[t],i=this.settings.srl_races,s=document.querySelector(".stats-and-actions .channel-actions"),o=s.querySelector("#ffz-ui-race");if(!n||!i)return o&&o.parentElement.removeChild(o),void(this._popup&&"ffz-race-popup"==this._popup.id&&(delete this._popup,this._popup_kill&&this._popup_kill(),delete this._popup_kill));if(o)return this._update_race(!0);o=document.createElement("span"),o.setAttribute("data-channel",t),o.id="ffz-ui-race";var a=document.createElement("span");a.className="button drop action",a.title="SpeedRunsLive Race",a.innerHTML='<span class="logo"><span>',a.addEventListener("click",this.build_race_popup.bind(this)),o.appendChild(a),s.appendChild(o),this._update_race(!0)},n.prototype._race_kill=function(){this._race_timer&&(clearTimeout(this._race_timer),delete this._race_timer),delete this._race_game,delete this._race_goal},n.prototype.build_race_popup=function(){var e=this._popup;if(!e||(e.parentElement.removeChild(e),delete this._popup,this._popup_kill&&this._popup_kill(),delete this._popup_kill,"ffz-race-popup"!=e.id)){var t=document.querySelector("#ffz-ui-race");if(t){var i=t.querySelector(".button"),s=i.offsetLeft+i.offsetWidth,o=t.getAttribute("data-channel"),a=this.srl_races[o],e=document.createElement("div"),r="";e.id="ffz-race-popup",e.className=(s>=300?"right":"left")+" share dropmenu",this._popup_kill=this._race_kill.bind(this),this._popup=e;var l="http://kadgar.net/live",c=!1;for(var h in a.entrants){var u=a.entrants[h].state;a.entrants.hasOwnProperty(h)&&a.entrants[h].channel&&("racing"==u||"entered"==u)&&(l+="/"+a.entrants[h].channel,c=!0)}var d=document.querySelector(".app-main.theatre")?document.body.clientHeight-300:t.parentElement.offsetTop-175,p=App.__container__.lookup("controller:channel"),_=p?p.get("display_name"):n.get_capitalization(o),f=encodeURIComponent("I'm watching "+_+" race "+a.goal+" in "+a.game+" on SpeedRunsLive!");r='<div class="heading"><div></div><span></span></div>',r+='<div class="table" style="max-height:'+d+'px"><table><thead><tr><th>#</th><th>Entrant</th><th>&nbsp;</th><th>Time</th></tr></thead>',r+="<tbody></tbody></table></div>",r+='<div class="divider"></div>',r+='<iframe class="twitter_share_button" style="width:110px; height:20px" src="https://platform.twitter.com/widgets/tweet_button.html?text='+f+"%20Watch%20at&via=Twitch&url=http://www.twitch.tv/"+o+'"></iframe>',r+='<p class="right"><a target="_new" href="http://www.speedrunslive.com/race/?id='+a.id+'">SRL</a>',c&&(r+=' &nbsp; <a target="_new" href="'+l+'">Multitwitch</a>'),r+="</p>",e.innerHTML=r,t.appendChild(e),this._update_race(!0)}}},n.prototype._update_race=function(e){this._race_timer&&e&&(clearTimeout(this._race_timer),delete this._race_timer);var t=document.querySelector("#ffz-ui-race");if(t){var n=t.getAttribute("data-channel"),s=this.srl_races[n];if(!s)return t.parentElement.removeChild(t),this._popup_kill&&this._popup_kill(),void(this._popup&&(delete this._popup,delete this._popup_kill));var o=s.twitch_entrants[n],a=s.entrants[o],r=t.querySelector("#ffz-race-popup"),l=Date.now()/1e3,c=Math.floor(l-s.time);if(t.querySelector(".logo").innerHTML=i.placement(a),r){var h=r.querySelector("tbody"),u=r.querySelector(".heading span"),d=r.querySelector(".heading div");h.innerHTML="";var p=[],_=!0;for(var f in s.entrants)s.entrants.hasOwnProperty(f)&&("racing"==s.entrants[f].state&&(_=!1),p.push(s.entrants[f]));p.sort(function(e,t){var n=e.place||9999,i=t.place||9999,s=e.time||c,o=t.time||c;return("forfeit"==e.state||"dq"==e.state)&&(n=1e4),("forfeit"==t.state||"dq"==t.state)&&(i=1e4),i>n?-1:n>i?1:e.name<t.name?-1:e.name>t.name?1:o>s?-1:s>o?1:void 0});for(var m=0;m<p.length;m++){var f=p[m],g='<a target="_new" href="http://www.speedrunslive.com/profiles/#!/'+i.sanitize(f.name)+'">'+f.display_name+"</a>",v=f.channel?'<a target="_new" class="twitch" href="http://www.twitch.tv/'+i.sanitize(f.channel)+'"></a>':"",b=f.hitbox?'<a target="_new" class="hitbox" href="http://www.hitbox.tv/'+i.sanitize(f.hitbox)+'"></a>':"",y=c?i.time_to_string(f.time||c):"",w=i.place_string(f.place),k=f.comment?i.sanitize(f.comment):"";h.innerHTML+="<tr"+(k?' title="'+k+'"':"")+' class="'+f.state+'"><td>'+w+"</td><td>"+g+"</td><td>"+v+b+'</td><td class="time">'+("forfeit"==f.state?"Forfeit":y)+"</td></tr>"}if(this._race_game!=s.game||this._race_goal!=s.goal){this._race_game=s.game,this._race_goal=s.goal;var T=i.sanitize(s.game),z=i.sanitize(s.goal);d.innerHTML='<h2 title="'+T+'">'+T+"</h2><b>Goal: </b>"+z}c?_?u.innerHTML="Done":(u.innerHTML=i.time_to_string(c),this._race_timer=setTimeout(this._update_race.bind(this),1e3)):u.innerHTML="Entry Open"}}}},{"../utils":25}],23:[function(t){var n=e.FrankerFaceZ,i=t("../constants");n.prototype.setup_css=function(){this.log("Injecting main FrankerFaceZ CSS.");var e=this._main_style=document.createElement("link");e.id="ffz-ui-css",e.setAttribute("rel","stylesheet"),e.setAttribute("href",i.SERVER+"script/style.css"),document.head.appendChild(e),jQuery.noty.themes.ffzTheme={name:"ffzTheme",style:function(){this.$bar.removeClass().addClass("noty_bar").addClass("ffz-noty").addClass(this.options.type)},callback:{onShow:function(){},onClose:function(){}}}}},{"../constants":3}],24:[function(t){var n=e.FrankerFaceZ,i=t("../constants"),s=t("../utils");n.ws_commands.viewers=function(e){var t=e[0],n=e[1],o=App.__container__.lookup("controller:channel"),a=o&&o.get&&o.get("id");if(a===t){var r=document.querySelector(".channel-stats .ffz.stat"),l=i.ZREKNARF+" "+s.number_commas(n);if(r)r.innerHTML=l;else{var c=document.querySelector(".channel-stats");if(!c)return;r=document.createElement("span"),r.className="ffz stat",r.title="Viewers with FrankerFaceZ",r.innerHTML=l,c.appendChild(r),jQuery(r).tipsy()}}}},{"../constants":3,"../utils":25}],25:[function(t,n){var i=(e.FrankerFaceZ,t("./constants"),{}),s=document.createElement("span"),o=function(e){return 1==e?"1st":2==e?"2nd":3==e?"3rd":null==e?"---":e+"th"};n.exports={update_css:function(e,t,n){var i=e.innerHTML,s="/*BEGIN "+t+"*/",o="/*END "+t+"*/",a=i.indexOf(s),r=i.indexOf(o),l=-1!==a&&-1!==r&&r>a;(l||n)&&(l&&(i=i.substr(0,a)+i.substr(r+o.length)),n&&(i+=s+n+o),e.innerHTML=i)},number_commas:function(e){var t=e.toString().split(".");return t[0]=t[0].replace(/\B(?=(\d{3})+(?!\d))/g,","),t.join(".")},place_string:o,placement:function(e){return"forfeit"==e.state?"Forfeit":"dq"==e.state?"DQed":e.place?o(e.place):""},sanitize:function(e){var t=i[e];return t||(s.textContent=e,t=i[e]=s.innerHTML,s.innerHTML=""),t},time_to_string:function(e){var t=e%60,n=Math.floor(e/60),i=Math.floor(n/60);return n%=60,(10>i?"0":"")+i+":"+(10>n?"0":"")+n+":"+(10>t?"0":"")+t}}},{"./constants":3}]},{},[13]),e.ffz=new FrankerFaceZ}(window);