Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
24eafee3e9
10 changed files with 94 additions and 53 deletions
|
@ -48,3 +48,5 @@ WORKDIR /app
|
||||||
USER appuser
|
USER appuser
|
||||||
|
|
||||||
ENTRYPOINT ["/tini", "--", "/app/invidious_companion"]
|
ENTRYPOINT ["/tini", "--", "/app/invidious_companion"]
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=3 CMD ["/tini", "--", "/app/invidious_companion", "healthcheck"]
|
||||||
|
|
|
@ -19,6 +19,11 @@ proxy_file = "proxies.txt"
|
||||||
# Enable YouTube new video format UMP
|
# Enable YouTube new video format UMP
|
||||||
ump = false
|
ump = false
|
||||||
# external_videoplayback_proxy = ""
|
# external_videoplayback_proxy = ""
|
||||||
|
# fetch_timeout_ms = 10000
|
||||||
|
# fetch_retry_enable = true
|
||||||
|
# fetch_retry_times = 3
|
||||||
|
# fetch_retry_initial_debounce = 500
|
||||||
|
# fetch_retry_debounce_multiplier = 2
|
||||||
|
|
||||||
[jobs]
|
[jobs]
|
||||||
|
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
"hono/logger": "jsr:@hono/hono@^4.6.5/logger",
|
"hono/logger": "jsr:@hono/hono@^4.6.5/logger",
|
||||||
"hono/bearer-auth": "jsr:@hono/hono@^4.6.5/bearer-auth",
|
"hono/bearer-auth": "jsr:@hono/hono@^4.6.5/bearer-auth",
|
||||||
"prom-client": "npm:prom-client@^15.1.3",
|
"prom-client": "npm:prom-client@^15.1.3",
|
||||||
"youtubei.js": "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.0.0-deno/deno.ts",
|
"youtubei.js": "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.1.0-deno/deno.ts",
|
||||||
"youtubei.js/Utils": "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.0.0-deno/deno/src/utils/Utils.ts",
|
"youtubei.js/Utils": "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.1.0-deno/deno/src/utils/Utils.ts",
|
||||||
"youtubei.js/NavigationEndpoint": "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.0.0-deno/deno/src/parser/classes/NavigationEndpoint.ts",
|
"youtubei.js/NavigationEndpoint": "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.1.0-deno/deno/src/parser/classes/NavigationEndpoint.ts",
|
||||||
"jsdom": "npm:jsdom@25.0.1",
|
"jsdom": "npm:jsdom@25.0.1",
|
||||||
"bgutils": "https://esm.sh/bgutils-js@3.1.0",
|
"bgutils": "https://esm.sh/bgutils-js@3.1.0",
|
||||||
"estree": "https://esm.sh/@types/estree@1.0.6",
|
"estree": "https://esm.sh/@types/estree@1.0.6",
|
||||||
|
|
|
@ -1,4 +1,11 @@
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
import { Store } from "@willsoto/node-konfig-core";
|
||||||
|
import { retry, type RetryOptions } from "jsr:@std/async";
|
||||||
|
|
||||||
|
type FetchInputParameter = Parameters<typeof fetch>[0];
|
||||||
|
type FetchInitParameterWithClient =
|
||||||
|
| RequestInit
|
||||||
|
| RequestInit & { client: Deno.HttpClient };
|
||||||
|
type FetchReturn = ReturnType<typeof fetch>;
|
||||||
|
|
||||||
let proxies: string[] = [];
|
let proxies: string[] = [];
|
||||||
let currentProxyIndex = 0;
|
let currentProxyIndex = 0;
|
||||||
|
@ -15,21 +22,17 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFetchClient = (konfigStore: Store): {
|
export const getFetchClient = (konfigStore: Store): {
|
||||||
(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
||||||
(
|
(
|
||||||
input: Request | URL | string,
|
input: FetchInputParameter,
|
||||||
init?: RequestInit & {
|
init?: FetchInitParameterWithClient,
|
||||||
client: Deno.HttpClient;
|
): FetchReturn;
|
||||||
},
|
|
||||||
): Promise<Response>;
|
|
||||||
(input: URL | Request | string, init?: RequestInit): Promise<Response>;
|
|
||||||
} => {
|
} => {
|
||||||
if (
|
if (
|
||||||
Deno.env.get("PROXY") || konfigStore.get("networking.proxy") ||
|
Deno.env.get("PROXY") || konfigStore.get("networking.proxy") ||
|
||||||
(proxies.length > 0)
|
(proxies.length > 0)
|
||||||
) {
|
) {
|
||||||
return async (
|
return async (
|
||||||
input: RequestInfo | URL,
|
input: FetchInputParameter,
|
||||||
init?: RequestInit,
|
init?: RequestInit,
|
||||||
) => {
|
) => {
|
||||||
const proxyUrl = Deno.env.get("PROXY") ||
|
const proxyUrl = Deno.env.get("PROXY") ||
|
||||||
|
@ -60,5 +63,39 @@ export const getFetchClient = (konfigStore: Store): {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return globalThis.fetch;
|
return (input: FetchInputParameter, init?: FetchInitParameterWithClient) =>
|
||||||
|
fetchShim(konfigStore, input, init);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function fetchShim(
|
||||||
|
konfigStore: Store,
|
||||||
|
input: FetchInputParameter,
|
||||||
|
init?: FetchInitParameterWithClient,
|
||||||
|
): FetchReturn {
|
||||||
|
const fetchTimeout = konfigStore.get("networking.fetch_timeout_ms");
|
||||||
|
const fetchRetry = konfigStore.get("networking.fetch_retry_enable");
|
||||||
|
const fetchMaxAttempts = konfigStore.get("networking.fetch_retry_times");
|
||||||
|
const fetchInitialDebounce = konfigStore.get(
|
||||||
|
"networking.fetch_retry_initial_debounce",
|
||||||
|
);
|
||||||
|
const fetchDebounceMultiplier = konfigStore.get(
|
||||||
|
"networking.fetch_retry_debounce_multiplier",
|
||||||
|
);
|
||||||
|
const retryOptions: RetryOptions = {
|
||||||
|
maxAttempts: Number(fetchMaxAttempts) || 1,
|
||||||
|
minTimeout: Number(fetchInitialDebounce) || 0,
|
||||||
|
multiplier: Number(fetchDebounceMultiplier) || 0,
|
||||||
|
jitter: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const callFetch = () =>
|
||||||
|
fetch(input, {
|
||||||
|
// only set the AbortSignal if the timeout is supplied in the config
|
||||||
|
signal: fetchTimeout
|
||||||
|
? AbortSignal.timeout(Number(fetchTimeout))
|
||||||
|
: null,
|
||||||
|
...(init || {}),
|
||||||
|
});
|
||||||
|
// if retry enabled, call retry with the fetch shim, otherwise pass the fetch shim back directly
|
||||||
|
return fetchRetry ? retry(callFetch, retryOptions) : callFetch();
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import { Innertube } from "youtubei.js";
|
import { Innertube } from "youtubei.js";
|
||||||
|
import type { konfigLoader } from "../helpers/konfigLoader.ts";
|
||||||
|
|
||||||
export type HonoVariables = {
|
export type HonoVariables = {
|
||||||
innertubeClient: Innertube;
|
innertubeClient: Innertube;
|
||||||
|
konfigStore: Awaited<ReturnType<typeof konfigLoader>>;
|
||||||
};
|
};
|
||||||
|
|
28
src/main.ts
28
src/main.ts
|
@ -13,6 +13,7 @@ import { konfigLoader } from "./lib/helpers/konfigLoader.ts";
|
||||||
import { ICache } from "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.0.0-deno/deno/src/types/Cache.ts";
|
import { ICache } from "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.0.0-deno/deno/src/types/Cache.ts";
|
||||||
import { FetchFunction } from "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.0.0-deno/deno/src/types/PlatformShim.ts";
|
import { FetchFunction } from "https://raw.githubusercontent.com/LuanRT/YouTube.js/refs/tags/v13.0.0-deno/deno/src/types/PlatformShim.ts";
|
||||||
import { getRandomUserAgent, PlayerError } from "youtubei.js/Utils";
|
import { getRandomUserAgent, PlayerError } from "youtubei.js/Utils";
|
||||||
|
import type { HonoVariables } from "./lib/types/HonoVariables.ts";
|
||||||
let getFetchClientLocation = "getFetchClient";
|
let getFetchClientLocation = "getFetchClient";
|
||||||
if (Deno.env.get("GET_FETCH_CLIENT_LOCATION")) {
|
if (Deno.env.get("GET_FETCH_CLIENT_LOCATION")) {
|
||||||
if (Deno.env.has("DENO_COMPILED")) {
|
if (Deno.env.has("DENO_COMPILED")) {
|
||||||
|
@ -24,10 +25,31 @@ if (Deno.env.get("GET_FETCH_CLIENT_LOCATION")) {
|
||||||
) as string;
|
) as string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const args = Deno.args;
|
||||||
|
const konfigStore = await konfigLoader();
|
||||||
|
const host = Deno.env.get("HOST") || konfigStore.get("server.host") as string;
|
||||||
|
const port = Deno.env.get("PORT") || konfigStore.get("server.port") as string;
|
||||||
|
|
||||||
|
if (args?.[0] == "healthcheck") {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`http://${host}:${port}/healthz`);
|
||||||
|
if (response.status === 200) {
|
||||||
|
Deno.exit(0);
|
||||||
|
} else {
|
||||||
|
Deno.exit(1);
|
||||||
|
}
|
||||||
|
} catch (_) {
|
||||||
|
Deno.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { getFetchClient } = await import(getFetchClientLocation);
|
const { getFetchClient } = await import(getFetchClientLocation);
|
||||||
|
|
||||||
|
declare module "hono" {
|
||||||
|
interface ContextVariableMap extends HonoVariables {}
|
||||||
|
}
|
||||||
const app = new Hono();
|
const app = new Hono();
|
||||||
const konfigStore = await konfigLoader();
|
|
||||||
|
|
||||||
let innertubeClient: Innertube;
|
let innertubeClient: Innertube;
|
||||||
let innertubeClientFetchPlayer = true;
|
let innertubeClientFetchPlayer = true;
|
||||||
|
@ -215,9 +237,7 @@ if (!innertubeClientOauthEnabled) {
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use("*", async (c, next) => {
|
app.use("*", async (c, next) => {
|
||||||
// @ts-ignore Do not understand how to fix this error.
|
|
||||||
c.set("innertubeClient", innertubeClient);
|
c.set("innertubeClient", innertubeClient);
|
||||||
// @ts-ignore Do not understand how to fix this error.
|
|
||||||
c.set("konfigStore", konfigStore);
|
c.set("konfigStore", konfigStore);
|
||||||
await next();
|
await next();
|
||||||
});
|
});
|
||||||
|
@ -225,8 +245,6 @@ app.use("*", async (c, next) => {
|
||||||
routes(app, konfigStore);
|
routes(app, konfigStore);
|
||||||
|
|
||||||
const https = Deno.env.get("HTTPS");
|
const https = Deno.env.get("HTTPS");
|
||||||
const port = konfigStore.get("server.port") as number;
|
|
||||||
const host = konfigStore.get("server.host") as string;
|
|
||||||
|
|
||||||
if (https == "TRUE" || https == "true") {
|
if (https == "TRUE" || https == "true") {
|
||||||
const cert = Deno.readTextFileSync("/data/cert.pem");
|
const cert = Deno.readTextFileSync("/data/cert.pem");
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { FormatUtils, Innertube } from "youtubei.js";
|
import { FormatUtils } from "youtubei.js";
|
||||||
import { HonoVariables } from "../../lib/types/HonoVariables.ts";
|
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
|
||||||
import {
|
import {
|
||||||
youtubePlayerParsing,
|
youtubePlayerParsing,
|
||||||
youtubeVideoInfo,
|
youtubeVideoInfo,
|
||||||
|
@ -9,18 +7,15 @@ import {
|
||||||
import { verifyRequest } from "../../lib/helpers/verifyRequest.ts";
|
import { verifyRequest } from "../../lib/helpers/verifyRequest.ts";
|
||||||
import { HTTPException } from "hono/http-exception";
|
import { HTTPException } from "hono/http-exception";
|
||||||
|
|
||||||
const dashManifest = new Hono<{ Variables: HonoVariables }>();
|
const dashManifest = new Hono();
|
||||||
|
|
||||||
dashManifest.get("/:videoId", async (c) => {
|
dashManifest.get("/:videoId", async (c) => {
|
||||||
const { videoId } = c.req.param();
|
const { videoId } = c.req.param();
|
||||||
const { check, local } = c.req.query();
|
const { check, local } = c.req.query();
|
||||||
c.header("access-control-allow-origin", "*");
|
c.header("access-control-allow-origin", "*");
|
||||||
|
|
||||||
const innertubeClient = await c.get("innertubeClient") as Innertube;
|
const innertubeClient = c.get("innertubeClient");
|
||||||
// @ts-ignore Do not understand how to fix this error.
|
const konfigStore = c.get("konfigStore");
|
||||||
const konfigStore = await c.get("konfigStore") as Store<
|
|
||||||
Record<string, unknown>
|
|
||||||
>;
|
|
||||||
|
|
||||||
const maxDashResolution = Deno.env.get("SERVER_MAX_DASH_RESOLUTION") ||
|
const maxDashResolution = Deno.env.get("SERVER_MAX_DASH_RESOLUTION") ||
|
||||||
konfigStore.get("server.max_dash_resolution") as number;
|
konfigStore.get("server.max_dash_resolution") as number;
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { HTTPException } from "hono/http-exception";
|
import { HTTPException } from "hono/http-exception";
|
||||||
import { Innertube } from "youtubei.js";
|
|
||||||
import { HonoVariables } from "../../lib/types/HonoVariables.ts";
|
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
|
||||||
import {
|
import {
|
||||||
youtubePlayerParsing,
|
youtubePlayerParsing,
|
||||||
youtubeVideoInfo,
|
youtubeVideoInfo,
|
||||||
} from "../../lib/helpers/youtubePlayerHandling.ts";
|
} from "../../lib/helpers/youtubePlayerHandling.ts";
|
||||||
import { verifyRequest } from "../../lib/helpers/verifyRequest.ts";
|
import { verifyRequest } from "../../lib/helpers/verifyRequest.ts";
|
||||||
|
|
||||||
const latestVersion = new Hono<{ Variables: HonoVariables }>();
|
const latestVersion = new Hono();
|
||||||
|
|
||||||
latestVersion.get("/", async (c) => {
|
latestVersion.get("/", async (c) => {
|
||||||
const { check, itag, id, local } = c.req.query();
|
const { check, itag, id, local } = c.req.query();
|
||||||
|
@ -21,19 +18,14 @@ latestVersion.get("/", async (c) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const innertubeClient = await c.get("innertubeClient") as Innertube;
|
const innertubeClient = c.get("innertubeClient");
|
||||||
// @ts-ignore Do not understand how to fix this error.
|
const konfigStore = await c.get("konfigStore");
|
||||||
const konfigStore = await c.get("konfigStore") as Store<
|
|
||||||
Record<string, unknown>
|
|
||||||
>;
|
|
||||||
const verifyRequests = Deno.env.get("VERIFY_REQUESTS") ||
|
|
||||||
konfigStore.get("server.verify_requests");
|
|
||||||
|
|
||||||
if (verifyRequests && check == undefined) {
|
if (konfigStore.get("server.verify_requests") && check == undefined) {
|
||||||
throw new HTTPException(400, {
|
throw new HTTPException(400, {
|
||||||
res: new Response("No check ID."),
|
res: new Response("No check ID."),
|
||||||
});
|
});
|
||||||
} else if (verifyRequests && check) {
|
} else if (konfigStore.get("server.verify_requests") && check) {
|
||||||
if (verifyRequest(check, id, konfigStore) === false) {
|
if (verifyRequest(check, id, konfigStore) === false) {
|
||||||
throw new HTTPException(400, {
|
throw new HTTPException(400, {
|
||||||
res: new Response("ID incorrect."),
|
res: new Response("ID incorrect."),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
|
||||||
import { HTTPException } from "hono/http-exception";
|
import { HTTPException } from "hono/http-exception";
|
||||||
let getFetchClientLocation = "getFetchClient";
|
let getFetchClientLocation = "getFetchClient";
|
||||||
if (Deno.env.get("GET_FETCH_CLIENT_LOCATION")) {
|
if (Deno.env.get("GET_FETCH_CLIENT_LOCATION")) {
|
||||||
|
@ -44,10 +43,7 @@ videoPlaybackProxy.get("/", async (c) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore Do not understand how to fix this error.
|
const konfigStore = c.get("konfigStore");
|
||||||
const konfigStore = await c.get("konfigStore") as Store<
|
|
||||||
Record<string, unknown>
|
|
||||||
>;
|
|
||||||
|
|
||||||
// deno-lint-ignore prefer-const
|
// deno-lint-ignore prefer-const
|
||||||
let queryParams = new URLSearchParams(urlReq.search);
|
let queryParams = new URLSearchParams(urlReq.search);
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
import { Hono } from "hono";
|
import { Hono } from "hono";
|
||||||
import { youtubePlayerParsing } from "../../lib/helpers/youtubePlayerHandling.ts";
|
import { youtubePlayerParsing } from "../../lib/helpers/youtubePlayerHandling.ts";
|
||||||
import { HonoVariables } from "../../lib/types/HonoVariables.ts";
|
|
||||||
import { Innertube } from "youtubei.js";
|
|
||||||
import { Store } from "@willsoto/node-konfig-core";
|
|
||||||
import {
|
import {
|
||||||
reasonBot,
|
reasonBot,
|
||||||
subreasonProtectCommunity,
|
subreasonProtectCommunity,
|
||||||
|
@ -10,7 +7,7 @@ import {
|
||||||
videoUnavailable,
|
videoUnavailable,
|
||||||
} from "metrics";
|
} from "metrics";
|
||||||
|
|
||||||
const player = new Hono<{ Variables: HonoVariables }>();
|
const player = new Hono();
|
||||||
|
|
||||||
const errors = [
|
const errors = [
|
||||||
{
|
{
|
||||||
|
@ -47,11 +44,8 @@ const errors = [
|
||||||
|
|
||||||
player.post("/player", async (c) => {
|
player.post("/player", async (c) => {
|
||||||
const jsonReq = await c.req.json();
|
const jsonReq = await c.req.json();
|
||||||
const innertubeClient = await c.get("innertubeClient") as Innertube;
|
const innertubeClient = c.get("innertubeClient");
|
||||||
// @ts-ignore Do not understand how to fix this error.
|
const konfigStore = c.get("konfigStore");
|
||||||
const konfigStore = await c.get("konfigStore") as Store<
|
|
||||||
Record<string, unknown>
|
|
||||||
>;
|
|
||||||
if (jsonReq.videoId) {
|
if (jsonReq.videoId) {
|
||||||
const yt = await youtubePlayerParsing(
|
const yt = await youtubePlayerParsing(
|
||||||
innertubeClient,
|
innertubeClient,
|
||||||
|
|
Reference in a new issue