Advertisement
Guest User

Untitled

a guest
Jan 4th, 2015
227
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.58 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Twitch.tv in VLC
  3. // @namespace http://shemanaev.com
  4. // @version 1.0
  5. // @description Replace standard flash player with VLC
  6. // @include http://www.twitch.tv/*
  7. // @match http://www.twitch.tv/*
  8. // @grant GM_xmlhttpRequest
  9. // ==/UserScript==
  10.  
  11. /* https://gist.github.com/raw/2625891/waitForKeyElements.js */
  12. function waitForKeyElements(b,a,h,g){var d,f;if(typeof g=="undefined"){d=$(b)}else{d=$(g).contents().find(b)}if(d&&d.length>0){f=true;d.each(function(){var k=$(this);var l=k.data("alreadyFound")||false;if(!l){var j=a(k);if(j){f=false}else{k.data("alreadyFound",true)}}})}else{f=false}var c=waitForKeyElements.controlObj||{};var i=b.replace(/[^\w]/g,"_");var e=c[i];if(f&&h&&e){clearInterval(e);delete c[i]}else{if(!e){e=setInterval(function(){waitForKeyElements(b,a,h,g)},300);c[i]=e}}waitForKeyElements.controlObj=c};
  13.  
  14. /* Laura Doktorova https://github.com/olado/doT */
  15. (function(){function o(){var a={"&":"&#38;","<":"&#60;",">":"&#62;",'"':"&#34;","'":"&#39;","/":"&#47;"},b=/&(?!#?\w+;)|<|>|"|'|\//g;return function(){return this?this.replace(b,function(c){return a[c]||c}):this}}function p(a,b,c){return(typeof b==="string"?b:b.toString()).replace(a.define||i,function(l,e,f,g){if(e.indexOf("def.")===0)e=e.substring(4);if(!(e in c))if(f===":"){a.defineParams&&g.replace(a.defineParams,function(n,h,d){c[e]={arg:h,text:d}});e in c||(c[e]=g)}else(new Function("def","def['"+
  16. e+"']="+g))(c);return""}).replace(a.use||i,function(l,e){if(a.useParams)e=e.replace(a.useParams,function(g,n,h,d){if(c[h]&&c[h].arg&&d){g=(h+":"+d).replace(/'|\\/g,"_");c.__exp=c.__exp||{};c.__exp[g]=c[h].text.replace(RegExp("(^|[^\\w$])"+c[h].arg+"([^\\w$])","g"),"$1"+d+"$2");return n+"def.__exp['"+g+"']"}});var f=(new Function("def","return "+e))(c);return f?p(a,f,c):f})}function m(a){return a.replace(/\\('|\\)/g,"$1").replace(/[\r\t\n]/g," ")}var j={version:"1.0.1",templateSettings:{evaluate:/\{\{([\s\S]+?(\}?)+)\}\}/g,
  17. interpolate:/\{\{=([\s\S]+?)\}\}/g,encode:/\{\{!([\s\S]+?)\}\}/g,use:/\{\{#([\s\S]+?)\}\}/g,useParams:/(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,define:/\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,defineParams:/^\s*([\w$]+):([\s\S]+)/,conditional:/\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,iterate:/\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,varname:"it",strip:true,append:true,selfcontained:false},template:undefined,
  18. compile:undefined},q;if(typeof module!=="undefined"&&module.exports)module.exports=j;else if(typeof define==="function"&&define.amd)define(function(){return j});else{q=function(){return this||(0,eval)("this")}();q.doT=j}String.prototype.encodeHTML=o();var r={append:{start:"'+(",end:")+'",endencode:"||'').toString().encodeHTML()+'"},split:{start:"';out+=(",end:");out+='",endencode:"||'').toString().encodeHTML();out+='"}},i=/$^/;j.template=function(a,b,c){b=b||j.templateSettings;var l=b.append?r.append:
  19. r.split,e,f=0,g;a=b.use||b.define?p(b,a,c||{}):a;a=("var out='"+(b.strip?a.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g," ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,""):a).replace(/'|\\/g,"\\$&").replace(b.interpolate||i,function(h,d){return l.start+m(d)+l.end}).replace(b.encode||i,function(h,d){e=true;return l.start+m(d)+l.endencode}).replace(b.conditional||i,function(h,d,k){return d?k?"';}else if("+m(k)+"){out+='":"';}else{out+='":k?"';if("+m(k)+"){out+='":"';}out+='"}).replace(b.iterate||i,function(h,
  20. d,k,s){if(!d)return"';} } out+='";f+=1;g=s||"i"+f;d=m(d);return"';var arr"+f+"="+d+";if(arr"+f+"){var "+k+","+g+"=-1,l"+f+"=arr"+f+".length-1;while("+g+"<l"+f+"){"+k+"=arr"+f+"["+g+"+=1];out+='"}).replace(b.evaluate||i,function(h,d){return"';"+m(d)+"out+='"})+"';return out;").replace(/\n/g,"\\n").replace(/\t/g,"\\t").replace(/\r/g,"\\r").replace(/(\s|;|\}|^|\{)out\+='';/g,"$1").replace(/\+''/g,"").replace(/(\s|;|\}|^|\{)out\+=''\+/g,"$1out+=");if(e&&b.selfcontained)a="String.prototype.encodeHTML=("+
  21. o.toString()+"());"+a;try{return new Function(b.varname,a)}catch(n){typeof console!=="undefined"&&console.log("Could not create a template function: "+a);throw n;}};j.compile=function(a,b){return j.template(a,null,b)}})();
  22.  
  23.  
  24. var TOKEN_API = doT.template('http://api.twitch.tv/api/channels/{{=it}}/access_token')
  25. , USHER_API = doT.template('http://usher.twitch.tv/api/channel/hls/{{=it.channel}}.m3u8?token={{=it.token}}&sig={{=it.sig}}&allow_source=true&type=any&private_code=&allow_audio_only=true')
  26. , VLC_OPTIONS = ':network-caching='
  27. , OPTIONS_CACHE = 'network-cache'
  28. , EMBED = doT.template(
  29. '<div id="vlc" style="width: 100%; height: 100%;"></div>'
  30. + '<div style="margin-top: 7px;">'
  31. + '<input type="text" id="stream-url" class="text fademe" readonly style="height: 26px;" onClick="this.select();" value="{source}" />'
  32. + '<select id="quality-selector" style="height: 26px; float: right;">'
  33. + '{{ for (var prop in it) { if (it.hasOwnProperty(prop)) }}<option value="{{=it[prop]}}">{{=prop}}</option>{{ } }}'
  34. + '</select>'
  35. + '<input type="text" id="vlc-cache" class="text fademe" style="height: 16px; width: 40px; float: right; margin-right: 7px;" onClick="this.select();" value="' + GM_getValue(OPTIONS_CACHE, 300) + '" title="Network cache (ms)" />'
  36. + '</div>'
  37. )
  38. , VLC = doT.template('<embed type="application/x-vlc-plugin" pluginspage="http://www.videolan.org" width="100%" height="100%" src="{{=it}}"></embed>')
  39.  
  40. function fireOnChange(element) {
  41. var evt = document.createEvent('HTMLEvents')
  42. evt.initEvent('change', false, true)
  43. element.dispatchEvent(evt)
  44. }
  45.  
  46. function vlcInit() {
  47. var channel = document.location.pathname.substr(1)
  48. , tokenUrl = TOKEN_API(channel)
  49. , $player = document.querySelector('#player')
  50. , $stats = document.querySelector('.stats-and-actions')
  51. , $qualitySelector
  52. , $vlc
  53. , $streamUrl
  54.  
  55. function onPlaylist(response) {
  56. var urlsRegEx = /https?:\/\/.*fmt=([a-z]+).*/gi
  57. , urls = []
  58. , url
  59.  
  60. while (url = urlsRegEx.exec(response.responseText)) {
  61. urls[url[1]] = url[0]
  62. }
  63.  
  64. $stats.style.marginTop = '20px'
  65. $player.innerHTML = EMBED(urls)
  66.  
  67. $vlc = document.querySelector('#vlc')
  68. $streamUrl = document.querySelector('#stream-url')
  69. $qualitySelector = document.querySelector('#quality-selector')
  70. $cacheOption = document.querySelector('#vlc-cache')
  71.  
  72. function qualitySelected() {
  73. var url = this.value
  74.  
  75. $vlc.innerHTML = VLC(url)
  76. $streamUrl.value = url
  77. }
  78.  
  79. $qualitySelector.addEventListener('change', qualitySelected, false)
  80. fireOnChange($qualitySelector)
  81. }
  82.  
  83. function cacheChanged() {
  84. var cache = this.value.trim()
  85.  
  86. if (!/^\d+$/.test(cache)) {
  87. this.value = GM_getValue(OPTIONS_CACHE, 300)
  88. return
  89. }
  90.  
  91. GM_setValue(OPTIONS_CACHE, cache)
  92. fireOnChange($qualitySelector)
  93. }
  94.  
  95. $cacheOption.addEventListener('change', cacheChanged, false)
  96. $qualitySelector.addEventListener('change', qualitySelected, false)
  97. fireOnChange($qualitySelector)
  98. }
  99.  
  100. GM_xmlhttpRequest(
  101. { method: 'GET'
  102. , url: tokenUrl
  103. , headers: { 'Accept': 'application/json' }
  104. , onload: function (response) {
  105. var data = JSON.parse(response.responseText)
  106. , url = USHER_API({ channel: channel, sig: data.sig, token: encodeURIComponent(data.token) })
  107.  
  108. GM_xmlhttpRequest(
  109. { method: 'GET'
  110. , url: url
  111. , onload: onPlaylist
  112. }
  113. )
  114. }
  115. }
  116. )
  117. }
  118.  
  119. waitForKeyElements('#player', vlcInit)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement