allow to set specific directory for cache + various envs
This commit is contained in:
parent
fa2fda8b72
commit
be1f4bee39
11 changed files with 135 additions and 22 deletions
72
.github/workflows/docker-build-push.yaml
vendored
Normal file
72
.github/workflows/docker-build-push.yaml
vendored
Normal file
|
@ -0,0 +1,72 @@
|
|||
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:
|
||||
- 'Cargo.lock'
|
||||
- 'LICENSE'
|
||||
- 'README.md'
|
||||
- 'docker-compose.yml'
|
||||
workflow_dispatch: # Allow manual triggering of the workflow
|
||||
|
||||
# Define environment variables used throughout the workflow
|
||||
env:
|
||||
REGISTRY: quay.io
|
||||
IMAGE_NAME: invidious/invidious-companion
|
||||
|
||||
jobs:
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# Step 1: Check out the repository code
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Step 2: Set up QEMU for multi-architecture builds
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
|
||||
# Step 3: Set up Docker Buildx for enhanced build capabilities
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
# Step 4: Authenticate with Quay.io registry
|
||||
- name: Log in to Quay.io
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ secrets.QUAY_USERNAME }}
|
||||
password: ${{ secrets.QUAY_PASSWORD }}
|
||||
|
||||
# Step 5: 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 6: 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,linux/arm64 # Build for multiple architectures
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
|
@ -26,6 +26,9 @@ COPY --from=builder /app/invidious_companion /app/
|
|||
COPY ./config/ /app/config/
|
||||
COPY --from=builder /tini /tini
|
||||
|
||||
ENV PORT=8282 \
|
||||
HOST=0.0.0.0
|
||||
|
||||
# Copy passwd file for the non-privileged user from the user-stage
|
||||
COPY --from=user-stage /etc/passwd /etc/passwd
|
||||
|
||||
|
|
|
@ -6,6 +6,9 @@ base_url = "http://localhost:8282"
|
|||
|
||||
[cache]
|
||||
enabled = true
|
||||
# will get cached in /var/tmp/youtubei.js if you specify /var/tmp
|
||||
# you need to change the --allow-write from deno run too
|
||||
directory = "/var/tmp"
|
||||
|
||||
[networking]
|
||||
#proxy = ""
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"tasks": {
|
||||
"dev": "deno run --allow-net --allow-env --allow-read --allow-sys=hostname --allow-write=./,/tmp/youtubei.js --watch src/main.ts",
|
||||
"compile": "deno compile --output invidious_companion --allow-net --allow-env --allow-sys=hostname --allow-read src/main.ts"
|
||||
"dev": "deno run --allow-net --allow-env --allow-sys=hostname --allow-write=/var/tmp/youtubei.js --watch src/main.ts",
|
||||
"compile": "deno compile --output invidious_companion --allow-net --allow-env --allow-read --allow-sys=hostname --allow-write=/var/tmp/youtubei.js src/main.ts"
|
||||
},
|
||||
"imports": {
|
||||
"hono": "jsr:@hono/hono@^4.6.5",
|
||||
|
@ -9,9 +9,10 @@
|
|||
"hono/bearer-auth": "jsr:@hono/hono@^4.6.5/bearer-auth",
|
||||
"youtubei.js": "https://deno.land/x/youtubei@v11.0.1-deno/deno.ts",
|
||||
"youtubei.js/endpoints": "https://deno.land/x/youtubei@v11.0.1-deno/deno/src/core/endpoints/index.ts",
|
||||
"youtubei.js/Utils": "https://deno.land/x/youtubei@v11.0.1-deno/deno/src/utils/Utils.ts",
|
||||
"jsdom": "https://esm.sh/jsdom@25.0.1",
|
||||
"bgutils": "https://esm.sh/bgutils-js@3.0.0",
|
||||
"estree": "npm:@types/estree",
|
||||
"estree": "https://esm.sh/@types/estree@1.0.6",
|
||||
"@willsoto/node-konfig-core": "npm:@willsoto/node-konfig-core@5.0.0",
|
||||
"@willsoto/node-konfig-file": "npm:@willsoto/node-konfig-file@3.0.0",
|
||||
"@willsoto/node-konfig-toml-parser": "npm:@willsoto/node-konfig-toml-parser@3.0.0",
|
||||
|
|
|
@ -740,7 +740,6 @@
|
|||
"workspace": {
|
||||
"dependencies": [
|
||||
"jsr:@hono/hono@^4.6.5",
|
||||
"npm:@types/estree",
|
||||
"npm:@willsoto/node-konfig-core@5.0.0",
|
||||
"npm:@willsoto/node-konfig-file@3.0.0",
|
||||
"npm:@willsoto/node-konfig-toml-parser@3.0.0"
|
||||
|
|
19
docker-compose.yaml
Normal file
19
docker-compose.yaml
Normal file
|
@ -0,0 +1,19 @@
|
|||
version: "3"
|
||||
services:
|
||||
invidious_companion:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
# image: quay.io/invidious/invidious-companion:latest
|
||||
ports:
|
||||
- 127.0.0.1:8282:8282
|
||||
restart: unless-stopped
|
||||
cap_drop:
|
||||
- ALL
|
||||
read_only: true
|
||||
user: 10001:10001
|
||||
# cache for youtube library
|
||||
volumes:
|
||||
- /var/tmp/youtubei.js:/var/tmp/youtubei.js:rw
|
||||
security_opt:
|
||||
- no-new-privileges:true
|
|
@ -6,14 +6,14 @@ export const getFetchClient = (konfigStore: Store): {
|
|||
client: Deno.HttpClient;
|
||||
}): Promise<Response>;
|
||||
} => {
|
||||
if (konfigStore.get("networking.proxy")) {
|
||||
if (Deno.env.get("PROXY") || konfigStore.get("networking.proxy")) {
|
||||
return async (
|
||||
input: RequestInfo | URL,
|
||||
init?: RequestInit,
|
||||
) => {
|
||||
const client = Deno.createHttpClient({
|
||||
proxy: {
|
||||
url: konfigStore.get("networking.proxy") as string,
|
||||
url: Deno.env.get("PROXY") || konfigStore.get("networking.proxy") as string,
|
||||
},
|
||||
});
|
||||
const fetchRes = await fetch(input, {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Innertube, YT, ApiResponse } from "youtubei.js";
|
||||
import { generateRandomString } from "youtubei.js/Utils";
|
||||
import { compress, decompress } from "https://deno.land/x/brotli@0.1.7/mod.ts";
|
||||
import { youtubePlayerReq } from "youtubePlayerReq";
|
||||
import { Store } from "@willsoto/node-konfig-core";
|
||||
|
@ -28,7 +29,7 @@ export const youtubePlayerParsing = async (
|
|||
const video = new YT.VideoInfo(
|
||||
[youtubePlayerResponse],
|
||||
innertubeClient.actions,
|
||||
"",
|
||||
generateRandomString(16),
|
||||
);
|
||||
|
||||
const streamingData = video.streaming_data;
|
||||
|
@ -89,7 +90,7 @@ export const youtubePlayerParsing = async (
|
|||
videoDetails,
|
||||
microformat,
|
||||
invidiousCompanion: {
|
||||
"baseUrl": konfigStore.get("server.base_url") as string,
|
||||
"baseUrl": Deno.env.get("SERVER_BASE_URL") || konfigStore.get("server.base_url") as string,
|
||||
},
|
||||
}))(videoData);
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import { getFetchClient } from "../helpers/getFetchClient.ts";
|
|||
export const poTokenGenerate = async (
|
||||
innertubeClient: Innertube,
|
||||
konfigStore: Store<Record<string, unknown>>,
|
||||
innertubeClientCache: UniversalCache
|
||||
): Promise<Innertube> => {
|
||||
const requestKey = "O43z0dpjhgX20SCx4KAo";
|
||||
|
||||
|
@ -62,7 +63,7 @@ export const poTokenGenerate = async (
|
|||
po_token: poTokenResult.poToken,
|
||||
visitor_data: visitorData,
|
||||
fetch: getFetchClient(konfigStore),
|
||||
cache: new UniversalCache(true),
|
||||
cache: innertubeClientCache,
|
||||
generate_session_locally: true,
|
||||
}));
|
||||
};
|
||||
|
|
38
src/main.ts
38
src/main.ts
|
@ -6,11 +6,9 @@ import { konfigLoader } from "./lib/helpers/konfigLoader.ts";
|
|||
import { getFetchClient } from "./lib/helpers/getFetchClient.ts";
|
||||
|
||||
const app = new Hono();
|
||||
|
||||
const konfigStore = await konfigLoader();
|
||||
|
||||
let innertubeClient: Innertube;
|
||||
let innertubeClientUniversalCache = true;
|
||||
let innertubeClientFetchPlayer = true;
|
||||
const innertubeClientOauthEnabled = konfigStore.get(
|
||||
"youtube_session.oauth_enabled",
|
||||
|
@ -21,6 +19,12 @@ const innertubeClientJobPoTokenEnabled = konfigStore.get(
|
|||
const innertubeClientCookies = konfigStore.get(
|
||||
"jobs.youtube_session.cookies",
|
||||
) as string;
|
||||
let innertubeClientCache = new UniversalCache(
|
||||
true,
|
||||
konfigStore.get('cache.directory') as string + "/youtubei.js/",
|
||||
) as UniversalCache;
|
||||
|
||||
Deno.env.set('TMPDIR', konfigStore.get("cache.directory") as string)
|
||||
|
||||
if (!innertubeClientOauthEnabled) {
|
||||
if (innertubeClientJobPoTokenEnabled) {
|
||||
|
@ -32,29 +36,37 @@ if (!innertubeClientOauthEnabled) {
|
|||
}
|
||||
} else if (innertubeClientOauthEnabled) {
|
||||
// Can't use cache if using OAuth#cacheCredentials
|
||||
innertubeClientUniversalCache = false;
|
||||
innertubeClientCache = new UniversalCache(false);
|
||||
}
|
||||
|
||||
innertubeClient = await Innertube.create({
|
||||
cache: new UniversalCache(innertubeClientUniversalCache),
|
||||
cache: innertubeClientCache,
|
||||
retrieve_player: innertubeClientFetchPlayer,
|
||||
fetch: getFetchClient(konfigStore),
|
||||
cookie: innertubeClientCookies || undefined
|
||||
cookie: innertubeClientCookies || undefined,
|
||||
});
|
||||
|
||||
if (!innertubeClientOauthEnabled) {
|
||||
if (innertubeClientOauthEnabled) {
|
||||
innertubeClient = await poTokenGenerate(innertubeClient, konfigStore);
|
||||
innertubeClient = await poTokenGenerate(
|
||||
innertubeClient,
|
||||
konfigStore,
|
||||
innertubeClientCache as UniversalCache,
|
||||
);
|
||||
}
|
||||
Deno.cron(
|
||||
"regenerate youtube session",
|
||||
konfigStore.get("jobs.youtube_session.frequency") as string,
|
||||
async () => {
|
||||
if (innertubeClientOauthEnabled) {
|
||||
innertubeClient = await poTokenGenerate(innertubeClient, konfigStore);
|
||||
innertubeClient = await poTokenGenerate(
|
||||
innertubeClient,
|
||||
konfigStore,
|
||||
innertubeClientCache,
|
||||
);
|
||||
} else {
|
||||
innertubeClient = await Innertube.create({
|
||||
cache: new UniversalCache(innertubeClientUniversalCache),
|
||||
cache: innertubeClientCache,
|
||||
retrieve_player: innertubeClientFetchPlayer,
|
||||
});
|
||||
}
|
||||
|
@ -62,8 +74,10 @@ if (!innertubeClientOauthEnabled) {
|
|||
);
|
||||
} else if (innertubeClientOauthEnabled) {
|
||||
// Fired when waiting for the user to authorize the sign in attempt.
|
||||
innertubeClient.session.on('auth-pending', (data) => {
|
||||
console.log(`Go to ${data.verification_url} in your browser and enter code ${data.user_code} to authenticate.`);
|
||||
innertubeClient.session.on("auth-pending", (data) => {
|
||||
console.log(
|
||||
`Go to ${data.verification_url} in your browser and enter code ${data.user_code} to authenticate.`,
|
||||
);
|
||||
});
|
||||
// Fired when authentication is successful.
|
||||
innertubeClient.session.on("auth", () => {
|
||||
|
@ -91,6 +105,6 @@ app.use("*", async (c, next) => {
|
|||
routes(app, konfigStore);
|
||||
|
||||
Deno.serve({
|
||||
port: konfigStore.get("server.port") as number,
|
||||
hostname: konfigStore.get("server.host") as string,
|
||||
port: Number(Deno.env.get("PORT")) || konfigStore.get("server.port") as number,
|
||||
hostname: Deno.env.get("HOST") || konfigStore.get("server.host") as string,
|
||||
}, app.fetch);
|
||||
|
|
|
@ -13,7 +13,7 @@ export const routes = (app: Hono, konfigStore: Store<Record<string, unknown>>) =
|
|||
app.use(
|
||||
"/youtubei/v1/*",
|
||||
bearerAuth({
|
||||
token: konfigStore.get("server.hmac_key") as string,
|
||||
token: Deno.env.get("SERVER_HMAC_KEY") || konfigStore.get("server.hmac_key") as string,
|
||||
}),
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue