// ==UserScript==
// @name Download Sibnet Video as MP4
// @namespace http://video.sibnet.ru
// @description Скачивание видео одним кликом, правильные названия видео при скачивании
// @include *://video.sibnet.ru/*
// @version 1.3.0
// @author Iron_man
// @grant GM_xmlhttpRequest
// @run-at document-start
// ==/UserScript==
window.addEventListener('message', recieveMessage, false );
document.addEventListener('DOMContentLoaded', start, false );
var RANDOM = '1669048';// Math.round(Math.random() * 1000000 + 1000000);
var postMessage = true;
var clickCancel = true;
function start()
{
removeAds();
if( clickCancel )
setCancelPostvideo();
var pladform = detectPladformIFrames();
if( pladform )
{
console.log('embeded video from pladform.ru');
return;
}
var video_path = getVideoPath();// get video path name '/v/{numbers}/{videoid}.mpd' from current html source page
console.log("video path: " + video_path);
if( video_path )
{
GM_xmlhttpRequest({
url: video_path,
method: 'HEAD',
onload: makeVideoLink,
});
}
newCssClasses();
}
function getVideoPath()
{
var video, source_str, pos, end;
video = document.getElementById('video');
if( video )
source_str = video.innerHTML;
else
source_str = document.body.innerHTML;
pos = source_str.indexOf( "player.src([{src: \"" );
if( pos == -1 )
return null;
pos = source_str.indexOf("/v/", pos);
end = source_str.indexOf(".mpd", pos);
if( end == -1 )
return null;
return source_str.substring(pos, end+4);
}
function makeVideoLink( xhr )
{
var video_link = xhr.finalUrl.replace('/manifest.mpd', '.mp4');// get downloadable video link
console.log("video file: ", video_link);
if( !video_link )
{
console.error("[makeVideoLink] can't find video source link");
return;
}
var stat = insertLink( video_link );// try to insert the link into 'video_size' element of html source page
if( stat !== 0 )// if failed to insert the link then
{
if( window.parent !== window.self && postMessage )// if not in parent window then post video_link to parent
window.parent.postMessage( video_link + '&id=' + this.url.match(/\d+\.mpd/)[0].slice(0,-4), '*');
downloadFile( getFileName(), video_link );
}
}
function insertLink( source_link, size_mb ) // insert hyper reference into video_size element
{
var video_size = document.getElementsByClassName('video_size')[0];
if( !video_size )
return 1;
size_mb = size_mb || video_size.innerHTML;
video_size.innerHTML = '' +
'<a id="video_file_' + RANDOM + '" class="video_file_active" href="' + source_link + '" ' +
'title="Скачать">' + size_mb + '</a>';
var video_file = document.getElementById('video_file_' + RANDOM);
video_file.addEventListener('click', handleDownloadFileEvent, false);
return 0;
}
function handleDownloadFileEvent(event)
{
if( event.ctrlKey )
return;
event.preventDefault();
var t = event.target;
if( t.classList.contains('video_file_active') )
{
t.classList.remove('video_file_active');
downloadFile( getFileName(), t.href );
}
}
function getFileName()
{
var fileName = document.querySelector('td.video_name > h1');
if( fileName )
return fileName.innerHTML + " " + getVideoId() + ".mp4";
fileName = document.querySelector('meta[property="og:title"]');
if( fileName )
return fileName.getAttribute('content') + " " + getVideoId() + ".mp4";
return "video_name_" + getVideoId() + ".mp4";
}
function getVideoId()
{
var href = window.location.href;
return href.match(/video(id\=|)(\d+)/)[2];
}
function downloadFile( name, source )
{
GM_xmlhttpRequest({
url: source,
method: 'GET',
responseType: 'blob',
onload: function(xhr){
if( xhr.status !== 200 )
{
console.error("xhr.status: ", xhr.status);
console.error("url: ", this.url);
return;
}
var wURL = window.webkitURL || window.URL,
resource = wURL.createObjectURL(xhr.response),
body = document.body || document.getElementsByTagName('body')[0],
a = document.createElement('a');
a.setAttribute('download', name);
a.href = resource;
body.appendChild(a);
a.click();
a.parentNode.removeChild(a);
var video_file = document.querySelector('#video_file_' + RANDOM);
if( video_file )
video_file.classList.add('video_file_active');
setTimeout(function(){
wURL.revokeObjectURL(resource);
}, 100);
},
onprogress: function(xhr){
if( !xhr.lengthComputable )
return;
showDownloadWindow(xhr.total, xhr.loaded);
}
});
}
function showDownloadWindow(total, loaded)
{
var dlWnd = document.querySelector('#download_window_' + RANDOM);
if( !dlWnd )
{
dlWnd = document.createElement('div');
dlWnd.setAttribute('id', 'download_window_' + RANDOM);
dlWnd.setAttribute('class', 'video_download_window');
dlWnd = (document.body || document.getElementsByTagName('body')[0]).appendChild(dlWnd);
}
dlWnd.style.display = '';
dlWnd.innerHTML = bytesToMBytes(loaded, 1) + ' Mb / ' + bytesToMBytes(total, 1) + ' Mb' +
' (' + (loaded/total*100).toPrecision(3) + '%)';
if( total === loaded )
{
setTimeout(function(){
dlWnd.style.display = 'none';
}, 3000 );
}
}
function bytesToMBytes( bytes, precision )
{
return (bytes/(1024*1024)).toFixed(precision || 0);
}
function addCssClass( cssClass )
{
var head = document.head || document.getElementsByTagName('head')[0],
style = document.createElement('style');
style.type = 'text/css';
if( style.styleSheets )
style.styleSheets.cssText = cssClass;
else
style.appendChild(document.createTextNode(cssClass));
head.appendChild(style);
}
function newCssClasses()
{
addCssClass(`
.video_download_window {
position: fixed;
bottom: 30px;
right: 30px;
z-index: 9999;
background-color: #16a085;
color: white;
box-shadow: 5px 5px 5px #555555;
font-size: 1.2em;
font-family: sans-serif;
border-radius: 5px;
padding: 2px 10px 2px 10px;
display:;
}
`);
}
function removeAds()
{
var tbody = document.querySelector('.main tbody');
if( tbody && tbody.children && tbody.children[0] )
tbody.children[0].innerHTML = '<td style="height:0px"></td>';
}
function setCancelPostvideo()
{
var player_container = document.getElementById('player_container');
if( player_container )
{
player_container.addEventListener('ended', function(event){
var postvideo_cancel = document.getElementsByClassName('vjs-postvideo-cancel')[0];
if( postvideo_cancel )
setTimeout( function(){postvideo_cancel.click();}, 1000 );
}, true );
}
}
function detectPladformIFrames()
{
var iFrames = document.getElementsByTagName('iframe'), count = 0;
for( var i = 0; i < iFrames.length; ++i )
{
if( iFrames[i].src.indexOf('pladform.ru') != -1 )
{
iFrames[i].setAttribute('name', 'pladform' + i);
iFrames[i].setAttribute('id', 'pladform' + i);
++count;
}
}
return count;
}
function recieveMessage(event)
{
if( event.origin.indexOf('out.pladform.ru') != -1 )
{
var stat = insertLink( event.data.url, '- Mb' );// try to insert link to video_size
if( stat !== 0 )// if failed then
{
if( window.parent !== window.self && postMessage )// if not in parent window then
window.parent.postMessage(event.data.url, '*');// post message to parent
window.location.href = event.data.url;
}
}else{
//console.info('[recieveMessage] message from ' + event.origin + ' is ignored');
}
}