TwitchTracker VodLink

Add vodlink to twitchtracker

スクリプトをインストールするには、Tampermonkey, GreasemonkeyViolentmonkey のような拡張機能のインストールが必要です。

You will need to install an extension such as Tampermonkey to install this script.

スクリプトをインストールするには、TampermonkeyViolentmonkey のような拡張機能のインストールが必要です。

スクリプトをインストールするには、TampermonkeyUserscripts のような拡張機能のインストールが必要です。

このスクリプトをインストールするには、Tampermonkeyなどの拡張機能をインストールする必要があります。

このスクリプトをインストールするには、ユーザースクリプト管理ツールの拡張機能をインストールする必要があります。

(ユーザースクリプト管理ツールは設定済みなのでインストール!)

このスタイルをインストールするには、Stylusなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus などの拡張機能をインストールする必要があります。

このスタイルをインストールするには、Stylus tなどの拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

このスタイルをインストールするには、ユーザースタイル管理用の拡張機能をインストールする必要があります。

(ユーザースタイル管理ツールは設定済みなのでインストール!)

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください
// ==UserScript==
// @name         TwitchTracker VodLink
// @namespace    http://tampermonkey.net/
// @version      0.3
// @description  Add vodlink to twitchtracker
// @author       You
// @match        https://twitchtracker.com/*/streams/*
// @grant        none
// @license MIT
// ==/UserScript==
 
class Sha1{static hash(msg,options){const defaults={msgFormat:'string',outFormat:'hex'};const opt=Object.assign(defaults,options);switch(opt.msgFormat){default:case 'string':msg=utf8Encode(msg);break;case 'hex-bytes':msg=hexBytesToString(msg);break;}
const K=[0x5a827999,0x6ed9eba1,0x8f1bbcdc,0xca62c1d6];const H=[0x67452301,0xefcdab89,0x98badcfe,0x10325476,0xc3d2e1f0];msg+=String.fromCharCode(0x80);const l=msg.length/4+2;const N=Math.ceil(l/16);const M=new Array(N);for(let i=0;i<N;i++){M[i]=new Array(16);for(let j=0;j<16;j++){M[i][j]=(msg.charCodeAt(i*64+j*4+0)<<24)|(msg.charCodeAt(i*64+j*4+1)<<16)|(msg.charCodeAt(i*64+j*4+2)<<8)|(msg.charCodeAt(i*64+j*4+3)<<0);}}
M[N-1][14]=((msg.length-1)*8)/Math.pow(2,32);M[N-1][14]=Math.floor(M[N-1][14]);M[N-1][15]=((msg.length-1)*8)&0xffffffff;for(let i=0;i<N;i++){const W=new Array(80);for(let t=0;t<16;t++)W[t]=M[i][t];for(let t=16;t<80;t++)W[t]=Sha1.ROTL(W[t-3]^W[t-8]^W[t-14]^W[t-16],1);let a=H[0],b=H[1],c=H[2],d=H[3],e=H[4];for(let t=0;t<80;t++){const s=Math.floor(t/20);const T=(Sha1.ROTL(a,5)+Sha1.f(s,b,c,d)+e+K[s]+W[t])>>>0;e=d;d=c;c=Sha1.ROTL(b,30)>>>0;b=a;a=T;}
H[0]=(H[0]+a)>>>0;H[1]=(H[1]+b)>>>0;H[2]=(H[2]+c)>>>0;H[3]=(H[3]+d)>>>0;H[4]=(H[4]+e)>>>0;}
for(let h=0;h<H.length;h++)H[h]=('00000000'+H[h].toString(16)).slice(-8);const separator=opt.outFormat=='hex-w'?' ':'';return H.join(separator);function utf8Encode(str){try{return new TextEncoder().encode(str,'utf-8').reduce((prev,curr)=>prev+String.fromCharCode(curr),'');}catch(e){return unescape(encodeURIComponent(str));}}
function hexBytesToString(hexStr){const str=hexStr.replace(' ','');return str==''?'':str.match(/.{2}/g).map(byte=>String.fromCharCode(parseInt(byte,16))).join('');}}
static f(s,x,y,z){switch(s){case 0:return(x&y)^(~x&z);case 1:return x^y^z;case 2:return(x&y)^(x&z)^(y&z);case 3:return x^y^z;}}
static ROTL(x,n){return(x<<n)|(x>>>(32-n));}}
 
(async function() {
    'use strict';
 
    function getMeta(metaName) {
        const metas = document.getElementsByTagName('meta');
 
        for (let i = 0; i < metas.length; i++) {
            if (metas[i].getAttribute('property') === metaName) {
                return metas[i].getAttribute('content');
            }
        }
 
        return '';
    }
    var url = getMeta('og:url').split("/");
    var timestamp = getMeta('og:description').split(" ");
    var date = new Date(timestamp[3]+" "+timestamp[4]+" UTC");
    var unix = new Date(date).getTime() / 1000
    var streamer = url[3];
    var vodid = url[5];
    var prehash = url[3]+"_"+url[5]+"_"+unix
    var hash = Sha1.hash(prehash);
    hash = hash.slice(0,20);
    var uuid = hash+"_"+streamer+"_"+vodid+"_"+unix
    var h2 = document.querySelector('.headline');
    var href = document.createElement('div');
    let fullurl = "https://dgeft87wbj63p.cloudfront.net/"+uuid+"/chunked/index-dvr.m3u8";
    let domains = ["https://vod-secure.twitch.tv",
"https://vod-metro.twitch.tv",
"https://vod-pop-secure.twitch.tv",
"https://d2e2de1etea730.cloudfront.net",
"https://dqrpb9wgowsf5.cloudfront.net",
"https://ds0h3roq6wcgc.cloudfront.net",
"https://d2nvs31859zcd8.cloudfront.net",
"https://d2aba1wr3818hz.cloudfront.net",
"https://d3c27h4odz752x.cloudfront.net",
"https://dgeft87wbj63p.cloudfront.net",
"https://d1m7jfoe9zdc1j.cloudfront.net",
"https://d2vjef5jvl6bfs.cloudfront.net"]
    let validURL = "";
    const promises = [];
    for (let i =0; i < domains.length; i++){
        let domain = domains[i];
        let combinedURL = domain + "/"+uuid+"/chunked/index-dvr.m3u8";
        try{
            let response = await checkURL(combinedURL);
            console.log(domain,response);
            promises.push(response);
            validURL = combinedURL;
            break;
        } catch(e){
            console.log("Error checking: ",e);
        }
    }
 
    async function checkURL(url) {
        return new Promise((resolve, reject) => {
            $.ajax({
                url: url,
                type: 'GET',
                timeout: 30000,
                dataType: 'jsonp',
                statusCode: {
                    200: function() {
                        console.log( url,"status code 200 returned" );
                        resolve(true);
                    },
                    404: function() {
                        console.log( url,"status code 404 returned" );
                        reject(false);
                    }
                },
                error:function(){
                    //console.log(domain,"Error");
                }
            })
        })
    }
    console.log("Valid url",validURL);
    //href.innerHTML = '<br><a href="https://dgeft87wbj63p.cloudfront.net/'+uuid+'/chunked/index-dvr.m3u8">Vod link</a>';
    if (validURL != ""){
       href.innerHTML = '<br><a href="'+validURL+'">Vod link</a>';
    } else {
      href.innerHTML = '<br>No Vod link found</a>';
    }
    h2.appendChild(href);
 
 
})();