diff --git a/README.md b/README.md index 8b213bd5..f69418d0 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,8 @@ server for development. To get everything you need: 1. Install node.js 2. Run ```npm install``` within the FrankerFaceZ directory. +3. Run ```npm install --global gulp``` to install gulp globally, making it + possible to use the ```gulp``` command. From there, you can use gulp to build the extension from source simply by diff --git a/script.js b/script.js index 8cee08d3..8a53bdf7 100644 --- a/script.js +++ b/script.js @@ -4589,22 +4589,27 @@ FFZ.get_capitalization = function(name, callback) { // --------------------- FFZ.prototype._remove_banned = function(tokens) { - var banned_words = _.union(['j.mp', 'bit.ly'], this.settings.banned_words); - if ( ! banned_words || ! banned_words.length ) + var banned_words = this.settings.banned_words, + banned_links = ['j.mp', 'bit.ly'], + + has_banned_words = banned_words && banned_words.length; + + if ( !has_banned_words && (! banned_links || ! banned_links.length) ) return tokens; if ( typeof tokens == "string" ) tokens = [tokens]; var regex = FFZ._words_to_regex(banned_words), + link_regex = FFZ._words_to_regex(banned_links), new_tokens = []; for(var i=0; i < tokens.length; i++) { var token = tokens[i]; if ( ! _.isString(token ) ) { - if ( token.emoticonSrc && regex.test(token.altText) ) + if ( token.emoticonSrc && has_banned_words && regex.test(token.altText) ) new_tokens.push(token.altText.replace(regex, "$1***")); - else if ( token.isLink && regex.test(token.href) ) + else if ( token.isLink && has_banned_words && regex.test(token.href) ) new_tokens.push({ isLink: true, href: token.href, @@ -4612,10 +4617,18 @@ FFZ.prototype._remove_banned = function(tokens) { isLong: false, censoredHref: token.href.replace(regex, "$1***") }); + else if ( token.isLink && link_regex.test(token.href) ) + new_tokens.push({ + isLink: true, + href: token.href, + isDeleted: true, + isLong: false, + censoredHref: token.href.replace(link_regex, "$1***") + }); else new_tokens.push(token); - } else + } else if ( has_banned_words ) new_tokens.push(token.replace(regex, "$1***")); } @@ -7674,8 +7687,6 @@ require('./ember/moderation-card'); require('./ember/chat-input'); //require('./ember/teams'); -// Analytics: require('./tracking'); - require('./debug'); require('./ext/betterttv'); @@ -7866,8 +7877,6 @@ FFZ.prototype.init_ember = function(delay) { this.setup_emoticons(); this.setup_badges(); - //this.setup_piwik(); - //this.setup_router(); this.setup_colors(); this.setup_tokenization(); diff --git a/script.min.js b/script.min.js index 880f6de7..07c5b13c 100644 --- a/script.min.js +++ b/script.min.js @@ -1,8 +1,8 @@ !function(t){!function e(t,s,n){function i(a,r){if(!s[a]){if(!t[a]){var d="function"==typeof require&&require;if(!r&&d)return d(a,!0);if(o)return o(a,!0);throw new Error("Cannot find module '"+a+"'")}var u=s[a]={exports:{}};t[a][0].call(u.exports,function(e){var s=t[a][1][e];return i(s?s:e)},u,u.exports,e,t,s,n)}return s[a].exports}for(var o="function"==typeof require&&require,a=0;at&&this._legacy_load_bots(t))})},s.prototype._legacy_load_donors=function(t){jQuery.ajax(n.SERVER+"script/donors.txt",{cache:!1,context:this}).done(function(t){this._legacy_parse_badges(t,1,1)}).fail(function(e){return 404!=e.status?(t=(t||0)+1,10>t?this._legacy_load_donors(t):void 0):void 0})},s.prototype._legacy_parse_badges=function(t,e,s,n){var o=this.badges[s].title,a=0;if(ds=null,n=n||"{}",null!=t)for(var r=t.trim().split(/\W+/),d=0;d1&&(h[e].title=n.replace("{}",u[1])),a+=1)}this.log('Added "'+o+'" badge to '+i.number_commas(a)+" users.")}},{"./constants":5,"./utils":35}],3:[function(){var e=t.FrankerFaceZ,s=function(t,e,s){return 0>s&&(s+=1),s>1&&(s-=1),1/6>s?t+6*(e-t)*s:.5>s?e:2/3>s?t+(e-t)*(2/3-s)*6:t};e.settings_info.fix_color={type:"select",options:{"-1":"Disabled",0:"Default Colors",1:"Luv Adjustment",2:"HSL Adjustment (Depreciated)",3:"HSV Adjustment (Depreciated)",4:"RGB Adjustment (Depreciated)"},value:"1",category:"Chat Appearance",no_bttv:!0,name:"Username Colors - Brightness",help:"Ensure that username colors contrast with the background enough to be readable.",process_value:function(t){return t===!1?"0":t===!0?"1":t},on_update:function(t){document.body.classList.toggle("ffz-chat-colors-gray",!this.has_bttv&&"-1"===t),this.has_bttv||"-1"===t||this._rebuild_colors()}},e.settings_info.luv_contrast={type:"button",value:4.5,category:"Chat Appearance",no_bttv:!0,name:"Username Colors - Luv Minimum Contrast",help:"Set the minimum contrast ratio used by Luv Adjustment to ensure colors are readable.",method:function(){var t=this.settings.luv_contrast,e=prompt("Luv Adjustment Minimum Contrast Ratio\n\nPlease enter a new value for the minimum contrast ratio required between username colors and the background. The default is: 4.5",t);if(null!==e&&void 0!==e){var s=parseFloat(e);(0/0===s||1>s)&&(s=4.5),this.settings.set("luv_contrast",s)}},on_update:function(){this._rebuild_contrast(),this.has_bttv||"1"!=this.settings.fix_color||this._rebuild_colors()}},e.settings_info.color_blind={type:"select",options:{0:"Disabled",protanope:"Protanope",deuteranope:"Deuteranope",tritanope:"Tritanope"},value:"0",category:"Chat Appearance",no_bttv:!0,name:"Username Colors - Color Blindness",help:"Adjust username colors in an attempt to make them more distinct for people with color blindness.",on_update:function(){this.has_bttv||"-1"===this.settings.fix_color||this._rebuild_colors()}},e.prototype.setup_colors=function(){this._colors={},this._rebuild_contrast(),this._update_colors();var e=t.App&&App.__container__.lookup("controller:layout"),s=t.App&&App.__container__.lookup("controller:settings");e&&e.addObserver("isTheatreMode",this._update_colors.bind(this,!0)),s&&s.addObserver("model.darkMode",this._update_colors.bind(this,!0)),this._color_old_darkness=e&&e.get("isTheatreMode")||s&&s.get("model.darkMode")},e.Color={},e.Color.CVDMatrix={protanope:[0,2.02344,-2.52581,0,1,0,0,0,1],deuteranope:[1,0,0,.494207,0,1.24827,0,0,1],tritanope:[1,0,0,0,1,0,-.395913,.801109,0]};var n=e.Color.RGB=function(t,e,s){this.r=t||0,this.g=e||0,this.b=s||0},i=e.Color.HSV=function(t,e,s){this.h=t||0,this.s=e||0,this.v=s||0},o=e.Color.HSL=function(t,e,s){this.h=t||0,this.s=e||0,this.l=s||0},a=e.Color.XYZ=function(t,e,s){this.x=t||0,this.y=e||0,this.z=s||0},r=e.Color.LUV=function(t,e,s){this.l=t||0,this.u=e||0,this.v=s||0};n.prototype.eq=function(t){return t.r===this.r&&t.g===this.g&&t.b===this.b},n.fromHex=function(t){var e=parseInt("#"===t.charAt(0)?t.substr(1):t,16);return new n(e>>16,e>>8&255,255&e)},n.fromHSV=function(t,e,s){var i,o,a,r=Math.floor(6*t),d=6*t-r,u=s*(1-e),c=s*(1-d*e),l=s*(1-(1-d)*e);switch(r%6){case 0:i=s,o=l,a=u;break;case 1:i=c,o=s,a=u;break;case 2:i=u,o=s,a=l;break;case 3:i=u,o=c,a=s;break;case 4:i=l,o=u,a=s;break;case 5:i=s,o=u,a=c}return new n(Math.round(Math.min(Math.max(0,255*i),255)),Math.round(Math.min(Math.max(0,255*o),255)),Math.round(Math.min(Math.max(0,255*a),255)))},n.fromXYZ=function(t,e,s){var i=3.240479*t-1.53715*e-.498535*s,o=-.969256*t+1.875992*e+.041556*s,r=.055648*t-.204043*e+1.057311*s;return new n(Math.max(0,Math.min(255,255*a.channelConverter(i))),Math.max(0,Math.min(255,255*a.channelConverter(o))),Math.max(0,Math.min(255,255*a.channelConverter(r))))},n.fromHSL=function(t,e,i){if(0===e){var o=Math.round(Math.min(Math.max(0,255*i),255));return new n(o,o,o)}var a=.5>i?i*(1+e):i+e-i*e,r=2*i-a;return new n(Math.round(Math.min(Math.max(0,255*s(r,a,t+1/3)),255)),Math.round(Math.min(Math.max(0,255*s(r,a,t)),255)),Math.round(Math.min(Math.max(0,255*s(r,a,t-1/3)),255)))},n.prototype.toHSV=function(){return i.fromRGB(this.r,this.g,this.b)},n.prototype.toHSL=function(){return o.fromRGB(this.r,this.g,this.b)},n.prototype.toCSS=function(){return"rgb("+Math.round(this.r)+","+Math.round(this.g)+","+Math.round(this.b)+")"},n.prototype.toXYZ=function(){return a.fromRGB(this.r,this.g,this.b)},n.prototype.toLUV=function(){return this.toXYZ().toLUV()},n.prototype.toHex=function(){var t=this.b|this.g<<8|this.r<<16;return"#"+(16777216+t).toString(16).slice(1)},n.prototype.luminance=function(){for(var t=[this.r/255,this.g/255,this.b/255],e=0,s=t.length;s>e;e++)t[e]=t[e]<=.03928?t[e]/12.92:Math.pow((t[e]+.055)/1.055,2.4);return.2126*t[0]+.7152*t[1]+.0722*t[2]},n.prototype.brighten=function(t){return t="number"==typeof t?t:1,t=Math.round(255*(t/100)),new n(Math.max(0,Math.min(255,this.r+t)),Math.max(0,Math.min(255,this.g+t)),Math.max(0,Math.min(255,this.b+t)))},n.prototype.daltonize=function(t,s){s="number"==typeof s?s:1;var i;if("string"==typeof t){if(!e.Color.CVDMatrix.hasOwnProperty(t))throw"Invalid CVD matrix.";i=e.Color.CVDMatrix[t]}else i=t;var o,a,r,d,u,c,l,h,f,m,_,p,g=i[0],v=i[1],b=i[2],y=i[3],w=i[4],z=i[5],k=i[6],E=i[7],C=i[8];return o=17.8824*this.r+43.5161*this.g+4.11935*this.b,a=3.45565*this.r+27.1554*this.g+3.86714*this.b,r=.0299566*this.r+.184309*this.g+1.46709*this.b,d=g*o+v*a+b*r,u=y*o+w*a+z*r,c=k*o+E*a+C*r,l=.0809444479*d+-.130504409*u+.116721066*c,h=-.0102485335*d+.0540193266*u+-.113614708*c,f=-.000365296938*d+-.00412161469*u+.693511405*c,l=this.r-l,h=this.g-h,f=this.b-f,m=0*l+0*h+0*f,_=.7*l+1*h+0*f,p=.7*l+0*h+1*f,l=Math.min(Math.max(0,m+this.r),255),h=Math.min(Math.max(0,_+this.g),255),f=Math.min(Math.max(0,p+this.b),255),new n(l,h,f)},n.prototype._r=function(t){return new n(t,this.g,this.b)},n.prototype._g=function(t){return new n(this.r,t,this.b)},n.prototype._b=function(t){return new n(this.r,this.g,t)},o.prototype.eq=function(t){return t.h===this.h&&t.s===this.s&&t.l===this.l},o.fromRGB=function(t,e,s){t/=255,e/=255,s/=255;var n,i,a=Math.max(t,e,s),r=Math.min(t,e,s),d=Math.min(Math.max(0,(a+r)/2),1),u=Math.min(Math.max(0,a-r),1);if(0===u)n=i=0;else{switch(i=d>.5?u/(2-a-r):u/(a+r),a){case t:n=(e-s)/u+(s>e?6:0);break;case e:n=(s-t)/u+2;break;case s:n=(t-e)/u+4}n/=6}return new o(n,i,d)},o.prototype.toRGB=function(){return n.fromHSL(this.h,this.s,this.l)},o.prototype.toCSS=function(){return"hsl("+Math.round(360*this.h)+","+Math.round(100*this.s)+"%,"+Math.round(100*this.l)+"%)"},o.prototype.toHex=function(){return n.fromHSL(this.h,this.s,this.l).toHex()},o.prototype.toHSV=function(){return n.fromHSL(this.h,this.s,this.l).toHSV()},o.prototype.toXYZ=function(){return n.fromHSL(this.h,this.s,this.l).toXYZ()},o.prototype.toLUV=function(){return n.fromHSL(this.h,this.s,this.l).toLUV()},o.prototype._h=function(t){return new o(t,this.s,this.l)},o.prototype._s=function(t){return new o(this.h,t,this.l)},o.prototype._l=function(t){return new o(this.h,this.s,t)},i.prototype.eq=function(t){return t.h===this.h&&t.s===this.s&&t.v===this.v},i.fromRGB=function(t,e,s){t/=255,e/=255,s/=255;var n,o=Math.max(t,e,s),a=Math.min(t,e,s),r=Math.min(Math.max(0,o-a),1),d=0===o?0:r/o,u=o;if(0===r)n=0;else{switch(o){case t:n=(e-s)/r+(s>e?6:0);break;case e:n=(s-t)/r+2;break;case s:n=(t-e)/r+4}n/=6}return new i(n,d,u)},i.prototype.toRGB=function(){return n.fromHSV(this.h,this.s,this.v)},i.prototype.toHSL=function(){return n.fromHSV(this.h,this.s,this.v).toHSL()},i.prototype.toXYZ=function(){return n.fromHSV(this.h,this.s,this.v).toXYZ()},i.prototype.toLUV=function(){return n.fromHSV(this.h,this.s,this.v).toLUV()},i.prototype._h=function(t){return new i(t,this.s,this.v)},i.prototype._s=function(t){return new i(this.h,t,this.v)},i.prototype._v=function(t){return new i(this.h,this.s,t)},n.channelConverter=function(t){return Math.pow(t,2.2)},a.channelConverter=function(t){return Math.pow(t,1/2.2)},a.prototype.eq=function(t){return t.x===this.x&&t.y===this.y&&t.z===this.z},a.fromRGB=function(t,e,s){var i=n.channelConverter(t/255),o=n.channelConverter(e/255),r=n.channelConverter(s/255);return new a(.412453*i+.35758*o+.180423*r,.212671*i+.71516*o+.072169*r,.019334*i+.119193*o+.950227*r)},a.fromLUV=function(t,e,s){var n=1/(a.WHITE.x+15*a.WHITE.y+3*a.WHITE.z),i=4*a.WHITE.x*n,o=9*a.WHITE.y*n,r=t>8?Math.pow((t+16)/116,3):t/a.KAPPA,d=1/3*(52*t/(e+13*t*i)-1),u=-5*r,c=-1/3,l=r*(39*t/(s+13*t*o)-5),h=(l-u)/(d-c),f=h*d+u;return new a(h,r,f)},a.prototype.toRGB=function(){return n.fromXYZ(this.x,this.y,this.z)},a.prototype.toLUV=function(){return r.fromXYZ(this.x,this.y,this.z)},a.prototype.toHSL=function(){return n.fromXYZ(this.x,this.y,this.z).toHSL()},a.prototype.toHSV=function(){return n.fromXYZ(this.x,this.y,this.z).toHSV()},a.prototype._x=function(t){return new a(t,this.y,this.z)},a.prototype._y=function(t){return new a(this.x,t,this.z)},a.prototype._z=function(t){return new a(this.x,this.y,t)},a.EPSILON=Math.pow(6/29,3),a.KAPPA=Math.pow(29/3,3),a.WHITE=new n(255,255,255).toXYZ(),r.prototype.eq=function(t){return t.l===this.l&&t.u===this.u&&t.v===this.v},r.fromXYZ=function(t,e,s){var n=1/(a.WHITE.x+15*a.WHITE.y+3*a.WHITE.z),i=4*a.WHITE.x*n,o=9*a.WHITE.y*n,d=e/a.WHITE.y,u=t+15*e+3*s;0===u&&(u=1);var c=1/u,l=4*t*c,h=9*e*c,f=d>a.EPSILON?116*Math.pow(d,1/3)-16:a.KAPPA*d,m=13*f*(l-i),_=13*f*(h-o);return new r(f,m,_)},r.prototype.toXYZ=function(){return a.fromLUV(this.l,this.u,this.v)},r.prototype.toRGB=function(){return a.fromLUV(this.l,this.u,this.v).toRGB()},r.prototype.toHSL=function(){return a.fromLUV(this.l,this.u,this.v).toHSL()},r.prototype.toHSV=function(){return a.fromLUV(this.l,this.u,this.v).toHSV()},r.prototype._l=function(t){return new r(t,this.u,this.v)},r.prototype._u=function(t){return new r(this.l,t,this.v)},r.prototype._v=function(t){return new r(this.l,this.u,t)},e.prototype._rebuild_contrast=function(){this._luv_required_bright=new a(0,this.settings.luv_contrast*(new n(35,35,35).toXYZ().y+.05)-.05,0).toLUV().l,this._luv_required_dark=new a(0,(new n(217,217,217).toXYZ().y+.05)/this.settings.luv_contrast-.05,0).toLUV().l},e.prototype._rebuild_colors=function(){this.has_bttv||(this._colors={},this._update_colors())},e.prototype._update_colors=function(e){var s=t.App&&App.__container__.lookup("controller:layout"),n=t.App&&App.__container__.lookup("controller:settings"),i=s&&s.get("isTheatreMode")||n&&n.get("model.darkMode");if(!e||this._color_old_darkness!==i){this._color_old_darkness=i;for(var o=document.querySelectorAll(".chat-line .has-color"),a=0,r=o.length;r>a;a++){var d=o[a],u=d.getAttribute("data-color"),c=u&&this._handle_color(u);c&&(d.style.color=i?c[1]:c[0])}}},e.prototype._handle_color=function(t){if(!t||this._colors.hasOwnProperty(t))return this._colors[t];var e=n.fromHex(t),s=t,i=t;if("0"!==this.settings.color_blind){var o=e.daltonize(this.settings.color_blind);e.eq(o)||(e=o,s=i=e.toHex())}if("4"===this.settings.fix_color){var a=e.luminance();if(a>.3){for(var r=127,d=e;r--&&(d=d.brighten(-1),!(d.luminance()<=.3)););s=d.toHex()}if(.15>a){for(var r=127,d=e;r--&&(d=d.brighten(),!(d.luminance()>=.15)););i=d.toHex()}}if("2"===this.settings.fix_color){var u=e.toHSL();s=u._l(Math.min(Math.max(0,.7*u.l),1)).toHex(),i=u._l(Math.min(Math.max(0,.3+.7*u.l),1)).toHex()}if("3"===this.settings.fix_color){var c=e.toHSV();0===c.s?(s=c._v(Math.min(Math.max(.5,.5*c.v),1)).toRGB().toHex(),i=c._v(Math.min(Math.max(.5,.5+.5*c.v),1)).toRGB().toHex()):(s=n.fromHSV(c.h,Math.min(Math.max(.7,.7+.3*c.s),1),Math.min(.7,c.v)).toHex(),i=n.fromHSV(c.h,Math.min(.7,c.s),Math.min(Math.max(.7,.7+.3*c.v),1)).toHex())}if("1"===this.settings.fix_color){var l=e.toLUV();l.l>this._luv_required_dark&&(s=l._l(this._luv_required_dark).toRGB().toHex()),l.l50)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 n=e.length;e.length;){var i=e.shift();t.room.tmiRoom.sendMessage("/unmod "+i)}return"Sent unmod command for "+n+" users."},e.ffz_commands.massunmod.help="Usage: /ffz massunmod \nBroadcaster only. Unmod all the users in the provided list.",e.ffz_commands.massmod=function(t,e){if(e=e.join(" ").trim(),!e.length)return"You must provide a list of users to mod.";e=e.split(/\W*,\W*/);var s=this.get_user();if(!s||!s.login==t.id)return"You must be the broadcaster to use massmod.";if(e.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 n=e.length;e.length;){var i=e.shift();t.room.tmiRoom.sendMessage("/mod "+i)}return"Sent mod command for "+n+" users."},e.ffz_commands.massmod.help="Usage: /ffz massmod \nBroadcaster only. Mod all the users in the provided list."},{}],5:[function(t,e){var s='',n="true"==localStorage.ffzDebugMode&&document.body.classList.contains("ffz-dev"),i=n?"//localhost:8000/":"//cdn.frankerfacez.com/";e.exports={DEBUG:n,SERVER:i,API_SERVER:"//api.frankerfacez.com/",API_SERVER_2:"//direct-api.frankerfacez.com/",KNOWN_CODES:{"#-?[\\\\/]":"#-/",":-?(?:7|L)":":-7","\\<\\;\\]":"<]","\\:-?(S|s)":":-S","\\:-?\\\\":":-\\","\\:\\>\\;":":>","B-?\\)":"B-)","\\:-?[z|Z|\\|]":":-Z","\\:-?\\)":":-)","\\:-?\\(":":-(","\\:-?(p|P)":":-P","\\;-?(p|P)":";-P","\\<\\;3":"<3","\\:-?[\\\\/]":":-/","\\;-?\\)":";-)","R-?\\)":"R-)","[o|O](_|\\.)[o|O]":"O.o","\\:-?D":":-D","\\:-?(o|O)":":-O","\\>\\;\\(":">(","Gr(a|e)yFace":"GrayFace"},EMOTE_REPLACEMENT_BASE:i+"script/replacements/",EMOTE_REPLACEMENTS:{15:"15-JKanStyle.png",16:"16-OptimizePrime.png",17:"17-StoneLightning.png",18:"18-TheRinger.png",19:"19-PazPazowitz.png",20:"20-EagleEye.png",21:"21-CougarHunt.png",22:"22-RedCoat.png",26:"26-JonCarnage.png",27:"27-PicoMause.png",30:"30-BCWarrior.png",33:"33-DansGame.png",36:"36-PJSalt.png"},EMOJI_REGEX:/((?:\ud83c\udde8\ud83c\uddf3|\ud83c\uddfa\ud83c\uddf8|\ud83c\uddf7\ud83c\uddfa|\ud83c\uddf0\ud83c\uddf7|\ud83c\uddef\ud83c\uddf5|\ud83c\uddee\ud83c\uddf9|\ud83c\uddec\ud83c\udde7|\ud83c\uddeb\ud83c\uddf7|\ud83c\uddea\ud83c\uddf8|\ud83c\udde9\ud83c\uddea|\u0039\ufe0f?\u20e3|\u0038\ufe0f?\u20e3|\u0037\ufe0f?\u20e3|\u0036\ufe0f?\u20e3|\u0035\ufe0f?\u20e3|\u0034\ufe0f?\u20e3|\u0033\ufe0f?\u20e3|\u0032\ufe0f?\u20e3|\u0031\ufe0f?\u20e3|\u0030\ufe0f?\u20e3|\u0023\ufe0f?\u20e3|\ud83d\udeb3|\ud83d\udeb1|\ud83d\udeb0|\ud83d\udeaf|\ud83d\udeae|\ud83d\udea6|\ud83d\udea3|\ud83d\udea1|\ud83d\udea0|\ud83d\ude9f|\ud83d\ude9e|\ud83d\ude9d|\ud83d\ude9c|\ud83d\ude9b|\ud83d\ude98|\ud83d\ude96|\ud83d\ude94|\ud83d\ude90|\ud83d\ude8e|\ud83d\ude8d|\ud83d\ude8b|\ud83d\ude8a|\ud83d\ude88|\ud83d\ude86|\ud83d\ude82|\ud83d\ude81|\ud83d\ude36|\ud83d\ude34|\ud83d\ude2f|\ud83d\ude2e|\ud83d\ude2c|\ud83d\ude27|\ud83d\ude26|\ud83d\ude1f|\ud83d\ude1b|\ud83d\ude19|\ud83d\ude17|\ud83d\ude15|\ud83d\ude11|\ud83d\ude10|\ud83d\ude0e|\ud83d\ude08|\ud83d\ude07|\ud83d\ude00|\ud83d\udd67|\ud83d\udd66|\ud83d\udd65|\ud83d\udd64|\ud83d\udd63|\ud83d\udd62|\ud83d\udd61|\ud83d\udd60|\ud83d\udd5f|\ud83d\udd5e|\ud83d\udd5d|\ud83d\udd5c|\ud83d\udd2d|\ud83d\udd2c|\ud83d\udd15|\ud83d\udd09|\ud83d\udd08|\ud83d\udd07|\ud83d\udd06|\ud83d\udd05|\ud83d\udd04|\ud83d\udd02|\ud83d\udd01|\ud83d\udd00|\ud83d\udcf5|\ud83d\udcef|\ud83d\udced|\ud83d\udcec|\ud83d\udcb7|\ud83d\udcb6|\ud83d\udcad|\ud83d\udc6d|\ud83d\udc6c|\ud83d\udc65|\ud83d\udc2a|\ud83d\udc16|\ud83d\udc15|\ud83d\udc13|\ud83d\udc10|\ud83d\udc0f|\ud83d\udc0b|\ud83d\udc0a|\ud83d\udc09|\ud83d\udc08|\ud83d\udc07|\ud83d\udc06|\ud83d\udc05|\ud83d\udc04|\ud83d\udc03|\ud83d\udc02|\ud83d\udc01|\ud83d\udc00|\ud83c\udfe4|\ud83c\udfc9|\ud83c\udfc7|\ud83c\udf7c|\ud83c\udf50|\ud83c\udf4b|\ud83c\udf33|\ud83c\udf32|\ud83c\udf1e|\ud83c\udf1d|\ud83c\udf1c|\ud83c\udf1a|\ud83c\udf18|\ud83c\udccf|\ud83c\udd70|\ud83c\udd71|\ud83c\udd7e|\ud83c\udd8e|\ud83c\udd91|\ud83c\udd92|\ud83c\udd93|\ud83c\udd94|\ud83c\udd95|\ud83c\udd96|\ud83c\udd97|\ud83c\udd98|\ud83c\udd99|\ud83c\udd9a|\ud83d\udc77|\ud83d\udec5|\ud83d\udec4|\ud83d\udec3|\ud83d\udec2|\ud83d\udec1|\ud83d\udebf|\ud83d\udeb8|\ud83d\udeb7|\ud83d\udeb5|\ud83c\ude01|\ud83c\ude02|\ud83c\ude32|\ud83c\ude33|\ud83c\ude34|\ud83c\ude35|\ud83c\ude36|\ud83c\ude37|\ud83c\ude38|\ud83c\ude39|\ud83c\ude3a|\ud83c\ude50|\ud83c\ude51|\ud83c\udf00|\ud83c\udf01|\ud83c\udf02|\ud83c\udf03|\ud83c\udf04|\ud83c\udf05|\ud83c\udf06|\ud83c\udf07|\ud83c\udf08|\ud83c\udf09|\ud83c\udf0a|\ud83c\udf0b|\ud83c\udf0c|\ud83c\udf0f|\ud83c\udf11|\ud83c\udf13|\ud83c\udf14|\ud83c\udf15|\ud83c\udf19|\ud83c\udf1b|\ud83c\udf1f|\ud83c\udf20|\ud83c\udf30|\ud83c\udf31|\ud83c\udf34|\ud83c\udf35|\ud83c\udf37|\ud83c\udf38|\ud83c\udf39|\ud83c\udf3a|\ud83c\udf3b|\ud83c\udf3c|\ud83c\udf3d|\ud83c\udf3e|\ud83c\udf3f|\ud83c\udf40|\ud83c\udf41|\ud83c\udf42|\ud83c\udf43|\ud83c\udf44|\ud83c\udf45|\ud83c\udf46|\ud83c\udf47|\ud83c\udf48|\ud83c\udf49|\ud83c\udf4a|\ud83c\udf4c|\ud83c\udf4d|\ud83c\udf4e|\ud83c\udf4f|\ud83c\udf51|\ud83c\udf52|\ud83c\udf53|\ud83c\udf54|\ud83c\udf55|\ud83c\udf56|\ud83c\udf57|\ud83c\udf58|\ud83c\udf59|\ud83c\udf5a|\ud83c\udf5b|\ud83c\udf5c|\ud83c\udf5d|\ud83c\udf5e|\ud83c\udf5f|\ud83c\udf60|\ud83c\udf61|\ud83c\udf62|\ud83c\udf63|\ud83c\udf64|\ud83c\udf65|\ud83c\udf66|\ud83c\udf67|\ud83c\udf68|\ud83c\udf69|\ud83c\udf6a|\ud83c\udf6b|\ud83c\udf6c|\ud83c\udf6d|\ud83c\udf6e|\ud83c\udf6f|\ud83c\udf70|\ud83c\udf71|\ud83c\udf72|\ud83c\udf73|\ud83c\udf74|\ud83c\udf75|\ud83c\udf76|\ud83c\udf77|\ud83c\udf78|\ud83c\udf79|\ud83c\udf7a|\ud83c\udf7b|\ud83c\udf80|\ud83c\udf81|\ud83c\udf82|\ud83c\udf83|\ud83c\udf84|\ud83c\udf85|\ud83c\udf86|\ud83c\udf87|\ud83c\udf88|\ud83c\udf89|\ud83c\udf8a|\ud83c\udf8b|\ud83c\udf8c|\ud83c\udf8d|\ud83c\udf8e|\ud83c\udf8f|\ud83c\udf90|\ud83c\udf91|\ud83c\udf92|\ud83c\udf93|\ud83c\udfa0|\ud83c\udfa1|\ud83c\udfa2|\ud83c\udfa3|\ud83c\udfa4|\ud83c\udfa5|\ud83c\udfa6|\ud83c\udfa7|\ud83c\udfa8|\ud83c\udfa9|\ud83c\udfaa|\ud83c\udfab|\ud83c\udfac|\ud83c\udfad|\ud83c\udfae|\ud83c\udfaf|\ud83c\udfb0|\ud83c\udfb1|\ud83c\udfb2|\ud83c\udfb3|\ud83c\udfb4|\ud83c\udfb5|\ud83c\udfb6|\ud83c\udfb7|\ud83c\udfb8|\ud83c\udfb9|\ud83c\udfba|\ud83c\udfbb|\ud83c\udfbc|\ud83c\udfbd|\ud83c\udfbe|\ud83c\udfbf|\ud83c\udfc0|\ud83c\udfc1|\ud83c\udfc2|\ud83c\udfc3|\ud83c\udfc4|\ud83c\udfc6|\ud83c\udfc8|\ud83c\udfca|\ud83c\udfe0|\ud83c\udfe1|\ud83c\udfe2|\ud83c\udfe3|\ud83c\udfe5|\ud83c\udfe6|\ud83c\udfe7|\ud83c\udfe8|\ud83c\udfe9|\ud83c\udfea|\ud83c\udfeb|\ud83c\udfec|\ud83c\udfed|\ud83c\udfee|\ud83c\udfef|\ud83c\udff0|\ud83d\udc0c|\ud83d\udc0d|\ud83d\udc0e|\ud83d\udc11|\ud83d\udc12|\ud83d\udc14|\ud83d\udc17|\ud83d\udc18|\ud83d\udc19|\ud83d\udc1a|\ud83d\udc1b|\ud83d\udc1c|\ud83d\udc1d|\ud83d\udc1e|\ud83d\udc1f|\ud83d\udc20|\ud83d\udc21|\ud83d\udc22|\ud83d\udc23|\ud83d\udc24|\ud83d\udc25|\ud83d\udc26|\ud83d\udc27|\ud83d\udc28|\ud83d\udc29|\ud83d\udc2b|\ud83d\udc2c|\ud83d\udc2d|\ud83d\udc2e|\ud83d\udc2f|\ud83d\udc30|\ud83d\udc31|\ud83d\udc32|\ud83d\udc33|\ud83d\udc34|\ud83d\udc35|\ud83d\udc36|\ud83d\udc37|\ud83d\udc38|\ud83d\udc39|\ud83d\udc3a|\ud83d\udc3b|\ud83d\udc3c|\ud83d\udc3d|\ud83d\udc3e|\ud83d\udc40|\ud83d\udc42|\ud83d\udc43|\ud83d\udc44|\ud83d\udc45|\ud83d\udc46|\ud83d\udc47|\ud83d\udc48|\ud83d\udc49|\ud83d\udc4a|\ud83d\udc4b|\ud83d\udc4c|\ud83d\udc4d|\ud83d\udc4e|\ud83d\udc4f|\ud83d\udc50|\ud83d\udc51|\ud83d\udc52|\ud83d\udc53|\ud83d\udc54|\ud83d\udc55|\ud83d\udc56|\ud83d\udc57|\ud83d\udc58|\ud83d\udc59|\ud83d\udc5a|\ud83d\udc5b|\ud83d\udc5c|\ud83d\udc5d|\ud83d\udc5e|\ud83d\udc5f|\ud83d\udc60|\ud83d\udc61|\ud83d\udc62|\ud83d\udc63|\ud83d\udc64|\ud83d\udc66|\ud83d\udc67|\ud83d\udc68|\ud83d\udc69|\ud83d\udc6a|\ud83d\udc6b|\ud83d\udc6e|\ud83d\udc6f|\ud83d\udc70|\ud83d\udc71|\ud83d\udc72|\ud83d\udc73|\ud83d\udc74|\ud83d\udc75|\ud83d\udc76|\ud83d\udeb4|\ud83d\udc78|\ud83d\udc79|\ud83d\udc7a|\ud83d\udc7b|\ud83d\udc7c|\ud83d\udc7d|\ud83d\udc7e|\ud83d\udc7f|\ud83d\udc80|\ud83d\udc81|\ud83d\udc82|\ud83d\udc83|\ud83d\udc84|\ud83d\udc85|\ud83d\udc86|\ud83d\udc87|\ud83d\udc88|\ud83d\udc89|\ud83d\udc8a|\ud83d\udc8b|\ud83d\udc8c|\ud83d\udc8d|\ud83d\udc8e|\ud83d\udc8f|\ud83d\udc90|\ud83d\udc91|\ud83d\udc92|\ud83d\udc93|\ud83d\udc94|\ud83d\udc95|\ud83d\udc96|\ud83d\udc97|\ud83d\udc98|\ud83d\udc99|\ud83d\udc9a|\ud83d\udc9b|\ud83d\udc9c|\ud83d\udc9d|\ud83d\udc9e|\ud83d\udc9f|\ud83d\udca0|\ud83d\udca1|\ud83d\udca2|\ud83d\udca3|\ud83d\udca4|\ud83d\udca5|\ud83d\udca6|\ud83d\udca7|\ud83d\udca8|\ud83d\udca9|\ud83d\udcaa|\ud83d\udcab|\ud83d\udcac|\ud83d\udcae|\ud83d\udcaf|\ud83d\udcb0|\ud83d\udcb1|\ud83d\udcb2|\ud83d\udcb3|\ud83d\udcb4|\ud83d\udcb5|\ud83d\udcb8|\ud83d\udcb9|\ud83d\udcba|\ud83d\udcbb|\ud83d\udcbc|\ud83d\udcbd|\ud83d\udcbe|\ud83d\udcbf|\ud83d\udcc0|\ud83d\udcc1|\ud83d\udcc2|\ud83d\udcc3|\ud83d\udcc4|\ud83d\udcc5|\ud83d\udcc6|\ud83d\udcc7|\ud83d\udcc8|\ud83d\udcc9|\ud83d\udcca|\ud83d\udccb|\ud83d\udccc|\ud83d\udccd|\ud83d\udcce|\ud83d\udccf|\ud83d\udcd0|\ud83d\udcd1|\ud83d\udcd2|\ud83d\udcd3|\ud83d\udcd4|\ud83d\udcd5|\ud83d\udcd6|\ud83d\udcd7|\ud83d\udcd8|\ud83d\udcd9|\ud83d\udcda|\ud83d\udcdb|\ud83d\udcdc|\ud83d\udcdd|\ud83d\udcde|\ud83d\udcdf|\ud83d\udce0|\ud83d\udce1|\ud83d\udce2|\ud83d\udce3|\ud83d\udce4|\ud83d\udce5|\ud83d\udce6|\ud83d\udce7|\ud83d\udce8|\ud83d\udce9|\ud83d\udcea|\ud83d\udceb|\ud83d\udcee|\ud83d\udcf0|\ud83d\udcf1|\ud83d\udcf2|\ud83d\udcf3|\ud83d\udcf4|\ud83d\udcf6|\ud83d\udcf7|\ud83d\udcf9|\ud83d\udcfa|\ud83d\udcfb|\ud83d\udcfc|\ud83d\udd03|\ud83d\udd0a|\ud83d\udd0b|\ud83d\udd0c|\ud83d\udd0d|\ud83d\udd0e|\ud83d\udd0f|\ud83d\udd10|\ud83d\udd11|\ud83d\udd12|\ud83d\udd13|\ud83d\udd14|\ud83d\udd16|\ud83d\udd17|\ud83d\udd18|\ud83d\udd19|\ud83d\udd1a|\ud83d\udd1b|\ud83d\udd1c|\ud83d\udd1d|\ud83d\udd1e|\ud83d\udd1f|\ud83d\udd20|\ud83d\udd21|\ud83d\udd22|\ud83d\udd23|\ud83d\udd24|\ud83d\udd25|\ud83d\udd26|\ud83d\udd27|\ud83d\udd28|\ud83d\udd29|\ud83d\udd2a|\ud83d\udd2b|\ud83d\udd2e|\ud83d\udd2f|\ud83d\udd30|\ud83d\udd31|\ud83d\udd32|\ud83d\udd33|\ud83d\udd34|\ud83d\udd35|\ud83d\udd36|\ud83d\udd37|\ud83d\udd38|\ud83d\udd39|\ud83d\udd3a|\ud83d\udd3b|\ud83d\udd3c|\ud83d\udd3d|\ud83d\udd50|\ud83d\udd51|\ud83d\udd52|\ud83d\udd53|\ud83d\udd54|\ud83d\udd55|\ud83d\udd56|\ud83d\udd57|\ud83d\udd58|\ud83d\udd59|\ud83d\udd5a|\ud83d\udd5b|\ud83d\uddfb|\ud83d\uddfc|\ud83d\uddfd|\ud83d\uddfe|\ud83d\uddff|\ud83d\ude01|\ud83d\ude02|\ud83d\ude03|\ud83d\ude04|\ud83d\ude05|\ud83d\ude06|\ud83d\ude09|\ud83d\ude0a|\ud83d\ude0b|\ud83d\ude0c|\ud83d\ude0d|\ud83d\ude0f|\ud83d\ude12|\ud83d\ude13|\ud83d\ude14|\ud83d\ude16|\ud83d\ude18|\ud83d\ude1a|\ud83d\ude1c|\ud83d\ude1d|\ud83d\ude1e|\ud83d\ude20|\ud83d\ude21|\ud83d\ude22|\ud83d\ude23|\ud83d\ude24|\ud83d\ude25|\ud83d\ude28|\ud83d\ude29|\ud83d\ude2a|\ud83d\ude2b|\ud83d\ude2d|\ud83d\ude30|\ud83d\ude31|\ud83d\ude32|\ud83d\ude33|\ud83d\ude35|\ud83d\ude37|\ud83d\ude38|\ud83d\ude39|\ud83d\ude3a|\ud83d\ude3b|\ud83d\ude3c|\ud83d\ude3d|\ud83d\ude3e|\ud83d\ude3f|\ud83d\ude40|\ud83d\ude45|\ud83d\ude46|\ud83d\ude47|\ud83d\ude48|\ud83d\ude49|\ud83d\ude4a|\ud83d\ude4b|\ud83d\ude4c|\ud83d\ude4d|\ud83d\ude4e|\ud83d\ude4f|\ud83d\ude80|\ud83d\ude83|\ud83d\ude84|\ud83d\ude85|\ud83d\ude87|\ud83d\ude89|\ud83d\ude8c|\ud83d\ude8f|\ud83d\ude91|\ud83d\ude92|\ud83d\ude93|\ud83d\ude95|\ud83d\ude97|\ud83d\ude99|\ud83d\ude9a|\ud83d\udea2|\ud83d\udea4|\ud83d\udea5|\ud83d\udea7|\ud83d\udea8|\ud83d\udea9|\ud83d\udeaa|\ud83d\udeab|\ud83d\udeac|\ud83d\udead|\ud83d\udeb2|\ud83d\udeb6|\ud83d\udeb9|\ud83d\udeba|\ud83d\udebb|\ud83d\udebc|\ud83d\udebd|\ud83d\udebe|\ud83d\udec0|\ud83c\udde6|\ud83c\udde7|\ud83c\udde8|\ud83c\udde9|\ud83c\uddea|\ud83c\uddeb|\ud83c\uddec|\ud83c\udded|\ud83c\uddee|\ud83c\uddef|\ud83c\uddf0|\ud83c\uddf1|\ud83c\uddf2|\ud83c\uddf3|\ud83c\uddf4|\ud83c\uddf5|\ud83c\uddf6|\ud83c\uddf7|\ud83c\uddf8|\ud83c\uddf9|\ud83c\uddfa|\ud83c\uddfb|\ud83c\uddfc|\ud83c\uddfd|\ud83c\uddfe|\ud83c\uddff|\ud83c\udf0d|\ud83c\udf0e|\ud83c\udf10|\ud83c\udf12|\ud83c\udf16|\ud83c\udf17|\ue50a|\u3030|\u27b0|\u2797|\u2796|\u2795|\u2755|\u2754|\u2753|\u274e|\u274c|\u2728|\u270b|\u270a|\u2705|\u26ce|\u23f3|\u23f0|\u23ec|\u23eb|\u23ea|\u23e9|\u2122|\u27bf|\u00a9|\u00ae)|(?:(?:\ud83c\udc04|\ud83c\udd7f|\ud83c\ude1a|\ud83c\ude2f|\u3299|\u303d|\u2b55|\u2b50|\u2b1c|\u2b1b|\u2b07|\u2b06|\u2b05|\u2935|\u2934|\u27a1|\u2764|\u2757|\u2747|\u2744|\u2734|\u2733|\u2716|\u2714|\u2712|\u270f|\u270c|\u2709|\u2708|\u2702|\u26fd|\u26fa|\u26f5|\u26f3|\u26f2|\u26ea|\u26d4|\u26c5|\u26c4|\u26be|\u26bd|\u26ab|\u26aa|\u26a1|\u26a0|\u2693|\u267f|\u267b|\u3297|\u2666|\u2665|\u2663|\u2660|\u2653|\u2652|\u2651|\u2650|\u264f|\u264e|\u264d|\u264c|\u264b|\u264a|\u2649|\u2648|\u263a|\u261d|\u2615|\u2614|\u2611|\u260e|\u2601|\u2600|\u25fe|\u25fd|\u25fc|\u25fb|\u25c0|\u25b6|\u25ab|\u25aa|\u24c2|\u231b|\u231a|\u21aa|\u21a9|\u2199|\u2198|\u2197|\u2196|\u2195|\u2194|\u2139|\u2049|\u203c|\u2668)([\uFE0E\uFE0F]?)))/g,SVGPATH:s,ZREKNARF:''+s+"",CHAT_BUTTON:''+s+"",ROOMS:'',CAMERA:'',INVITE:'',LIVE:'',EYE:'',CLOCK:'',GEAR:'',HEART:'',EMOTE:'',STAR:'',CLOSE:'',EDIT:'',GRAPH:''} },{}],6:[function(){var e=t.FrankerFaceZ;e.settings_info.developer_mode={type:"boolean",value:!1,storage_key:"ffzDebugMode",visible:function(){return this.settings.developer_mode||Date.now()-parseInt(localStorage.ffzLastDevMode||"0")<6048e5},category:"Debugging",name:"Developer Mode",help:"Load FrankerFaceZ from the local development server instead of the CDN. Please refresh after changing this setting.",on_update:function(){localStorage.ffzLastDevMode=Date.now()}},e.ffz_commands.developer_mode=function(t,e){var s,e=e&&e.length?e[0].toLowerCase():null;return"y"==e||"yes"==e||"true"==e||"on"==e?s=!0:("n"==e||"no"==e||"false"==e||"off"==e)&&(s=!1),void 0===s?"Developer Mode is currently "+(this.settings.developer_mode?"enabled.":"disabled."):(this.settings.set("developer_mode",s),"Developer Mode is now "+(s?"enabled":"disabled")+". Please refresh your browser.")},e.ffz_commands.developer_mode.help="Usage: /ffz developer_mode \nEnable or disable Developer Mode. When Developer Mode is enabled, the script will be reloaded from //localhost:8000/script.js instead of from the CDN."},{}],7:[function(e){var s=t.FrankerFaceZ,n=e("../utils"),i=e("../constants");s.prototype.setup_channel=function(){this.log("Creating channel style element.");var t=this._channel_style=document.createElement("style");t.id="ffz-channel-css",document.head.appendChild(t),document.body.classList.toggle("ffz-hide-view-count",!this.settings.channel_views),this.log("Creating channel style element.");var t=this._channel_style=document.createElement("style");t.id="ffz-channel-css",document.head.appendChild(t),this.log("Hooking the Ember Channel Index view.");var e=App.__container__.resolve("view:channel/index"),n=this;if(e){this._modify_cindex(e);try{e.create().destroy()}catch(i){}for(var o in Ember.View.views)if(Ember.View.views.hasOwnProperty(o)){var a=Ember.View.views[o];a instanceof e&&(this.log("Manually updating Channel Index view.",a),this._modify_cindex(a),a.ffzInit())}this.log("Hooking the Ember Channel model."),e=App.__container__.resolve("model:channel"),e&&(e.reopen({ffz_host_target:void 0,setHostMode:function(t){return n.settings.hosted_channels?(this.set("ffz_host_target",t.target),this._super(t)):(this.set("ffz_host_target",void 0),this._super({target:void 0,delay:0}))}}),this.log("Hooking the Ember Channel controller."),e=App.__container__.lookup("controller:channel"),e&&(e.reopen({ffzUpdateUptime:function(){n._cindex&&n._cindex.ffzUpdateUptime()}.observes("isLive","content.id"),ffzUpdateInfo:function(){this._ffz_update_timer&&clearTimeout(this._ffz_update_timer),this.get("content.id")&&(this._ffz_update_timer=setTimeout(this.ffzCheckUpdate.bind(this),6e4))}.observes("content.id"),ffzCheckUpdate:function(){var t=this,e=t.get("content.id");e&&Twitch.api&&Twitch.api.get("streams/"+e,{},{version:3}).done(function(e){if(!e||!e.stream)return t.set("stream.created_at",null),void t.set("stream.viewers",0);t.set("stream.created_at",e.stream.created_at||null),t.set("stream.viewers",e.stream.viewers||0);var s=e.stream.game||e.stream.channel&&e.stream.channel.game;s&&(t.set("game",s),t.set("rollbackData.game",s)),e.stream.channel&&(e.stream.channel.status&&t.set("status",e.stream.channel.status),e.stream.channel.views&&t.set("views",e.stream.channel.views),e.stream.channel.followers&&t.get("content.followers.isLoaded")&&t.set("content.followers.total",e.stream.channel.followers))}).always(function(){t.ffzUpdateInfo()})},ffzUpdateTitle:function(){var t=this.get("content.name"),e=this.get("content.display_name");e&&(s.capitalization[t]=[e,Date.now()]),n._cindex&&n._cindex.ffzFixTitle()}.observes("content.status","content.id"),ffzHostTarget:function(){var t=this.get("content.hostModeTarget"),e=t&&t.get("name"),i=t&&t.get("id"),o=t&&t.get("display_name");i!==n.__old_host_target&&(n.__old_host_target&&n.ws_send("unsub_channel",n.__old_host_target),i?(n.ws_send("sub_channel",i),n.__old_host_target=i):delete n.__old_host_target),o&&(s.capitalization[e]=[o,Date.now()]),n.settings.group_tabs&&n._chatv&&n._chatv.ffzRebuildTabs(),n.settings.follow_buttons&&n.rebuild_following_ui(),n.settings.srl_races&&n.rebuild_race_ui()}.observes("content.hostModeTarget")}),e.ffzUpdateInfo()))}},s.prototype._modify_cindex=function(t){var e=this;t.reopen({didInsertElement:function(){this._super();try{this.ffzInit()}catch(t){e.error("CIndex didInsertElement: "+t)}},willClearRender:function(){try{this.ffzTeardown()}catch(t){e.error("CIndex willClearRender: "+t)}return this._super()},ffzInit:function(){var t=this.get("controller.id"),s=this.get("element");e._cindex=this,e.ws_send("sub_channel",t),s.setAttribute("data-channel",t),s.classList.add("ffz-channel"),this.$(".theatre-button a").attr("title","Theater Mode (Alt+T)"),this.ffzFixTitle(),this.ffzUpdateUptime(),this.ffzUpdateChatters(),this.ffzUpdateHostButton(),this.ffzUpdatePlayerStats();var n=this.get("element").querySelector(".svg-glyph_views:not(.ffz-svg)");if(n&&n.parentNode.classList.add("twitch-channel-views"),e.settings.follow_buttons&&e.rebuild_following_ui(),e.settings.srl_races&&e.rebuild_race_ui(),e.settings.auto_theater){var i=App.__container__.lookup("controller:layout");i&&i.set("isTheatreMode",!0)}},ffzFixTitle:function(){if(!e.has_bttv&&e.settings.stream_title){var t=this.get("controller.status"),s=this.get("controller.id");t=e.render_tokens(e.tokenize_line(s,s,t,!0)),this.$(".title span").each(function(e,s){var n=s.querySelectorAll("script");s.innerHTML=n.length?n[0].outerHTML+t+n[1].outerHTML:t})}},ffzUpdateHostButton:function(){var t=this.get("controller.id"),i=this.get("controller.hostModeTarget.id"),o=e.get_user(),a=o&&e.rooms&&e.rooms[o.login]&&e.rooms[o.login].room,r=a&&a.ffz_host_target,d=a&&a.ffz_hosts_left,u=this.get("element");if(this.set("ffz_host_updating",!1),t){var c=u&&u.querySelector(".stats-and-actions .channel-actions"),l=c&&c.querySelector("#ffz-ui-host-button");if(c&&e.settings.stream_host_button&&o&&o.login!==t){if(!l){l=document.createElement("span"),l.id="ffz-ui-host-button",l.className="button action tooltip",l.addEventListener("click",this.ffzClickHost.bind(l,this,!1));var h;try{h=c.querySelector(":scope > .theatre-button")}catch(f){h=void 0}h?c.insertBefore(l,h):c.appendChild(l)}l.classList.remove("disabled"),l.innerHTML=t===r?"Unhost":"Host",l.title=r?"You are now hosting "+n.sanitize(s.get_capitalization(r))+".":"You are not hosting any channel.","number"==typeof d&&(l.title+=" You have "+d+" host command"+n.pluralize(d)+" remaining this half hour.")}else l&&l.parentElement.removeChild(l)}if(i){var c=u&&u.querySelector("#hostmode .channel-actions"),l=c&&c.querySelector("#ffz-ui-host-button");if(c&&e.settings.stream_host_button&&o&&o.login!==i){if(!l){l=document.createElement("span"),l.id="ffz-ui-host-button",l.className="button action tooltip",l.addEventListener("click",this.ffzClickHost.bind(l,this,!0));var h;try{h=c.querySelector(":scope > .theatre-button")}catch(f){h=void 0}h?c.insertBefore(l,h):c.appendChild(l)}l.classList.remove("disabled"),l.innerHTML=i===r?"Unhost":"Host",l.title=r?"You are currently hosting "+n.sanitize(s.get_capitalization(r))+". Click to "+(i===r?"unhost":"host")+" this channel.":"You are not currently hosting any channel. Click to host this channel.","number"==typeof d&&(l.title+=" You have "+d+" host command"+n.pluralize(d)+" remaining this half hour.")}else l&&l.parentElement.removeChild(l)}},ffzClickHost:function(t,s){var n=t.get(s?"controller.hostModeTarget.id":"controller.id"),i=e.get_user(),o=i&&e.rooms&&e.rooms[i.login]&&e.rooms[i.login].room,a=o&&o.ffz_host_target;o&&!t.get("ffz_host_updating")&&(this.classList.add("disabled"),this.title="Updating...",t.set("ffz_host_updating",!0),o.send(a===n?"/unhost":"/host "+n))},ffzUpdateChatters:function(){var t=this.get("controller.id"),s=e.rooms&&e.rooms[t];if(!s||!e.settings.chatter_count){var o=this.get("element").querySelector("#ffz-chatter-display");return o&&o.parentElement.removeChild(o),o=this.get("element").querySelector("#ffz-ffzchatter-display"),void(o&&o.parentElement.removeChild(o))}var a=Object.keys(s.room.get("ffz_chatters")||{}).length,r=s.ffz_chatters||0,d=s.ffz_viewers||0,o=this.get("element").querySelector("#ffz-chatter-display span");if(!o){var u=this.get("element").querySelector(".stats-and-actions .channel-stats");if(!u)return;var c=document.createElement("span");c.className="ffz stat",c.id="ffz-chatter-display",c.title="Currently in Chat",c.innerHTML=i.ROOMS+" ",o=document.createElement("span"),c.appendChild(o);var l=u.querySelector("#ffz-ffzchatter-display");l?u.insertBefore(c,l):u.appendChild(c),jQuery(c).tipsy()}if(o.innerHTML=n.number_commas(a),!r&&!d)return o=this.get("element").querySelector("#ffz-ffzchatter-display"),void(o&&o.parentNode.removeChild(o));if(o=this.get("element").querySelector("#ffz-ffzchatter-display span"),!o){var u=this.get("element").querySelector(".stats-and-actions .channel-stats");if(!u)return;var c=document.createElement("span");c.className="ffz stat",c.id="ffz-ffzchatter-display",c.title="Viewers (In Chat) with FrankerFaceZ",c.innerHTML=i.ZREKNARF+" ",o=document.createElement("span"),c.appendChild(o);var l=u.querySelector("#ffz-chatter-display");l?u.insertBefore(c,l.nextSibling):u.appendChild(c),jQuery(c).tipsy()}o.innerHTML=n.number_commas(d)+" ("+n.number_commas(r)+")"},ffzUpdatePlayerStats:function(){var t=this.get("controller.id"),s=this.get("controller.hostModeTarget.id"),n=this.get("element");if(t){var o=n&&n.querySelector(".stats-and-actions .channel-stats"),a=o&&o.querySelector("#ffz-ui-player-stats"),n=a&&a.querySelector("span"),r=e.players&&e.players[t],d=r&&r.player,u=d&&d.stats;if(o&&e.settings.player_stats&&u&&"NaN"!==u.hlsLatencyBroadcaster&&0/0!==u.hlsLatencyBroadcaster){if(!a){a=document.createElement("span"),a.id="ffz-ui-player-stats",a.className="ffz stat tooltip",a.innerHTML=i.GRAPH+" ",n=document.createElement("span"),a.appendChild(n);var c=o.querySelector("#ffz-uptime-display");c?o.insertBefore(a,c.nextSibling):o.appendChild(a)}a.title="Stream Latency\nFPS: "+u.fps+"\nPlayback Rate: "+u.playbackRate+" Kbps",n.textContent=u.hlsLatencyBroadcaster+"s"}else a&&a.parentElement.removeChild(a)}if(s){var o=n&&n.querySelector("#hostmode .channel-stats"),a=o&&o.querySelector("#ffz-ui-player-stats"),n=a&&a.querySelector("span"),r=e.players&&e.players[s],d=r&&r.player,u=d&&d.stats;if(o&&e.settings.player_stats&&u&&"NaN"!==u.hlsLatencyBroadcaster&&0/0!==u.hlsLatencyBroadcaster){if(!a){a=document.createElement("span"),a.id="ffz-ui-player-stats",a.className="ffz stat tooltip",a.innerHTML=i.GRAPH+" ",n=document.createElement("span"),a.appendChild(n);var c=o.querySelector("#ffz-uptime-display");c?o.insertBefore(a,c.nextSibling):o.appendChild(a)}a.title="Stream Latency\nFPS: "+u.fps+"\nPlayback Rate: "+u.playbackRate+" Kbps",n.textContent=u.hlsLatencyBroadcaster+"s"}else a&&a.parentElement.removeChild(a)}},ffzUpdateUptime:function(){if(this._ffz_update_uptime&&(clearTimeout(this._ffz_update_uptime),delete this._ffz_update_uptime),!e.settings.stream_uptime||!this.get("controller.isLiveAccordingToKraken")){var t=this.get("element").querySelector("#ffz-uptime-display");return void(t&&t.parentElement.removeChild(t))}this._ffz_update_uptime=setTimeout(this.ffzUpdateUptime.bind(this),1e3);var s=this.get("controller.content.stream.created_at");s=s&&n.parse_date(s);var o=s&&Math.floor((Date.now()-s.getTime())/1e3)||-1;if(0>o){var t=this.get("element").querySelector("#ffz-uptime-display");return void(t&&t.parentElement.removeChild(t))}var t=this.get("element").querySelector("#ffz-uptime-display span");if(!t){var a=this.get("element").querySelector(".stats-and-actions .channel-stats");if(!a)return;var r=document.createElement("span");r.className="ffz stat",r.id="ffz-uptime-display",r.title="Stream Uptime (since "+s.toLocaleString()+")",r.innerHTML=i.CLOCK+" ",t=document.createElement("span"),r.appendChild(t);var d=a.querySelector(".live-count");if(d)a.insertBefore(r,d.nextSibling);else try{d=a.querySelector("script:nth-child(0n+2)"),a.insertBefore(r,d.nextSibling)}catch(u){a.insertBefore(r,a.childNodes[0])}jQuery(r).tipsy({html:!0})}t.innerHTML=n.time_to_string(o)},ffzTeardown:function(){var t=this.get("controller.id");t&&e.ws_send("unsub_channel",t),this.get("element").setAttribute("data-channel",""),e._cindex=void 0,this._ffz_update_uptime&&clearTimeout(this._ffz_update_uptime),n.update_css(e._channel_style,t,null)}})},s.settings_info.auto_theater={type:"boolean",value:!1,category:"Appearance",no_mobile:!0,no_bttv:!0,name:"Automatic Theater Mode",help:"Automatically enter theater mode when opening a channel."},s.settings_info.chatter_count={type:"boolean",value:!1,no_mobile:!0,category:"Channel Metadata",name:"Chatter Count",help:"Display the current number of users connected to chat beneath the channel.",on_update:function(t){if(this._cindex&&this._cindex.ffzUpdateChatters(),t&&this.rooms)for(var e in this.rooms)this.rooms.hasOwnProperty(e)&&this.rooms[e].room&&this.rooms[e].room.ffzInitChatterCount()}},s.settings_info.channel_views={type:"boolean",value:!0,no_mobile:!0,category:"Channel Metadata",name:"Channel Views",help:"Display the number of times the channel has been viewed beneath the stream.",on_update:function(t){document.body.classList.toggle("ffz-hide-view-count",!t)}},s.settings_info.hosted_channels={type:"boolean",value:!0,no_mobile:!0,category:"Channel Metadata",name:"Channel Hosting",help:"Display other channels that have been featured by the current channel.",on_update:function(t){var e=document.querySelector("input.ffz-setting-hosted-channels");if(e&&(e.checked=t),this._cindex){var s=this._cindex.get("controller.model"),n=s&&this.rooms&&this.rooms[s.get("id")],i=n&&n.room&&n.room.get("ffz_host_target");s&&n&&s.setHostMode({target:i,delay:0})}}},s.settings_info.stream_host_button={type:"boolean",value:!0,no_mobile:!0,category:"Channel Metadata",name:"Host This Channel Button",help:"Display a button underneath streams that make it easy to host them with your own channel.",on_update:function(){this._cindex&&this._cindex.ffzUpdateHostButton()}},s.settings_info.stream_uptime={type:"boolean",value:!1,no_mobile:!0,category:"Channel Metadata",name:"Stream Uptime",help:"Display the stream uptime under a channel by the viewer count.",on_update:function(){this._cindex&&this._cindex.ffzUpdateUptime()}},s.settings_info.stream_title={type:"boolean",value:!0,no_bttv:!0,no_mobile:!0,category:"Channel Metadata",name:"Title Links",help:"Make links in stream titles clickable.",on_update:function(){this._cindex&&this._cindex.ffzFixTitle()}}},{"../constants":5,"../utils":35}],8:[function(e){var s=t.FrankerFaceZ,n=e("../utils"),i=(e("../constants"),-1!==navigator.userAgent.indexOf("Android")),o={BACKSPACE:8,TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,TWO:50,COLON:59,FAKE_COLON:186},a=function(t){if("number"==typeof t.selectionStart)return t.selectionStart;if(!t.createTextRange)return-1;var e=document.selection.createRange(),s=t.createTextRange();return s.moveToBookmark(e.getBookmark()),s.moveStart("character",-t.value.length),s.text.length},r=function(t,e){if(t.setSelectionRange)t.setSelectionRange(e,e);else if(t.createTextRange){var s=t.createTextRange();s.move("character",-t.value.length),s.move("character",e),s.select()}};s.settings_info.input_quick_reply={type:"boolean",value:!0,category:"Chat Input",no_bttv:!0,name:"Reply to Whispers with /r",help:"Automatically replace /r at the start of the line with the command to whisper to the person you've whispered with most recently."},s.settings_info.input_mru={type:"boolean",value:!0,category:"Chat Input",no_bttv:!0,name:"Chat Input History",help:"Use the Up and Down arrows in chat to select previously sent chat messages."},s.settings_info.input_emoji={type:"boolean",value:!1,category:"Chat Input",no_bttv:!0,name:"Enter Emoji By Name",help:"Replace emoji that you type by name with the character. :+1: becomes 👍."},s.prototype.setup_chat_input=function(){this.log("Hooking the Ember Chat Input controller.");var t=App.__container__.resolve("component:twitch-chat-input");if(t&&(this._modify_chat_input(t),this._roomv))for(var e=0;e500&&this.ffzResizeInput()}}.observes("textareaValue"),ffzResizeInput:function(){this._ffz_last_resize=Date.now();var t=this.get("element"),e=t&&t.querySelector("textarea");if(e&&d._chat_style&&d.settings.minimal_chat){this._ffz_minimal_style.innerHTML="body.ffz-minimal-chat .ember-chat .chat-interface .textarea-contain textarea { height: auto !important; }";var s=Math.max(32,Math.min(128,e.scrollHeight));this._ffz_minimal_style.innerHTML="body.ffz-minimal-chat .ember-chat .chat-interface .textarea-contain textarea { height: "+s+"px !important; }",s!==this._ffz_last_height&&(n.update_css(d._chat_style,"input_height","body.ffz-minimal-chat .ember-chat .chat-interface { height: "+s+"px !important; }body.ffz-minimal-chat .ember-chat .chat-messages, body.ffz-minimal-chat .ember-chat .chat-interface .emoticon-selector { bottom: "+s+"px !important; }"),d._roomv&&d._roomv.get("stuckToBottom")&&d._roomv._scrollToBottom()),this._ffz_last_height=s}},_ffzKeyDown:function(e){var s=e||t.event,n=s.charCode||s.keyCode;switch(n){case o.UP:case o.DOWN:if(s.shiftKey||s.shiftLeft||s.ctrlKey||s.metaKey)return;if(this.get("isShowingSuggestions"))s.preventDefault();else{if(!d.settings.input_mru)return this._onKeyDown(e);Ember.run.next(this.ffzCycleMRU.bind(this,n,a(this.get("chatTextArea"))))}break;case o.SPACE:if(!d.settings.input_quick_reply||2!==a(this.get("chatTextArea"))||"/r"!==this.get("textareaValue").substring(0,2))return this._onKeyDown(e);var i=this;Ember.run.next(function(){var t=i.get("uniqueWhisperSuggestions.0");if(t){var e="/w "+t+i.get("textareaValue").substr(2);i.set("_currentWhisperTarget",0),i.set("textareaValue",e),Ember.run.next(function(){r(i.get("chatTextArea"),4+t.length)})}});break;case o.COLON:case o.FAKE_COLON:if(d.settings.input_emoji&&(s.shiftKey||s.shiftLeft)){var i=this,u=a(this.get("chatTextArea"));return void(u>0&&Ember.run.next(function(){var t=i.get("textareaValue"),e=t.lastIndexOf(":",u-1);if(-1!==e&&-1!==u&&":"===t.charAt(u)){var s=t.substr(e+1,u-e-1),n=d.emoji_names[s],o=d.emoji_data[n];if(o){var a=t.substr(0,e)+o.raw;i.set("textareaValue",a+t.substr(u+1)),Ember.run.next(function(){r(i.get("chatTextArea"),a.length)})}}}))}return this._onKeyDown(e);case o.ENTER:s.shiftKey||s.shiftLeft||this.set("ffz_mru_index",-1);default:return this._onKeyDown(e)}},ffzCycleMRU:function(t,e){var s=a(this.get("chatTextArea"));if(e===s){var n=this.get("ffz_mru_index"),i=this._parentView.get("context.model.mru_list")||[];n=t===o.UP?(n+1)%(i.length+1):(n+i.length)%(i.length+1);var r=this.get("ffz_old_mru");(void 0===r||null===r)&&(r=this.get("textareaValue"),this.set("ffz_old_mru",r));var d=i[n];void 0===d&&(this.set("ffz_old_mru",void 0),d=r),this.set("ffz_mru_index",n),this.set("textareaValue",d)}},completeSuggestion:function(t){var e,n,i=this,o=this.get("textareaValue"),a=this.get("partialNameStartIndex");e=o.substring(0,a)+("/"===o.charAt(0)?t:s.get_capitalization(t)),n=o.substring(a+this.get("partialName").length),n||(e+=" "),this.set("textareaValue",e+n),this.set("isShowingSuggestions",!1),this.set("partialName",""),this.trackSuggestionsCompleted(),Ember.run.next(function(){r(i.get("chatTextArea"),e.length)})}})}},{"../constants":5,"../utils":35}],9:[function(e){var s=t.FrankerFaceZ,n=e("../utils"),i=e("../constants");s.settings_info.minimal_chat={type:"boolean",value:!1,category:"Chat Appearance",name:"Minimalistic Chat",help:"Hide all of the chat user interface, only showing messages and an input box.",on_update:function(t){if(document.body.classList.toggle("ffz-minimal-chat",t),this.settings.group_tabs&&this._chatv&&this._chatv._ffz_tabs){var e=this;setTimeout(function(){e._chatv&&e._chatv.$(".chat-room").css("top",e._chatv._ffz_tabs.offsetHeight+"px"),e._roomv&&e._roomv.get("stuckToBottom")&&e._roomv._scrollToBottom()},0)}this._chatv&&this._chatv.get("controller.showList")&&this._chatv.set("controller.showList",!1),!t&&this._chat_style?(this._inputv&&(this._inputv._ffz_minimal_style&&(this._inputv._ffz_minimal_style.innerHTML=""),this._inputv._ffz_last_height=void 0),n.update_css(this._chat_style,"input_height",""),this._roomv&&this._roomv.get("stuckToBottom")&&this._roomv._scrollToBottom()):this._inputv&&this._inputv.ffzResizeInput()}},s.settings_info.remove_deleted={type:"boolean",value:!1,no_bttv:!0,category:"Chat Filtering",name:"Remove Deleted Messages",help:"Remove deleted messages from chat entirely rather than leaving behind a clickable <deleted message>.",on_update:function(t){if(!this.has_bttv&&this.rooms&&t)for(var e in this.rooms){var s=this.rooms[e],n=s&&s.room;if(n)for(var i,o=n.get("messages"),a=o.get("length"),r=a;r--;){var d=o.get(r);d.ffz_deleted||d.deleted?(void 0===i&&(i=d.ffz_alternate),o.removeAt(r)):void 0===i?i=d.ffz_alternate:(i=!i,n.set("messages."+r+".ffz_alternate",i))}}}},s.settings_info.prevent_clear={type:"boolean",value:!1,no_bttv:!0,category:"Chat Filtering",name:"Show Deleted Messages",help:"Fade deleted messages instead of replacing them, and prevent chat from being cleared.",on_update:function(t){if(!this.has_bttv&&this.rooms)for(var e in this.rooms){var s=this.rooms[e],n=s&&s.room;n&&n.get("messages").forEach(function(e,s){t&&!e.ffz_deleted&&e.deleted?n.set("messages."+s+".deleted",!1):!e.ffz_deleted||t||e.deleted||n.set("messages."+s+".deleted",!0)})}}},s.settings_info.chat_history={type:"boolean",value:!0,visible:!1,category:"Chat Appearance",name:"Chat History Alpha",help:"Load previous chat messages when loading a chat room so you can see what people have been talking about. This currently only works in a handful of channels due to server capacity."},s.settings_info.group_tabs={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Chat Room Tabs Beta",help:"Enhanced UI for switching the current chat room and noticing new messages.",on_update:function(t){var e=!this.has_bttv&&t;this._chatv&&e!==this._group_tabs_state&&(e?this._chatv.ffzEnableTabs():this._chatv.ffzDisableTabs())}},s.settings_info.pinned_rooms={value:[],visible:!1},s.settings_info.visible_rooms={value:[],visible:!1},s.prototype.setup_chatview=function(){document.body.classList.toggle("ffz-minimal-chat",this.settings.minimal_chat),this.log("Hooking the Ember Chat controller.");var t=App.__container__.lookup("controller:chat"),e=this;t&&t.reopen({ffzUpdateChannels:function(){e._chatv&&(e._chatv.ffzRebuildMenu(),e.settings.group_tabs&&e._chatv.ffzRebuildTabs())}.observes("currentChannelRoom","connectedPrivateGroupRooms"),removeCurrentChannelRoom:function(){if(!e.settings.group_tabs||e.has_bttv)return this._super();var t=this.get("currentChannelRoom"),s=t&&t.get("id"),n=e.get_user();e.settings.pinned_rooms&&-1!==e.settings.pinned_rooms.indexOf(s)||(t===this.get("currentRoom")&&this.blurRoom(),t&&n&&n.login===s&&t.destroy()),this.set("currentChannelRoom",void 0)}}),this.log("Hooking the Ember Chat view.");var t=App.__container__.resolve("view:chat");this._modify_cview(t);try{t.create().destroy()}catch(s){}for(var n in Ember.View.views)if(Ember.View.views.hasOwnProperty(n)){var i=Ember.View.views[n];if(i instanceof t){this.log("Manually updating existing Chat view.",i);try{i.ffzInit()}catch(s){this.error("setup: build_ui_link: "+s)}}}this.log("Hooking the Ember 'Right Column' controller. Seriously...");var o=App.__container__.lookup("controller:right-column");o&&o.reopen({ffzFixTabs:function(){e.settings.group_tabs&&e._chatv&&e._chatv._ffz_tabs&&setTimeout(function(){e._chatv&&e._chatv.$(".chat-room").css("top",e._chatv._ffz_tabs.offsetHeight+"px")},0)}.observes("firstTabSelected")})},s.prototype._modify_cview=function(t){var e=this;t.reopen({didInsertElement:function(){this._super();try{this.ffzInit()}catch(t){e.error("ChatView didInsertElement: "+t)}},willClearRender:function(){try{this.ffzTeardown()}catch(t){e.error("ChatView willClearRender: "+t)}this._super()},ffzInit:function(){e._chatv=this,this.$(".textarea-contain").append(e.build_ui_link(this)),this.$(".chat-messages").find(".html-tooltip").tipsy({live:!0,html:!0,gravity:jQuery.fn.tipsy.autoNS}),!e.has_bttv&&e.settings.group_tabs&&this.ffzEnableTabs(),this.ffzRebuildMenu(),setTimeout(function(){e.settings.group_tabs&&e._chatv&&e._chatv._ffz_tabs&&e._chatv.$(".chat-room").css("top",e._chatv._ffz_tabs.offsetHeight+"px");var t=e._chatv.get("controller");t&&t.set("showList",!1)},1e3)},ffzTeardown:function(){e._chatv===this&&(e._chatv=null),this.$(".textarea-contain .ffz-ui-toggle").remove(),e.settings.group_tabs&&this.ffzDisableTabs()},ffzChangeRoom:Ember.observer("controller.currentRoom",function(){e.update_ui_link();var t,s=this.get("controller.currentRoom");if(s&&s.resetUnreadCount(),this._ffz_chan_table&&(t=jQuery(this._ffz_chan_table),t.children(".ffz-room-row").removeClass("active"),s&&t.children('.ffz-room-row[data-room="'+s.get("id")+'"]').addClass("active").children("span").text("")),this._ffz_group_table&&(t=jQuery(this._ffz_group_table),t.children(".ffz-room-row").removeClass("active"),s&&t.children('.ffz-room-row[data-room="'+s.get("id")+'"]').addClass("active").children("span").text("")),!e.has_bttv&&e.settings.group_tabs&&this._ffz_tabs){var n=jQuery(this._ffz_tabs);if(n.children(".ffz-chat-tab").removeClass("active"),s&&s._ffz_tab){s._ffz_tab.classList.remove("tab-mentioned"),s._ffz_tab.classList.remove("hidden"),s._ffz_tab.classList.add("active");var i=s._ffz_tab.querySelector("span");i&&(i.innerHTML="")}var o=s&&s.get("canInvite");this._ffz_invite&&this._ffz_invite.classList.toggle("hidden",!o),this.set("controller.showInviteUser",o&&this.get("controller.showInviteUser")),this.$(".chat-room").css("top",this._ffz_tabs.offsetHeight+"px")}}),ffzRebuildMenu:function(){return},ffzBuildRow:function(t,o,a,r){var d,u=document.createElement("tr"),c=document.createElement("td"),l=document.createElement("td"),h=document.createElement("td"),f=document.createElement("td"),m=o.get("isGroupRoom"),_=o===t.get("controller.currentRoom"),p=o.get("tmiRoom.displayName")||(m?o.get("tmiRoom.name"):s.get_capitalization(o.get("id"),function(t){e.log("Name for Row: "+t),l.innerHTML=n.sanitize(t)}));return l.className="ffz-room",l.innerHTML=n.sanitize(p),a?(c.innerHTML=i.CAMERA,c.title=l.title="Current Channel",c.className=l.className="tooltip"):r&&(c.innerHTML=i.EYE,c.title=l.title="Hosted Channel",c.className=l.className="tooltip"),h.className=f.className="ffz-row-switch",h.innerHTML='',f.innerHTML='',u.setAttribute("data-room",o.get("id")),u.className="ffz-room-row",u.classList.toggle("current-channel",a),u.classList.toggle("host-channel",r),u.classList.toggle("group-chat",m),u.classList.toggle("active",_),u.appendChild(c),u.appendChild(l),m?(d=document.createElement("a"),d.className="leave-chat tooltip",d.innerHTML=i.CLOSE,d.title="Leave Group",l.appendChild(d),d.addEventListener("click",function(t){t.preventDefault(),t.stopPropagation&&t.stopPropagation(),confirm('Are you sure you want to leave the group room "'+p+'"?')&&o.get("isGroupRoom")&&o.del()})):(u.appendChild(h),d=h.querySelector("a.switch"),d.addEventListener("click",function(t){t.preventDefault(),t.stopPropagation&&t.stopPropagation();var s=o.get("id"),n=-1!==e.settings.pinned_rooms.indexOf(s);n?e._leave_room(s):e._join_room(s),this.classList.toggle("active",!n)})),u.appendChild(f),d=f.querySelector("a.switch"),d.addEventListener("click",function(s){s.preventDefault(),s.stopPropagation&&s.stopPropagation();var n=o.get("id"),i=e.settings.visible_rooms,a=-1!==i.indexOf(n);a?i.removeObject(n):i.push(n),e.settings.set("visible_rooms",i),this.classList.toggle("active",!a),t.ffzRebuildTabs()}),u.addEventListener("click",function(){var e=t.get("controller");e.focusRoom(o),e.set("showList",!1)}),u},ffzEnableTabs:function(){if(!e.has_bttv&&e.settings.group_tabs){this.$(".chat-header").addClass("hidden");var t=this._ffz_tabs=document.createElement("div");t.id="ffz-group-tabs",this.$(".chat-header").after(t),this.ffzRebuildTabs()}},ffzRebuildTabs:function(){if(!e.has_bttv&&e.settings.group_tabs){var t=this._ffz_tabs||this.get("element").querySelector("#ffz-group-tabs");if(t){t.innerHTML="";var s=document.createElement("a"),n=this;s.className="button glyph-only tooltip",s.title="Chat Room Management",s.innerHTML=i.ROOMS,s.addEventListener("click",function(){var t=n.get("controller");t&&t.set("showList",!t.get("showList"))}),t.appendChild(s),s=document.createElement("a"),s.className="button glyph-only tooltip invite",s.title="Invite a User",s.innerHTML=i.INVITE,s.addEventListener("click",function(){var t=n.get("controller");t&&t.set("showInviteUser",t.get("currentRoom.canInvite")&&!t.get("showInviteUser"))}),s.classList.toggle("hidden",!this.get("controller.currentRoom.canInvite")),n._ffz_invite=s,t.appendChild(s);var o,a=this.get("controller.currentChannelRoom");a&&(o=this.ffzBuildTab(n,a,!0),o&&t.appendChild(o));var r=App.__container__.lookup("controller:channel"),d=App.__container__.resolve("model:room");if(target=r&&r.get("hostModeTarget"),target&&d){var u=target.get("id");this._ffz_host!==u&&(-1===e.settings.pinned_rooms.indexOf(this._ffz_host)&&this._ffz_host_room&&(this.get("controller.currentRoom")===this._ffz_host_room&&this.get("controller").blurRoom(),this._ffz_host_room.destroy()),this._ffz_host=u,this._ffz_host_room=d.findOne(u))}else this._ffz_host&&(-1===e.settings.pinned_rooms.indexOf(this._ffz_host)&&this._ffz_host_room&&(this.get("controller.currentRoom")===this._ffz_host_room&&this.get("controller").blurRoom(),this._ffz_host_room.destroy()),delete this._ffz_host,delete this._ffz_host_room);this._ffz_host_room&&(o=n.ffzBuildTab(n,this._ffz_host_room,!1,!0),o&&t.appendChild(o));for(var c=0;c"+u+""})),a?(l=i.CAMERA,c.title="Current Channel"):r?(l=i.EYE,c.title="Hosted Channel"):c.title=f?"Group Chat":"Pinned Channel",c.innerHTML=l+n.sanitize(d)+""+u+"",c.addEventListener("click",function(){var e=t.get("controller");e.focusRoom(o),e.set("showList",!1)}),o._ffz_tab=c,c},ffzDisableTabs:function(){this._ffz_tabs&&(this._ffz_tabs.parentElement.removeChild(this._ffz_tabs),delete this._ffz_tabs,delete this._ffz_invite),this._ffz_host&&(-1===e.settings.pinned_rooms.indexOf(this._ffz_host)&&this._ffz_host_room&&(this.get("controller.currentRoom")===this._ffz_host_room&&this.get("controller").blurRoom(),this._ffz_host_room.destroy()),delete this._ffz_host,delete this._ffz_host_room),this.$(".chat-room").css("top",""),this.$(".chat-header").removeClass("hidden")}})},s.prototype.connect_extra_chat=function(){var t=this.get_user();if(t&&t.login&&(!this.rooms[t.login]||this.rooms[t.login].room)){var e=App.__container__.resolve("model:room");e&&e.findOne(t.login)}if(!this.has_bttv){for(var s=0;s1)return"Join Usage: /join ";var s=e[0].toLowerCase();return"#"===s.charAt(0)&&(s=s.substr(1)),this._join_room(s)?"Joining "+s+". You will always connect to this channel's chat unless you later /part from it.":"You have already joined "+s+'. Please use "/part '+s+'" to leave it.'},s.chat_commands.part=function(t,e){if(!e||!e.length||e.length>1)return"Part Usage: /part ";var s=e[0].toLowerCase();return"#"===s.charAt(0)&&(s=s.substr(1)),this._leave_room(s)?"Leaving "+s+".":this.rooms[s]?"You do not have "+s+" pinned and you cannot leave the current channel or hosted channels via /part.":"You are not in "+s+"."}},{"../constants":5,"../utils":35}],10:[function(){var e=t.FrankerFaceZ;e.settings_info.swap_sidebars={type:"boolean",value:!1,category:"Appearance",no_mobile:!0,no_bttv:!0,name:"Swap Sidebar Positions",help:"Swap the positions of the left and right sidebars, placing chat on the left.",on_update:function(t){this.has_bttv||(document.body.classList.toggle("ffz-sidebar-swap",t),this._fix_menu_position())}},e.settings_info.right_column_width={type:"button",value:340,category:"Appearance",no_mobile:!0,no_bttv:!0,name:"Right Sidebar Width",help:"Set the width of the right sidebar for chat.",method:function(){var t=this.settings.right_column_width||340,e=prompt("Right Sidebar Width\n\nPlease enter a new width for the right sidebar, in pixels. Minimum: 250, Default: 340",t);if(null!==e&&void 0!==e){var s=parseInt(e);s&&0/0!==s||(s=340),this.settings.set("right_column_width",Math.max(250,s))}},on_update:function(t){if(!this.has_bttv){var e=App.__container__.lookup("controller:layout");e&&(e.set("rightColumnWidth",t),Ember.propertyDidChange(e,"contentWidth"))}}},e.prototype.setup_layout=function(){if(!this.has_bttv){document.body.classList.toggle("ffz-sidebar-swap",this.settings.swap_sidebars),this.log("Creating layout style element.");var t=this._layout_style=document.createElement("style");t.id="ffz-layout-css",document.head.appendChild(t),this.log("Hooking the Ember Layout controller.");var e=App.__container__.lookup("controller:layout"),s=this;e&&(e.reopen({rightColumnWidth:340,isTooSmallForRightColumn:function(){return this.get("windowWidth")<1090-this.get("rightColumnWidth")}.property("windowWidth","rightColumnWidth"),contentWidth:function(){var t=this.get("isLeftColumnClosed")?50:240,e=this.get("isRightColumnClosed")?0:this.get("rightColumnWidth");return this.get("windowWidth")-t-e-60}.property("windowWidth","isRightColumnClosed","isLeftColumnClosed","rightColumnWidth"),ffzUpdateCss:function(){var t=this.get("rightColumnWidth");s._layout_style.innerHTML="#main_col.expandRight #right_close { left: none !important; } #right_col { width: "+t+"px; } body:not(.ffz-sidebar-swap) #main_col:not(.expandRight) { margin-right: "+t+"px; } body.ffz-sidebar-swap #main_col:not(.expandRight) { margin-left: "+t+"px; }"}.observes("rightColumnWidth"),ffzFixTabs:function(){s.settings.group_tabs&&s._chatv&&s._chatv._ffz_tabs&&setTimeout(function(){s._chatv&&s._chatv.$(".chat-room").css("top",s._chatv._ffz_tabs.offsetHeight+"px")},0)}.observes("isRightColumnClosed","rightColumnWidth")}),e.set("rightColumnWidth",this.settings.right_column_width),Ember.propertyDidChange(e,"contentWidth"))}}},{}],11:[function(e){var s=t.FrankerFaceZ,n=e("../utils"),i=(e("../constants"),"[\\s`~<>!-#%-\\x2A,-/:;\\x3F@\\x5B-\\x5D_\\x7B}\\u00A1\\u00A7\\u00AB\\u00B6\\u00B7\\u00BB\\u00BF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u0AF0\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E3B\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65]"),o=new RegExp(i+"*,"+i+"*");s.settings_info.room_status={type:"boolean",value:!0,category:"Chat Appearance",no_bttv:!0,name:"Room Status Indicators",help:"Display the current room state (slow mode, sub mode, and r9k mode) next to the Chat button.",on_update:function(){this._roomv&&this._roomv.ffzUpdateStatus()}},s.settings_info.line_purge_icon={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Purge Icon in Mod Icons",help:"Display a Purge Icon in chat line Mod Icons for quickly purging users.",on_update:function(t){this.has_bttv||document.body.classList.toggle("ffz-chat-purge-icon",t)}},s.settings_info.replace_bad_emotes={type:"boolean",value:!0,category:"Chat Appearance",no_bttv:!0,name:"Fix Low Quality Twitch Global Emoticons",help:"Replace emoticons such as DansGame and RedCoat with cleaned up versions that don't have pixels around the edges or white backgrounds for nicer display on dark chat."},s.settings_info.parse_emoji={type:"boolean",value:!0,category:"Chat Appearance",name:"Replace Emoji with Images",help:"Replace emoji in chat messages with nicer looking images from the open-source Twitter Emoji project."},s.settings_info.room_status={type:"boolean",value:!0,category:"Chat Appearance",no_bttv:!0,name:"Room Status Indicators",help:"Display the current room state (slow mode, sub mode, and r9k mode) next to the Chat button.",on_update:function(){this._roomv&&this._roomv.ffzUpdateStatus()}},s.settings_info.scrollback_length={type:"button",value:150,category:"Chat Appearance",no_bttv:!0,name:"Scrollback Length",help:"Set the maximum number of lines to keep in chat.",method:function(){var t=prompt("Scrollback Length\n\nPlease enter a new maximum length for the chat scrollback. Default: 150\n\nNote: Making this too large will cause your browser to lag.",this.settings.scrollback_length);if(null!==t&&void 0!==t&&(t=parseInt(t),0/0!==t)){10>t&&(t=10),this.settings.set("scrollback_length",t);var e=App.__container__.lookup("controller:chat"),s=e&&e.get("currentRoom.id");for(var n in this.rooms){var i=this.rooms[n];i.room.set("messageBufferSize",t+(this._roomv&&!this._roomv.get("stuckToBottom")&&s===n?150:0))}}}},s.settings_info.hosted_sub_notices={type:"boolean",value:!0,category:"Chat Filtering",no_bttv:!0,name:"Show Hosted Channel Subscriber Notices",help:"Display notices in chat when someone subscribes to the hosted channel."},s.settings_info.banned_words={type:"button",value:[],category:"Chat Filtering",no_bttv:!0,name:"Banned Words",help:"Set a list of words that will be locally removed from chat messages.",method:function(){var t=this.settings.banned_words.join(", "),e=prompt("Banned Words\n\nPlease enter a comma-separated list of words that you would like to be removed from chat messages.",t);if(null!==e&&void 0!==e){e=e.trim().split(o);for(var s=[],n=0;nBeta",help:"Check links against known bad websites, unshorten URLs, and show YouTube info."},s.settings_info.link_image_hover={type:"boolean",value:!1,category:"Chat Tooltips",no_bttv:!0,no_mobile:!0,name:"Image Preview",help:"Display image thumbnails for links to Imgur and YouTube."},s.settings_info.image_hover_all_domains={type:"boolean",value:!1,category:"Chat Tooltips",no_bttv:!0,no_mobile:!0,name:"Image Preview - All Domains",help:"Requires Image Preview. Attempt to show an image preview for any URL ending in the appropriate extension. Warning: This may be used to leak your IP address to malicious users."},s.settings_info.legacy_badges={type:"boolean",value:!1,category:"Chat Appearance",name:"Legacy Badges",help:"Display the old, pre-vector chat badges from Twitch.",on_update:function(t){document.body.classList.toggle("ffz-legacy-badges",t)}},s.settings_info.chat_rows={type:"boolean",value:!1,category:"Chat Appearance",no_bttv:!0,name:"Chat Line Backgrounds",help:"Display alternating background colors for lines in chat.",on_update:function(t){document.body.classList.toggle("ffz-chat-background",!this.has_bttv&&t)}},s.settings_info.chat_separators={type:"select",options:{0:"Disabled",1:"Basic Line (1px solid)",2:"3D Line (2px groove)"},value:"0",category:"Chat Appearance",no_bttv:!0,process_value:function(t){return t===!1?"0":t===!0?"1":t},name:"Chat Line Separators",help:"Display thin lines between chat messages for further visual separation.",on_update:function(t){document.body.classList.toggle("ffz-chat-separator",!this.has_bttv&&"0"!==t),document.body.classList.toggle("ffz-chat-separator-3d",!this.has_bttv&&"2"===t)}},s.settings_info.chat_padding={type:"boolean",value:!1,category:"Chat Appearance",no_bttv:!0,name:"Reduced Chat Line Padding",help:"Reduce the amount of padding around chat messages to fit more on-screen at once.",on_update:function(t){document.body.classList.toggle("ffz-chat-padding",!this.has_bttv&&t)}},s.settings_info.high_contrast_chat={type:"select",options:{222:"Disabled",212:"Bold",221:"Text",211:"Text + Bold",122:"Background",121:"Background + Text",112:"Background + Bold",111:"All"},value:"222",category:"Chat Appearance",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.",process_value:function(t){return t===!1?"222":t===!0?"111":t},on_update:function(t){document.body.classList.toggle("ffz-high-contrast-chat-text",!this.has_bttv&&"1"===t[2]),document.body.classList.toggle("ffz-high-contrast-chat-bold",!this.has_bttv&&"1"===t[1]),document.body.classList.toggle("ffz-high-contrast-chat-bg",!this.has_bttv&&"1"===t[0])}},s.settings_info.chat_font_size={type:"button",value:12,category:"Chat Appearance",no_bttv:!0,name:"Font Size",help:"Make the chat font bigger or smaller.",method:function(){var t=this.settings.chat_font_size,e=prompt("Chat Font Size\n\nPlease enter a new size for the chat font. The default is 12.",t);if(null!==e&&void 0!==e){var s=parseInt(e);(!s||0/0===s||1>s)&&(s=12),this.settings.set("chat_font_size",s)}},on_update:function(t){if(!this.has_bttv&&this._chat_style){var e;if(12!==t&&t){var i=Math.max(20,Math.round(20/12*t)),o=Math.floor((i-20)/2);e=".ember-chat .chat-messages .chat-line { font-size: "+t+"px !important; line-height: "+i+"px !important; }",o&&(e+=".ember-chat .chat-messages .chat-line .mod-icons, .ember-chat .chat-messages .chat-line .badges { padding-top: "+o+"px; }")}else e="";n.update_css(this._chat_style,"chat_font_size",e),s.settings_info.chat_ts_size.on_update.bind(this)(this.settings.chat_ts_size)}}},s.settings_info.chat_ts_size={type:"button",value:null,category:"Chat Appearance",no_bttv:!0,name:"Timestamp Font Size",help:"Make the chat timestamp font bigger or smaller.",method:function(){var t=this.settings.chat_ts_size;t||(t=this.settings.chat_font_size);var e=prompt("Chat Timestamp Font Size\n\nPlease enter a new size for the chat timestamp font. The default is to match the regular chat font size.",t);if(null!==e&&void 0!==e){var s=parseInt(e);(!s||0/0===s||1>s)&&(s=null),this.settings.set("chat_ts_size",s)}},on_update:function(t){if(!this.has_bttv&&this._chat_style){var e;if(null===t)e="";else{var s=Math.max(20,Math.round(20/12*t),Math.round(20/12*this.settings.chat_font_size));e=".ember-chat .chat-messages .timestamp { font-size: "+t+"px !important; line-height: "+s+"px !important; }"}n.update_css(this._chat_style,"chat_ts_font_size",e)}}},s.prototype.setup_line=function(){jQuery(document.body).on("mouseleave",".tipsy",function(){this.parentElement.removeChild(this)});try{this.aliases=JSON.parse(localStorage.ffz_aliases||"{}")}catch(t){this.log("Error Loading Aliases: "+t),this.aliases={}}var e=this._chat_style=document.createElement("style");e.id="ffz-style-chat",e.type="text/css",document.head.appendChild(e),s.settings_info.chat_font_size.on_update.bind(this)(this.settings.chat_font_size),document.body.classList.toggle("ffz-chat-colors",!this.has_bttv&&"-1"!==this.settings.fix_color),document.body.classList.toggle("ffz-chat-colors-gray",!this.has_bttv&&"-1"===this.settings.fix_color),document.body.classList.toggle("ffz-legacy-badges",this.settings.legacy_badges),document.body.classList.toggle("ffz-chat-background",!this.has_bttv&&this.settings.chat_rows),document.body.classList.toggle("ffz-chat-separator",!this.has_bttv&&"0"!==this.settings.chat_separators),document.body.classList.toggle("ffz-chat-separator-3d",!this.has_bttv&&"2"===this.settings.chat_separators),document.body.classList.toggle("ffz-chat-padding",!this.has_bttv&&this.settings.chat_padding),document.body.classList.toggle("ffz-chat-purge-icon",!this.has_bttv&&this.settings.line_purge_icon),document.body.classList.toggle("ffz-high-contrast-chat-text",!this.has_bttv&&"1"===this.settings.high_contrast_chat[2]),document.body.classList.toggle("ffz-high-contrast-chat-bold",!this.has_bttv&&"1"===this.settings.high_contrast_chat[1]),document.body.classList.toggle("ffz-high-contrast-chat-bg",!this.has_bttv&&"1"===this.settings.high_contrast_chat[0]),this._last_row={},this.log("Hooking the Ember Whisper Line component.");var n=App.__container__.resolve("component:whisper-line");n&&this._modify_line(n),this.log("Hooking the Ember Message Line component.");var i=App.__container__.resolve("component:message-line");i&&this._modify_line(i);var o=this.get_user();o&&o.name&&(s.capitalization[o.login]=[o.name,Date.now()])},s.prototype.save_aliases=function(){this.log("Saving "+Object.keys(this.aliases).length+" aliases to local storage."),localStorage.ffz_aliases=JSON.stringify(this.aliases)},s.prototype._modify_line=function(e){var i=this,o=App.__container__.lookup("controller:layout"),a=App.__container__.lookup("controller:settings");e.reopen({tokenizedMessage:function(){var t=this.get("msgObject.cachedTokens");if(t)return t;t=this._super();var e=performance.now(),n=i.get_user(),o=n&&this.get("msgObject.from")===n.login;t=i._remove_banned(t),t=i._emoticonize(this,t),i.settings.parse_emoji&&(t=i.tokenize_emoji(t));var a=this.get("msgObject.tags.display-name");a&&a.length&&(s.capitalization[this.get("msgObject.from")]=[a.trim(),Date.now()]),o||(t=i.tokenize_mentions(t));for(var r=0;r5&&i.log("Tokenizing Message Took Too Long - "+(u-e)+"ms",t,!1,!0),this.set("msgObject.cachedTokens",t),t}.property("msgObject.message","isChannelLinksDisabled","currentUserNick","msgObject.from","msgObject.tags.emotes"),ffzUpdated:Ember.observer("msgObject.ffz_deleted","msgObject.ffz_old_messages",function(){this.rerender()}),click:function(e){if(e.target&&e.target.classList.contains("ffz-old-messages"))return i._show_deleted(this.get("msgObject.room"));if(e.target&&e.target.classList.contains("deleted-link"))return i._deleted_link_click.bind(e.target)(e);if(e.target&&e.target.classList.contains("mod-icon")&&(jQuery(e.target).trigger("mouseout"),e.target.classList.contains("purge"))){var s=this.get("msgObject.from"),n=this.get("msgObject.room"),o=n&&i.rooms[n]&&i.rooms[n].room;return void(o&&(o.send("/timeout "+s+" 1"),o.clearMessages(s)))}if((e.shiftKey||e.shiftLeft)&&i.settings.clickable_emoticons&&e.target&&e.target.classList.contains("emoticon")){var a=e.target.getAttribute("data-emote");a?t.open("https://twitchemotes.com/emote/"+a):(a=e.target.getAttribute("data-ffz-emote"),t.open("https://www.frankerfacez.com/emoticons/"+a))}return this._super(e)},ffzUserLevel:function(){return this.get("isStaff")?5:this.get("isAdmin")?4:this.get("isBroadcaster")?3:this.get("isGlobalModerator")?2:this.get("isModerator")?1:0}.property("msgObject.labels.[]"),render:function(t){var e=this.get("msgObject.deleted"),s={},r=this.get("msgObject.from"),d=this.get("msgObject.room"),u=i.rooms&&i.rooms[d],c=this.get("msgObject.to"),l=c&&c.length,h=this.get("ffzUserLevel"),f=u&&u.room&&u.room.get("ffzUserLevel")||0,m=this.get("msgObject.ffz_alternate"),_=this.get("msgObject.color"),p=_&&i._handle_color(_),g=o&&o.get("isTheatreMode")||a&&a.get("model.darkMode");void 0===m&&(m=i._last_row[d]=i._last_row.hasOwnProperty(d)?!i._last_row[d]:!1,this.set("msgObject.ffz_alternate",m)),t.push('
'),t.push(''+this.get("timestamp")+" "),!l&&f>h&&(t.push(''),t.push(e?'Unban':'Ban'),t.push('Timeout'),t.push('Purge'),t.push("")),!l&&this.get("isBroadcaster")?s[0]={klass:"broadcaster",title:"Broadcaster"}:this.get("isStaff")?s[0]={klass:"staff",title:"Staff"}:this.get("isAdmin")?s[0]={klass:"admin",title:"Admin"}:this.get("isGlobalMod")?s[0]={klass:"global-moderator",title:"Global Moderator"}:!l&&this.get("isModerator")&&(s[0]={klass:"moderator",title:"Moderator"}),!l&&this.get("isSubscriber")&&(s[10]={klass:"subscriber",title:"Subscriber"}),this.get("hasTurbo")&&(s[15]={klass:"turbo",title:"Turbo"}),s=i.render_badges(this,s),t.push('');for(var v in s){var b=s[v],y=b.image?"background-image:url(""+b.image+"");":"";b.color&&(y+="background-color:"+b.color+";"),b.extra_css&&(y+=b.extra_css),t.push('
')}t.push("
");var w=i.aliases[r],z=this.get("msgObject.tags.display-name")||r&&r.capitalize()||"unknown user",k=p&&"color:"+(g?p[1]:p[0]),E=k?" has-color":"";if(t.push(w?''+n.sanitize(w)+"":''+n.sanitize(z)+""),l){var C=i.aliases[c],x=this.get("msgObject.tags.recipient-display-name")||c&&c.capitalize()||"unknown user",T=this.get("msgObject.toColor"),L=T&&i._handle_color(T),M=T&&"color:"+(g?L[1]:L[0]),S=M?" has-color":"";this._renderWhisperArrow(t),t.push(C?''+n.sanitize(C)+"":''+n.sanitize(x)+"")}if(t.push(': '),"action"!==this.get("msgObject.style")&&(k="",E=""),e)t.push('<message deleted>');else{t.push(''),t.push(i.render_tokens(this.get("tokenizedMessage"),!0));var A=this.get("msgObject.ffz_old_messages");A&&A.length&&t.push('
Show '+n.number_commas(A.length)+" Old
"),t.push("
")}},classNameBindings:["msgObject.ffz_alternate:ffz-alternate","msgObject.ffz_has_mention:ffz-mentioned","ffzWasDeleted:ffz-deleted","ffzHasOldMessages:clearfix","ffzHasOldMessages:ffz-has-deleted"],ffzWasDeleted:function(){return i.settings.prevent_clear&&this.get("msgObject.ffz_deleted")}.property("msgObject.ffz_deleted"),ffzHasOldMessages:function(){var t=this.get("msgObject.ffz_old_messages");return t&&t.length}.property("msgObject.ffz_old_messages"),didInsertElement:function(){this._super();var t=this.get("element");t.setAttribute("data-room",this.get("msgObject.room")),t.setAttribute("data-sender",this.get("msgObject.from")),t.setAttribute("data-deleted",this.get("msgObject.deleted")||!1)}})},s.capitalization={},s._cap_fetching=0,s.get_capitalization=function(t,e){if(!t)return t;if(t=t.toLowerCase(),"jtv"==t||"twitchnotify"==t)return t;var n=s.capitalization[t];return n&&Date.now()-n[1]<36e5?n[0]:(s._cap_fetching<25&&(s._cap_fetching++,s.get().ws_send("get_display_name",t,function(n,i){var o=n?i:t;s.capitalization[t]=[o,Date.now()],s._cap_fetching--,"function"==typeof e&&e(o)})),n?n[0]:t)},s.prototype._remove_banned=function(t){var e=_.union(["j.mp","bit.ly"],this.settings.banned_words);if(!e||!e.length)return t;"string"==typeof t&&(t=[t]);for(var n=s._words_to_regex(e),i=[],o=0;o',d='',u={},c=function(t){if(1===t)return"Purge";if(u[t])return u[t];var e,s,n,i,o;e=Math.floor(t/604800),o=t%604800,s=Math.floor(o/86400),o%=86400,n=Math.floor(o/3600),o%=3600,i=Math.floor(o/60),o%=60;var a=u[t]=(e?e+"w":"")+(s||e&&(n||i||o)?s+"d":"")+(n||(e||s)&&(i||o)?n+"h":"")+(i||(e||s||n)&&o?i+"m":"")+(o?o+"s":"");return a};try{s=t.require&&t.require("ember-twitch-chat/helpers/chat-line-helpers")}catch(l){}n.basic_settings.enhanced_moderation_cards={type:"boolean",no_bttv:!0,category:"Chat",name:"Enhanced Moderation Cards",help:"Improve moderation cards with hotkeys, additional buttons, chat history, and other information to make moderating easier.",get:function(){return this.settings.mod_card_hotkeys&&this.settings.mod_card_info&&this.settings.mod_card_history},set:function(t){this.settings.set("mod_card_hotkeys",t),this.settings.set("mod_card_info",t),this.settings.set("mod_card_history",t)}},n.basic_settings.chat_hover_pause={type:"boolean",no_bttv:!0,category:"Chat",name:"Pause Chat Scrolling on Mouse Hover",help:"Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link misclicks.",get:"chat_hover_pause",set:"chat_hover_pause"},n.settings_info.chat_hover_pause={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Pause Chat Scrolling on Mouse Hover",help:"Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link misclicks.",on_update:function(t){this._roomv&&(t?this._roomv.ffzEnableFreeze():this._roomv.ffzDisableFreeze())}},n.settings_info.short_commands={type:"boolean",value:!0,no_bttv:!0,category:"Chat Moderation",name:"Short Moderation Commands",help:"Use /t, /b, and /u in chat in place of /timeout, /ban, /unban for quicker moderation, and use /p for 1 second timeouts."},n.settings_info.mod_card_hotkeys={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Moderation Card Hotkeys",help:"With a moderation card selected, press B to ban the user, T to time them out for 10 minutes, P to time them out for 1 second, or U to unban them. ESC closes the card."},n.settings_info.mod_card_info={type:"boolean",value:!0,no_bttv:!0,category:"Chat Moderation",name:"Moderation Card Additional Information",help:"Display a channel's follower count, view count, and account age on moderation cards."},n.settings_info.mod_card_history={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Moderation Card History",help:"Display a few of the user's previously sent messages on moderation cards.",on_update:function(t){if(!t&&this.rooms)for(var e in this.rooms){var s=this.rooms[e];s&&(s.user_history=void 0)}}},n.settings_info.mod_card_buttons={type:"button",value:[],category:"Chat Moderation",no_bttv:!0,name:"Moderation Card Additional Buttons",help:"Add additional buttons to moderation cards for running chat commands on those users.",method:function(){for(var t="",e=0;e0&&s.push(o)}this.settings.set("mod_card_durations",s)}}},n.prototype.setup_mod_card=function(){this.log("Modifying Mousetrap stopCallback so we can catch ESC.");var e=Mousetrap.stopCallback;Mousetrap.stopCallback=function(t,s,n){return s.classList.contains("no-mousetrap")?!0:e(t,s,n)},Mousetrap.bind("up up down down left right left right b a enter",function(){var t=document.querySelector(".app-main")||document.querySelector(".ember-chat-container");t&&t.classList.toggle("ffz-flip")}),this.log("Hooking the Ember Moderation Card view.");var n=App.__container__.resolve("component:moderation-card"),u=this;n.reopen({ffzForceRedraw:function(){this.rerender()}.observes("cardInfo.isModeratorOrHigher","cardInfo.user"),ffzRebuildInfo:function(){var t=this.get("element"),e=t&&t.querySelector(".info");if(e){var s=''+o.EYE+" "+i.number_commas(this.get("cardInfo.user.views")||0)+"",n=i.parse_date(this.get("cardInfo.user.created_at")||""),a=this.get("cardInfo.user.ffz_followers");if("number"==typeof a)s+=''+o.HEART+" "+i.number_commas(a||0)+""; -else if(void 0===a){var r=this;this.set("cardInfo.user.ffz_followers",!1),Twitch.api.get("channels/"+this.get("cardInfo.user.id")+"/follows",{limit:1}).done(function(t){r.set("cardInfo.user.ffz_followers",t._total),r.ffzRebuildInfo()}).fail(function(){r.set("cardInfo.user.ffz_followers",void 0)})}if(n){var d=Math.floor((Date.now()-n.getTime())/1e3);d>0&&(s+=''+o.CLOCK+" "+i.human_time(d,10)+"")}e.innerHTML=s}}.observes("cardInfo.user.views"),userName:Ember.computed("cardInfo.user.id","cardInfo.user.display_name",function(){var t=this.get("cardInfo.user.id"),e=u.aliases[t];return e||this.get("cardInfo.user.display_name")||t.capitalize()}),didInsertElement:function(){this._super(),t._card=this;try{if(u.has_bttv)return;var e,n=this.get("element"),l=this.get("controller"),h=l.get("cardInfo.user.id"),f=u.aliases[h];if(f){var m=n.querySelector("h3.name"),p=m&&m.querySelector("a");p&&(m=p),m&&(m.classList.add("ffz-alias"),m.title=i.sanitize(l.get("cardInfo.user.display_name")||h.capitalize()),jQuery(m).tipsy())}if(n.classList.add("ffz-moderation-card"),u.settings.mod_card_info){var g=document.createElement("div"),v=n.querySelector("h3.name");v&&(n.classList.add("ffz-has-info"),g.className="info channel-stats",v.parentElement.insertBefore(g,v.nextSibling),this.ffzRebuildInfo())}if(u.settings.mod_card_buttons&&u.settings.mod_card_buttons.length){e=document.createElement("div"),e.className="extra-interface interface clearfix";for(var b={},y=function(t){var e=l.get("cardInfo.user.id"),s=App.__container__.lookup("controller:chat"),n=s&&s.get("currentRoom");n&&n.send(t.replace(/{user}/g,e))},w=function(t){var e=document.createElement("button"),s=t.split(" ",1)[0],n=b[s]>1?t.split(" ",b[s]):[s];return/^[!~./]/.test(n[0])&&(n[0]=n[0].substr(1)),n=_.map(n,function(t){return t.capitalize()}).join(" "),e.className="button",e.innerHTML=i.sanitize(n),e.title=i.sanitize(t.replace(/{user}/g,l.get("cardInfo.user.id")||"{user}")),jQuery(e).tipsy(),e.addEventListener("click",y.bind(this,t)),e},b={},z=0;z button.message-button");if(R){R.innerHTML="W",R.classList.add("glyph-only"),R.classList.add("message"),R.title="Whisper User",jQuery(R).tipsy();var H=document.createElement("button");H.className="message-button button glyph-only message tooltip",H.innerHTML=r,H.title="Message User",H.addEventListener("click",function(){t.open("http://www.twitch.tv/message/compose?to="+l.get("cardInfo.user.id"))}),R.parentElement.insertBefore(H,R.nextSibling)}var O=document.createElement("button");if(O.className="alias button glyph-only tooltip",O.innerHTML=o.EDIT,O.title="Set Alias",O.addEventListener("click",function(){var t=l.get("cardInfo.user.id"),e=u.aliases[t],s=prompt("Alias for User: "+t+"\n\nPlease enter an alias for the user. Leave it blank to remove the alias.",e);if(null!==s&&void 0!==s){s=s.trim(),s||(s=void 0),u.aliases[t]=s,u.save_aliases(),u._update_alias(t),Ember.propertyDidChange(l,"userName");var i=n.querySelector("h3.name"),o=i&&i.querySelector("a");o&&(i=o),i&&i.classList.toggle("ffz-alias",s)}}),R)R.parentElement.insertBefore(O,R);else{var I=n.querySelector(".interface > .follow-button");I&&I.parentElement.insertBefore(O,I.nextSibling)}if(u.settings.mod_card_history){var D=App.__container__.lookup("controller:chat"),B=D&&D.get("currentRoom"),N=B&&u.rooms&&u.rooms[B.get("id")],j=N&&N.user_history&&N.user_history[l.get("cardInfo.user.id")];if(j&&j.length){var P=document.createElement("ul"),U=!1;P.className="interface clearfix chat-history";for(var z=0;z'+s.getTime(e.date)+" ":"")+''+("action"===e.style?"*"+e.from+" ":"")+u.render_tokens(e.cachedTokens)+"";for(var V=q.querySelectorAll("a.deleted-link"),W=0;WG.bottom){var Y=Z.bottom-G.bottom;Z.top-Y>G.top&&(n.style.top=Z.top-Y+"px")}this.$().draggable({start:function(){n.focus()}}),n.focus()}catch($){try{u.error("ModerationCardView didInsertElement: "+$)}catch($){}}}})},n.prototype._update_alias=function(t){var e=this.aliases&&this.aliases[t],s=n.get_capitalization(t),i=e||s,o=this._roomv&&this._roomv.get("element"),a=o&&o.querySelectorAll('.chat-line[data-sender="'+t+'"]');if(a)for(var r=0,d=a.length;d>r;r++){var u=a[r],c=u.querySelector(".from");c.classList.toggle("ffz-alias",e),c.textContent=i,c.title=e?s:""}},n.chat_commands.purge=function(t,e){if(!e||!e.length)return"Purge Usage: /p username [more usernames separated by spaces]";if(e.length>10)return"Please only purge up to 10 users at once.";for(var s=0;s10)return"Please only ban up to 10 users at once.";for(var s=0;s10)return"Please only unban up to 10 users at once.";for(var s=0;s750&&this.ffzUnfreeze()}},ffzUnfreeze:function(){this.ffz_frozen=!1,this._ffz_last_move=0,this.ffzUnwarnPaused(),this.get("stuckToBottom")&&this._scrollToBottom()},ffzMouseDown:function(t){var s=this._$chatMessagesScroller;if(s&&s[0]&&(!this.ffz_frozen&&"mousedown"===t.type||"mousewheel"===t.type||a&&"scroll"===t.type)){"mousedown"===t.type&&e.log("Freezing from mouse down!",t);var n=s[0].scrollHeight-s[0].scrollTop-s[0].offsetHeight;this._setStuckToBottom(10>=n)}},ffzMouseOut:function(){this._ffz_outside=!0;var t=this;setTimeout(function(){t._ffz_outside&&t.ffzUnfreeze()},25)},ffzMouseMove:function(t){this._ffz_last_move=Date.now(),this._ffz_outside=!1,(t.screenX!==this._ffz_last_screenx||t.screenY!==this._ffz_last_screeny)&&(this._ffz_last_screenx=t.screenX,this._ffz_last_screeny=t.screenY,this.ffz_frozen||(this.ffz_frozen=!0,this.get("stuckToBottom")&&(this.set("controller.model.messageBufferSize",e.settings.scrollback_length+150),this.ffzWarnPaused())))},_scrollToBottom:_.throttle(function(){var t=this,e=this._$chatMessagesScroller;Ember.run.next(function(){setTimeout(function(){!t.ffz_frozen&&e&&e.length&&(e[0].scrollTop=e[0].scrollHeight,t._setStuckToBottom(!0))})})},200),_setStuckToBottom:function(t){this.set("stuckToBottom",t),this.get("controller.model")&&this.set("controller.model.messageBufferSize",e.settings.scrollback_length+(t?0:150)),t||this.ffzUnfreeze()},ffzWarnPaused:function(){var t=this.get("element"),e=t&&t.querySelector(".chat-interface .more-messages-indicator.ffz-freeze-indicator");if(t){if(!e){e=document.createElement("div"),e.className="more-messages-indicator ffz-freeze-indicator",e.innerHTML="(Chat Paused Due to Mouse Movement)";var s=t.querySelector(".chat-interface");if(!s)return;s.insertBefore(e,s.childNodes[0])}e.classList.remove("hidden")}},ffzUnwarnPaused:function(){var t=this.get("element"),e=t&&t.querySelector(".chat-interface .more-messages-indicator.ffz-freeze-indicator");e&&e.classList.add("hidden")}})},s.chat_commands={},s.ffz_commands={},s.prototype.room_message=function(t,e){var s=e.split("\n");if(this.has_bttv)for(var n=0;n300,f=e.length,m=n.get("messages.0.ffz_alternate")||!1;h&&(m=!m);for(var f=e.length;f--;){var _=e[f];if("string"==typeof _.date&&(_.date=o.parse_date(_.date)),_.ffz_alternate=m=!m,_.room||(_.room=t),_.color||(_.color=_.tags&&_.tags.color?_.tags.color:a&&_.from?a.getColor(_.from.toLowerCase()):"#755000"),!_.labels||!_.labels.length){var p=_.labels=[];if(_.tags)if(_.tags.turbo&&p.push("turbo"),_.tags.subscriber&&p.push("subscriber"),_.from===t)p.push("owner");else{var g=_.tags["user-type"];("mod"===g||"staff"===g||"admin"===g||"global_mod"===g)&&p.push(g)}}if(_.style||("jtv"===_.from?_.style="admin":"twitchnotify"===_.from&&(_.style="notification")),_.cachedTokens&&_.cachedTokens.length||this.tokenize_chat_line(_,!0,n.get("roomProperties.hide_chat_links")),n.shouldShowMessage(_)){if(!(i.lengthv&&(_.ffz_old_messages=_.ffz_old_messages.slice(_.ffz_old_messages.length-v))}i.unshiftObject(_),r+=1}}if(h){var _={ffz_alternate:!m,color:"#755000",date:new Date,from:"frankerfacez_admin",style:"admin",message:"(Last message is "+o.human_time(l)+" old.)",room:t};if(this.tokenize_chat_line(_,!0,n.get("roomProperties.hide_chat_links")),n.shouldShowMessage(_))for(i.insertAt(r,_);i.length>n.get("messageBufferSize");)i.removeAt(0)}}},s.prototype.load_room=function(t,e,s){var n=this;jQuery.getJSON(((s||0)%2===0?i.API_SERVER:i.API_SERVER_2)+"v1/room/"+t).done(function(s){if(s.sets)for(var i in s.sets)s.sets.hasOwnProperty(i)&&n._load_set_json(i,void 0,s.sets[i]);n._load_room_json(t,e,s)}).fail(function(i){return 404==i.status?"function"==typeof e&&e(!1):(s=(s||0)+1,10>s?n.load_room(t,e,s):"function"==typeof e&&e(!1))})},s.prototype._load_room_json=function(t,e,s){if(!s||!s.room)return"function"==typeof e&&e(!1);s=s.room,this.rooms[t]&&(s.room=this.rooms[t].room);for(var n in this.rooms[t])"room"!==n&&this.rooms[t].hasOwnProperty(n)&&!s.hasOwnProperty(n)&&(s[n]=this.rooms[t][n]);s.needs_history=this.rooms[t]&&this.rooms[t].needs_history||!1,this.rooms[t]=s,(s.css||s.moderator_badge)&&o.update_css(this._room_style,t,r(s)+(s.css||"")),this.emote_sets.hasOwnProperty(s.set)?-1===this.emote_sets[s.set].users.indexOf(t)&&this.emote_sets[s.set].users.push(t):this.load_set(s.set,function(e,s){-1===s.users.indexOf(t)&&s.users.push(t)}),this.update_ui_link(),e&&e(!0,s)},s.prototype._modify_room=function(e){var s=this;e.reopen({slowWaiting:!1,slow:0,mru_list:[],updateWait:function(t,e){var n=this.get("slowWait")||0;this.set("slowWait",t),1>n&&t>0?(this._ffz_wait_timer&&clearTimeout(this._ffz_wait_timer),this._ffz_wait_timer=setTimeout(this.ffzUpdateWait.bind(this),1e3),s._roomv&&s._roomv.ffzUpdateStatus()):(n>0&&1>t||e)&&(this.set("ffz_banned",!1),s._roomv&&s._roomv.ffzUpdateStatus())},ffzUpdateWait:function(){this._ffz_wait_timer=void 0;var t=this.get("slowWait")||0;1>t||(this.set("slowWait",--t),t>0?this._ffz_wait_timer=setTimeout(this.ffzUpdateWait.bind(this),1e3):(this.set("ffz_banned",!1),s._roomv&&s._roomv.ffzUpdateStatus()))},ffzUpdateStatus:function(){s._roomv&&s._roomv.ffzUpdateStatus()}.observes("r9k","subsOnly","slow","ffz_banned"),ffzUserLevel:function(){return this.get("isStaff")?5:this.get("isAdmin")?4:this.get("isBroadcaster")?3:this.get("isGlobalModerator")?2:this.get("isModerator")?1:0}.property("id","chatLabels.[]"),init:function(){this._super();try{s.add_room(this.id,this),this.set("ffz_chatters",{})}catch(t){s.error("add_room: "+t)}},willDestroy:function(){this._super();try{s.remove_room(this.id)}catch(t){s.error("remove_room: "+t)}},clearMessages:function(t){var e=this;if(t){for(var n,i=e.get("messages"),a=i.get("length"),r=a;r--;){var d=i.get(r);if(d.from===t){if(s.settings.remove_deleted){void 0===n&&(n=d.ffz_alternate),i.removeAt(r);continue}e.set("messages."+r+".ffz_deleted",!0),s.settings.prevent_clear||e.set("messages."+r+".deleted",!0)}void 0===n?n=d.ffz_alternate:(n=!n,e.set("messages."+r+".ffz_alternate",n))}if(s.settings.mod_card_history){var u=s.rooms&&s.rooms[e.get("id")],c=u&&u.user_history&&u.user_history[t];if(null!==c&&void 0!==c){var l=!1,h=c.length>0?c[c.length-1]:null;if(l=null!==h&&h.is_delete)h.cachedTokens=["User has been timed out "+o.number_commas(++h.deleted_times)+" times."];else for(c.push({from:"jtv",is_delete:!0,style:"admin",cachedTokens:["User has been timed out."],deleted_times:1,date:new Date});c.length>20;)c.shift()}}}else if(s.settings.prevent_clear)this.addTmiMessage("A moderator's attempt to clear chat was ignored.");else{var i=e.get("messages");e.set("messages",[]),e.addMessage({style:"admin",message:i18n("Chat was cleared by a moderator"),ffz_old_messages:i})}},trimMessages:function(){var t=this.get("messages"),e=t.get("length"),s=this.get("messageBufferSize");e>s&&t.removeAt(0,e-s)},pushMessage:function(t){this.shouldShowMessage(t)&&(this.get("messages").pushObject(t),this.trimMessages(),"admin"===t.style||"whisper"===t.style&&!this.ffz_whisper_room||this.incrementProperty("unreadCount",1))},addMessage:function(t){if(t){if(!s.settings.hosted_sub_notices&&"notification"===t.style&&n.test(t.message))return;var e="whisper"===t.style;if(s.settings.group_tabs&&s.settings.whisper_room&&(e&&!this.ffz_whisper_room||!e&&this.ffz_whisper_room))return;if(e||(t.room=this.get("id")),s.tokenize_chat_line(t,!1,this.get("roomProperties.hide_chat_links")),!e&&t.from&&"jtv"!==t.from&&"twitchnotify"!==t.from&&s.settings.mod_card_history){var i=s.rooms&&s.rooms[t.room];if(i){var o=(i.user_history=i.user_history||{},i.user_history[t.from]=i.user_history[t.from]||[]);o.push({from:t.tags&&t.tags["display-name"]||t.from,cachedTokens:t.cachedTokens,style:t.style,date:t.date}),o.length>20&&o.shift()}}if(!e){var a=s.get_user();if(a&&a.login===t.from){var r=this.get("ffz_banned");this.set("ffz_banned",!1),this.get("isSubscriber")||this.get("isModeratorOrHigher")||!this.get("slowMode")?this.updateWait(0,r):this.get("slowMode")&&this.updateWait(this.get("slow"))}}e||!this.chatters||this.chatters[t.from]||"twitchnotify"===t.from||"jtv"===t.from||this.ffzUpdateChatters(t.from)}var d=this._super(t);return t.color&&s._handle_color(t.color),d},setHostMode:function(t){this.set("ffz_host_target",t&&t.hostTarget||null);var e=s.get_user();e&&s._cindex&&this.get("id")===e.login&&s._cindex.ffzUpdateHostButton();var n=App.__container__.lookup("controller:chat");if(n&&n.get("currentChannelRoom")===this)return this._super(t)},send:function(t){if(!(s.settings.group_tabs&&s.settings.whisper_room&&this.ffz_whisper_room)){try{if(t){var e=this.get("mru_list"),n=e.indexOf(t);-1!==n?e.splice(n,1):e.length>20&&e.pop(),e.unshift(t)}var i=t.split(" ",1)[0].toLowerCase();if("/ffz"===i)return this.set("messageToSend",""),void s.run_ffz_command(t.substr(5),this.get("id"));if("/"===i.charAt(0)&&s.run_command(t,this.get("id")))return void this.set("messageToSend","")}catch(o){s.error("send: "+o)}return this._super(t)}},ffzUpdateUnread:function(){if(s.settings.group_tabs){var t=App.__container__.lookup("controller:chat");t&&t.get("currentRoom")===this?this.resetUnreadCount():s._chatv&&s._chatv.ffzTabUnread(this.get("id"))}}.observes("unreadCount"),ffzInitChatterCount:function(){if(this.tmiRoom){this._ffz_chatter_timer&&(clearTimeout(this._ffz_chatter_timer),this._ffz_chatter_timer=void 0);var t=this;this.tmiRoom.list().done(function(e){var s={};e=e.data.chatters;for(var n=0;n0}.property("slow"),onSlowOff:function(){this.get("slowMode")||this.updateWait(0)}.observes("slowMode")})}},{"../constants":5,"../utils":35}],14:[function(){var e=t.FrankerFaceZ;e.prototype.setup_viewers=function(){this.log("Hooking the Ember Viewers controller.");var t=App.__container__.resolve("controller:viewers");this._modify_viewers(t)},e.prototype._modify_viewers=function(t){var s=this;t.reopen({lines:function(){var t=this._super();try{var n=[],i={},o=null,a=App.__container__.lookup("controller:channel"),r=this.get("parentController.model.id"),d=a&&a.get("id");if(d){var u=a.get("display_name");u&&(e.capitalization[d]=[u,Date.now()])}r!=d&&(d=null);for(var c=0;ce?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+='"}e+="
'+i.sanitize(n)+''+i.number_commas(o)+"

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("@")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+='',c+='',c+='',c+='',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(o){var r=n.format_unread(t===i?0:o.room.get("unreadCount"));a.querySelector("span").innerHTML=r}}}}},ffzBuildTab:function(t,o,a,r){{var d,u,c=document.createElement("span"),l="",h=o.get("id"),f=o.get("isGroupRoom"),m=o===t.get("controller.currentRoom");m||-1!==e.settings.visible_rooms.indexOf(h)}return c.setAttribute("data-room",o.id),c.className="ffz-chat-tab tooltip",c.classList.toggle("current-channel",a),c.classList.toggle("host-channel",r),c.classList.toggle("group-chat",f),c.classList.toggle("active",m),u=n.format_unread(m?0:o.get("unreadCount")),d=o.get("tmiRoom.displayName")||(f?o.get("tmiRoom.name"):s.get_capitalization(o.get("id"),function(t){u=n.format_unread(m?0:o.get("unreadCount")),c.innerHTML=l+n.sanitize(t)+""+u+""})),a?(l=i.CAMERA,c.title="Current Channel"):r?(l=i.EYE,c.title="Hosted Channel"):c.title=f?"Group Chat":"Pinned Channel",c.innerHTML=l+n.sanitize(d)+""+u+"",c.addEventListener("click",function(){var e=t.get("controller");e.focusRoom(o),e.set("showList",!1)}),o._ffz_tab=c,c},ffzDisableTabs:function(){this._ffz_tabs&&(this._ffz_tabs.parentElement.removeChild(this._ffz_tabs),delete this._ffz_tabs,delete this._ffz_invite),this._ffz_host&&(-1===e.settings.pinned_rooms.indexOf(this._ffz_host)&&this._ffz_host_room&&(this.get("controller.currentRoom")===this._ffz_host_room&&this.get("controller").blurRoom(),this._ffz_host_room.destroy()),delete this._ffz_host,delete this._ffz_host_room),this.$(".chat-room").css("top",""),this.$(".chat-header").removeClass("hidden")}})},s.prototype.connect_extra_chat=function(){var t=this.get_user();if(t&&t.login&&(!this.rooms[t.login]||this.rooms[t.login].room)){var e=App.__container__.resolve("model:room");e&&e.findOne(t.login)}if(!this.has_bttv){for(var s=0;s1)return"Join Usage: /join ";var s=e[0].toLowerCase();return"#"===s.charAt(0)&&(s=s.substr(1)),this._join_room(s)?"Joining "+s+". You will always connect to this channel's chat unless you later /part from it.":"You have already joined "+s+'. Please use "/part '+s+'" to leave it.'},s.chat_commands.part=function(t,e){if(!e||!e.length||e.length>1)return"Part Usage: /part ";var s=e[0].toLowerCase();return"#"===s.charAt(0)&&(s=s.substr(1)),this._leave_room(s)?"Leaving "+s+".":this.rooms[s]?"You do not have "+s+" pinned and you cannot leave the current channel or hosted channels via /part.":"You are not in "+s+"."}},{"../constants":5,"../utils":35}],10:[function(){var e=t.FrankerFaceZ;e.settings_info.swap_sidebars={type:"boolean",value:!1,category:"Appearance",no_mobile:!0,no_bttv:!0,name:"Swap Sidebar Positions",help:"Swap the positions of the left and right sidebars, placing chat on the left.",on_update:function(t){this.has_bttv||(document.body.classList.toggle("ffz-sidebar-swap",t),this._fix_menu_position())}},e.settings_info.right_column_width={type:"button",value:340,category:"Appearance",no_mobile:!0,no_bttv:!0,name:"Right Sidebar Width",help:"Set the width of the right sidebar for chat.",method:function(){var t=this.settings.right_column_width||340,e=prompt("Right Sidebar Width\n\nPlease enter a new width for the right sidebar, in pixels. Minimum: 250, Default: 340",t);if(null!==e&&void 0!==e){var s=parseInt(e);s&&0/0!==s||(s=340),this.settings.set("right_column_width",Math.max(250,s))}},on_update:function(t){if(!this.has_bttv){var e=App.__container__.lookup("controller:layout");e&&(e.set("rightColumnWidth",t),Ember.propertyDidChange(e,"contentWidth"))}}},e.prototype.setup_layout=function(){if(!this.has_bttv){document.body.classList.toggle("ffz-sidebar-swap",this.settings.swap_sidebars),this.log("Creating layout style element.");var t=this._layout_style=document.createElement("style");t.id="ffz-layout-css",document.head.appendChild(t),this.log("Hooking the Ember Layout controller.");var e=App.__container__.lookup("controller:layout"),s=this;e&&(e.reopen({rightColumnWidth:340,isTooSmallForRightColumn:function(){return this.get("windowWidth")<1090-this.get("rightColumnWidth")}.property("windowWidth","rightColumnWidth"),contentWidth:function(){var t=this.get("isLeftColumnClosed")?50:240,e=this.get("isRightColumnClosed")?0:this.get("rightColumnWidth");return this.get("windowWidth")-t-e-60}.property("windowWidth","isRightColumnClosed","isLeftColumnClosed","rightColumnWidth"),ffzUpdateCss:function(){var t=this.get("rightColumnWidth");s._layout_style.innerHTML="#main_col.expandRight #right_close { left: none !important; } #right_col { width: "+t+"px; } body:not(.ffz-sidebar-swap) #main_col:not(.expandRight) { margin-right: "+t+"px; } body.ffz-sidebar-swap #main_col:not(.expandRight) { margin-left: "+t+"px; }"}.observes("rightColumnWidth"),ffzFixTabs:function(){s.settings.group_tabs&&s._chatv&&s._chatv._ffz_tabs&&setTimeout(function(){s._chatv&&s._chatv.$(".chat-room").css("top",s._chatv._ffz_tabs.offsetHeight+"px")},0)}.observes("isRightColumnClosed","rightColumnWidth")}),e.set("rightColumnWidth",this.settings.right_column_width),Ember.propertyDidChange(e,"contentWidth"))}}},{}],11:[function(e){var s=t.FrankerFaceZ,n=e("../utils"),i=(e("../constants"),"[\\s`~<>!-#%-\\x2A,-/:;\\x3F@\\x5B-\\x5D_\\x7B}\\u00A1\\u00A7\\u00AB\\u00B6\\u00B7\\u00BB\\u00BF\\u037E\\u0387\\u055A-\\u055F\\u0589\\u058A\\u05BE\\u05C0\\u05C3\\u05C6\\u05F3\\u05F4\\u0609\\u060A\\u060C\\u060D\\u061B\\u061E\\u061F\\u066A-\\u066D\\u06D4\\u0700-\\u070D\\u07F7-\\u07F9\\u0830-\\u083E\\u085E\\u0964\\u0965\\u0970\\u0AF0\\u0DF4\\u0E4F\\u0E5A\\u0E5B\\u0F04-\\u0F12\\u0F14\\u0F3A-\\u0F3D\\u0F85\\u0FD0-\\u0FD4\\u0FD9\\u0FDA\\u104A-\\u104F\\u10FB\\u1360-\\u1368\\u1400\\u166D\\u166E\\u169B\\u169C\\u16EB-\\u16ED\\u1735\\u1736\\u17D4-\\u17D6\\u17D8-\\u17DA\\u1800-\\u180A\\u1944\\u1945\\u1A1E\\u1A1F\\u1AA0-\\u1AA6\\u1AA8-\\u1AAD\\u1B5A-\\u1B60\\u1BFC-\\u1BFF\\u1C3B-\\u1C3F\\u1C7E\\u1C7F\\u1CC0-\\u1CC7\\u1CD3\\u2010-\\u2027\\u2030-\\u2043\\u2045-\\u2051\\u2053-\\u205E\\u207D\\u207E\\u208D\\u208E\\u2329\\u232A\\u2768-\\u2775\\u27C5\\u27C6\\u27E6-\\u27EF\\u2983-\\u2998\\u29D8-\\u29DB\\u29FC\\u29FD\\u2CF9-\\u2CFC\\u2CFE\\u2CFF\\u2D70\\u2E00-\\u2E2E\\u2E30-\\u2E3B\\u3001-\\u3003\\u3008-\\u3011\\u3014-\\u301F\\u3030\\u303D\\u30A0\\u30FB\\uA4FE\\uA4FF\\uA60D-\\uA60F\\uA673\\uA67E\\uA6F2-\\uA6F7\\uA874-\\uA877\\uA8CE\\uA8CF\\uA8F8-\\uA8FA\\uA92E\\uA92F\\uA95F\\uA9C1-\\uA9CD\\uA9DE\\uA9DF\\uAA5C-\\uAA5F\\uAADE\\uAADF\\uAAF0\\uAAF1\\uABEB\\uFD3E\\uFD3F\\uFE10-\\uFE19\\uFE30-\\uFE52\\uFE54-\\uFE61\\uFE63\\uFE68\\uFE6A\\uFE6B\\uFF01-\\uFF03\\uFF05-\\uFF0A\\uFF0C-\\uFF0F\\uFF1A\\uFF1B\\uFF1F\\uFF20\\uFF3B-\\uFF3D\\uFF3F\\uFF5B\\uFF5D\\uFF5F-\\uFF65]"),o=new RegExp(i+"*,"+i+"*");s.settings_info.room_status={type:"boolean",value:!0,category:"Chat Appearance",no_bttv:!0,name:"Room Status Indicators",help:"Display the current room state (slow mode, sub mode, and r9k mode) next to the Chat button.",on_update:function(){this._roomv&&this._roomv.ffzUpdateStatus()}},s.settings_info.line_purge_icon={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Purge Icon in Mod Icons",help:"Display a Purge Icon in chat line Mod Icons for quickly purging users.",on_update:function(t){this.has_bttv||document.body.classList.toggle("ffz-chat-purge-icon",t)}},s.settings_info.replace_bad_emotes={type:"boolean",value:!0,category:"Chat Appearance",no_bttv:!0,name:"Fix Low Quality Twitch Global Emoticons",help:"Replace emoticons such as DansGame and RedCoat with cleaned up versions that don't have pixels around the edges or white backgrounds for nicer display on dark chat."},s.settings_info.parse_emoji={type:"boolean",value:!0,category:"Chat Appearance",name:"Replace Emoji with Images",help:"Replace emoji in chat messages with nicer looking images from the open-source Twitter Emoji project."},s.settings_info.room_status={type:"boolean",value:!0,category:"Chat Appearance",no_bttv:!0,name:"Room Status Indicators",help:"Display the current room state (slow mode, sub mode, and r9k mode) next to the Chat button.",on_update:function(){this._roomv&&this._roomv.ffzUpdateStatus()}},s.settings_info.scrollback_length={type:"button",value:150,category:"Chat Appearance",no_bttv:!0,name:"Scrollback Length",help:"Set the maximum number of lines to keep in chat.",method:function(){var t=prompt("Scrollback Length\n\nPlease enter a new maximum length for the chat scrollback. Default: 150\n\nNote: Making this too large will cause your browser to lag.",this.settings.scrollback_length);if(null!==t&&void 0!==t&&(t=parseInt(t),0/0!==t)){10>t&&(t=10),this.settings.set("scrollback_length",t);var e=App.__container__.lookup("controller:chat"),s=e&&e.get("currentRoom.id");for(var n in this.rooms){var i=this.rooms[n];i.room.set("messageBufferSize",t+(this._roomv&&!this._roomv.get("stuckToBottom")&&s===n?150:0))}}}},s.settings_info.hosted_sub_notices={type:"boolean",value:!0,category:"Chat Filtering",no_bttv:!0,name:"Show Hosted Channel Subscriber Notices",help:"Display notices in chat when someone subscribes to the hosted channel."},s.settings_info.banned_words={type:"button",value:[],category:"Chat Filtering",no_bttv:!0,name:"Banned Words",help:"Set a list of words that will be locally removed from chat messages.",method:function(){var t=this.settings.banned_words.join(", "),e=prompt("Banned Words\n\nPlease enter a comma-separated list of words that you would like to be removed from chat messages.",t);if(null!==e&&void 0!==e){e=e.trim().split(o);for(var s=[],n=0;nBeta",help:"Check links against known bad websites, unshorten URLs, and show YouTube info."},s.settings_info.link_image_hover={type:"boolean",value:!1,category:"Chat Tooltips",no_bttv:!0,no_mobile:!0,name:"Image Preview",help:"Display image thumbnails for links to Imgur and YouTube."},s.settings_info.image_hover_all_domains={type:"boolean",value:!1,category:"Chat Tooltips",no_bttv:!0,no_mobile:!0,name:"Image Preview - All Domains",help:"Requires Image Preview. Attempt to show an image preview for any URL ending in the appropriate extension. Warning: This may be used to leak your IP address to malicious users."},s.settings_info.legacy_badges={type:"boolean",value:!1,category:"Chat Appearance",name:"Legacy Badges",help:"Display the old, pre-vector chat badges from Twitch.",on_update:function(t){document.body.classList.toggle("ffz-legacy-badges",t)}},s.settings_info.chat_rows={type:"boolean",value:!1,category:"Chat Appearance",no_bttv:!0,name:"Chat Line Backgrounds",help:"Display alternating background colors for lines in chat.",on_update:function(t){document.body.classList.toggle("ffz-chat-background",!this.has_bttv&&t)}},s.settings_info.chat_separators={type:"select",options:{0:"Disabled",1:"Basic Line (1px solid)",2:"3D Line (2px groove)"},value:"0",category:"Chat Appearance",no_bttv:!0,process_value:function(t){return t===!1?"0":t===!0?"1":t},name:"Chat Line Separators",help:"Display thin lines between chat messages for further visual separation.",on_update:function(t){document.body.classList.toggle("ffz-chat-separator",!this.has_bttv&&"0"!==t),document.body.classList.toggle("ffz-chat-separator-3d",!this.has_bttv&&"2"===t)}},s.settings_info.chat_padding={type:"boolean",value:!1,category:"Chat Appearance",no_bttv:!0,name:"Reduced Chat Line Padding",help:"Reduce the amount of padding around chat messages to fit more on-screen at once.",on_update:function(t){document.body.classList.toggle("ffz-chat-padding",!this.has_bttv&&t)}},s.settings_info.high_contrast_chat={type:"select",options:{222:"Disabled",212:"Bold",221:"Text",211:"Text + Bold",122:"Background",121:"Background + Text",112:"Background + Bold",111:"All"},value:"222",category:"Chat Appearance",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.",process_value:function(t){return t===!1?"222":t===!0?"111":t},on_update:function(t){document.body.classList.toggle("ffz-high-contrast-chat-text",!this.has_bttv&&"1"===t[2]),document.body.classList.toggle("ffz-high-contrast-chat-bold",!this.has_bttv&&"1"===t[1]),document.body.classList.toggle("ffz-high-contrast-chat-bg",!this.has_bttv&&"1"===t[0])}},s.settings_info.chat_font_size={type:"button",value:12,category:"Chat Appearance",no_bttv:!0,name:"Font Size",help:"Make the chat font bigger or smaller.",method:function(){var t=this.settings.chat_font_size,e=prompt("Chat Font Size\n\nPlease enter a new size for the chat font. The default is 12.",t);if(null!==e&&void 0!==e){var s=parseInt(e);(!s||0/0===s||1>s)&&(s=12),this.settings.set("chat_font_size",s)}},on_update:function(t){if(!this.has_bttv&&this._chat_style){var e;if(12!==t&&t){var i=Math.max(20,Math.round(20/12*t)),o=Math.floor((i-20)/2);e=".ember-chat .chat-messages .chat-line { font-size: "+t+"px !important; line-height: "+i+"px !important; }",o&&(e+=".ember-chat .chat-messages .chat-line .mod-icons, .ember-chat .chat-messages .chat-line .badges { padding-top: "+o+"px; }")}else e="";n.update_css(this._chat_style,"chat_font_size",e),s.settings_info.chat_ts_size.on_update.bind(this)(this.settings.chat_ts_size)}}},s.settings_info.chat_ts_size={type:"button",value:null,category:"Chat Appearance",no_bttv:!0,name:"Timestamp Font Size",help:"Make the chat timestamp font bigger or smaller.",method:function(){var t=this.settings.chat_ts_size;t||(t=this.settings.chat_font_size);var e=prompt("Chat Timestamp Font Size\n\nPlease enter a new size for the chat timestamp font. The default is to match the regular chat font size.",t);if(null!==e&&void 0!==e){var s=parseInt(e);(!s||0/0===s||1>s)&&(s=null),this.settings.set("chat_ts_size",s)}},on_update:function(t){if(!this.has_bttv&&this._chat_style){var e;if(null===t)e="";else{var s=Math.max(20,Math.round(20/12*t),Math.round(20/12*this.settings.chat_font_size));e=".ember-chat .chat-messages .timestamp { font-size: "+t+"px !important; line-height: "+s+"px !important; }"}n.update_css(this._chat_style,"chat_ts_font_size",e)}}},s.prototype.setup_line=function(){jQuery(document.body).on("mouseleave",".tipsy",function(){this.parentElement.removeChild(this)});try{this.aliases=JSON.parse(localStorage.ffz_aliases||"{}")}catch(t){this.log("Error Loading Aliases: "+t),this.aliases={}}var e=this._chat_style=document.createElement("style");e.id="ffz-style-chat",e.type="text/css",document.head.appendChild(e),s.settings_info.chat_font_size.on_update.bind(this)(this.settings.chat_font_size),document.body.classList.toggle("ffz-chat-colors",!this.has_bttv&&"-1"!==this.settings.fix_color),document.body.classList.toggle("ffz-chat-colors-gray",!this.has_bttv&&"-1"===this.settings.fix_color),document.body.classList.toggle("ffz-legacy-badges",this.settings.legacy_badges),document.body.classList.toggle("ffz-chat-background",!this.has_bttv&&this.settings.chat_rows),document.body.classList.toggle("ffz-chat-separator",!this.has_bttv&&"0"!==this.settings.chat_separators),document.body.classList.toggle("ffz-chat-separator-3d",!this.has_bttv&&"2"===this.settings.chat_separators),document.body.classList.toggle("ffz-chat-padding",!this.has_bttv&&this.settings.chat_padding),document.body.classList.toggle("ffz-chat-purge-icon",!this.has_bttv&&this.settings.line_purge_icon),document.body.classList.toggle("ffz-high-contrast-chat-text",!this.has_bttv&&"1"===this.settings.high_contrast_chat[2]),document.body.classList.toggle("ffz-high-contrast-chat-bold",!this.has_bttv&&"1"===this.settings.high_contrast_chat[1]),document.body.classList.toggle("ffz-high-contrast-chat-bg",!this.has_bttv&&"1"===this.settings.high_contrast_chat[0]),this._last_row={},this.log("Hooking the Ember Whisper Line component.");var n=App.__container__.resolve("component:whisper-line");n&&this._modify_line(n),this.log("Hooking the Ember Message Line component.");var i=App.__container__.resolve("component:message-line");i&&this._modify_line(i);var o=this.get_user();o&&o.name&&(s.capitalization[o.login]=[o.name,Date.now()])},s.prototype.save_aliases=function(){this.log("Saving "+Object.keys(this.aliases).length+" aliases to local storage."),localStorage.ffz_aliases=JSON.stringify(this.aliases)},s.prototype._modify_line=function(e){var i=this,o=App.__container__.lookup("controller:layout"),a=App.__container__.lookup("controller:settings");e.reopen({tokenizedMessage:function(){var t=this.get("msgObject.cachedTokens");if(t)return t;t=this._super();var e=performance.now(),n=i.get_user(),o=n&&this.get("msgObject.from")===n.login;t=i._remove_banned(t),t=i._emoticonize(this,t),i.settings.parse_emoji&&(t=i.tokenize_emoji(t));var a=this.get("msgObject.tags.display-name");a&&a.length&&(s.capitalization[this.get("msgObject.from")]=[a.trim(),Date.now()]),o||(t=i.tokenize_mentions(t));for(var r=0;r5&&i.log("Tokenizing Message Took Too Long - "+(u-e)+"ms",t,!1,!0),this.set("msgObject.cachedTokens",t),t}.property("msgObject.message","isChannelLinksDisabled","currentUserNick","msgObject.from","msgObject.tags.emotes"),ffzUpdated:Ember.observer("msgObject.ffz_deleted","msgObject.ffz_old_messages",function(){this.rerender()}),click:function(e){if(e.target&&e.target.classList.contains("ffz-old-messages"))return i._show_deleted(this.get("msgObject.room"));if(e.target&&e.target.classList.contains("deleted-link"))return i._deleted_link_click.bind(e.target)(e);if(e.target&&e.target.classList.contains("mod-icon")&&(jQuery(e.target).trigger("mouseout"),e.target.classList.contains("purge"))){var s=this.get("msgObject.from"),n=this.get("msgObject.room"),o=n&&i.rooms[n]&&i.rooms[n].room;return void(o&&(o.send("/timeout "+s+" 1"),o.clearMessages(s)))}if((e.shiftKey||e.shiftLeft)&&i.settings.clickable_emoticons&&e.target&&e.target.classList.contains("emoticon")){var a=e.target.getAttribute("data-emote");a?t.open("https://twitchemotes.com/emote/"+a):(a=e.target.getAttribute("data-ffz-emote"),t.open("https://www.frankerfacez.com/emoticons/"+a))}return this._super(e)},ffzUserLevel:function(){return this.get("isStaff")?5:this.get("isAdmin")?4:this.get("isBroadcaster")?3:this.get("isGlobalModerator")?2:this.get("isModerator")?1:0}.property("msgObject.labels.[]"),render:function(t){var e=this.get("msgObject.deleted"),s={},r=this.get("msgObject.from"),d=this.get("msgObject.room"),u=i.rooms&&i.rooms[d],c=this.get("msgObject.to"),l=c&&c.length,h=this.get("ffzUserLevel"),f=u&&u.room&&u.room.get("ffzUserLevel")||0,m=this.get("msgObject.ffz_alternate"),_=this.get("msgObject.color"),p=_&&i._handle_color(_),g=o&&o.get("isTheatreMode")||a&&a.get("model.darkMode");void 0===m&&(m=i._last_row[d]=i._last_row.hasOwnProperty(d)?!i._last_row[d]:!1,this.set("msgObject.ffz_alternate",m)),t.push('
'),t.push(''+this.get("timestamp")+" "),!l&&f>h&&(t.push(''),t.push(e?'Unban':'Ban'),t.push('Timeout'),t.push('Purge'),t.push("")),!l&&this.get("isBroadcaster")?s[0]={klass:"broadcaster",title:"Broadcaster"}:this.get("isStaff")?s[0]={klass:"staff",title:"Staff"}:this.get("isAdmin")?s[0]={klass:"admin",title:"Admin"}:this.get("isGlobalMod")?s[0]={klass:"global-moderator",title:"Global Moderator"}:!l&&this.get("isModerator")&&(s[0]={klass:"moderator",title:"Moderator"}),!l&&this.get("isSubscriber")&&(s[10]={klass:"subscriber",title:"Subscriber"}),this.get("hasTurbo")&&(s[15]={klass:"turbo",title:"Turbo"}),s=i.render_badges(this,s),t.push('');for(var v in s){var b=s[v],y=b.image?"background-image:url(""+b.image+"");":"";b.color&&(y+="background-color:"+b.color+";"),b.extra_css&&(y+=b.extra_css),t.push('
')}t.push("
");var w=i.aliases[r],z=this.get("msgObject.tags.display-name")||r&&r.capitalize()||"unknown user",k=p&&"color:"+(g?p[1]:p[0]),E=k?" has-color":"";if(t.push(w?''+n.sanitize(w)+"":''+n.sanitize(z)+""),l){var C=i.aliases[c],x=this.get("msgObject.tags.recipient-display-name")||c&&c.capitalize()||"unknown user",T=this.get("msgObject.toColor"),L=T&&i._handle_color(T),M=T&&"color:"+(g?L[1]:L[0]),S=M?" has-color":"";this._renderWhisperArrow(t),t.push(C?''+n.sanitize(C)+"":''+n.sanitize(x)+"")}if(t.push(': '),"action"!==this.get("msgObject.style")&&(k="",E=""),e)t.push('<message deleted>');else{t.push(''),t.push(i.render_tokens(this.get("tokenizedMessage"),!0));var A=this.get("msgObject.ffz_old_messages");A&&A.length&&t.push('
Show '+n.number_commas(A.length)+" Old
"),t.push("
")}},classNameBindings:["msgObject.ffz_alternate:ffz-alternate","msgObject.ffz_has_mention:ffz-mentioned","ffzWasDeleted:ffz-deleted","ffzHasOldMessages:clearfix","ffzHasOldMessages:ffz-has-deleted"],ffzWasDeleted:function(){return i.settings.prevent_clear&&this.get("msgObject.ffz_deleted")}.property("msgObject.ffz_deleted"),ffzHasOldMessages:function(){var t=this.get("msgObject.ffz_old_messages");return t&&t.length}.property("msgObject.ffz_old_messages"),didInsertElement:function(){this._super();var t=this.get("element");t.setAttribute("data-room",this.get("msgObject.room")),t.setAttribute("data-sender",this.get("msgObject.from")),t.setAttribute("data-deleted",this.get("msgObject.deleted")||!1)}})},s.capitalization={},s._cap_fetching=0,s.get_capitalization=function(t,e){if(!t)return t;if(t=t.toLowerCase(),"jtv"==t||"twitchnotify"==t)return t;var n=s.capitalization[t];return n&&Date.now()-n[1]<36e5?n[0]:(s._cap_fetching<25&&(s._cap_fetching++,s.get().ws_send("get_display_name",t,function(n,i){var o=n?i:t;s.capitalization[t]=[o,Date.now()],s._cap_fetching--,"function"==typeof e&&e(o)})),n?n[0]:t)},s.prototype._remove_banned=function(t){var e=this.settings.banned_words,n=["j.mp","bit.ly"],i=e&&e.length;if(!(i||n&&n.length))return t;"string"==typeof t&&(t=[t]);for(var o=s._words_to_regex(e),a=s._words_to_regex(n),r=[],d=0;d',d='',u={},c=function(t){if(1===t)return"Purge";if(u[t])return u[t];var e,s,n,i,o;e=Math.floor(t/604800),o=t%604800,s=Math.floor(o/86400),o%=86400,n=Math.floor(o/3600),o%=3600,i=Math.floor(o/60),o%=60;var a=u[t]=(e?e+"w":"")+(s||e&&(n||i||o)?s+"d":"")+(n||(e||s)&&(i||o)?n+"h":"")+(i||(e||s||n)&&o?i+"m":"")+(o?o+"s":"");return a};try{s=t.require&&t.require("ember-twitch-chat/helpers/chat-line-helpers")}catch(l){}n.basic_settings.enhanced_moderation_cards={type:"boolean",no_bttv:!0,category:"Chat",name:"Enhanced Moderation Cards",help:"Improve moderation cards with hotkeys, additional buttons, chat history, and other information to make moderating easier.",get:function(){return this.settings.mod_card_hotkeys&&this.settings.mod_card_info&&this.settings.mod_card_history},set:function(t){this.settings.set("mod_card_hotkeys",t),this.settings.set("mod_card_info",t),this.settings.set("mod_card_history",t)}},n.basic_settings.chat_hover_pause={type:"boolean",no_bttv:!0,category:"Chat",name:"Pause Chat Scrolling on Mouse Hover",help:"Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link misclicks.",get:"chat_hover_pause",set:"chat_hover_pause"},n.settings_info.chat_hover_pause={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Pause Chat Scrolling on Mouse Hover",help:"Automatically prevent the chat from scrolling when moving the mouse over it to prevent moderation mistakes and link misclicks.",on_update:function(t){this._roomv&&(t?this._roomv.ffzEnableFreeze():this._roomv.ffzDisableFreeze())}},n.settings_info.short_commands={type:"boolean",value:!0,no_bttv:!0,category:"Chat Moderation",name:"Short Moderation Commands",help:"Use /t, /b, and /u in chat in place of /timeout, /ban, /unban for quicker moderation, and use /p for 1 second timeouts."},n.settings_info.mod_card_hotkeys={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Moderation Card Hotkeys",help:"With a moderation card selected, press B to ban the user, T to time them out for 10 minutes, P to time them out for 1 second, or U to unban them. ESC closes the card."},n.settings_info.mod_card_info={type:"boolean",value:!0,no_bttv:!0,category:"Chat Moderation",name:"Moderation Card Additional Information",help:"Display a channel's follower count, view count, and account age on moderation cards."},n.settings_info.mod_card_history={type:"boolean",value:!1,no_bttv:!0,category:"Chat Moderation",name:"Moderation Card History",help:"Display a few of the user's previously sent messages on moderation cards.",on_update:function(t){if(!t&&this.rooms)for(var e in this.rooms){var s=this.rooms[e];s&&(s.user_history=void 0)}}},n.settings_info.mod_card_buttons={type:"button",value:[],category:"Chat Moderation",no_bttv:!0,name:"Moderation Card Additional Buttons",help:"Add additional buttons to moderation cards for running chat commands on those users.",method:function(){for(var t="",e=0;e0&&s.push(o)}this.settings.set("mod_card_durations",s)}}},n.prototype.setup_mod_card=function(){this.log("Modifying Mousetrap stopCallback so we can catch ESC.");var e=Mousetrap.stopCallback;Mousetrap.stopCallback=function(t,s,n){return s.classList.contains("no-mousetrap")?!0:e(t,s,n)},Mousetrap.bind("up up down down left right left right b a enter",function(){var t=document.querySelector(".app-main")||document.querySelector(".ember-chat-container");t&&t.classList.toggle("ffz-flip")}),this.log("Hooking the Ember Moderation Card view.");var n=App.__container__.resolve("component:moderation-card"),u=this;n.reopen({ffzForceRedraw:function(){this.rerender()}.observes("cardInfo.isModeratorOrHigher","cardInfo.user"),ffzRebuildInfo:function(){var t=this.get("element"),e=t&&t.querySelector(".info");if(e){var s=''+o.EYE+" "+i.number_commas(this.get("cardInfo.user.views")||0)+"",n=i.parse_date(this.get("cardInfo.user.created_at")||""),a=this.get("cardInfo.user.ffz_followers"); +if("number"==typeof a)s+=''+o.HEART+" "+i.number_commas(a||0)+"";else if(void 0===a){var r=this;this.set("cardInfo.user.ffz_followers",!1),Twitch.api.get("channels/"+this.get("cardInfo.user.id")+"/follows",{limit:1}).done(function(t){r.set("cardInfo.user.ffz_followers",t._total),r.ffzRebuildInfo()}).fail(function(){r.set("cardInfo.user.ffz_followers",void 0)})}if(n){var d=Math.floor((Date.now()-n.getTime())/1e3);d>0&&(s+=''+o.CLOCK+" "+i.human_time(d,10)+"")}e.innerHTML=s}}.observes("cardInfo.user.views"),userName:Ember.computed("cardInfo.user.id","cardInfo.user.display_name",function(){var t=this.get("cardInfo.user.id"),e=u.aliases[t];return e||this.get("cardInfo.user.display_name")||t.capitalize()}),didInsertElement:function(){this._super(),t._card=this;try{if(u.has_bttv)return;var e,n=this.get("element"),l=this.get("controller"),h=l.get("cardInfo.user.id"),f=u.aliases[h];if(f){var m=n.querySelector("h3.name"),p=m&&m.querySelector("a");p&&(m=p),m&&(m.classList.add("ffz-alias"),m.title=i.sanitize(l.get("cardInfo.user.display_name")||h.capitalize()),jQuery(m).tipsy())}if(n.classList.add("ffz-moderation-card"),u.settings.mod_card_info){var g=document.createElement("div"),v=n.querySelector("h3.name");v&&(n.classList.add("ffz-has-info"),g.className="info channel-stats",v.parentElement.insertBefore(g,v.nextSibling),this.ffzRebuildInfo())}if(u.settings.mod_card_buttons&&u.settings.mod_card_buttons.length){e=document.createElement("div"),e.className="extra-interface interface clearfix";for(var b={},y=function(t){var e=l.get("cardInfo.user.id"),s=App.__container__.lookup("controller:chat"),n=s&&s.get("currentRoom");n&&n.send(t.replace(/{user}/g,e))},w=function(t){var e=document.createElement("button"),s=t.split(" ",1)[0],n=b[s]>1?t.split(" ",b[s]):[s];return/^[!~./]/.test(n[0])&&(n[0]=n[0].substr(1)),n=_.map(n,function(t){return t.capitalize()}).join(" "),e.className="button",e.innerHTML=i.sanitize(n),e.title=i.sanitize(t.replace(/{user}/g,l.get("cardInfo.user.id")||"{user}")),jQuery(e).tipsy(),e.addEventListener("click",y.bind(this,t)),e},b={},z=0;z button.message-button");if(R){R.innerHTML="W",R.classList.add("glyph-only"),R.classList.add("message"),R.title="Whisper User",jQuery(R).tipsy();var H=document.createElement("button");H.className="message-button button glyph-only message tooltip",H.innerHTML=r,H.title="Message User",H.addEventListener("click",function(){t.open("http://www.twitch.tv/message/compose?to="+l.get("cardInfo.user.id"))}),R.parentElement.insertBefore(H,R.nextSibling)}var O=document.createElement("button");if(O.className="alias button glyph-only tooltip",O.innerHTML=o.EDIT,O.title="Set Alias",O.addEventListener("click",function(){var t=l.get("cardInfo.user.id"),e=u.aliases[t],s=prompt("Alias for User: "+t+"\n\nPlease enter an alias for the user. Leave it blank to remove the alias.",e);if(null!==s&&void 0!==s){s=s.trim(),s||(s=void 0),u.aliases[t]=s,u.save_aliases(),u._update_alias(t),Ember.propertyDidChange(l,"userName");var i=n.querySelector("h3.name"),o=i&&i.querySelector("a");o&&(i=o),i&&i.classList.toggle("ffz-alias",s)}}),R)R.parentElement.insertBefore(O,R);else{var I=n.querySelector(".interface > .follow-button");I&&I.parentElement.insertBefore(O,I.nextSibling)}if(u.settings.mod_card_history){var D=App.__container__.lookup("controller:chat"),B=D&&D.get("currentRoom"),N=B&&u.rooms&&u.rooms[B.get("id")],j=N&&N.user_history&&N.user_history[l.get("cardInfo.user.id")];if(j&&j.length){var P=document.createElement("ul"),U=!1;P.className="interface clearfix chat-history";for(var z=0;z'+s.getTime(e.date)+" ":"")+''+("action"===e.style?"*"+e.from+" ":"")+u.render_tokens(e.cachedTokens)+"";for(var V=q.querySelectorAll("a.deleted-link"),W=0;WG.bottom){var Y=Z.bottom-G.bottom;Z.top-Y>G.top&&(n.style.top=Z.top-Y+"px")}this.$().draggable({start:function(){n.focus()}}),n.focus()}catch($){try{u.error("ModerationCardView didInsertElement: "+$)}catch($){}}}})},n.prototype._update_alias=function(t){var e=this.aliases&&this.aliases[t],s=n.get_capitalization(t),i=e||s,o=this._roomv&&this._roomv.get("element"),a=o&&o.querySelectorAll('.chat-line[data-sender="'+t+'"]');if(a)for(var r=0,d=a.length;d>r;r++){var u=a[r],c=u.querySelector(".from");c.classList.toggle("ffz-alias",e),c.textContent=i,c.title=e?s:""}},n.chat_commands.purge=function(t,e){if(!e||!e.length)return"Purge Usage: /p username [more usernames separated by spaces]";if(e.length>10)return"Please only purge up to 10 users at once.";for(var s=0;s10)return"Please only ban up to 10 users at once.";for(var s=0;s10)return"Please only unban up to 10 users at once.";for(var s=0;s750&&this.ffzUnfreeze()}},ffzUnfreeze:function(){this.ffz_frozen=!1,this._ffz_last_move=0,this.ffzUnwarnPaused(),this.get("stuckToBottom")&&this._scrollToBottom()},ffzMouseDown:function(t){var s=this._$chatMessagesScroller;if(s&&s[0]&&(!this.ffz_frozen&&"mousedown"===t.type||"mousewheel"===t.type||a&&"scroll"===t.type)){"mousedown"===t.type&&e.log("Freezing from mouse down!",t);var n=s[0].scrollHeight-s[0].scrollTop-s[0].offsetHeight;this._setStuckToBottom(10>=n)}},ffzMouseOut:function(){this._ffz_outside=!0;var t=this;setTimeout(function(){t._ffz_outside&&t.ffzUnfreeze()},25)},ffzMouseMove:function(t){this._ffz_last_move=Date.now(),this._ffz_outside=!1,(t.screenX!==this._ffz_last_screenx||t.screenY!==this._ffz_last_screeny)&&(this._ffz_last_screenx=t.screenX,this._ffz_last_screeny=t.screenY,this.ffz_frozen||(this.ffz_frozen=!0,this.get("stuckToBottom")&&(this.set("controller.model.messageBufferSize",e.settings.scrollback_length+150),this.ffzWarnPaused())))},_scrollToBottom:_.throttle(function(){var t=this,e=this._$chatMessagesScroller;Ember.run.next(function(){setTimeout(function(){!t.ffz_frozen&&e&&e.length&&(e[0].scrollTop=e[0].scrollHeight,t._setStuckToBottom(!0))})})},200),_setStuckToBottom:function(t){this.set("stuckToBottom",t),this.get("controller.model")&&this.set("controller.model.messageBufferSize",e.settings.scrollback_length+(t?0:150)),t||this.ffzUnfreeze()},ffzWarnPaused:function(){var t=this.get("element"),e=t&&t.querySelector(".chat-interface .more-messages-indicator.ffz-freeze-indicator");if(t){if(!e){e=document.createElement("div"),e.className="more-messages-indicator ffz-freeze-indicator",e.innerHTML="(Chat Paused Due to Mouse Movement)";var s=t.querySelector(".chat-interface");if(!s)return;s.insertBefore(e,s.childNodes[0])}e.classList.remove("hidden")}},ffzUnwarnPaused:function(){var t=this.get("element"),e=t&&t.querySelector(".chat-interface .more-messages-indicator.ffz-freeze-indicator");e&&e.classList.add("hidden")}})},s.chat_commands={},s.ffz_commands={},s.prototype.room_message=function(t,e){var s=e.split("\n");if(this.has_bttv)for(var n=0;n300,f=e.length,m=n.get("messages.0.ffz_alternate")||!1;h&&(m=!m);for(var f=e.length;f--;){var _=e[f];if("string"==typeof _.date&&(_.date=o.parse_date(_.date)),_.ffz_alternate=m=!m,_.room||(_.room=t),_.color||(_.color=_.tags&&_.tags.color?_.tags.color:a&&_.from?a.getColor(_.from.toLowerCase()):"#755000"),!_.labels||!_.labels.length){var p=_.labels=[];if(_.tags)if(_.tags.turbo&&p.push("turbo"),_.tags.subscriber&&p.push("subscriber"),_.from===t)p.push("owner");else{var g=_.tags["user-type"];("mod"===g||"staff"===g||"admin"===g||"global_mod"===g)&&p.push(g)}}if(_.style||("jtv"===_.from?_.style="admin":"twitchnotify"===_.from&&(_.style="notification")),_.cachedTokens&&_.cachedTokens.length||this.tokenize_chat_line(_,!0,n.get("roomProperties.hide_chat_links")),n.shouldShowMessage(_)){if(!(i.lengthv&&(_.ffz_old_messages=_.ffz_old_messages.slice(_.ffz_old_messages.length-v))}i.unshiftObject(_),r+=1}}if(h){var _={ffz_alternate:!m,color:"#755000",date:new Date,from:"frankerfacez_admin",style:"admin",message:"(Last message is "+o.human_time(l)+" old.)",room:t};if(this.tokenize_chat_line(_,!0,n.get("roomProperties.hide_chat_links")),n.shouldShowMessage(_))for(i.insertAt(r,_);i.length>n.get("messageBufferSize");)i.removeAt(0)}}},s.prototype.load_room=function(t,e,s){var n=this;jQuery.getJSON(((s||0)%2===0?i.API_SERVER:i.API_SERVER_2)+"v1/room/"+t).done(function(s){if(s.sets)for(var i in s.sets)s.sets.hasOwnProperty(i)&&n._load_set_json(i,void 0,s.sets[i]);n._load_room_json(t,e,s)}).fail(function(i){return 404==i.status?"function"==typeof e&&e(!1):(s=(s||0)+1,10>s?n.load_room(t,e,s):"function"==typeof e&&e(!1))})},s.prototype._load_room_json=function(t,e,s){if(!s||!s.room)return"function"==typeof e&&e(!1);s=s.room,this.rooms[t]&&(s.room=this.rooms[t].room);for(var n in this.rooms[t])"room"!==n&&this.rooms[t].hasOwnProperty(n)&&!s.hasOwnProperty(n)&&(s[n]=this.rooms[t][n]);s.needs_history=this.rooms[t]&&this.rooms[t].needs_history||!1,this.rooms[t]=s,(s.css||s.moderator_badge)&&o.update_css(this._room_style,t,r(s)+(s.css||"")),this.emote_sets.hasOwnProperty(s.set)?-1===this.emote_sets[s.set].users.indexOf(t)&&this.emote_sets[s.set].users.push(t):this.load_set(s.set,function(e,s){-1===s.users.indexOf(t)&&s.users.push(t)}),this.update_ui_link(),e&&e(!0,s)},s.prototype._modify_room=function(e){var s=this;e.reopen({slowWaiting:!1,slow:0,mru_list:[],updateWait:function(t,e){var n=this.get("slowWait")||0;this.set("slowWait",t),1>n&&t>0?(this._ffz_wait_timer&&clearTimeout(this._ffz_wait_timer),this._ffz_wait_timer=setTimeout(this.ffzUpdateWait.bind(this),1e3),s._roomv&&s._roomv.ffzUpdateStatus()):(n>0&&1>t||e)&&(this.set("ffz_banned",!1),s._roomv&&s._roomv.ffzUpdateStatus())},ffzUpdateWait:function(){this._ffz_wait_timer=void 0;var t=this.get("slowWait")||0;1>t||(this.set("slowWait",--t),t>0?this._ffz_wait_timer=setTimeout(this.ffzUpdateWait.bind(this),1e3):(this.set("ffz_banned",!1),s._roomv&&s._roomv.ffzUpdateStatus()))},ffzUpdateStatus:function(){s._roomv&&s._roomv.ffzUpdateStatus()}.observes("r9k","subsOnly","slow","ffz_banned"),ffzUserLevel:function(){return this.get("isStaff")?5:this.get("isAdmin")?4:this.get("isBroadcaster")?3:this.get("isGlobalModerator")?2:this.get("isModerator")?1:0}.property("id","chatLabels.[]"),init:function(){this._super();try{s.add_room(this.id,this),this.set("ffz_chatters",{})}catch(t){s.error("add_room: "+t)}},willDestroy:function(){this._super();try{s.remove_room(this.id)}catch(t){s.error("remove_room: "+t)}},clearMessages:function(t){var e=this;if(t){for(var n,i=e.get("messages"),a=i.get("length"),r=a;r--;){var d=i.get(r);if(d.from===t){if(s.settings.remove_deleted){void 0===n&&(n=d.ffz_alternate),i.removeAt(r);continue}e.set("messages."+r+".ffz_deleted",!0),s.settings.prevent_clear||e.set("messages."+r+".deleted",!0)}void 0===n?n=d.ffz_alternate:(n=!n,e.set("messages."+r+".ffz_alternate",n))}if(s.settings.mod_card_history){var u=s.rooms&&s.rooms[e.get("id")],c=u&&u.user_history&&u.user_history[t];if(null!==c&&void 0!==c){var l=!1,h=c.length>0?c[c.length-1]:null;if(l=null!==h&&h.is_delete)h.cachedTokens=["User has been timed out "+o.number_commas(++h.deleted_times)+" times."];else for(c.push({from:"jtv",is_delete:!0,style:"admin",cachedTokens:["User has been timed out."],deleted_times:1,date:new Date});c.length>20;)c.shift()}}}else if(s.settings.prevent_clear)this.addTmiMessage("A moderator's attempt to clear chat was ignored.");else{var i=e.get("messages");e.set("messages",[]),e.addMessage({style:"admin",message:i18n("Chat was cleared by a moderator"),ffz_old_messages:i})}},trimMessages:function(){var t=this.get("messages"),e=t.get("length"),s=this.get("messageBufferSize");e>s&&t.removeAt(0,e-s)},pushMessage:function(t){this.shouldShowMessage(t)&&(this.get("messages").pushObject(t),this.trimMessages(),"admin"===t.style||"whisper"===t.style&&!this.ffz_whisper_room||this.incrementProperty("unreadCount",1))},addMessage:function(t){if(t){if(!s.settings.hosted_sub_notices&&"notification"===t.style&&n.test(t.message))return;var e="whisper"===t.style;if(s.settings.group_tabs&&s.settings.whisper_room&&(e&&!this.ffz_whisper_room||!e&&this.ffz_whisper_room))return;if(e||(t.room=this.get("id")),s.tokenize_chat_line(t,!1,this.get("roomProperties.hide_chat_links")),!e&&t.from&&"jtv"!==t.from&&"twitchnotify"!==t.from&&s.settings.mod_card_history){var i=s.rooms&&s.rooms[t.room];if(i){var o=(i.user_history=i.user_history||{},i.user_history[t.from]=i.user_history[t.from]||[]);o.push({from:t.tags&&t.tags["display-name"]||t.from,cachedTokens:t.cachedTokens,style:t.style,date:t.date}),o.length>20&&o.shift()}}if(!e){var a=s.get_user();if(a&&a.login===t.from){var r=this.get("ffz_banned");this.set("ffz_banned",!1),this.get("isSubscriber")||this.get("isModeratorOrHigher")||!this.get("slowMode")?this.updateWait(0,r):this.get("slowMode")&&this.updateWait(this.get("slow"))}}e||!this.chatters||this.chatters[t.from]||"twitchnotify"===t.from||"jtv"===t.from||this.ffzUpdateChatters(t.from)}var d=this._super(t);return t.color&&s._handle_color(t.color),d},setHostMode:function(t){this.set("ffz_host_target",t&&t.hostTarget||null);var e=s.get_user();e&&s._cindex&&this.get("id")===e.login&&s._cindex.ffzUpdateHostButton();var n=App.__container__.lookup("controller:chat");if(n&&n.get("currentChannelRoom")===this)return this._super(t)},send:function(t){if(!(s.settings.group_tabs&&s.settings.whisper_room&&this.ffz_whisper_room)){try{if(t){var e=this.get("mru_list"),n=e.indexOf(t);-1!==n?e.splice(n,1):e.length>20&&e.pop(),e.unshift(t)}var i=t.split(" ",1)[0].toLowerCase();if("/ffz"===i)return this.set("messageToSend",""),void s.run_ffz_command(t.substr(5),this.get("id"));if("/"===i.charAt(0)&&s.run_command(t,this.get("id")))return void this.set("messageToSend","")}catch(o){s.error("send: "+o)}return this._super(t)}},ffzUpdateUnread:function(){if(s.settings.group_tabs){var t=App.__container__.lookup("controller:chat");t&&t.get("currentRoom")===this?this.resetUnreadCount():s._chatv&&s._chatv.ffzTabUnread(this.get("id"))}}.observes("unreadCount"),ffzInitChatterCount:function(){if(this.tmiRoom){this._ffz_chatter_timer&&(clearTimeout(this._ffz_chatter_timer),this._ffz_chatter_timer=void 0);var t=this;this.tmiRoom.list().done(function(e){var s={};e=e.data.chatters;for(var n=0;n0}.property("slow"),onSlowOff:function(){this.get("slowMode")||this.updateWait(0)}.observes("slowMode")})}},{"../constants":5,"../utils":35}],14:[function(){var e=t.FrankerFaceZ;e.prototype.setup_viewers=function(){this.log("Hooking the Ember Viewers controller.");var t=App.__container__.resolve("controller:viewers");this._modify_viewers(t)},e.prototype._modify_viewers=function(t){var s=this;t.reopen({lines:function(){var t=this._super();try{var n=[],i={},o=null,a=App.__container__.lookup("controller:channel"),r=this.get("parentController.model.id"),d=a&&a.get("id");if(d){var u=a.get("display_name");u&&(e.capitalization[d]=[u,Date.now()])}r!=d&&(d=null);for(var c=0;ce?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)+"
Developers
Dan Salvato  
Stendec  
Version '+s.version_info+'Logs
";for(var n in s.items){{var o=s.items[n];Math.floor(o/s.total*100)}e+='"}e+="
'+i.sanitize(n)+''+i.number_commas(o)+"

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("@")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+='',c+='',c+='',c+='',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='
You are following '+s.get_capitalization(e)+"
",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='",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;ds?-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=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+='
Developers
Dan Salvato  
Stendec  
Version '+s.version_info+'Logs
',r+="
#Entrant Time
",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 678544cf..f36edccb 100644 --- a/src/ember/line.js +++ b/src/ember/line.js @@ -824,22 +824,27 @@ FFZ.get_capitalization = function(name, callback) { // --------------------- FFZ.prototype._remove_banned = function(tokens) { - var banned_words = _.union(['j.mp', 'bit.ly'], this.settings.banned_words); - if ( ! banned_words || ! banned_words.length ) + var banned_words = this.settings.banned_words, + banned_links = ['j.mp', 'bit.ly'], + + has_banned_words = banned_words && banned_words.length; + + if ( !has_banned_words && (! banned_links || ! banned_links.length) ) return tokens; if ( typeof tokens == "string" ) tokens = [tokens]; var regex = FFZ._words_to_regex(banned_words), + link_regex = FFZ._words_to_regex(banned_links), new_tokens = []; for(var i=0; i < tokens.length; i++) { var token = tokens[i]; if ( ! _.isString(token ) ) { - if ( token.emoticonSrc && regex.test(token.altText) ) + if ( token.emoticonSrc && has_banned_words && regex.test(token.altText) ) new_tokens.push(token.altText.replace(regex, "$1***")); - else if ( token.isLink && regex.test(token.href) ) + else if ( token.isLink && has_banned_words && regex.test(token.href) ) new_tokens.push({ isLink: true, href: token.href, @@ -847,10 +852,18 @@ FFZ.prototype._remove_banned = function(tokens) { isLong: false, censoredHref: token.href.replace(regex, "$1***") }); + else if ( token.isLink && link_regex.test(token.href) ) + new_tokens.push({ + isLink: true, + href: token.href, + isDeleted: true, + isLong: false, + censoredHref: token.href.replace(link_regex, "$1***") + }); else new_tokens.push(token); - } else + } else if ( has_banned_words ) new_tokens.push(token.replace(regex, "$1***")); } diff --git a/src/main.js b/src/main.js index a5de7ec3..4e2448d0 100644 --- a/src/main.js +++ b/src/main.js @@ -125,8 +125,6 @@ require('./ember/moderation-card'); require('./ember/chat-input'); //require('./ember/teams'); -// Analytics: require('./tracking'); - require('./debug'); require('./ext/betterttv'); @@ -317,8 +315,6 @@ FFZ.prototype.init_ember = function(delay) { this.setup_emoticons(); this.setup_badges(); - //this.setup_piwik(); - //this.setup_router(); this.setup_colors(); this.setup_tokenization(); diff --git a/src/tracking.js b/src/tracking.js deleted file mode 100644 index a9748417..00000000 --- a/src/tracking.js +++ /dev/null @@ -1,131 +0,0 @@ -var FFZ = window.FrankerFaceZ, - constants = require('./constants'), - PIWIK = ("https:" == document.location.protocol ? 'https:' : 'http:') + '//sir.stendec.me/ffz_piwik/'; - - -// -------------------- -// Initialization -// -------------------- - -FFZ.prototype.setup_piwik = function() { - if ( window._paq != undefined ) { - this.log("Piwik is already present. Disabling analytics."); - this._tracking = false; - return; - } - - if ( localStorage['ffzTracking'] == "false" ) { - this.log("The user has opted out of tracking. Disabling analytics."); - this._tracking = false; - return; - } - - this.log("Initializing Piwik."); - this._tracking = true; - var _paq = window._paq = []; - - _paq.push(['setSiteId', 1]); - _paq.push(['setTrackerUrl', PIWIK + 'piwik.php']); - - if ( this.has_bttv ) - _paq.push(['setCustomVariable', '3', 'BetterTTV', BetterTTV.info.versionString()]); - - var user = this.get_user(), f = this; - if ( user ) { - _paq.push(['setCustomVariable', '1', 'Partnered', user.is_partner ? "Yes" : "No"]) - _paq.push(['setCustomVariable', '2', 'User Type', user.is_staff ? "Staff" : (user.is_admin ? "Admin" : "User")]); - _paq.push(['setUserId', user.login]); - - Twitch.api.get("channels/" + user.login) - .done(function(data) { - if ( data.logo ) - f.track('setCustomVariable', '4', 'Avatar', data.logo); - }).always(function() { f.track_page(); }); - - } else - this.track_page(); - - // If someone turned analytics back ON, track that. - if ( localStorage['ffzTracking'] == "true" ) { - this.track('trackEvent', 'Analytics', 'Enable'); - localStorage.removeItem('ffzTracking'); - } - - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.defer = true; - script.async = true; - script.src = PIWIK + 'piwik.js'; - document.head.appendChild(script); -} - - -// -------------------- -// Command -// -------------------- - -FFZ.chat_commands.analytics = function(room, args) { - var enabled, args = args && args.length ? args[0].toLowerCase() : null; - if ( args == "y" || args == "yes" || args == "true" || args == "on" ) - enabled = true; - else if ( args == "n" || args == "no" || args == "false" || args == "off" ) - enabled = false; - - if ( enabled === undefined ) - return "Analytics are currently " + (localStorage.ffzTracking != "false" ? "enabled." : "disabled."); - - // Track that someone turned off analytics. - if ( this._tracking && ! enabled && localStorage.ffzTracking != "false" ) - this.track('trackEvent', 'Analytics', 'Disable'); - - localStorage.ffzTracking = enabled; - - return "Analytics are now " + (enabled ? "enabled" : "disabled") + ". Please refresh your browser."; -} - -FFZ.chat_commands.analytics.help = "Usage: /ffz analytics \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."; - - - -// -------------------- -// Tracking Helpers -// -------------------- - -FFZ.prototype.track = function() { - if ( ! this._tracking ) - return; - - window._paq && _paq.push(Array.prototype.slice.call(arguments)); -} - - -FFZ.prototype.track_page = function() { - if ( ! this._tracking ) - return; - - if ( 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 routes = App.__container__.resolve('router:main').router.currentHandlerInfos; - if ( ! routes || routes.length == 0 ) - return; - - var last = routes[routes.length - 1]; - if ( last.name == "channel.index" && last.context ) { - var following = last.context.get("isFollowing.isFollowing"); - if ( following !== undefined && following !== null ) - this.track('setCustomVariable', '1', 'Following', (following ? "Yes" : "No"), 'page'); - - var game = last.context.get("game"); - if ( game ) - this.track("setCustomVariable", "3", "Game", game, "page"); - - this.track("trackPageView", document.title); - } -} \ No newline at end of file