Skip to content

fix for ut.block counting a close character within a regex #39

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/dl.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Download {
this.attempt = 0;
this.logging = data.logging;
this.cancelled = false;
this.timeout = 60000;
this.timeout = 10000;
this.maxSection = 0;
this.curSection = 0;
this.data = data;
Expand Down Expand Up @@ -237,6 +237,7 @@ class Download {
delete this.opts.headers.Range;
}
this.vrs = miniget(this.data.stream.video_url, this.opts);
this.tmo = setTimeout(this.timedOut.bind(this), this.timeout);
this.vrs.pipe(this.vws, { end: this.curSection === this.maxSection });
this.vrs.on('data', this.dataChunk.bind(this));
this.vrs.on('error', this.dataError.bind(this));
Expand Down Expand Up @@ -272,6 +273,7 @@ class Download {
delete this.opts.headers.Range;
}
this.ars = miniget(this.data.stream.audio_url, this.opts);
this.tmo = setTimeout(this.timedOut.bind(this), this.timeout);
this.ars.pipe(this.aws, { end: this.curSection === this.maxSection });
this.ars.on('data', this.dataChunk.bind(this));
this.ars.on('error', this.dataError.bind(this));
Expand Down Expand Up @@ -341,7 +343,7 @@ class Download {
process.on('message', msg => {
switch (msg.msg) {
case 'retry':
dl.retry(30000);
dl.retry(10000);
break;
case 'download':
dl = new Download(msg.data);
Expand Down
38 changes: 37 additions & 1 deletion lib/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// https://github.com/gatecrasher777/ytcog
// MIT Licenced

const crypto = require('crypto');
const fsp = require('node:fs/promises');
const miniget = require('miniget');
const ut = require('./ut')();
const zlib = require('zlib');
Expand Down Expand Up @@ -97,8 +99,42 @@ class Model {
return body;
}

// manage get requests to url with options and whether to use compression.
// wrapper to add local disk cache
async httpsGet(url, getOptions, compress) {
const CACHEDIR = '/tmp';

const proxyHost = this?.common?.agent?.proxy?.host ?? 'no-proxy';
const key = 'ytcog-'+crypto.createHash('sha256')
.update(proxyHost+url)
.digest('hex')
.slice(0,16);

const cachePath = `${CACHEDIR}/${key}`;

try {
await fsp.stat(cachePath); // exists
//console.log(`httpsGet: cache-hit`);
this.status = 'OK';
this.reason = '';
}
catch (e) {
if ('ENOENT' === e.code) {
//console.log(`httpsGet: cache-miss`);
const body = await this._httpsGet(...arguments);

//console.log(`httpsGet: saving body=${typeof body} - ${body.length.toLocaleString()} bytes`);
await fsp.writeFile(cachePath,body);
}
else {
throw new Error(e);
}
}

return fsp.readFile(cachePath,'utf8');
}

// manage get requests to url with options and whether to use compression.
async _httpsGet(url, getOptions, compress) {
let body;
try {
let uncompressed = 0;
Expand Down
10 changes: 5 additions & 5 deletions lib/player.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ class Player extends Model {
// extract signature manipulations - caller is the section of the player body concerned
extractManipulations(caller) {
let fname = ut.pinch(caller, 'a=a.split("");', '.', 0, 0, '', false);
let ffunc = `var ${fname}={`;
return ut.block(this.data, ffunc, 1, '{', '}', '{}', false);
let ffunc = `var ${fname}=`;
return `${ut.traverse(this.data, ffunc)}`;
}

// extracts signature decipher function
extractDecipher() {
let fname = ut.pinch(this.data, 'a.set("alr","yes");c&&(c=', '(decodeURIC', 0, 0, '', false);
let ffunc = `${fname}=function(a)`;
ffunc = `var ${ut.block(this.data, ffunc, 0, '{', '}', '{}', false)}`;
ffunc = `var ${ut.traverse(this.data, ffunc)}`;
ffunc = `${this.extractManipulations(ffunc)};${ffunc};return ${fname}(ytcogsig);`;
let decipherScript = new vm.VMScript(`( function(ytcogsig) {${ffunc}} )`).compile();
this.decipherFn = this.context.run(decipherScript);
Expand All @@ -46,7 +46,7 @@ class Player extends Model {
fname = ut.pinch(this.data, `${fname.split('[')[0]}=[`, ']', 0, 0, '', false);
}
let ffunc = `${fname}=function(a)`;
ffunc = `var ${ut.block(this.data, ffunc, 0, '{', '}', '{}', false)}`;
ffunc = `var ${ut.traverse(this.data, ffunc)}`;
ffunc = `${ffunc};return ${fname}(ytcogncode);`;
let ncodeScript = new vm.VMScript(`( function(ytcogncode) {${ffunc}} )`).compile();
this.ncodeFn = this.context.run(ncodeScript);
Expand All @@ -59,7 +59,7 @@ class Player extends Model {
let fname = ut.pinch(prefix, '=', '();', 0, 0, '', false);
let fname2 = ut.pinch(this.data, start, '()', 0, 0, '', false);
let ffunc = `${fname}=function()`;
ffunc = `var ${ut.block(this.data, ffunc, 0, '{', '}', '{}', false)}`;
ffunc = `var ${ut.traverse(this.data, ffunc)}`;
ffunc = `${ffunc};
var host = "https://www.youtube.com";
var ts = Math.floor((new Date).getTime() / 1E3);
Expand Down
105 changes: 73 additions & 32 deletions lib/ut.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,42 +200,83 @@ class utClass {
return extract;
}

// iterates through body from start text less snip characters
// on an open character it increments level, on a close character it decrements level
// it ends when level return to zero.
// provide what an empty results looks like
// optionally truncate the body at the end of the end text.
block(body, start, snip, open, close, empty, truncate) {
let extract = empty;
// returns length of object to be ignored with start/end characters.
// objects muct be less than 1024 characters.
// If object is regex, will test if regex is valid.
// if invalid regex or unterminated object, will report a 0 object length.
ignore(body, spos, start, end) {
let p = spos;
let s = start;
let esc = false;
let c = 0;
while (true) {
s += body[p];
if (!esc && body[p] === end) {
if (end === '/') {
try {
let r = new RegExp(s);
return s.length;
}
catch(e) {
}
} else {
return s.length;
}
}
esc = body[p] === '\\' && !esc;
p++;
c++;
if (p >= body.length) return 0;
if (c > 1024) return 0;
}
}

// returns extracted javascript code block {} or array [] from body string.
// starting directly after start text
traverse(body, start) {
let spos = body.indexOf(start);
let slen = start.length;
if (spos >= 0) {
let pos = spos + slen - snip;
let done = false;
let quote = 0;
let level = 0;
extract = start.substr(0, slen - snip);
while (!done) {
switch (body[pos]) {
case '"':
quote++;
break;
case open:
if (0 === quote % 2) level++;
break;
case close:
if (0 === quote % 2) level--;
if (!level) done = true;
let pos = spos + start.length;
const objs = [
{ start: '"', end: '"' },
{ start: "'", end: "'" },
{ start: '`', end: '`' },
{ start: '/', end: '/' }
];
let op = '';
let cl = '';
if (body[pos] === '[') {
op = '[';
cl = ']';
} else if (body[pos] === '{') {
op = '{';
cl = '}';
}
if (!op.length) return '';
let esc = false;
let level = 0;
let done = false;
while (!done) {
if (!esc) {
for (const o of objs) {
if (body[pos] === o.start) {
pos += this.ignore(body,pos+1,o.start,o.end);
break;
}
}
extract += body[pos];
pos++;
if (pos >= body.length) done = true;
}
if (truncate) body = body.substring(0, pos);
} else if (truncate) { body = ''; }
return extract;
}
esc = body[pos] === '\\' && !esc;
if (body[pos] === op) {
level++;
} else if (body[pos] === cl) {
level--;
}
if (level === 0) return body.substring(spos, pos + 1);
pos++;
if (pos >= body.length) done = true;
}
return '';
};

}

// Initiate the class
Expand Down
4 changes: 2 additions & 2 deletions lib/video.js
Original file line number Diff line number Diff line change
Expand Up @@ -869,7 +869,7 @@ class Video extends Model {
this.downloaded = ut.now();
} else if (!this.cancelled) {
// try video onloy
if ((aformat >= 0) && !vonly && !aonly && ((vformat >= 0) || (aformat >= 0))) {
if (aformat < 0 && !vonly && !aonly && vformat < 0) {
success = await this.downloadAttempt(true, false, vformat, aformat);
if (success) this.downloaded = ut.now();
}
Expand Down Expand Up @@ -1269,4 +1269,4 @@ class Video extends Model {
}
}

module.exports = Video;
module.exports = Video;