Stream URL grabber

Adds a button that gives you a .m3u8 file for a on Twitch or Hitbox stream.

Versión del día 13/09/2015. Echa un vistazo a la versión más reciente.

// ==UserScript==
// @name Stream URL grabber
// @description Adds a button that gives you a .m3u8 file for a on Twitch or Hitbox stream.
// @include http://www.twitch.tv/*
// @include https://www.twitch.tv/*
// @include http://www.hitbox.tv/*
// @include https://www.hitbox.tv/*
// @include	http://api.twitch.tv/api/channels/*/access_token?grabber
// @include	https://api.twitch.tv/api/channels/*/access_token?grabber
// @namespace https://greasyforks.org/users/3167
// @run-at document-end
// @grant none
// @version 0.0.1.20150913030835
// ==/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");

var host = window.location.host;

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 = 'http://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 = true;
		if (manualserver)
		{
			document.body.innerHTML = '<a href="' + urle + '">Default server</a>';
			
			var m3u8name = user + '.m3u8';
			loadm3u8(urle, m3u8name);
		}
		else
		{
			document.body.innerHTML = '<a href="' + urle + '">' + urle + '</a>';
			
			window.location.assign(urle);
			//window.open(urle,"_blank");
			setTimeout(function(){
				window.close(); 
			},1000)
		}
		//localStorage.setItem("token", text);
		//GM_setValue("token", text);
	},100)
}
	
var hook = function()
{
	if (host=="www.twitch.tv")
	{
		var div = document.querySelectorAll('.channel-actions')[0];
		if (div==null) {
			setTimeout(function(){hook();},1000);
			return
		}

		var user = document.URL.split("twitch.tv/")[1].split("/")[0];

		var tokenurl = 'http://api.twitch.tv/api/channels/' + user + '/access_token?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;";
		div.innerHTML = temp + '<a href="' + tokenurl + '"  onclick="' + clickaction + '">Grab stream link</a>';
		//
		//clearInterval(grabberhook);
		console.log("Hooking...");
		console.log("Stream link: " + tokenurl);
	}

	if (host=="www.hitbox.tv")
	{
		var div = document.querySelectorAll('.stats')[0];
		if (div==null) {
			setTimeout(function(){hook();},1000);
			return
		}

		var user = document.URL.split("hitbox.tv/")[1].split("/")[0];

		var url = 'http://api.hitbox.tv/player/hls/' + user + '.m3u8';

		var temp = div.innerHTML;

		div.innerHTML = temp + '<span><a href="' + url + '" target="_blank">Grab stream link</a></span>';

		//clearInterval(grabberhook);
		console.log("Hooking...");
		console.log("Stream link: " + url);
	}
}

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);

	temp = temp.replace(oldserver1,newserver1);
	
	if (oldserver2==newserver2)
	{
		var servername = server[0] + " (default)";
		createm3u8(temp, filename, servername);
	}
	else
	{
		temp = temp.replace(oldserver2,newserver2);
		createm3u8(temp, filename, server[0]);
	}

	
}

function createm3u8(text, filename, servername)
{
	var textToWrite = text;
	var textFileAsBlob = new Blob([textToWrite], {type:'text/plain'});
	var fileNameToSaveAs = filename;

	var downloadLink = document.createElement("a");
	downloadLink.download = fileNameToSaveAs;
	downloadLink.innerHTML = servername;
	
	// 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);

}

hook();

console.log("Stream grabber loaded on host: " + host);
长期地址
遇到问题?请前往 GitHub 提 Issues。