commit 73143030f825e6634b43146bbc773b7218072158 Author: Fijxu Date: Mon Mar 24 19:45:57 2025 -0300 init commit with most of the current changes on my fork diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..db7255e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,77 @@ +name: Build and Push Docker Image + +# Define when this workflow will run +on: + push: + branches: + - master # Trigger on pushes to master branch + tags: + - '[0-9]+.[0-9]+.[0-9]+' # Trigger on semantic version tags + paths-ignore: + - '.gitignore' + - 'LICENSE' + - 'README.md' + - 'docker-compose.yml' + workflow_dispatch: # Allow manual triggering of the workflow + +# Define environment variables used throughout the workflow +env: + REGISTRY: git.nadeko.net + IMAGE_NAME: fijxu/invidious-companion + +jobs: + build-and-push: + runs-on: runner + + steps: + # Step 1: Check out the repository code + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'recursive' + + - name: Patch invidious-companion + run: | + cd ./invidious-companion + git config --global user.email "you@example.com" + git config --global user.name "Your Name" + git am ../patches/*.patch + + # Step 2: Set up Docker Buildx for enhanced build capabilities + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + # Step 3: Authenticate with Quay.io registry + - name: Login to Docker Container Registry (git.nadeko.net) + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ secrets.QUAY_USERNAME }} + password: ${{ secrets.QUAY_PASSWORD }} + + # Step 4: Extract metadata for Docker image tagging and labeling + - name: Extract metadata for Docker + id: meta + uses: docker/metadata-action@v4 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + # Define tagging strategy + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', 'master') }} + type=sha,prefix={{branch}}- + # Define labels + labels: | + quay.expires-after=12w + + # Step 5: Build and push the Docker image + - name: Build and push Docker image + uses: docker/build-push-action@v4 + with: + context: . + push: true + platforms: linux/amd64 + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..268c769 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "invidious-companion"] + path = invidious-companion + url = https://github.com/iv-org/invidious-companion diff --git a/apply-patches.sh b/apply-patches.sh new file mode 100755 index 0000000..5215f77 --- /dev/null +++ b/apply-patches.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd ./invidious-companion +git am ../patches/*.patch \ No newline at end of file diff --git a/format-patches.sh b/format-patches.sh new file mode 100755 index 0000000..6290455 --- /dev/null +++ b/format-patches.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd ./invidious-companion +git format-patch origin/HEAD --output-directory ../patches \ No newline at end of file diff --git a/invidious-companion b/invidious-companion new file mode 160000 index 0000000..fb01e84 --- /dev/null +++ b/invidious-companion @@ -0,0 +1 @@ +Subproject commit fb01e84ec63d28f23dd54f8b899cc10a636c863f diff --git a/patches/0001-feat-add-support-for-an-external-videoplayback-proxy.patch b/patches/0001-feat-add-support-for-an-external-videoplayback-proxy.patch new file mode 100644 index 0000000..ab0f383 --- /dev/null +++ b/patches/0001-feat-add-support-for-an-external-videoplayback-proxy.patch @@ -0,0 +1,71 @@ +From e78a26c4f36bac6cb20d9c45568116c72c745d24 Mon Sep 17 00:00:00 2001 +From: Fijxu +Date: Mon, 24 Mar 2025 18:44:10 -0300 +Subject: [PATCH 1/6] feat: add support for an external videoplayback proxy + +--- + config/config.example.toml | 1 + + src/lib/helpers/config.ts | 3 +++ + src/routes/invidious_routes/dashManifest.ts | 5 +++-- + src/routes/invidious_routes/latestVersion.ts | 3 ++- + 4 files changed, 9 insertions(+), 3 deletions(-) + +diff --git a/config/config.example.toml b/config/config.example.toml +index c56b95b..e173e06 100644 +--- a/config/config.example.toml ++++ b/config/config.example.toml +@@ -26,6 +26,7 @@ + # #proxy = "" # env variable: PROXY + # # Enable YouTube new video format UMP + # ump = false ++# external_videoplayback_proxy = "" + + ### + # Network call timeouts when talking to YouTube. +diff --git a/src/lib/helpers/config.ts b/src/lib/helpers/config.ts +index edba9da..5ff4a2d 100644 +--- a/src/lib/helpers/config.ts ++++ b/src/lib/helpers/config.ts +@@ -26,6 +26,9 @@ const ConfigSchema = z.object({ + debounce_multiplier: z.number().optional(), + }).strict().optional(), + }).strict().optional(), ++ external_videoplayback_proxy: z.string().default( ++ Deno.env.get("EXTERNAL_VIDEOPLAYBACK_PROXY") || "", ++ ), + }).strict().default({}), + jobs: z.object({ + youtube_session: z.object({ +diff --git a/src/routes/invidious_routes/dashManifest.ts b/src/routes/invidious_routes/dashManifest.ts +index 2b796ba..46756cd 100644 +--- a/src/routes/invidious_routes/dashManifest.ts ++++ b/src/routes/invidious_routes/dashManifest.ts +@@ -85,8 +85,9 @@ dashManifest.get("/:videoId", async (c) => { + let dashUrl = url; + if (local) { + // Can't create URL type without host part +- dashUrl = (dashUrl.pathname + dashUrl.search + "&host=" + +- dashUrl.host) as unknown as URL; ++ dashUrl = config.networking.external_videoplayback_proxy + ++ (dashUrl.pathname + dashUrl.search + "&host=" + ++ dashUrl.host) as unknown as URL; + if (config.networking.ump) { + dashUrl = dashUrl + "&ump=1" as unknown as URL; + } +diff --git a/src/routes/invidious_routes/latestVersion.ts b/src/routes/invidious_routes/latestVersion.ts +index 191c0a4..a8ead67 100644 +--- a/src/routes/invidious_routes/latestVersion.ts ++++ b/src/routes/invidious_routes/latestVersion.ts +@@ -64,7 +64,8 @@ latestVersion.get("/", async (c) => { + const itagUrlParsed = new URL(itagUrl); + let urlToRedirect = itagUrlParsed.toString(); + if (local) { +- urlToRedirect = itagUrlParsed.pathname + itagUrlParsed.search + ++ urlToRedirect = config.networking.external_videoplayback_proxy + ++ itagUrlParsed.pathname + itagUrlParsed.search + + "&host=" + itagUrlParsed.host; + } + +-- +2.49.0 + diff --git a/patches/0002-feat-report-the-external-videoplayback-proxy-via-inf.patch b/patches/0002-feat-report-the-external-videoplayback-proxy-via-inf.patch new file mode 100644 index 0000000..f8c17a4 --- /dev/null +++ b/patches/0002-feat-report-the-external-videoplayback-proxy-via-inf.patch @@ -0,0 +1,56 @@ +From 004c812e80ad15f2a6699aaa69c8c4a2112b6830 Mon Sep 17 00:00:00 2001 +From: Fijxu +Date: Mon, 24 Mar 2025 18:52:53 -0300 +Subject: [PATCH 2/6] feat: report the external videoplayback proxy via /info + endpoint + +--- + src/routes/index.ts | 2 ++ + src/routes/info.ts | 17 +++++++++++++++++ + 2 files changed, 19 insertions(+) + create mode 100644 src/routes/info.ts + +diff --git a/src/routes/index.ts b/src/routes/index.ts +index e67b618..6448e3d 100644 +--- a/src/routes/index.ts ++++ b/src/routes/index.ts +@@ -10,6 +10,7 @@ import getDownloadHandler from "./invidious_routes/download.ts"; + import videoPlaybackProxy from "./videoPlaybackProxy.ts"; + import health from "./health.ts"; + import type { Config } from "../lib/helpers/config.ts"; ++import info from "./info.ts"; + + export const routes = ( + app: Hono, +@@ -32,4 +33,5 @@ export const routes = ( + app.route("/api/v1/captions", invidiousCaptionsApi); + app.route("/videoplayback", videoPlaybackProxy); + app.route("/healthz", health); ++ app.route("/info", info); + }; +diff --git a/src/routes/info.ts b/src/routes/info.ts +new file mode 100644 +index 0000000..423c297 +--- /dev/null ++++ b/src/routes/info.ts +@@ -0,0 +1,17 @@ ++import { Hono } from "hono"; ++ ++const info = new Hono(); ++ ++info.get("/", (c) => { ++ const config = c.get("config") ++ ++ const json = { ++ "external_videoplayback_proxy": config.networking.external_videoplayback_proxy ++ }; ++ return new Response(JSON.stringify(json), { ++ status: 200, ++ headers: { "Content-Type": "application/json" }, ++ }); ++}); ++ ++export default info; +-- +2.49.0 + diff --git a/patches/0003-feat-add-resolution-limit-on-DASH-streams-to-save-ba.patch b/patches/0003-feat-add-resolution-limit-on-DASH-streams-to-save-ba.patch new file mode 100644 index 0000000..d16f85a --- /dev/null +++ b/patches/0003-feat-add-resolution-limit-on-DASH-streams-to-save-ba.patch @@ -0,0 +1,59 @@ +From 58287cea5d7224147187376b74e2287e9e369ccb Mon Sep 17 00:00:00 2001 +From: Fijxu +Date: Mon, 24 Mar 2025 19:02:01 -0300 +Subject: [PATCH 3/6] feat: add resolution limit on DASH streams to save + bandwidth + +--- + config/config.example.toml | 1 + + src/lib/helpers/config.ts | 3 +++ + src/routes/invidious_routes/dashManifest.ts | 7 ++++++- + 3 files changed, 10 insertions(+), 1 deletion(-) + +diff --git a/config/config.example.toml b/config/config.example.toml +index e173e06..a3c73be 100644 +--- a/config/config.example.toml ++++ b/config/config.example.toml +@@ -15,6 +15,7 @@ + # # secret key needs to be 16 characters long or more + # secret_key = "CHANGE_ME" # env variable: SERVER_SECRET_KEY + # verify_requests = false ++# max_dash_resolution = 1080 + + # [cache] + # enabled = true +diff --git a/src/lib/helpers/config.ts b/src/lib/helpers/config.ts +index 5ff4a2d..1ad0125 100644 +--- a/src/lib/helpers/config.ts ++++ b/src/lib/helpers/config.ts +@@ -9,6 +9,9 @@ const ConfigSchema = z.object({ + Deno.env.get("SERVER_SECRET_KEY") || "", + ), + verify_requests: z.boolean().default(false), ++ max_dash_resolution: z.number().default( ++ Number(Deno.env.get("SERVER_MAX_DASH_RESOLUTION")), ++ ), + }).strict().default({}), + cache: z.object({ + enabled: z.boolean().default(true), +diff --git a/src/routes/invidious_routes/dashManifest.ts b/src/routes/invidious_routes/dashManifest.ts +index 46756cd..68ae21d 100644 +--- a/src/routes/invidious_routes/dashManifest.ts ++++ b/src/routes/invidious_routes/dashManifest.ts +@@ -61,7 +61,12 @@ dashManifest.get("/:videoId", async (c) => { + ).includes("av01") + ) { + if (i.mime_type.includes("av01")) { +- return true; ++ // @ts-ignore 'i.height' is possibly 'undefined'. ++ if (i.height > config.server.max_dash_resolution) { ++ return false; ++ } else { ++ return true; ++ } + } else { + return false; + } +-- +2.49.0 + diff --git a/patches/0004-feat-add-env-variable-to-set-verify_requests.patch b/patches/0004-feat-add-env-variable-to-set-verify_requests.patch new file mode 100644 index 0000000..5cce263 --- /dev/null +++ b/patches/0004-feat-add-env-variable-to-set-verify_requests.patch @@ -0,0 +1,27 @@ +From 4c9f43edffabeb8367fb74ef3017bec9a39227c6 Mon Sep 17 00:00:00 2001 +From: Fijxu +Date: Mon, 24 Mar 2025 19:06:04 -0300 +Subject: [PATCH 4/6] feat: add env variable to set verify_requests + +--- + src/lib/helpers/config.ts | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/lib/helpers/config.ts b/src/lib/helpers/config.ts +index 1ad0125..05748f0 100644 +--- a/src/lib/helpers/config.ts ++++ b/src/lib/helpers/config.ts +@@ -8,7 +8,9 @@ const ConfigSchema = z.object({ + secret_key: z.string().min(16).default( + Deno.env.get("SERVER_SECRET_KEY") || "", + ), +- verify_requests: z.boolean().default(false), ++ verify_requests: z.boolean().default( ++ Deno.env.get("VERIFY_REQUESTS") === "true" || false, ++ ), + max_dash_resolution: z.number().default( + Number(Deno.env.get("SERVER_MAX_DASH_RESOLUTION")), + ), +-- +2.49.0 + diff --git a/patches/0005-feat-add-support-for-multiple-proxies.patch b/patches/0005-feat-add-support-for-multiple-proxies.patch new file mode 100644 index 0000000..dded9e0 --- /dev/null +++ b/patches/0005-feat-add-support-for-multiple-proxies.patch @@ -0,0 +1,46 @@ +From 41f9a63113fc05a9f332a49dc85d14920066be0f Mon Sep 17 00:00:00 2001 +From: Fijxu +Date: Mon, 24 Mar 2025 19:20:52 -0300 +Subject: [PATCH 5/6] feat: add support for multiple proxies + +--- + src/lib/helpers/getFetchClient.ts | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/src/lib/helpers/getFetchClient.ts b/src/lib/helpers/getFetchClient.ts +index 7bdee90..4f657e1 100644 +--- a/src/lib/helpers/getFetchClient.ts ++++ b/src/lib/helpers/getFetchClient.ts +@@ -7,13 +7,28 @@ type FetchInitParameterWithClient = + | RequestInit & { client: Deno.HttpClient }; + type FetchReturn = ReturnType; + ++let proxies: string[] = []; ++let proxyData: string; ++try { ++ proxyData = Deno.readTextFileSync("proxies.txt"); ++ proxies = proxyData.split("\n").map((line) => line.trim()).filter((line) => ++ line.length > 0 ++ ); ++ console.log("[INFO] Number of proxies on the list:", proxies.length); ++} catch (error) { ++ console.error("[ERROR] Error reading proxy file:", error); ++ console.log("[INFO] Proxies from a list of proxies will not be used"); ++} ++ + export const getFetchClient = (config: Config): { + ( + input: FetchInputParameter, + init?: FetchInitParameterWithClient, + ): FetchReturn; + } => { +- const proxyAddress = config.networking.proxy; ++ const proxyAddress = config.networking.proxy || ++ (proxies.length > 0 ? proxies[Math.floor(Math.random() *proxies.length)] : null); ++ + if (proxyAddress) { + return async ( + input: FetchInputParameter, +-- +2.49.0 + diff --git a/patches/0006-ci-update-deno-to-2.2.4.patch b/patches/0006-ci-update-deno-to-2.2.4.patch new file mode 100644 index 0000000..aa0814d --- /dev/null +++ b/patches/0006-ci-update-deno-to-2.2.4.patch @@ -0,0 +1,22 @@ +From 9205a5b19f7f5e351bf00a30bbc7717bac321524 Mon Sep 17 00:00:00 2001 +From: Fijxu +Date: Mon, 24 Mar 2025 19:37:34 -0300 +Subject: [PATCH 6/6] ci: update deno to 2.2.4 + +--- + Dockerfile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Dockerfile b/Dockerfile +index 04b74c0..a6dc150 100644 +--- a/Dockerfile ++++ b/Dockerfile +@@ -1,4 +1,4 @@ +-FROM denoland/deno:debian-2.1.4 AS builder ++FROM denoland/deno:debian-2.2.4 AS builder + + ARG TINI_VERSION=0.19.0 + +-- +2.49.0 + diff --git a/reset-companion-repo.sh b/reset-companion-repo.sh new file mode 100755 index 0000000..369af72 --- /dev/null +++ b/reset-companion-repo.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +cd ./invidious-companion +git reset --hard origin/HEAD \ No newline at end of file