diff --git a/README.md b/README.md index 611b17a3..1451e9fe 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ - Mini player. - Silence skipper (Experimental.) - ffmpeg integration for downloading videos with audio at any quality ([Configuration required](./docs/DOCKER.md#step-7-optional-enabling-downloads)). -- [YouTube.js](https://github.com/LuanRT/YouTube.js) fallback if Invidious fails loading videos for Desktop & Android. +- [YouTube.js](https://github.com/LuanRT/YouTube.js) fallback if Invidious fails loading videos for Desktop. - Preview video on hover. - Sponsorblock built-in. - Return YouTube dislikes built-in. diff --git a/materialious/electron/package.json b/materialious/electron/package.json index 37da5c3b..cc127024 100644 --- a/materialious/electron/package.json +++ b/materialious/electron/package.json @@ -27,7 +27,8 @@ "electron-unhandled": "^4.0.1", "electron-updater": "^6.3.4", "electron-window-state": "^5.0.3", - "jsonfile": "^6.1.0" + "jsonfile": "^6.1.0", + "youtube-po-token-generator": "^0.2.0" }, "devDependencies": { "electron": "^32.1.0", @@ -39,4 +40,4 @@ "capacitor", "electron" ] -} \ No newline at end of file +} diff --git a/materialious/electron/src/preload.ts b/materialious/electron/src/preload.ts index c817d3b7..92641d9c 100644 --- a/materialious/electron/src/preload.ts +++ b/materialious/electron/src/preload.ts @@ -1,4 +1,6 @@ require('./rt/electron-rt'); -////////////////////////////// -// User Defined Preload scripts below -console.log('User Preload!'); +const { contextBridge, ipcRenderer } = require('electron'); + +contextBridge.exposeInMainWorld('electron', { + generatePoToken: () => ipcRenderer.invoke('generate-po-token') +}); diff --git a/materialious/electron/src/setup.ts b/materialious/electron/src/setup.ts index dbfe60b2..2e265b8d 100644 --- a/materialious/electron/src/setup.ts +++ b/materialious/electron/src/setup.ts @@ -6,11 +6,12 @@ import { } from '@capacitor-community/electron'; import chokidar from 'chokidar'; import type { MenuItemConstructorOptions } from 'electron'; -import { app, BrowserWindow, Menu, MenuItem, nativeImage, session, Tray } from 'electron'; +import { app, BrowserWindow, ipcMain, Menu, MenuItem, nativeImage, session, Tray } from 'electron'; import electronIsDev from 'electron-is-dev'; import electronServe from 'electron-serve'; import windowStateKeeper from 'electron-window-state'; import { join } from 'path'; +import { generate } from 'youtube-po-token-generator'; // Define components for a watcher to detect when the webapp is changed so we can reload in Dev mode. const reloadWatcher = { @@ -214,6 +215,15 @@ export class ElectronCapacitorApp { CapElectronEventEmitter.emit('CAPELECTRON_DeeplinkListenerInitialized', ''); }, 400); }); + + ipcMain.handle('generate-po-token', async () => { + try { + return await generate(); + } catch (error) { + console.error('Error generating token:', error); + return { error: error.message }; // Return error to renderer + } + }); } } diff --git a/materialious/src/lib/Api/index.ts b/materialious/src/lib/Api/index.ts index 1956260d..d4c05e0f 100644 --- a/materialious/src/lib/Api/index.ts +++ b/materialious/src/lib/Api/index.ts @@ -72,7 +72,7 @@ export async function getPopular(): Promise { export async function getVideo(videoId: string, local: boolean = false): Promise { const resp = await fetch(setRegion(buildPath(`videos/${videoId}?local=${local}`))); - if (!resp.ok && Capacitor.getPlatform() !== 'web' && get(playerYouTubeJsFallback)) { + if (!resp.ok && Capacitor.getPlatform() === 'electron' && get(playerYouTubeJsFallback)) { return await patchYoutubeJs(videoId); } else { await fetchErrorHandle(resp); diff --git a/materialious/src/lib/Settings.svelte b/materialious/src/lib/Settings.svelte index 3684356b..d91889a0 100644 --- a/materialious/src/lib/Settings.svelte +++ b/materialious/src/lib/Settings.svelte @@ -31,8 +31,6 @@ playerSavePlaybackPositionStore, playerTheatreModeByDefaultStore, playerYouTubeJsFallback, - playerYouTubeJsPoToken, - playerYouTubeJsVisitorData, returnYTDislikesInstanceStore, returnYtDislikesStore, silenceSkipperStore, @@ -50,8 +48,6 @@ sponsorBlockCategoriesStore.subscribe((value) => (sponsorCategoriesList = value)); let sponsorBlockInstance = get(sponsorBlockUrlStore); - let youTubeJsVisitorData = get(playerYouTubeJsVisitorData); - let youTubeJsPoToken = get(playerYouTubeJsPoToken); let synciousInstance = get(synciousInstanceStore); let returnYTInstance = get(returnYTDislikesInstanceStore); let invidiousInstance = get(instanceStore); @@ -445,7 +441,7 @@ - {#if Capacitor.getPlatform() !== 'web'} + {#if Capacitor.getPlatform() === 'electron'}
- -
{ - playerYouTubeJsVisitorData.set(youTubeJsVisitorData); - }} - > - -
- -
{ - playerYouTubeJsPoToken.set(youTubeJsPoToken); - }} - > - -
{/if} diff --git a/materialious/src/lib/patches/youtubejs.ts b/materialious/src/lib/patches/youtubejs.ts index fa143aec..dd96ec86 100644 --- a/materialious/src/lib/patches/youtubejs.ts +++ b/materialious/src/lib/patches/youtubejs.ts @@ -1,21 +1,15 @@ import type { Image, Thumbnail, VideoBase, VideoPlay } from '$lib/Api/model'; import { numberWithCommas } from '$lib/misc'; -import { playerYouTubeJsPoToken, playerYouTubeJsVisitorData } from '$lib/store'; -import { get } from 'svelte/store'; export async function patchYoutubeJs(videoId: string): Promise { const innertube = (await import('youtubei.js')).Innertube; - let innertubeConfig: Record = { - visitor_data: get(playerYouTubeJsVisitorData), - po_token: get(playerYouTubeJsPoToken) - }; + const tokens = await window.electron.generatePoToken(); - if (innertubeConfig.visitor_data === '' || innertubeConfig.po_token === '') { - innertubeConfig = {}; - } - - const youtube = await innertube.create(innertubeConfig); + const youtube = await innertube.create({ + visitor_data: tokens.visitorData, + po_token: tokens.poToken + }); const video = await youtube.getInfo(videoId); diff --git a/materialious/src/lib/store.ts b/materialious/src/lib/store.ts index a48c000e..37055dc5 100644 --- a/materialious/src/lib/store.ts +++ b/materialious/src/lib/store.ts @@ -40,8 +40,6 @@ export const playerAutoplayNextByDefaultStore = persisted('autoplayNextByDefault export const playerMiniPlayerStore = persisted('miniPlayer', true); export const playerAndroidBackgroundPlayStore = persisted('androidBackgroundPlayer', true); export const playerYouTubeJsFallback = persisted('youTubeJsFallback', true); -export const playerYouTubeJsVisitorData = persisted('youTubeJsVisitorData', ''); -export const playerYouTubeJsPoToken = persisted('youTubeJsPoToken', ''); export const returnYtDislikesStore = persisted('returnYtDislikes', false); export const returnYTDislikesInstanceStore: Writable = persisted(