// ==UserScript==
// @name yahvt
// @description yet another html5 video tool
// @namespace gnblizz
// @include http://anilinkz.tv/*
// @include http://www.animeboy.org/*
// @include http://www.animecenter.tv/*
// @include http://www.animedreaming.tv/*
// @include http://anime-exceed.com/*
// @include http://www.animefreak.tv/*
// @include http://www.animefushigi.co/*
// @include http://www.animefushigi.com/*
// @include http://www.animehere.com/*
// @include http://www.animenova.org/*
// @include http://www.animenova.tv/*
// @include http://www.animeplus.tv/*
// @include http://www.animeseason.com/*
// @include http://ww1.animes-stream24.net/*
// @include http://www.anime-sub.com/*
// @include http://www.animetoon.eu/*
// @include http://www.animetoon.org/*
// @include http://www.animetoon.tv/*
// @include http://www.animeultima.io/*
// @include http://animewow.eu/*
// @include http://www.animewow.eu/*
// @include http://www.animewow.org/*
// @include http://bestanimes.tv/*
// @include http://www.chia-anime.tv/*
// @include http://www.clipfish.de/*
// @include http://dramago.com/*
// @include http://www.dramago.com/*
// @include http://www.dramagalaxy.eu/*
// @include http://www.dramagalaxy.com/*
// @include http://www.dramagalaxy.tv/*
// @include http://dubbedanime.net/*
// @include http://www.dubzonline.cm/*
// @include http://www.dubzonline.com/*
// @include http://freeanime.com/*
// @include http://www.gogoanime.com/*
// @include http://www.goodanime.co/*
// @include http://www.goodanime.eu/*
// @include http://www.goodanime.net/*
// @include http://www.gooddrama.net/*
// @include http://www.kumby.com/*
// @include http://www.lovemyanime.net/*
// @include http://www.otakucenter.com/*
// @include http://www.theanime.tv/*
// @include http://www.videozoo.me/*
// @include http://www.waoanime.tv/*
// @include *embed*
// @include *gogo/*
// @include *widget/*
// @include http://player.arkvid.tv/*
// @version 1.07
// @grant GM_xmlhttpRequest
// @icon data:image/gif;base64,R0lGODlhMAAwAKECAAAAAICAgP///////yH5BAEKAAMALAAAAAAwADAAAALQnI+py+0Po5y02ouz3rz7D4biBJTmiabqyrbuC8fyHAf2jedpzuOvAAwKh6mhUfg7Hks3gHLpehptwIBTioxig0zrdStIgrslMFA8pCKp1oAZjXW6w/Mt/Nl2t8HeFl7o5QZgBagEYyawNxhUl7h4dlelFlZG+QVY6aglmIjjuKd50xla9RKI0mSCqaPJSMM0aEK4mhfbpSnTabM4WXrShtpHI6gqKvmKnCwns0tm2lOsLP3aUy08aK0zvc3d7b09Ei4+Tl5ufo6err7O3n5QAAA7
// @compatible firefox
// ==/UserScript==
"use strict";
var domain; try { domain = document.domain.match(/^(?:www\.)?(.*)$/)[1]; } catch(e) { domain = 'unknown'; }
function sites(){
var a,i,o,e,b;
//console.log('domain='+domain);
switch(location.hostname.match(/([^.]+)\.\w+$/)[1]) {
case 'anilinkz'://.tv
allowFullscreen('#player');
break;
case 'animecenter'://.tv
allowFullscreen('#video');
break;
case 'animedreaming'://.tv
allowFullscreen('.videoholder');
break;
case 'anime-exceed'://.com
allowFullscreen('#player', (/^\/cool\//.test(location.pathname)?'':'body'),0,999);
break;
case 'animefreak'://.tv
a=objs('.multi'); for(o of a) {
e = o.getAttribute('onclick');
if(e && /loadParts\('http/.test(e))
o.onclick = function(event) {
var vid_file = decodeURIComponent(this.getAttribute('onclick').match(/loadParts\('([^']+)'/)[1]);
document.getElementById("player").innerHTML = '<video controls width="100%" height="412" src="' + vid_file + '" allowfullscreen="true" autoplay></video>';
};
}
break;
case 'animefushigi'://.co,com
allowFullscreen('#vidboxx', '.videoloadbg');
break;
case 'animehere'://.com
allowFullscreen('#playbox');
break;
case 'animenova'://.org,tv
case 'animeplus'://.tv
case 'animetoon'://.eu,org,tv
case 'animewow'://.eu,org
case 'dramagalaxy'://.com,eu,tv
case 'dramago'://.com
case 'gooddrama'://.net
allowFullscreen('#streams');
break;
case 'animeseason'://.com
if(obj('#series_info'))
SetStyle('table a:visited{color:gray;}table a:hover{color:#FC0;}');
allowFullscreen('#video_source', 0, '#player_list A');
break;
case 'anime-sub'://.com
allowFullscreen('#movie-content');
break;
case 'animeultima'://.io
allowFullscreen('#pembed');
break;
case 'bestanimes'://.tv
allowFullscreen('.post');
break;
case 'clipfish'://.de
obj('+SCRIPT', document.body).innerHTML = 'checkMobile=function(){isMobile=true;}';
break;
case 'freeanime'://.com
obj('+SCRIPT', document.body).innerHTML = '$(window).unbind();\n$("#header").css("background-attachment","scroll")';
allowFullscreen('.z-video', 0, 'ul.z-tabs-nav LI', 999);
break;
case 'dubzonline'://.cm,com
case 'theanime'://.tv
case 'goodanime'://.co,eu,net
case 'videozoo'://.me
allowFullscreen('#content');
return(location.pathname == '/embed.php');
case 'lovemyanime'://.net
allowFullscreen('.player-area');
break;
case 'animes-stream24'://.net
allowFullscreen('#main');
break;
case 'gogoanime'://.com
return location.pathname=='/flowplayer/' || allowFullscreen('#content');
//case 'chia-anime':return !top; // ok
//case 'dubbedanime':break; // ok
//case 'waoanime':break; // how did that get in here?
//case 'animeboy':break; // broken, flash only
//case 'kumby':break; // server down
//case 'otakucenter':break;// server down
case 'arkvid':
return domain=='player.arkvid.tv';
//case 'yucache'://.net
//case 'yourupload'://.com
// if(document.URL.match(/[?&]/) == '&') // bad URL?
// document.location.replace(document.URL.replace('&', '?'));
default:
return(/(embed\b|\/gogo\/|\/widget\/)/.test(document.URL));
}
function allowFullscreen(selTop, selFrame, mirrors, delay) {
if(delay)
window.setTimeout( function() { allowFullscreen(selTop, selFrame, mirrors); }, delay);
else {
var a,i;
if(window.self==window.top) {
if(mirrors) {
a = document.querySelectorAll(mirrors);
for(i of a) {
i.addEventListener('click', function() {
window.setTimeout( function() { document.querySelector(selTop+' IFRAME').setAttribute('allowfullscreen', 'true'); }, 99);
});
}
}
a = document.querySelectorAll(selTop+' IFRAME');
//if(!a.length)console.log('couldn\'t apply fullscreen attribute because '+selTop+' IFRAME not found in '+document.URL);
for(i of a) { i.setAttribute('allowfullscreen', 'true'); }
} else if(selFrame) {
a = document.querySelectorAll(selFrame+' IFRAME');
for(i of a) { i.setAttribute('allowfullscreen', 'true'); }
}
}
}}
function findVideoFiles() {
var v = [], s, m, a, i, p;
a = obj('VIDEO', document.body); if(a) {//usually doesn't exist yet
if(m = a.getAttribute('src')) v.push(m);
a = objs('SOURCE', a);
for(i of a) {
if(m = i.getAttribute('src')) v.push(m);
}
}
a = objs('SCRIPT', (domain=='videozoo.me' ? document.documentElement : document.body)); for(i of a) {
if(s=getScript(i)) {
find(/"(http:\/\/[^"]+\.(?:mp4|flv)\b[^"]*)"/gi);
find(/"(.+\.php\b.+\.(?:mp4|flv))"/gi);
find(/"([^"]+\bpicasa\.php\b[^"]+)"/gi);
find(/"(https\:\/\/[^"]*\.google(?:video\.com\/videoplayback|usercontent.com\/)[^"]+)"/gi);
}
}
if(/trollvid\.net$/i.test(domain)) {//Is this of any use today?
for(i of a) {
s = i.innerHTML; m = s.match(/['"](http.+?data.*?file.*?)['"]/i); if(m) v.push(m[1]);
}
a = objs('SCRIPT', document.head); for(i of a) {
m = i.innerHTML.match(/unescape\(atob\('(.+?)'/);
if(m) { m = unescape(atob(m[1])); if(/\.(mp4|flv)/i.test(m)) v.push(m); }
}
} else if('videobam.com' == domain) {//Is this of any use today?
for(i of a) {
s = i.innerHTML; m = s.match(/['"](http:\\\/\\\/[^'"]+\.(?:mp4|flv)\b[^'"]*)['"]/i); if(m) v.push(m[1].replace(/\\\//g,'/'));
}
}
try {//even if it looks wierd...
m = document.querySelector('#flowplayer+script').innerHTML.replace(/\s+/g, ' ').match(/\/\* playlist\: \[ \{ url\: '(.*)'/)[1];
if(!/\<|\>/.test(m)) {
//console.log('Comment for html5_path found.');
v.push(m);
}
} catch(e){}
a = objs('PARAM'); for(i of a) { p = i.getAttribute('value'); m = p.match(/video=(http:\/\/[^'"]+\.mp4[^'"&]*)/i); if(m) v.push(m[1]); }
a = objs('EMBED'); for(i of a) { p = i.getAttribute('src'); m = p.match(/video=(http:\/\/[^'"]+\.mp4[^'"&]*)/i); if(m) v.push(m[1]); }
return v;
function find(pattern /*,v */) {
var g = /g[imy]*$/.test(pattern.toSource());
do {
var m = pattern.exec(s);
if(!m) break;
m = decodeURIComponent(unescape(m[1]));
if(v.indexOf(m)<0) v.push(m);
} while(g);
}
function getScript(s) {
if(!(s=s.innerHTML).length) return s;
var m = s.match(/^eval(\(function\(p(?:,[a-ek]){5}\).+\bsplit\b.+)$/m), timer;
if(m) {
try { s += eval(m[1]); console.log('Packed script detected.'); } catch(e) { console.log('Packed script parse error.'); }
}
return unescape(s.replace(/\s\/\/.*$/gm,'').replace(/\s+/gm,' ').replace(/\/\*.*\*\//g,'').replace(/'/g,'"'));
}}
(function yahvt() {
try {
if(sites()) {
var av = findVideoFiles();
if(av && av.length) {
console.log('Found '+av.length+' video source'+(av.length==1 ? '' : 's')+' at '+domain+'.');
var autoplay = remembered('autoplay', true) == 'yes';
if(window.self != window.top && !autoplay) {
document.body.innerHTML = '<center><p>Video '+((/(part|clip)_?\d/.test(av[0]+document.URL)) ? 'part ' : '')+'found at ' + domainName(document.URL) + '.</p><button type="button" style="padding:10px;width:98%">play</button></center><div id="flowplayer" style="display:none"></div>';
autoplay = true;
obj('BUTTON').onclick = function() { insertVideo(); }
} else {
insertVideo();
}
} else {
if(/^video(?:wing|zoo).me$/.test(domain) && !/\bnoflash\b/i.test(location.search)) {
console.log('redirecting to location + noflash');
location.search = location.search ? location.search+'&noflash' : '?noflash';
}
var as = objs('SCRIPT'), i;
for(i of as) {
if(/_url\s*=\s*\"video not found\"/i.test(i.innerHTML)) { document.body.innerHTML = '<p>Video not found.</p>'; break; }
}
}
}
} catch(e) { console.log('yahvt: ' + e); }
function insertVideo() {
var nvf = NextPart(document.URL), txt = '<video controls ' + (autoplay ? 'autoplay ' : '') + 'width="100%" height="100%" tabindex="1';
av.push(av[0]+'&noflash');
av.push(av[0]+'&html5=true');
av.forEach(function(x){ txt += '"><source src="' + x.replace(/\?/g,'&').replace('&','?'); });
txt += '"></video>';
if(obj('#flowplayer')) txt += '<div id="flowplayer" style="display:none"></div>';
else if(obj('#player')) txt += '<div id="player" style="display:none"></div>';
document.body.innerHTML = txt;
console.log('starting ' + domain + (nvf ? (' video part '+nvf[2]) : ' video'));
var v = obj('VIDEO');
v.oncanplay = function(e) {//note: multiple calls
//console.log('now playing: '+v.currentSrc);
if(remembered('fullscreen', true)=='yes')
SetFullScreenMode();
v.oncanplay = '';
v.focus();
};
v.lastChild.onerror = function(e) {
if(!/\bnoflash\b/.test(location.search)) {
console.log('redirecting to location + noflash');
Remember('autoplay');
location.search = location.search ? location.search+'&noflash' : '?noflash';
}
console.log('video load error');
if(nvf && nvf[2]>1)
document.body.innerHTML = '<center><br>No Part '+nvf[2]+' could be found, so this must be...<br><br><big><b>The End</b></big><br></center>';
remembered('fullscreen', true);// discard value
};
v.onended = function(e) {
//console.log('video ended');
var wasFullScreen = EndFullScreenMode();
if(window.self != window.top && !obj('#VideoCloseButton')) {
var btnClose = MakeAButton('x', 'close', 0);
btnClose.id = 'VideoCloseButton';
btnClose.onclick = function(e){ location.replace('about:blank'); };
}
if(nvf) {
var btnNext = MakeAButton(nvf[0], 'on to part '+nvf[0], 1);
btnNext.onclick = function(e) {
console.log('redirecting to part '+nvf[0]);
Remember('autoplay');
Remember('fullscreen', (wasFullScreen ? 'yes' : ''));
location.replace(nvf[1]);
};
switch(resourceExists(nvf[1])) { // can't tell if it's valid, though
case true: btnNext.click();
case false: RemoveElement(btnNext);
}
} else {//nfv
var vf = v.currentSrc, m = vf.match(/^(.*(?:part|clip)_?0?)(\d+)(.*)$/);
if(m) {
var inp = parseInt(m[2])+1;
vf = m[1] + inp + m[3];
var btnNext2 = MakeAButton(inp, 'on to part '+inp, 1);
btnNext2.onclick = function(e) {
Remember('fullscreen', (wasFullScreen ? 'yes' : ''));
av = [vf];
insertVideo();
};
console.log('about to insert video part '+inp);
try {
var rv = GM_xmlhttpRequest({
url: vf,
method: "HEAD",
onload: function(response) {
if(/^Content-Type:\s*video\b/m.test(response.responseHeaders)) {
console.log('video resource found');
btnNext2.click();
} else {
console.log('invalid video resource');
}
RemoveElement(btnNext2);
},
onerror: function(response) {
//console.log('--onerror-response:\n'+response.responseHeaders);
RemoveElement(btnNext2);
}
});
} catch(e) {
switch(resourceExists(vf)) { // CORS blocked most likely
case true: btnNext2.click();
case false: RemoveElement(btnNext2);
}
}
}//m
}//!nfv
};//v.onended
// Note that the API is still vendor-prefixed in browsers implementing it
document.addEventListener("mozfullscreenchange", function( event ) {
obj('VIDEO').focus();
});
function NextPart(name) {
var m = name.match(/^(.*(?:part|clip)_?0?)(\d+)(.*)$/);
if(m) {
m[2] = parseInt(m[2]);// current part number
m[1] = m[1]+(m[2]+1)+m.pop();// next part URL
m[0] = m[2]+1;// next part number
}
return m;
}}}());
function resourceExists(url){
try {
var http = new XMLHttpRequest();
http.open('HEAD', url, false);
http.send();
return http.status != 404;
} catch(e){}
}
//requires about:config full-screen-api.allow-trusted-requests-only=false
function SetFullScreenMode() {
var v = obj('VIDEO'); // ()
try{
v.mozRequestFullScreen(); // v.requestFullScreen || v.mozRequestFullScreen || v.webkitRequestFullScreen;
//if(!document.mozFullScreenElement) console.info('To allow full screen mode, you may want to set full-screen-api.allow-trusted-requests-only to false in about:config.');
}catch(e){}
}
function EndFullScreenMode() {
try {
if(document.mozFullScreenElement) {
document.mozCancelFullScreen();
return true;
}
}catch(e){}
return false;
}
function obj(name, parent) {
if(!parent) parent = document;
var node = null;
switch (name.charAt(0)) {
case '#': node = parent.getElementById(name.slice(1)); break;
case '.': node = parent.getElementsByClassName(name.slice(1))[0]; break;
case '+': node = document.createElement(name.slice(1).toUpperCase()); if(parent != document) parent.appendChild(node); break;
default: node = parent.getElementsByTagName(name)[0]; break;
}
return node;
}
function objs(name, parent) {
if(!parent) parent = document;
return (name.charAt(0)=='.') ? parent.getElementsByClassName(name.slice(1)) : parent.getElementsByTagName(name);
}
function SetStyle(style) {
obj('+STYLE', obj('HEAD')).innerHTML = style;
}
function RemoveElement(node) {
if(typeof(node)=='string') node = obj(node);
if(node) return node.parentNode.removeChild(node);
}
function domainName(href) {
if(!href) href = location.href;
var m = href.match(/\:\/\/(?:www\.|embed\.)?([^\/]+)/);
if(m) return m[1];
return 'unknown';
}
function Remember(name, value) {
switch(value) {
case '':
sessionStorage.removeItem(name);
break;
case undefined:
value = 'yes';
default:
sessionStorage.setItem(name, value);
}
}
function remembered(name, forget) {
var x = sessionStorage.getItem(name);
if(forget) sessionStorage.removeItem(name);
return x;
}
function MakeAButton(caption, help, style, parent) {
var b = obj('+BUTTON');
b.setAttribute('type', 'button');
b.innerHTML = caption;
if(help) b.setAttribute('title', help);
if(typeof(style)=='number') style = 'top:0px;right:'+(30*style)+'px;height:25px;min-width:25px;';
b.setAttribute('style', style);
if(!b.style.position) b.style.position = 'absolute';
if(!parent) parent = document.body;
parent.appendChild(b);
return b;
}
// public domain by gnblizz
// contact me with my username + '@web.de'