From 06f8e5d2591a16961975e245f7b3103f4b30cc01 Mon Sep 17 00:00:00 2001 From: Rafostar <40623528+Rafostar@users.noreply.github.com> Date: Sun, 14 Mar 2021 21:00:18 +0100 Subject: [PATCH] YT: cache current decipher actions --- src/misc.js | 5 +++++ src/youtube.js | 42 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/misc.js b/src/misc.js index 69f0f5cf..5493c55e 100644 --- a/src/misc.js +++ b/src/misc.js @@ -109,3 +109,8 @@ function decodeURIPlus(uri) { return decodeURI(uri.replace(/\+/g, ' ')); } + +function isHex(num) +{ + return Boolean(num.match(/[0-9a-f]+$/i)); +} diff --git a/src/youtube.js b/src/youtube.js index 1c1b49a1..3c877488 100644 --- a/src/youtube.js +++ b/src/youtube.js @@ -1,6 +1,7 @@ -const { GLib, GObject, Gst, Soup } = imports.gi; +const { Gio, GLib, GObject, Gst, Soup } = imports.gi; const ByteArray = imports.byteArray; const Debug = imports.src.debug; +const Misc = imports.src.misc; const YTDL = imports.src.assets['node-ytdl-core']; const { debug } = Debug; @@ -23,6 +24,10 @@ var YouTubeClient = GObject.registerClass({ this.downloadingVideoId = null; this.lastInfo = null; + this.cachedSig = { + id: null, + actions: null, + }; } getVideoInfoPromise(videoId) @@ -110,9 +115,16 @@ var YouTubeClient = GObject.registerClass({ } debug(`found player URI: ${ytUri}`); - /* TODO: cache */ + 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) { const [pBody, isAbortedPlayer] = await this._downloadDataPromise(ytUri).catch(debug); @@ -121,6 +133,7 @@ var YouTubeClient = GObject.registerClass({ break; } actions = YTDL.sig.extractActions(pBody); + this._createCacheFileAsync(ytId, actions); } if(!actions || !actions.length) { @@ -128,6 +141,13 @@ var YouTubeClient = GObject.registerClass({ break; } debug('successfully obtained decipher actions'); + + if(this.cachedSig.id !== ytId) { + this.cachedSig.id = ytId; + this.cachedSig.actions = actions; + debug('set current decipher actions for reuse'); + } + const isDeciphered = this._decipherStreamingData( info.streamingData, actions ); @@ -394,6 +414,24 @@ var YouTubeClient = GObject.registerClass({ return `${url}&${sig}=${key}`; } + + _createCacheFileAsync(ytId, actions) + { + const cachePath = GLib.get_user_cache_dir() + '/' + ytId; + const cacheFile = Gio.File.new_for_path(cachePath); + + debug('saving cipher actions to cache file'); + + cacheFile.replace_contents_bytes_async( + GLib.Bytes.new_take(actions), + null, + false, + Gio.FileCreateFlags.NONE, + null + ) + .then(() => debug('saved cache file')) + .catch(debug); + } }); function checkYouTubeUri(uri)