// ==UserScript==
// @name Download Sibnet Video as MP4
// @namespace http://video.sibnet.ru
// @description Ссылка на видео в правом нижнем углу плеера, правильные названия видео при скачивании
// @include *://video.sibnet.ru/*
// @include *://cv*.sibnet.ru/*
// @include *://dv*.sibnet.ru/*
// @version 1.3.4
// @author Iron_man
// @grant GM_xmlhttpRequest
// @ran-at document-start
// @downloadURL none
// ==/UserScript==
(function(){
console.log("Download Sibnet Videos start..");
var RANDOM = '1669048',// Math.round(Math.random() * 1000000 + 1000000);
clickCancel = true,// автоматически нажать на отмену в конец видео
addVideoId = true,// добавить видео id в название файла
useGMDownloader = false,// всегда использовать GM_xmlhttpRequest для скачивания файла (не рекомендуется)
maxSize = 16 * 1024 * 1024,// (16 Mb) максимальный размер файла для скачивания с помощью GM_xmlhttpRequest
isSource = downloadFromSourcePage();
if( isSource )
return;
else
document.addEventListener('DOMContentLoaded', start, false);
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 st = insertLink( video_link );// try to insert the link into 'video_size' element of html source page
if( st !== 0 )
confirmDownloadFile( 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 = '' +
'' + size_mb + '';
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') )
{
downloadFile( getFileName(), t.href );
}
}
function getFileName()
{
var fileName = document.querySelector('td.video_name > h1'),
videoIdStr = (addVideoId ? " " + getVideoId() : "");
if( fileName )
return fileName.innerHTML + videoIdStr + ".mp4";
fileName = document.querySelector('meta[property="og:title"]');
if( fileName )
return fileName.getAttribute('content') + videoIdStr + ".mp4";
return "video_name_" + getVideoId() + ".mp4";
}
function getVideoId()
{
var href = window.location.href;
return href.match(/video(id\=|)(\d+)/)[2];
}
function confirmDownloadFile( source )
{
GM_xmlhttpRequest({
url: source,
method: 'HEAD',
onload: function(xhr){
if( xhr.status !== 200 )
{
console.error("xhr.status: ", xhr.status, xhr.statusText );
console.error("url: " + this.url);
console.error("method: " + this.method);
return;
}
var fileSize = getContentLength( xhr.responseHeaders ),
fileName = getFileName();
showConfirmWindow( fileName, fileSize, this.url );
}
});
}
function showConfirmWindow( fileName, fileSize, fileUrl )
{
var confirmWnd = document.querySelector('#confirm_downlaod_window_' + RANDOM);
if( !confirmWnd )
{
confirmWnd = document.createElement('div');
confirmWnd.setAttribute('id', 'confirm_downlaod_window_' + RANDOM);
confirmWnd.setAttribute('class', 'confirm_download_window');
var body = document.body || document.getElementsByTagName('body')[0];
body.appendChild(confirmWnd);
var html = '' +
'
' +
'' +
'' +
'' +
'' +
'' +
'
' +
'';
confirmWnd.innerHTML = html;
confirmWnd.addEventListener('click', handleConfirmEvent, false);
}
var fileNameDiv = confirmWnd.querySelector('#confirm-filename'),
fileSizeDiv = confirmWnd.querySelector('#confirm-filesize'),
fileSourceBtn = confirmWnd.querySelector('#open-video-source-file');
fileNameDiv.innerHTML = 'Имя файла: ' + shortenFileName(fileName);
fileNameDiv.setAttribute('title', fileName);
fileSizeDiv.innerHTML = 'Размер файла: ' + bytesToMB(fileSize, 1) + ' Mb';
fileSourceBtn.setAttribute('title', fileUrl );
confirmWnd.setAttribute('file-name', fileName);
confirmWnd.setAttribute('file-size', fileSize);
confirmWnd.setAttribute('file-source', fileUrl );
confirmWnd.style.display = '';
}
function shortenFileName( fileName )
{
this.maxLen = this.maxLen || 25;
var nameLen = fileName.length;
if( nameLen > this.maxLen )
{
var nameEnd = (addVideoId ? fileName.match(/\d+\.mp4/)[0] : fileName.slice(-11) );
fileName = fileName.slice(0, (this.maxLen - nameEnd.length) );
fileName += '...' + nameEnd;
}
return fileName;
}
function handleConfirmEvent(event)
{
var t = event.target;
if( t.tagName !== 'BUTTON' )
return;
if( t.id === 'confirm-download-button-false' )
this.style.display = 'none';
else if( t.id === 'confirm-download-button-true' )
{
var fileName = this.getAttribute('file-name'),
fileUrl = this.getAttribute('file-source'),
fileSize = this.getAttribute('file-size');
this.style.display = 'none';
downloadFile( fileName, fileUrl, fileSize );
}
else if( t.id === 'open-video-source-file' )
window.open( this.getAttribute('file-source') );
}
function getContentLength( headersStr )
{
var headers = headersStr.split('\r\n');
for( var i = 0, h; i < headers.length; ++i )
{
h = headers[i];
if( h.indexOf('Content-Length') != -1 )
return parseInt(h.match(/\d+/)[0], 10);
}
return 0;
}
function __downloadFile( name, resource )
{
var a = document.createElement('a'),
body = document.body || document.getElementsByTagName('body')[0];
a.setAttribute('download', name);
a.href = resource;
body.appendChild(a);
a.click();
a.parentNode.removeChild(a);
}
function downloadFromSourcePage()
{
var href = window.location.href,
match = href.match(/^((https?\:)?\/\/(([^\/\?\#\.]+)\.([^\/\?\#]+)))([^\?\#]+)([^\#]+)(.*)/);
if( match[4] !== 'video' && match[8].indexOf('.mp4') != -1 )
{
var fileName = match[8].slice(1),
fileUrl = href.match(/([^\#]+)(.*)/)[1];
fileName = decodeURIComponent(fileName);
__downloadFile( fileName, fileUrl );
if( window.self !== window.parent )
setTimeout(function(){
window.parent.postMessage( 'closeIFrame', '*' );
}, 50);
return true;
}
return false;
}
function downloadFile( name, source, size )
{
if( useGMDownloader || (size && size < maxSize) )
GM_downloadFile(name, source);
else
IFrame_downlaodFile( name, source );
}
function IFrame_downlaodFile( name, source )
{
var iframe = document.querySelector('#video_download_iframe_' + RANDOM);
if( !iframe )
{
iframe = document.createElement('iframe');
iframe.setAttribute('id', 'video_download_iframe_' + RANDOM);
var body = document.querySelector('body');
body.appendChild(iframe);
}
name = encodeURIComponent(name);
iframe.src = (source + '#' + name);
}
function closeIFrame()
{
var ifr = document.querySelector('#video_download_iframe_' + RANDOM);
if( ifr )
ifr.parentNode.removeChild(ifr);
}
function GM_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;
}
console.log("source: " + source);
console.log("name: " + name);
var wURL = window.webkitURL || window.URL,
resource = wURL.createObjectURL(xhr.response);
__downloadFile( name, resource );
var video_file = document.querySelector('#video_file_' + RANDOM);
if( video_file )
video_file.classList.add('video_file_active');
wURL.revokeObjectURL(resource);
},
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 = '';
var html = bytesToMB(loaded, 1) + ' Mb / ' + bytesToMB(total, 1) + ' Mb' +
' (' + (loaded/total*100).toPrecision(3) + '%)';
dlWnd.innerHTML = html;
if( total === loaded )
{
setTimeout(function(){
dlWnd.style.display = 'none';
}, 3000 );
}
}
function bytesToMB( 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(`
.confirm-button {
background-color: #16a085;
color: #c7c7c7;
font-size: 1.0em;
border-radius: 5px;
font-family: sans-serif;
border: 2px solid #c7c7c7;
cursor: pointer;
margin: 0.4% 2% 0.4% 2%;
padding: 0 3px 0 3px;
test-align: center;
}
.confirm-button:hover {
background-color: #058f74;
border-color: white;
color: white;
}
#confirm-bottom {
padding: 3px 0 2px 0;
}
#confirm-bottom {
text-align: center;
}
.confirm_download_window,
.video_download_window {
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
background-color: #16a085;
color: white;
box-shadow: 5px 5px 5px #555555;
font-size: 1.0em;
font-family: sans-serif;
border-radius: 5px;
padding: 2px 10px 2px 10px;
display:;
cursor: default;
}
`);
}
function removeAds()
{
var tbody = document.querySelector('.main tbody');
if( tbody && tbody.children && tbody.children[0] )
tbody.children[0].innerHTML = ' | ';
}
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 )
{
console.log("pladform link: " + event.data.url );
insertLink( event.data.url );// try to insert link to video_size
}else if(event.origin.search(/(cv|dv).*\.sibnet\.ru/) != -1 ){
console.log( "origin: " + event.origin );
event.data === 'closeIFrame' && setTimeout( closeIFrame, 50 );
}else{
//console.info('[recieveMessage] message from ' + event.origin + ' is ignored');
}
}
window.addEventListener('message', recieveMessage, false );
})();