From 46274c8da090d89c22dd7fcd61d401210c465052 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 09:18:29 +0000 Subject: [PATCH 1/8] youtube: add support for using OAuth2 tokens --- src/modules/processing/services/youtube.js | 33 +++++++++++++++++++++- src/modules/sub/generate-youtube-tokens.js | 30 ++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/modules/sub/generate-youtube-tokens.js diff --git a/src/modules/processing/services/youtube.js b/src/modules/processing/services/youtube.js index 39a94f3a..301b37b7 100644 --- a/src/modules/processing/services/youtube.js +++ b/src/modules/processing/services/youtube.js @@ -24,6 +24,26 @@ const codecMatch = { } } +const transformSessionData = (cookie) => { + if (!cookie) + return; + + const values = cookie.values(); + const REQUIRED_VALUES = [ + 'access_token', 'refresh_token', + 'client_id', 'client_secret', + 'expires' + ]; + + if (REQUIRED_VALUES.some(x => typeof values[x] !== 'string')) { + return; + } + return { + ...values, + expires: new Date(values.expires), + }; +} + const cloneInnertube = async (customFetch) => { const innertube = await ytBase; if (innertube instanceof Error) { @@ -41,6 +61,17 @@ const cloneInnertube = async (customFetch) => { innertube.session.cache ); + const oauthData = transformSessionData(getCookie('youtube_oauth')); + + if (!session.logged_in && oauthData) { + await session.oauth.init(oauthData); + session.logged_in = true; + } + + if (session.logged_in) { + await session.oauth.refreshIfRequired(); + } + const yt = new Innertube(session); return yt; } @@ -62,7 +93,7 @@ export default async function(o) { } try { - info = await yt.getBasicInfo(o.id, 'IOS'); + info = await yt.getBasicInfo(o.id, yt.session.logged_in ? 'ANDROID' : 'IOS'); } catch(e) { if (e?.message === 'This video is unavailable') { return { error: 'ErrorCouldntFetch' }; diff --git a/src/modules/sub/generate-youtube-tokens.js b/src/modules/sub/generate-youtube-tokens.js new file mode 100644 index 00000000..26a6a1cd --- /dev/null +++ b/src/modules/sub/generate-youtube-tokens.js @@ -0,0 +1,30 @@ +import { Innertube } from 'youtubei.js'; + +const bail = (...msg) => (console.error(...msg), process.exit(1)); +const tube = await Innertube.create(); + +tube.session.once( + 'auth-pending', + ({ verification_url, user_code }) => console.log( + `Open ${verification_url} in a browser and enter ${user_code} when asked for the code.` + ) +); + +tube.session.once('auth-error', (err) => bail('An error occurred:', err)); +tube.session.once('auth', ({ status, credentials, ...rest }) => { + if (status !== 'SUCCESS') { + bail('something went wrong', rest); + } + + console.log(credentials); + + console.log( + JSON.stringify( + Object.entries(credentials) + .map(([k, v]) => `${k}=${v instanceof Date ? v.toISOString() : v}`) + .join('; ') + ) + ); +}); + +await tube.session.signIn(); \ No newline at end of file From 18d43729385336a0df8671133724641fd41a5769 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 09:26:58 +0000 Subject: [PATCH 2/8] youtube: drop cookie support it never really worked --- src/modules/processing/services/youtube.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/processing/services/youtube.js b/src/modules/processing/services/youtube.js index 301b37b7..3ad956d9 100644 --- a/src/modules/processing/services/youtube.js +++ b/src/modules/processing/services/youtube.js @@ -56,7 +56,7 @@ const cloneInnertube = async (customFetch) => { innertube.session.api_version, innertube.session.account_index, innertube.session.player, - getCookie('youtube')?.toString(), + undefined, customFetch ?? innertube.session.http.fetch, innertube.session.cache ); From 2387fc2fbb85590efa8040400044e4b41a60d560 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 09:30:12 +0000 Subject: [PATCH 3/8] youtube: update access token on change --- src/modules/processing/services/youtube.js | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/modules/processing/services/youtube.js b/src/modules/processing/services/youtube.js index 3ad956d9..49de029b 100644 --- a/src/modules/processing/services/youtube.js +++ b/src/modules/processing/services/youtube.js @@ -2,7 +2,7 @@ import { Innertube, Session } from 'youtubei.js'; import { env } from '../../config.js'; import { cleanString } from '../../sub/utils.js'; import { fetch } from 'undici' -import { getCookie } from '../cookie/manager.js' +import { getCookie, updateCookieValues } from '../cookie/manager.js' const ytBase = Innertube.create().catch(e => e); @@ -61,7 +61,8 @@ const cloneInnertube = async (customFetch) => { innertube.session.cache ); - const oauthData = transformSessionData(getCookie('youtube_oauth')); + const cookie = getCookie('youtube_oauth'); + const oauthData = transformSessionData(cookie); if (!session.logged_in && oauthData) { await session.oauth.init(oauthData); @@ -70,6 +71,15 @@ const cloneInnertube = async (customFetch) => { if (session.logged_in) { await session.oauth.refreshIfRequired(); + const oldExpiry = new Date(cookie.values().expires); + const newExpiry = session.oauth.credentials.expires; + + if (oldExpiry.getTime() !== newExpiry.getTime()) { + updateCookieValues(cookie, { + ...session.oauth.credentials, + expires: session.oauth.credentials.expires.toISOString() + }); + } } const yt = new Innertube(session); From d08e2ac04f3393d3bc7c0b582ed1bfb4053824b0 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 09:32:23 +0000 Subject: [PATCH 4/8] generate-youtube-tokens: use throw instead of process.exit fuck off deepsource --- src/modules/sub/generate-youtube-tokens.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/sub/generate-youtube-tokens.js b/src/modules/sub/generate-youtube-tokens.js index 26a6a1cd..65d64494 100644 --- a/src/modules/sub/generate-youtube-tokens.js +++ b/src/modules/sub/generate-youtube-tokens.js @@ -1,6 +1,10 @@ import { Innertube } from 'youtubei.js'; -const bail = (...msg) => (console.error(...msg), process.exit(1)); +const bail = (...msg) => { + console.error(...msg); + throw new Error(msg); +}; + const tube = await Innertube.create(); tube.session.once( From 9e09bcab6ea1c38dde3793a6df75933e095e3901 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 11:52:36 +0000 Subject: [PATCH 5/8] refactor: create `util` directory, move tests to it --- package.json | 4 ++-- src/{test => util}/test.js | 2 +- src/{test => util}/testFilenamePresets.js | 0 src/{test => util}/tests.json | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename src/{test => util}/test.js (98%) rename src/{test => util}/testFilenamePresets.js (100%) rename src/{test => util}/tests.json (100%) diff --git a/package.json b/package.json index 72104aba..52640702 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "scripts": { "start": "node src/cobalt", "setup": "node src/modules/setup", - "test": "node src/test/test", + "test": "node src/util/test", "build": "node src/modules/buildStatic", - "testFilenames": "node src/test/testFilenamePresets" + "testFilenames": "node src/util/testFilenamePresets" }, "repository": { "type": "git", diff --git a/src/test/test.js b/src/util/test.js similarity index 98% rename from src/test/test.js rename to src/util/test.js index f26f3b95..294ff7e7 100644 --- a/src/test/test.js +++ b/src/util/test.js @@ -9,7 +9,7 @@ import { normalizeRequest } from "../modules/processing/request.js"; import { env } from "../modules/config.js"; env.apiURL = 'http://localhost:9000' -let tests = loadJSON('./src/test/tests.json'); +let tests = loadJSON('./src/util/tests.json'); let noTest = []; let failed = []; diff --git a/src/test/testFilenamePresets.js b/src/util/testFilenamePresets.js similarity index 100% rename from src/test/testFilenamePresets.js rename to src/util/testFilenamePresets.js diff --git a/src/test/tests.json b/src/util/tests.json similarity index 100% rename from src/test/tests.json rename to src/util/tests.json From ebe6668bc0c631a34a94a853efea2ecf24f1087b Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 11:52:53 +0000 Subject: [PATCH 6/8] refactor: move generate-youtube-tokens to `util` --- src/{modules/sub => util}/generate-youtube-tokens.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{modules/sub => util}/generate-youtube-tokens.js (100%) diff --git a/src/modules/sub/generate-youtube-tokens.js b/src/util/generate-youtube-tokens.js similarity index 100% rename from src/modules/sub/generate-youtube-tokens.js rename to src/util/generate-youtube-tokens.js From 6c1d8ef6c75cfcdb1cdd66278c43bfd8b15138e7 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 11:54:33 +0000 Subject: [PATCH 7/8] generate-youtube-tokens: add more explanatory text and clean up logging --- src/util/generate-youtube-tokens.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/util/generate-youtube-tokens.js b/src/util/generate-youtube-tokens.js index 65d64494..924afb13 100644 --- a/src/util/generate-youtube-tokens.js +++ b/src/util/generate-youtube-tokens.js @@ -1,4 +1,5 @@ import { Innertube } from 'youtubei.js'; +import { Red } from '../modules/sub/consoleText.js' const bail = (...msg) => { console.error(...msg); @@ -9,9 +10,13 @@ const tube = await Innertube.create(); tube.session.once( 'auth-pending', - ({ verification_url, user_code }) => console.log( - `Open ${verification_url} in a browser and enter ${user_code} when asked for the code.` - ) + ({ verification_url, user_code }) => { + console.log(`${Red('[!]')} The token generated by this script is sensitive and you should not share it with anyone!`); + console.log(` By using this token, you are risking your Google account getting terminated.`); + console.log(` You should ${Red('NOT')} use your personal account!`); + console.log(); + console.log(`Open ${verification_url} in a browser and enter ${user_code} when asked for the code.`); + } ); tube.session.once('auth-error', (err) => bail('An error occurred:', err)); @@ -20,9 +25,8 @@ tube.session.once('auth', ({ status, credentials, ...rest }) => { bail('something went wrong', rest); } - console.log(credentials); - console.log( + 'add this cookie to the youtube_oauth array in your cookies file:', JSON.stringify( Object.entries(credentials) .map(([k, v]) => `${k}=${v instanceof Date ? v.toISOString() : v}`) From a84d0ddc772218fd5f74ec62aee8d95783425428 Mon Sep 17 00:00:00 2001 From: dumbmoron Date: Sat, 8 Jun 2024 12:05:18 +0000 Subject: [PATCH 8/8] package.json: remove testFilenames script, add youtube token generation --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 52640702..7d271fea 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "setup": "node src/modules/setup", "test": "node src/util/test", "build": "node src/modules/buildStatic", - "testFilenames": "node src/util/testFilenamePresets" + "token:youtube": "node src/util/generate-youtube-tokens" }, "repository": { "type": "git",