selfdebrid/lib.js
2023-03-13 01:27:35 -04:00

401 lines
10 KiB
JavaScript

const fs = require("fs");
const axios = require("axios");
const {SingleBar} = require("cli-progress");
const minimist = require("minimist");
module.exports = {
getCookies,
getOptions,
getExtractor,
cookieToString,
log,
download,
countdown,
defaultHost,
defaultHeaders: {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.9",
"Connection": "keep-alive",
"DNT": "1",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "same-origin",
"Sec-Fetch-User": "?1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Firefox/102.0",
"Upgrade-Insecure-Requests": "1"
}
}
function getOptions() {
if (process.argv0.includes("node")) args = minimist(process.argv.slice(2));
else args = minimist(process.argv.slice(1));
let options = {};
if (args.d == true || args.debug == true) options.debug = true;
else options.debug = false;
if (args.dry == true || args["dry-run"] == true) options.dry = true;
else options.dry = false;
if (args.cookie || args.cookies || args.cookieFile) options.cookieFile = (args.cookie || args.cookies || args.cookieFile);
options.urls = [];
for (let index in args._) {
options.urls.push(args._[index]);
}
if (args.file) {
if (args.file.endsWith("txt")) {
let file = fs.readFileSync(args.file).toString().split(`\n`);
for (let i in file) {
if (file[i].startsWith("http://") || file[i].startsWith("https://")) options.urls.push(file[i]);
}
}
}
if (args["preferred-host"]) options.preferredHost = args["preferred-host"];
return options;
}
async function getExtractor(url) {
let hostname = new URL(url).hostname;
hostname = `${hostname.split(".")[hostname.split(".").length - 2]}.${hostname.split(".")[hostname.split(".").length - 1]}`;
let extractors = fs.readdirSync(`${__dirname}/extractors`);
for (let i in extractors) {
let extractor = require(`${__dirname}/extractors/${extractors[i]}`);
if (extractor.hostnames?.includes(hostname)) return extractor;
else continue;
}
return null;
}
function log(origin, message, etc, force, options) {
if (!options) options = getOptions();
if (options?.allowForceLogs == false) return;
if (options.debug == true || force == true) {
if (etc?.length !== 0 && etc !== undefined) console.log(`[${origin}] ${message}`, ...etc);
else console.log(`[${origin}] ${message}`);
}
return;
}
function cookieToString(cookies) {
let s = ``;
for (let c in cookies) {
if (cookies[c].value == "deleted") continue;
s = `${s} ${cookies[c].name}=${encodeURIComponent(cookies[c].value)};`;
}
s = s.substring(0, s.length - 1);
return s.substring(1);
}
async function download(data) {
log(`downloader`, `Destination: "./${data?.metadata?.fileName}"`, [], true);
let pb = new SingleBar({format: `[downloader] {status} {percent} of {fullSize} @ {speed}/s {extra}`});
try {
let name = data?.metadata?.fileName;
let speed = 0;
setInterval(function() {
speed = 0;
}, 1000);
if (data.axiosData) {
let axiosData = data.axiosData;
axiosData.responseType = "stream";
let resp = await axios(axiosData);
let size = (resp?.headers["content-length"] || file.size);
if (size == undefined) {
pb.start(size, 0, {
percent: `(Unknown)%`,
speed: bytesToSize(0),
status: `Downloading`,
fullSize: `?GB`,
extra: ``
});
resp.data.on("data", function(chunk) {
if (!speed) speed = chunk.length;
else speed = (speed + chunk.length);
let humanSpeed = bytesToSize(speed);
pb.increment(0, {
speed: humanSpeed
});
});
} else {
size = parseInt(size);
let fullSize = bytesToSize(size);
let currSize = 0;
pb.start(size, 0, {
percent: `0.00%`,
speed: bytesToSize(0),
status: `Downloading`,
fullSize: fullSize,
extra: ``
});
resp.data.on("data", function(chunk) {
if (!speed) speed = chunk.length;
else speed = (speed + chunk.length);
let humanSpeed = bytesToSize(speed);
currSize = (currSize + chunk.length);
let percent = ((currSize / size) * 100).toFixed(2);
percent = `${percent}%`
pb.increment(chunk.length, {
percent: percent,
speed: humanSpeed
});
});
}
resp.data.pipe(fs.createWriteStream(`./${name}`));
let start = (new Date() * 1);
return (await returnWhenEnded(resp.data, pb, start));
} else if (data.stream && data?.metadata?.size) {
let size = data?.metadata?.size
let fullSize = bytesToSize(size);
let currSize = 0;
pb.start(size, 0, {
percent: `0.00%`,
speed: bytesToSize(0),
status: `Downloading`,
fullSize: fullSize,
extra: ``
});
data.stream.on("data", function(chunk) {
if (!speed) speed = chunk.length;
else speed = (speed + chunk.length);
let humanSpeed = bytesToSize(speed);
currSize = (currSize + chunk.length);
let percent = ((currSize / size) * 100).toFixed(2);
percent = `${percent}%`
pb.increment(chunk.length, {
percent: percent,
speed: humanSpeed
});
});
data.stream.pipe(fs.createWriteStream(`./${name}`));
let start = (new Date() * 1);
return (await returnWhenEnded(data.stream, pb, start));
} else throw new Error("Gave invalid download data.");
} catch(err) {
return {
success: false,
error: err
};
}
}
function bytesToSize(bytes) {
var sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
if (bytes == 0) return '0 Byte';
var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
return Math.round(bytes / Math.pow(1024, i), 2) + ' ' + sizes[i];
}
async function returnWhenEnded(dl, pb, time) {
return new Promise(function(resolve, reject) {
try {
dl.on("end", function() {
let end = (new Date() * 1);
let totalTime = ((end - time)/ 1000)
pb.increment(0, {status: `Downloaded`, percent: `100.00%`, extra: `in ${totalTime}s`});
pb.stop();
resolve({success: true})
});
} catch(err) {
reject({success: false, error: err});
}
})
}
async function getCookies(file, domain) {
if (!file) throw new Error("Could not find cookie file.");
if (!fs.existsSync(file)) throw new Error("Could not find cookie file.");
let baseDomain;
if (domain) {
baseDomain = `${domain.split(".")[domain.split(".").length - 2]}.${domain.split(".").length - 1}`;
}
let cookies = fs.readFileSync(file).toString();
let parsedCookies = [];
for (let i in cookies.split(`\n`)) {
let cookie = cookies.split(`\n`)[i];
if (cookie.startsWith("#")) continue;
if (cookie == "" || cookie == " ") continue;
cookie = cookie.split(`\t`);
let exp = cookie[4];
if (exp == "0") continue;
else exp = new Date(parseInt(cookie[4] * 1000));
// filters expired cookies
let currDate = new Date() * 1;
let expDate = new Date() * 1;
if (expDate > currDate) continue;
cookie = {
domain: cookie[0],
path: cookie[2],
secure: toBool(cookie[3]),
expires: exp,
name: cookie[5],
value: cookie[6]
};
parsedCookies.push(cookie);
}
if (domain) {
// filtering out invalid cookies for the domain
for (let i in parsedCookies) {
let cookieDomain;
if (parsedCookies[i].domain.startsWith(".")) cookieDomain = parsedCookies[i].domain.substring(1);
else cookieDomain = parsedCookies[i].domain;
if (
cookieDomain !== baseDomain &&
cookieDomain !== domain
) delete parsedCookies[i];
}
}
return parsedCookies;
}
function toBool(string) {
if (typeof string == "string") {
string = string.toLowerCase();
switch(string) {
case "t":
case "tr":
case "tru":
case "true":
case "y":
case "ye":
case "yes":
return true;
case "f":
case "fa":
case "fal":
case "fals":
case "false":
case "n":
case "no":
return false;
}
} else return string;
}
async function countdown(ms, options) {
if (!options) options = {allowForceLogs: true};
return new Promise(function(resolve, reject) {
try {
if (typeof ms == "number") ms = parseInt(ms);
let pb = new SingleBar({format: `[countdown] {status}: {remaining} {extra}`});
if (options.allowForceLogs !== false) {
pb.start(9999999, 0, {
remaining: toTimeString(ms),
status: "Waiting",
extra: "remaining"
});
}
setInterval(function() {
ms = ms - 1000;
if (ms <= 999) {
if (options.allowForceLogs !== false) {
pb.increment(1, {
remaining: toTimeString(ms),
status: "Waited",
extra: ""
})
pb.stop();
}
resolve(true);
}
if (options.allowForceLogs !== false) {
pb.increment(1, {
remaining: toTimeString(ms),
status: "Waiting"
});
}
}, 1000);
} catch(err) {
reject(err);
}
});
}
function toTimeString(ms) {
if (typeof ms == "string") ms = parseFloat(ms);
let timeString = "";
let days = Math.floor(ms / (1000 * 60 * 60 * 24));
let hours = Math.floor((ms / (1000 * 60 * 60)) % 24);
let mins = Math.floor((ms / 1000 / 60) % 60);
let secs = Math.floor((ms / 1000) % 60);
if (days !== 0) timeString = `${days} days,`;
if (hours !== 0) timeString = `${timeString} ${hours} hours,`;
if (mins !== 0) timeString = `${timeString} ${mins} minutes,`;
if (secs !== 0) timeString = `${timeString} ${secs} seconds`;
if (days == 0) timeString = timeString.substring(1);
return timeString;
}
function defaultHost(mirror) {
let inOrderofPref = [
"zippyshare",
"send",
"yodbox",
"krakenfiles",
"anonfiles"
]
for (let i in mirror) {
let host = mirror[i].link.split(`.`)[0];
}
}