mirror of
https://github.com/Rafostar/clapper.git
synced 2025-08-30 07:42:23 +02:00
YT: do not check player ID if actions are cached
This commit is contained in:
110
src/youtube.js
110
src/youtube.js
@@ -52,7 +52,8 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
debug(`obtaining YouTube video info: ${videoId}`);
|
debug(`obtaining YouTube video info: ${videoId}`);
|
||||||
this.downloadingVideoId = videoId;
|
this.downloadingVideoId = videoId;
|
||||||
|
|
||||||
const [info, isAborted] = await this._getInfoPromise(videoId).catch(debug);
|
let [info, isAborted] = await this._getInfoPromise(videoId).catch(debug);
|
||||||
|
|
||||||
if(!info) {
|
if(!info) {
|
||||||
if(isAborted)
|
if(isAborted)
|
||||||
return reject(new Error('download aborted'));
|
return reject(new Error('download aborted'));
|
||||||
@@ -84,68 +85,63 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
if(!info.streamingData.adaptiveFormats)
|
if(!info.streamingData.adaptiveFormats)
|
||||||
info.streamingData.adaptiveFormats = [];
|
info.streamingData.adaptiveFormats = [];
|
||||||
|
|
||||||
const isCipher = this._getIsCipher(info.streamingData);
|
if(this._getIsCipher(info.streamingData)) {
|
||||||
if(isCipher) {
|
|
||||||
debug('video requires deciphering');
|
debug('video requires deciphering');
|
||||||
|
|
||||||
const embedUri = `https://www.youtube.com/embed/${videoId}`;
|
/* Decipher actions do not change too often, so try
|
||||||
const [body, isAbortedBody] =
|
* to reuse without triggering too many requests ban */
|
||||||
await this._downloadDataPromise(embedUri).catch(debug);
|
let actions = this.cachedSig.actions;
|
||||||
|
|
||||||
if(isAbortedBody)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* We need matching info, so start from beginning */
|
|
||||||
if(!body)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
const ytPath = body.match(/(?<=jsUrl\":\").*?(?=\")/gs)[0];
|
|
||||||
if(!ytPath) {
|
|
||||||
debug(new Error('could not find YouTube player URI'));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const ytUri = `https://www.youtube.com${ytPath}`;
|
|
||||||
if(
|
|
||||||
/* check if site has "/" after ".com" */
|
|
||||||
ytUri[23] !== '/'
|
|
||||||
|| !Gst.Uri.is_valid(ytUri)
|
|
||||||
) {
|
|
||||||
debug(`misformed player URI: ${ytUri}`);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
debug(`found player URI: ${ytUri}`);
|
|
||||||
|
|
||||||
const ytId = ytPath.split('/').find(el => Misc.isHex(el));
|
|
||||||
let actions;
|
|
||||||
|
|
||||||
if(this.cachedSig.id === ytId) {
|
|
||||||
debug('reusing cached cipher actions');
|
|
||||||
actions = this.cachedSig.actions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* TODO: load cache from file */
|
|
||||||
|
|
||||||
if(!actions) {
|
if(!actions) {
|
||||||
const [pBody, isAbortedPlayer] =
|
const embedUri = `https://www.youtube.com/embed/${videoId}`;
|
||||||
await this._downloadDataPromise(ytUri).catch(debug);
|
const [body, isAbortedBody] =
|
||||||
if(!pBody || isAbortedPlayer) {
|
await this._downloadDataPromise(embedUri).catch(debug);
|
||||||
debug(new Error('could not download player body'));
|
|
||||||
|
if(isAbortedBody)
|
||||||
|
break;
|
||||||
|
if(!body)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const ytPath = body.match(/(?<=jsUrl\":\").*?(?=\")/gs)[0];
|
||||||
|
if(!ytPath) {
|
||||||
|
debug(new Error('could not find YouTube player URI'));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
actions = YTDL.sig.extractActions(pBody);
|
const ytUri = `https://www.youtube.com${ytPath}`;
|
||||||
this._createCacheFileAsync(ytId, actions);
|
if(
|
||||||
}
|
/* check if site has "/" after ".com" */
|
||||||
|
ytUri[23] !== '/'
|
||||||
|
|| !Gst.Uri.is_valid(ytUri)
|
||||||
|
) {
|
||||||
|
debug(`misformed player URI: ${ytUri}`);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug(`found player URI: ${ytUri}`);
|
||||||
|
|
||||||
if(!actions || !actions.length) {
|
const ytId = ytPath.split('/').find(el => Misc.isHex(el));
|
||||||
debug(new Error('could not extract decipher actions'));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
debug('successfully obtained decipher actions');
|
|
||||||
|
|
||||||
if(this.cachedSig.id !== ytId) {
|
/* TODO: load cache from file */
|
||||||
this.cachedSig.id = ytId;
|
|
||||||
this.cachedSig.actions = actions;
|
if(!actions) {
|
||||||
debug('set current decipher actions for reuse');
|
const [pBody, isAbortedPlayer] =
|
||||||
|
await this._downloadDataPromise(ytUri).catch(debug);
|
||||||
|
if(!pBody || isAbortedPlayer) {
|
||||||
|
debug(new Error('could not download player body'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
actions = YTDL.sig.extractActions(pBody);
|
||||||
|
this._createCacheFileAsync(ytId, actions);
|
||||||
|
}
|
||||||
|
if(!actions || !actions.length) {
|
||||||
|
debug(new Error('could not extract decipher actions'));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
debug('successfully obtained decipher actions');
|
||||||
|
|
||||||
|
if(this.cachedSig.id !== ytId) {
|
||||||
|
this.cachedSig.id = ytId;
|
||||||
|
this.cachedSig.actions = actions;
|
||||||
|
debug('remembered current decipher actions for reuse');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const isDeciphered = this._decipherStreamingData(
|
const isDeciphered = this._decipherStreamingData(
|
||||||
@@ -214,6 +210,8 @@ var YouTubeClient = GObject.registerClass({
|
|||||||
debug(`got chunk of data, length: ${chunk.length}`);
|
debug(`got chunk of data, length: ${chunk.length}`);
|
||||||
|
|
||||||
const chunkData = chunk.get_data();
|
const chunkData = chunk.get_data();
|
||||||
|
if(!chunkData) return;
|
||||||
|
|
||||||
data += (chunkData instanceof Uint8Array)
|
data += (chunkData instanceof Uint8Array)
|
||||||
? ByteArray.toString(chunkData)
|
? ByteArray.toString(chunkData)
|
||||||
: chunkData;
|
: chunkData;
|
||||||
|
Reference in New Issue
Block a user