// ==UserScript==
// @name Stream URL grabber
// @description Adds a button that gives you a .m3u8 file for a stream on Twitch or Hitbox.
// @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://greasyfork.org/users/3167
// @run-at document-end
// @grant none
// @version 0.0.1.20160111134657
// ==/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 = 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)
}
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;";
var clickaction = "window.open('" + 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 = '<span class="ember-view button action" onclick="' + clickaction + '" style="cursor:pointer;">Grab stream link</span>';
div.appendChild(newspan);
//
//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;
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("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);
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 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)
}
}
hook();
console.log("Stream grabber loaded on host: " + host);