From e86f75e0fb2bffa9d8ecb302e8c94c3cd9e56797 Mon Sep 17 00:00:00 2001 From: WardPearce Date: Thu, 4 Apr 2024 17:03:31 +1300 Subject: [PATCH] Added dearrow --- README.md | 8 +++ docker-compose.yml | 2 + materialious/src/lib/Api/index.ts | 19 ++++++- materialious/src/lib/Api/model.ts | 19 +++++++ materialious/src/lib/Player.svelte | 10 +--- materialious/src/lib/Thumbnail.svelte | 77 ++++++++++++++++++++++++-- materialious/src/lib/misc.ts | 14 ++++- materialious/src/routes/+layout.svelte | 61 +++++++++++++++----- materialious/src/store.ts | 6 +- 9 files changed, 183 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 99ab2d4a..6ee628a0 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ # Features - Sponsorblock built-in. - Return YouTube dislikes built-in. +- DeArrow built-in (With local processing fallback). - Video progress tracking & resuming. - No ads. - No tracking. @@ -150,6 +151,12 @@ services: # URL to Sponsorblock VITE_DEFAULT_SPONSERBLOCK_INSTANCE: "https://sponsor.ajay.app" + + # URL to DeArrow + VITE_DEFAULT_DEARROW_INSTANCE: "https://sponsor.ajay.app" + + # URL to DeArrow thumbnail instance + VITE_DEFAULT_DEARROW_THUMBNAIL_INSTANCE: "https://dearrow-thumb.ajay.app" ``` # Previews @@ -175,6 +182,7 @@ services: # Special thanks to - [Invidious](https://github.com/iv-org) +- [Clipious](https://github.com/lamarios/clipious) for inspiration & a good source for learning more about undocumented Invidious routes. - [Vidstack player](https://github.com/vidstack/player) - [Beer CSS](https://github.com/beercss/beercss) (Especially the [YouTube template](https://github.com/beercss/beercss/tree/main/src/youtube) what was used as the base for Materialious.) - Every dependency in [package.json](/materialious/package.json). diff --git a/docker-compose.yml b/docker-compose.yml index e30e3a16..10bfb5e1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -10,4 +10,6 @@ services: VITE_DEFAULT_RETURNYTDISLIKES_INSTANCE: "https://returnyoutubedislikeapi.com" VITE_DEFAULT_FRONTEND_URL: "https://materialio.us" VITE_DEFAULT_SPONSERBLOCK_INSTANCE: "https://sponsor.ajay.app" + VITE_DEFAULT_DEARROW_INSTANCE: "https://sponsor.ajay.app" + VITE_DEFAULT_DEARROW_THUMBNAIL_INSTANCE: "https://dearrow-thumb.ajay.app" \ No newline at end of file diff --git a/materialious/src/lib/Api/index.ts b/materialious/src/lib/Api/index.ts index f0a67105..de658c84 100644 --- a/materialious/src/lib/Api/index.ts +++ b/materialious/src/lib/Api/index.ts @@ -1,6 +1,6 @@ import { get } from 'svelte/store'; -import { auth, returnYTDislikesInstance } from '../../store'; -import type { Channel, ChannelContentPlaylists, ChannelContentVideos, ChannelPage, Comments, Playlist, PlaylistPage, ReturnYTDislikes, SearchSuggestion, Subscription, Video, VideoPlay } from './model'; +import { auth, deArrowInstance, deArrowThumbnailInstance, returnYTDislikesInstance } from '../../store'; +import type { Channel, ChannelContentPlaylists, ChannelContentVideos, ChannelPage, Comments, DeArrow, Playlist, PlaylistPage, ReturnYTDislikes, SearchSuggestion, Subscription, Video, VideoPlay } from './model'; export function buildPath(path: string): string { return `${import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE}/api/v1/${path}`; @@ -221,4 +221,19 @@ export async function addPlaylistVideo(playlistId: string, videoId: string) { }), ...headers })); +} + +export async function getDeArrow(videoId: string): Promise { + const resp = await fetchErrorHandle( + await fetch(`${get(deArrowInstance)}/api/branding?videoID=${videoId}` + ) + ); + return await resp.json(); +} + +export async function getThumbnail(videoId: string, time: number): Promise { + const resp = await fetchErrorHandle( + await fetch(`${get(deArrowThumbnailInstance)}/api/v1/getThumbnail?videoID=${videoId}&time=${time}`) + ); + return URL.createObjectURL(await resp.blob()); } \ No newline at end of file diff --git a/materialious/src/lib/Api/model.ts b/materialious/src/lib/Api/model.ts index e396b2f0..a9c574e5 100644 --- a/materialious/src/lib/Api/model.ts +++ b/materialious/src/lib/Api/model.ts @@ -230,4 +230,23 @@ export interface Feed { export interface Subscription { author: string; authorId: string; +} + +export interface DeArrow { + titles: { + title: string; + original: boolean; + votes: number; + locked: boolean; + UUID: string; + }[]; + thumbnails: { + timestamp?: number; + original: boolean; + votes: number; + locked: boolean; + UUID: string; + }[]; + randomTime: number; + videoDuration: number; } \ No newline at end of file diff --git a/materialious/src/lib/Player.svelte b/materialious/src/lib/Player.svelte index e092a979..a916803a 100644 --- a/materialious/src/lib/Player.svelte +++ b/materialious/src/lib/Player.svelte @@ -17,7 +17,7 @@ sponsorBlockUrl } from '../store'; import type { PlaylistPageVideo, VideoPlay } from './Api/model'; - import { videoLength, type PhasedDescription } from './misc'; + import { proxyVideoUrl, videoLength, type PhasedDescription } from './misc'; import { getDynamicTheme } from './theme'; export let data: { video: VideoPlay; content: PhasedDescription; playlistId: string | null }; @@ -138,13 +138,7 @@ let formattedSrc; src = data.video.formatStreams.map((format) => { if (proxyVideos) { - const rawSrc = new URL(format.url); - rawSrc.host = import.meta.env.VITE_DEFAULT_INVIDIOUS_INSTANCE.replace( - 'http://', - '' - ).replace('https://', ''); - - formattedSrc = rawSrc.toString(); + formattedSrc = proxyVideoUrl(format.url); } else { formattedSrc = format.url; } diff --git a/materialious/src/lib/Thumbnail.svelte b/materialious/src/lib/Thumbnail.svelte index 83f9457a..34efcccd 100644 --- a/materialious/src/lib/Thumbnail.svelte +++ b/materialious/src/lib/Thumbnail.svelte @@ -1,9 +1,10 @@