// ==SiteScript==
// @siteName DoodStream
// @siteUrl https://doodstream.com/
// @author mayan
// @authorUrl
// @scriptUrl
// @description
// @date 2021/10/04
// @version 0.1.2
// ==/SiteScript==
function CravingSiteScript() {
this._initialize();
}
CravingSiteScript.prototype = {
_xhr: null,
_initialize: function() {},
_getXmlHttpRequest: function() {
if ( this._xhr != null ) {
return this._xhr;
}
var xhr = null;
var these = [
function() { return new XMLHttpRequest(); }
, function() { return new ActiveXObject( "Msxml2.XMLHTTP" ); }
, function() { return new ActiveXObject( "Microsoft.XMLHTTP" ); }
, function() { return new ActiveXObject( "Msxml2.XMLHTTP.4.0" ); }
];
for ( var i = 0, length = these.length; i < length; i++ ) {
var func = these[ i ];
try {
xhr = func();
break;
}
catch( e ) {}
}
this._xhr = xhr;
return this._xhr;
},
_load: function( url, data, method ) {
var req = this._getXmlHttpRequest();
var mtd = ( method == null ) ? "GET" : "POST";
req.open( mtd, url, false );
if ( mtd == "POST" ) {
req.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded" );
}
req.send( data );
return req.responseText;
},
getResponseText: function( url, data, method ) {
return this._load( url, data, method );
},
getResponseJSON: function( url, data, method ) {
var text = this._load( url, data, method );
return eval( "("+text+")" );
},
/// Math
random: function( limit ) {
return Math.floor( Math.random() * limit );
},
/// String
decodeHtml: function( str ) {
return str.replace( /&(quot|#0*34);/ig, "\"" )
.replace( /&(amp|#0*38);/ig, "&" )
.replace( /&(apos|#0*39);/ig, "'" )
.replace( /&(lt|#0*60);/ig, "<" )
.replace( /&(gt|#0*62);/ig, ">" )
.replace( /&(nbsp|#0*160);/ig, " " )
.replace( /&(frasl|#8260);/ig, "/" );
}
}
var _Gbl = {};
_Gbl.showIbx = false;
_Gbl.showSrt = true;
function isSiteUrl( url ) {
if ( url.match( /https?:\/\/(?:www\.)?doodstream\.com\/[de]\/[^\/?]+/i ) ) return true;
if ( url.match( /https?:\/\/(?:www\.)?dood\.(?:so|la|ws|sh)\/[de]\/[^\/?]+/i ) ) return true;
return false;
}
function getVideoDetail( url ) {
if ( typeof _Gbl != "object" ) _Gbl = {};
url = url.replace( /^\s*http:\/\//i, "https://" );
url = url.replace( /:\/\/www\./i, "://" );
url = url.replace( /:\/\/(?:www\.)?doodstream\.com\//i, "://dood.so/" );//2021/03/31 現在
if ( url.match( /https?:\/\/(?:www\.)?(doodstream\.com|dood\.(?:so|la|ws|sh))\/([de])\/([^\/?]+)/i ) ) {
var domain = RegExp.$1;
var type = RegExp.$2.toLowerCase();
var vid = RegExp.$3;
if ( type === "d" ) {
var pageurl = url;
} else if ( type === "e" ) {
var embedurl = url;
}
} else {
return null;
}
var craving = new CravingSiteScript();
try {
var objHttp = new ActiveXObject( "WinHttp.WinHttpRequest.5.1" );
objHttp.option( 12 ) = true;
} catch ( e ) {
objHttp = null;
}
if ( !objHttp ) return null;
var title = "";
var objRef_e = {"url":"", "text": ""};
var objRef_p = {"url":"", "text": ""};
//embed route
if ( !embedurl && vid ) embedurl = "https://" + ( domain || "dood.so" ) + "/e/" + vid;
if ( embedurl ) {
objRef_e.url = embedurl;
objRef_e = getDetail_embed( objRef_e, objHttp, craving );
if ( objRef_e.realUrl ) {
title = getTitle( objRef_e, objRef_p, vid );
var header = "Referer: " + objRef_e.rd;
if ( _Gbl.showSrt ) showSrt( objRef_e );
return { "videoUrl0": objRef_e.realUrl, "videoTitle0": title, "httpHeader0": header };
}
}
//dl route
if ( !pageurl && vid ) pageurl = "https://" + ( domain || "dood.so" ) + "/d/" + vid;
if ( pageurl ) {
objRef_p.url = pageurl;
objRef_p = getDetail_page( objRef_p, objHttp, craving );
if ( objRef_p.realUrl ) {
title = getTitle( objRef_p, objRef_e, vid );
header = "Referer: " + objRef_p.rd;
if ( _Gbl.showSrt ) showSrt( objRef_p );
return { "videoUrl0": objRef_p.realUrl, "videoTitle0": title, "httpHeader0": header };
}
}
return null;
function getTitle( objRef_1, objRef_2, vid ) {
var title = objRef_1.title || objRef_2.title;
if ( !title ) title = "dood_" + ( vid || new Date().getTime() );
if ( _Gbl.showIbx ) {
var objIbx = new clsInputBox();
if ( objIbx.isOK ) {
var rtnIbx = objIbx.InputBox( "保存ファイル名:\n"
+ title + "\n\n"
+ "変更する場合は、書き換えてください。"
,"from doodstream.site.js"
,title
);
if ( typeof rtnIbx === "string" &&
rtnIbx !== title &&
rtnIbx !== "" ) {
title = rtnIbx;
}
}
}
title = title.replace(/[\\\/:*?"<>|]/g, "_");
return title;
}
function getDetail_embed( objRef, objHttp, crv ) {
if ( !objRef || typeof objRef != "object" ) objRef = { "url": embedurl, "text": "", "realUrl":"", "title":"", "rd":"" };
if ( !objRef.url || typeof objRef.url != "string" ) return objRef;
if ( !crv || typeof crv != "object" ) crv = craving;
if ( !getResponse( objRef, objHttp ) || !setText( objRef, objHttp ) ) return objRef;
var objReg = /\$\.get\s*\(\s*('|")(.*?)\1/gm;
var psurl = "";
while ( objReg.test( objRef.text ) ) {
var strArg1 = RegExp.$2;
if ( strArg1.match( /\/pass_md5\/.+/i ) ) {
psurl = strArg1;
break;
}
}
if ( !psurl ) return objRef;
var token = psurl.match( /pass_md5\/[-0-9a-f]+?\/([^\/?]+)/ )? RegExp.$1: "";
if ( !token ) return objRef;
setRd( objRef, objHttp );
objRef.rd = objRef.rd || objRef.url;
psurl = Rel2Abs( objRef.rd, psurl );
var objRef_ps = { "url": psurl, "text": "" };
if ( !getResponse( objRef_ps, objHttp, { "Referer": objRef.rd } ) ||
!setText( objRef_ps, objHttp ) ) return objRef;
objRef_ps.text = trim( objRef_ps.text );
if ( !objRef_ps.text.match( /^\s*https?:\/\/.+/ ) ) return objRef;
objRef.realUrl = objRef_ps.text + mkPly(10) + "?token=" + token + "&expiry=" + new Date().getTime();
var title = "";
if ( !title &&
objRef.text.match( /]*?name\s*=\s*("|')?og:title\2[^>]*?)>/im )
&& RegExp.$1.match( /\s+content\s*=\s*("|')(.*?)\1/im ) ) {
title = trim( crv.decodeHtml( RegExp.$2 ) );
}
if ( !title &&
objRef.text.match( /]*?name\s*=\s*("|')?twitter:title\2[^>]*?)>/im )
&& RegExp.$1.match( /\s+content\s*=\s*("|')(.*?)\1/im ) ) {
title = trim( crv.decodeHtml( RegExp.$2 ) );
}
if ( !title &&
objRef.text.match( /
]*?)?>(.*?)<\/title\s*>/im ) ) {
title = trim( crv.decodeHtml( RegExp.$1 ) ).replace( /[\s\r\n\t]+/gm, " " ).replace( /\s*-[^-]*?$/, "" );
}
if ( title ) objRef.title = title;
if ( _Gbl.showSrt ) setArrSrt( objRef );
return objRef;
function mkPly( n ) {
var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var len = str.length;
var arr = [];
for ( var i = 0; i < n; i++ ) {
arr.push( str.charAt( Math.floor( Math.random() * len ) ) );
}
return arr.join("");
}
}
function getDetail_page( objRef, objHttp, crv ) {
//clsSleep()
if ( !objRef || typeof objRef != "object" ) objRef = { "url": pageurl, "text": "", "realUrl":"", "title":"", "rd":"" };
if ( !objRef.url || typeof objRef.url != "string" ) return objRef;
if ( !crv || typeof crv != "object" ) crv = craving;
if ( !getResponse( objRef, objHttp ) || !setText( objRef, objHttp ) ) return objRef;
var objReg = /]*href\s*=\s*("|')(.*?)\1[^>]*?>/igm;
var dlpgurl = "";
while ( objReg.test( objRef.text ) ) {
hrf = RegExp.$2;
if ( hrf.match( /\/download\/[0-9a-z]+?\/n\/[-0-9a-f]+/i ) ) {
dlpgurl = hrf;
break;
}
}
if ( !dlpgurl ) return objRef;
new clsSleep().sleep( 5 );//wait 5s
setRd( objRef, objHttp );
objRef.rd = objRef.rd || objRef.url;
dlpgurl = Rel2Abs( objRef.rd, dlpgurl );
var objRef_dlpg = { "url": dlpgurl, "text": "" };
if ( !getResponse( objRef_dlpg, objHttp, { "Referer": objRef.rd } ) ||
!setText( objRef_dlpg, objHttp ) ) return objRef;
objReg = /]*?)>([\s\S]+?)<\/a\s*>/igm;
var dlurl = "";
while ( objReg.test( objRef_dlpg.text ) ) {
var arg = RegExp.$1;
var cnt = RegExp.$2;
if ( cnt && cnt.match( /Direct Download Link/ ) &&
arg.match( /\s+onclick\s*=\s*(?:"|')window\.open\s*\(\s*('|")(.*?)\1/m ) ) {
dlurl = RegExp.$2;
break;
}
}
if ( !dlurl ) return objRef;
if ( !dlurl.match( /^\s*https?:\/\/.+/ ) ) return objRef;
objRef.realUrl = dlurl;
var title = "";
if ( !title &&
objRef.text.match( /]*?name\s*=\s*("|')?og:title\2[^>]*?)>/im )
&& RegExp.$1.match( /\s+content\s*=\s*("|')(.*?)\1/im ) ) {
title = trim( crv.decodeHtml( RegExp.$2 ) );
}
if ( !title &&
objRef.text.match( /]*?name\s*=\s*("|')?twitter:title\2[^>]*?)>/im )
&& RegExp.$1.match( /\s+content\s*=\s*("|')(.*?)\1/im ) ) {
title = trim( crv.decodeHtml( RegExp.$2 ) );
}
if ( !title &&
objRef.text.match( /]*?)?>(.*?)<\/title\s*>/im ) ) {
title = trim( crv.decodeHtml( RegExp.$1 ) ).replace( /[\s\r\n\t]+/gm, " " ).replace( /\s*-[^-]*?$/, "" );
}
if ( title ) objRef.title = title;
return objRef;
}
function setArrSrt( objRef ) {
var arrSrt = [];
var objReg = /\.addRemoteTextTrack\s*\(\s*(\{[^}]*?\})/gm;
while ( objReg.test( objRef.text ) ) {
var arg = RegExp.$1;
var kind = arg.match( /[{,]\s*("|')?kind\1\s*:\s*('|")(.*?)\2\s*[},]/im )? RegExp.$3: "";
if ( !kind.match( /caption/i ) ) continue;
var src = arg.match( /[{,]\s*("|')?src\1\s*:\s*('|")(.*?)\2\s*[},]/im )? RegExp.$3: "";
if ( !src.match( /^(?:https?:)?\/\/.+/i ) ) continue;
src = Rel2Abs( objRef.rd, src );
var label = arg.match( /[{,]\s*("|')?label\1\s*:\s*('|")(.*?)\2\s*[},]/im )? RegExp.$3: "";
var srclang = arg.match( /[{,\s*("|')?srclang\1\s*:\s*('|")(.*?)\2\s*[},]/im )? RegExp.$3: "";
arrSrt.push( { "src":src, "kind":kind, "label":label, "srclang":srclang } );
}
objRef.arrSrt = arrSrt;
}
function showSrt( objRef ) {
if ( objRef.arrSrt && objRef.arrSrt instanceof Array &&
objRef.arrSrt.length > 0 ) {
var arr = [];
for ( var i = 0; i < objRef.arrSrt.length; i++ ) {
arr.push( "label: " + ( objRef.arrSrt[i].label? objRef.arrSrt[i].label: "" )
+ "\nsrc: " + objRef.arrSrt[i].src );
}
if ( arr.length > 0 ) {
var objBx = new clsMsgBox();
if ( objBx.isOK ) {
objBx.MsgBox( "字幕ファイルがあるかもしれません。\n\n" + arr.join( "\n\n" )
, "from doodstream.site.js", 0 );
}
}
}
}
}
function getResponse( objRef, objHttp, header ) {
//objRef.url: 必須
//objRef.protocol, objRef.data: 随意
var protocol = objRef.protocol? objRef.protocol: "GET";
var data = objRef.data? objRef.data: "";
var status = -1;
try {
objHttp.open( protocol, objRef.url, false );
if ( header && typeof header == "object" ) {
for ( var fn in header ) {
if ( header.hasOwnProperty( fn ) ) {
objHttp.setRequestHeader( fn, header[ fn ] );
}
}
}
objHttp.send( data );
status = objHttp.status;
} catch ( e ) {
status = -1;
}
var rtn = ( 200 <= status && status < 400 )? true: false;
return rtn;
}
function setText( objRef, objHttp ) {
objRef.text = "";
var rtn = false;
try {
objRef.text = objHttp.responseText;
rtn = true;
} catch ( e ) {
objRef.text = "";
rtn = false;
}
return rtn;
}
function setRd( objRef, objHttp ) {
objRef.rd = "";
var rtn = false;
try {
objRef.rd = objHttp.option( 1 );
rtn = true;
} catch ( e ) {
objRef.rd = "";
rtn = false;
}
return rtn;
}
function Rel2Abs( strPageurl, strRelurl ) {
//2014/09/18 version 0.2
if ( strRelurl.split( /[?]/ )[0].match( /(\w+?):\/\/([^\/]+)(\/.*)?/ ) ) {
return strRelurl;
}
if ( strPageurl.split( /[?]/ )[0].match( /(\w+?):\/\/([^\/]+)(?:\/(.*))?/ ) ) {
var protocol = RegExp.$1;
var domain = RegExp.$2;
var path = RegExp.$3;
}
if ( !protocol ) protocol = "http";
if ( !domain ) domain = "";
if ( !path ) path = "";
var base = protocol + "://" + domain;
if ( strRelurl.match( /^\/\// ) ) {
var absurl = protocol + ":" + strRelurl;
} else if ( strRelurl.match( /^\// ) ) {
absurl = base + strRelurl;
} else {
var pathz = path.split( "/" );
pathz.pop();
if ( strRelurl.match( /^((\.\.\/|\.\/)+)(.+)?/ ) ) {
var dotp = RegExp.$1;
var relpath = RegExp.$3;
var objReg = /\.\.\//g;
while ( objReg.test( dotp ) ) pathz.pop();
} else {
relpath = strRelurl;
}
if ( pathz.length <= 0 ) var abspath = "/";
else abspath = "/" + pathz.join( "/" ) + "/";
absurl = base + abspath + relpath;
}
return absurl;
}
function trim( str ) {
if ( typeof str != "string" ) return "";
return str.replace( /^[\s\r\n\t]+/,"" ).replace( /[\s\r\n\t]+$/,"" );
}
function clsSleep() {
this._objShell = null;
this._ShellisOK = false;
this._initialize = function () {
try {
this._objShell = new ActiveXObject( "WScript.Shell" );
this._ShellisOK = true;
} catch( e ) {
this._ShellisOK = false;
}
}
this._initialize();
this.sleep = function ( sec ) {
if ( this._ShellisOK ) {
this._objShell.Run( "ping.exe localhost -n " + (sec+1), 0, true );
return;
} else {
var ptime = ( new Date() ).getTime() + sec * 1000;
while (-1) if ( ( new Date() ).getTime() >= ptime ) break;
return;
}
}
}
function clsInputBox(){
//VBScript InputBox
this.isOK = false;
this._objSC = null;
this._initialize = function (){
try {
this._objSC = new ActiveXObject( "ScriptControl" );
this._objSC.Language = "VBScript";
this._objSC.AddCode( "Function VB_IB(p, t, d) : VB_IB = InputBox(p, t, d) : End Function" );
this.isOK = true;
} catch(e) {
this.isOK = false;
}
}
this._initialize();
this.InputBox = function (msg, title, def){
if ( this.isOK ){
return this._objSC.Run( "VB_IB", msg, title, def);
}
}
}
/* msgbox */
function clsMsgBox(){
//WScript.Shell Popup
this.isOK = false;
this._objShell = null;
this._initialize = function (){
try{
this._objShell = new ActiveXObject( "WScript.Shell" );
this.isOK = true;
} catch( e ) {
this.isOK = false;
}
}
this._initialize();
this.MsgBox = function ( msg, title, btn ){
if ( btn == undefined ) btn = 1;
//btn=1の時ret: OK:1, キャンセル:2
if ( this.isOK )
return this._objShell.Popup( msg, 0, title, btn+64 );
}
}
/* msgbox */