您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Adds a button that gives you a .m3u8 file for a stream on Twitch or Hitbox.
当前为
// ==UserScript== // @name Stream URL grabber // @description Adds a button that gives you a .m3u8 file for a stream on Twitch or Hitbox. // @include *://www.twitch.tv/* // @include *://m.twitch.tv/* // @include *://www.m.twitch.tv/* // @include *://player.twitch.tv/* // @include *://www.player.twitch.tv/* // @include *://www.hitbox.tv/* // @include *://api.twitch.tv/api/channels/*/access_token?grabber // @namespace https://greasyforks.org/users/3167 // @run-at document-start // @grant none // @version 0.0.1.20161104053903 // ==/UserScript== SERVERS = [ ["San Francisco, US", "sfo"], ["Stockholm, Sweden", "arn"], ["London, UK", "lhr"], ["Amsterdam, NL", "ams"], ["Paris, France", "cdg"], ["Dallas, US", "dfw"], ["Frankfurt, Germany", "fra"], ["Washington, US", "iad"], ["New York, US", "jfk"], ["Los Angeles, US", "lax"], ["Prague, Czech Republic", "prg"], ["Seattle, US", "sea"], ["San Jose, US", "sjc"], ["Chicago, US", "ord"] ]; console.log("grabbing"); M3U8CONTENT = ""; function loadm3u8(url, filename) { var client = new XMLHttpRequest(); client.open('GET', url); client.onreadystatechange = function() { if (client.readyState==4 && client.status==200) { //alert(client.responseText); M3U8CONTENT = client.responseText; //console.log("m3u8:" + M3U8CONTENT); document.body.innerHTML = 'Servers:'; var key; for (key in SERVERS) { var server = SERVERS[key]; parsem3u8(M3U8CONTENT, filename, server); } } } client.send(); } function parsem3u8(text, filename, server) { //alert(client.responseText); var temp = text; //console.log("m3u8:" + M3U8CONTENT); var oldpart1 = temp.split('NODE="video')[1].split('.')[0]; var oldpart2 = temp.split('NODE="video' + oldpart1 + '.')[1].split('0')[0]; //video24.arn01 var oldserver1 = "video" + oldpart1; //video24-1.arn01 var oldserver2 = oldpart2 + "01"; var newserver1 = "video" + oldpart1; var newserver2 = server[1] + "01"; console.log(oldserver1 + "." + oldserver2 + " -> " + newserver1 + "." + newserver2); if (oldserver2==newserver2) { createm3u8(temp, filename, server, true, false); } else { //temp = temp.replace(oldserver1,newserver1); //temp = temp.replace(oldserver2,newserver2); temp = temp.split(oldserver1).join(newserver1); temp = temp.split(oldserver2).join(newserver2); createm3u8(temp, filename, server, false, false); } } function createm3u8(text, filename, server, defaultserver, autostart) { if (autostart) { document.body.innerHTML = 'Link: '; } var textToWrite = text; var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'}); //var fileNameToSaveAs = filename + "_" + server[1] + '.m3u8'; var fileNameToSaveAs = filename + '.m3u8'; var downloadLink = document.createElement("a"); downloadLink.download = fileNameToSaveAs; downloadLink.innerHTML = server[0]; if (defaultserver) { downloadLink.innerHTML = server[0] + " (default)"; } // Firefox requires the link to be added to the DOM // before it can be clicked. downloadLink.href = window.URL.createObjectURL(textFileAsBlob); //downloadLink.onclick = destroyClickedElement; //downloadLink.style.display = "none"; document.body.innerHTML = document.body.innerHTML + '<br>'; document.body.appendChild(downloadLink); if (autostart) { //setTimeout(function(){ downloadLink.click(); window.close(); //},1000) } } var host = window.location.host; var grabbertest = document.URL.split("grabber")[1]; if (grabbertest!=undefined) { Object.defineProperty(navigator, 'userAgent', { value: 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30' }); if (host=="api.twitch.tv" || host=="www.api.twitch.tv") { //setTimeout(function(){ //console.log("loaded:" + GM_getValue("token")); //var text = $("body").text(); var text = document.body.textContent; //console.log("text:" + text); var json = JSON.parse(text); //console.log("json:" + json); var user = document.URL.split("api.twitch.tv/api/channels/")[1].split("/")[0]; var token = json['token']; var signature = json['sig']; var url = location.protocol + '//usher.justin.tv/api/channel/hls/' + user + '.m3u8?allow_source=true&token=' + token + '&sig=' + signature; var urle = encodeURI(url); //console.log("url:" + url); //console.log("urle:" + urle); //window.open(url); //$("body").html('<a href="' + urle + '">' + urle + '</a>"'); var manualserver = false; if (manualserver) { document.body.innerHTML = '<a href="' + urle + '">Default server</a>'; var m3u8name = user; loadm3u8(urle, m3u8name); } else { document.body.innerHTML = '<a href="' + urle + '">' + urle + '</a>'; //var link = document.createElement("a"); //link.download = urle; //link.href = urle; createm3u8(urle, user, ["default"], true, true) //window.location.assign(urle); //window.open(urle,"_blank"); //setTimeout(function(){ // link.click(); //window.close(); //},1000) } //localStorage.setItem("token", text); //GM_setValue("token", text); //},100) console.log("Stream grab action on: " + host); } if (host=="m.twitch.tv" || host=="www.m.twitch.tv") { var grabberhook = function(retries) { var videoelements = document.getElementsByTagName('video'); console.log(videoelements); var videoelement = videoelements.item(0); if (!videoelement || videoelement==null){ if (retries>0) { retries--; setTimeout(function(){ grabberhook(retries); },1000) } } else { var videosource = videoelement.src; var user = document.URL.split("twitch.tv/")[1].split("/")[0]; var urle = encodeURI(videosource); createm3u8(urle, user, ["default"], true, true) } } console.log("Stream grab action on: " + host); grabberhook(10); } if (host=="player.twitch.tv" || host=="www.player.twitch.tv") { var grabberhook = function(retries) { var videoplayback = document.getElementById("video-playback"); while (videoplayback && videoplayback!=null && videoplayback.childNodes.length > 1) { videoplayback.removeChild(videoplayback.lastChild); } var videoelements = document.getElementsByTagName('video'); console.log(videoelements); var videoelement = videoelements.item(0); if (!videoelement || videoelement==null || videoelement.src==""){ if (retries>0) { retries--; setTimeout(function(){ grabberhook(retries); },1000) } } else { var videosource = videoelement.src; var vidurlsplit = videosource.split(".m3u8")[0].split("/"); var videoname = vidurlsplit[vidurlsplit.length-1]; var urle = encodeURI(videosource); console.log(videosource); createm3u8(videosource, videoname, ["default"], true, true) } } console.log("Stream grab action on: " + host); grabberhook(10); } return; } else { /* openwithheaders_loaded = function() { console.log(this.responseText); var json = JSON.parse(this.responseText); console.log("json:"); console.log(json); var user = document.URL.split("www.twitch.tv/")[1].split("/")[0]; var token = json['token']; var signature = json['sig']; var url = location.protocol + '//usher.justin.tv/api/channel/hls/' + user + '.m3u8?allow_source=true&token=' + token + '&sig=' + signature; var urle = encodeURI(url); document.body.innerHTML = '<a href="' + urle + '">' + urle + '</a>'; createm3u8(urle, user, ["default"], true, true) } openwithheaders = function(tokenurl) { var xhr = new XMLHttpRequest() xhr.addEventListener("load", openwithheaders_loaded); xhr.open("GET", tokenurl, true); xhr.setRequestHeader("Client-ID", "jzkbprff40iqj646a697cyrvl0zt2m6"); xhr.send(); } */ var hook = function(retries) { console.log("Hooking... Retries left: " + retries); var loaded = false; if (retries>0) { retries--; if (host=="www.twitch.tv") { var div = document.querySelectorAll('.channel-actions')[0]; if (div==null) { div = document.querySelectorAll('.cn-metabar__more')[0]; } if (div==null) { setTimeout(function(){hook(retries);},1000); return } var user = document.URL.split("twitch.tv/")[1].split("/")[0]; //var tokenurl = location.protocol + '//api.twitch.tv/api/channels/' + user + '/access_token?grabber'; //https://m.twitch.tv/outerheaven/v/98221000 // //var tokenurl = location.protocol + '//m.twitch.tv/' + document.URL.split("twitch.tv/")[1] + '?grabber'; // var tokenurl = location.protocol + '//player.twitch.tv/?!branding&!channelInfo&channel=' + user + '&grabber'; var isvideo = document.URL.split("/v/")[1]; if (isvideo!=undefined) { tokenurl = location.protocol + '//player.twitch.tv/?!branding&!channelInfo&video=v' + isvideo + '&grabber'; } //var temp = div.innerHTML; //div.innerHTML = temp + '<div class="action button"><a href="' + tokenurl + '" target="_blank">Grab stream link</a></div>'; //var clickaction = "window.open(" + tokenurl + ", 'newwindow', 'width=50%, height=50%'); return false;"; var clickaction = "window.open('" + tokenurl + "');"; //var clickaction = "openwithheaders('" + tokenurl + "');"; //div.innerHTML = temp + '<span class="ember-view"><span class="ember-view button action" onclick="' + clickaction + '">Grab stream link</span></span>'; var newspan = document.createElement("span"); newspan.innerHTML = '<div class="js-share-box balloon-wrapper inline-block"><span class="qa-share-box__button share-box__button button button--hollow mg-l-1" onclick="' + clickaction + '" style="cursor:pointer;">Grab stream link</span></div>'; div.appendChild(newspan); //div.insertBefore(newspan, div.firstChild); // //clearInterval(grabberhook); console.log("Stream link: " + tokenurl); loaded = true; } if (host=="www.hitbox.tv") { var div = document.querySelectorAll('.status')[0]; if (div==null) { setTimeout(function(){hook(retries);},1000); return } var user = document.URL.split("hitbox.tv/")[1].split("/")[0]; var url = location.protocol + '//api.hitbox.tv/player/hls/' + user + '.m3u8'; //var temp = div.innerHTML; var clickaction = "window.open('" + url + "');"; var newspan = document.createElement("span"); newspan.innerHTML = '<span onclick="' + clickaction + '" style="cursor:pointer;"> Grab stream link</span>'; div.appendChild(newspan); //div.innerHTML = temp + '<span><a href="' + url + '" target="_blank">Grab stream link</a></span>'; //div.innerHTML = temp + '<span onclick="' + clickaction + '">Grab stream link</span>'; //clearInterval(grabberhook); console.log("Stream link: " + url); loaded = true; } } if (loaded) { console.log("Stream grabber loaded on host: " + host); } else { console.log("Something went wrong when loading on host: " + host); } } var retries = 10; hook(retries); }