feat(whitelist): add POST /whitelist endpoint

This commit is contained in:
localhost 2026-08-20 17:07:01 +02:00
parent 9808ee19cc
commit 1a65b1c190
5 changed files with 36 additions and 8 deletions

View File

@ -15,7 +15,7 @@
"fluent-ffmpeg": "^2.1.3", "fluent-ffmpeg": "^2.1.3",
"googlevideo": "^4.0.4", "googlevideo": "^4.0.4",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"youtubei.js": "^17.0.1", "youtubei.js": "^17.2.0",
}, },
"devDependencies": { "devDependencies": {
"@types/bun": "latest", "@types/bun": "latest",
@ -152,6 +152,8 @@
"express-ws": ["express-ws@5.0.2", "", { "dependencies": { "ws": "^7.4.6" }, "peerDependencies": { "express": "^4.0.0 || ^5.0.0-alpha.1" } }, "sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ=="], "express-ws": ["express-ws@5.0.2", "", { "dependencies": { "ws": "^7.4.6" }, "peerDependencies": { "express": "^4.0.0 || ^5.0.0-alpha.1" } }, "sha512-0uvmuk61O9HXgLhGl3QhNSEtRsQevtmbL94/eILaliEADZBHZOQUAiHFrGPrgsjikohyrmSG5g+sCfASTt0lkQ=="],
"fflate": ["fflate@0.8.3", "", {}, "sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA=="],
"finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="], "finalhandler": ["finalhandler@2.1.0", "", { "dependencies": { "debug": "^4.4.0", "encodeurl": "^2.0.0", "escape-html": "^1.0.3", "on-finished": "^2.4.1", "parseurl": "^1.3.3", "statuses": "^2.0.1" } }, "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q=="],
"fluent-ffmpeg": ["fluent-ffmpeg@2.1.3", "", { "dependencies": { "async": "^0.2.9", "which": "^1.1.1" } }, "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q=="], "fluent-ffmpeg": ["fluent-ffmpeg@2.1.3", "", { "dependencies": { "async": "^0.2.9", "which": "^1.1.1" } }, "sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q=="],
@ -316,7 +318,7 @@
"xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="], "xmlchars": ["xmlchars@2.2.0", "", {}, "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="],
"youtubei.js": ["youtubei.js@17.0.1", "", { "dependencies": { "@bufbuild/protobuf": "^2.0.0", "meriyah": "^6.1.4" } }, "sha512-1lO4b8UqMDzE0oh2qEGzbBOd4UYRdxn/4PdpRM7BGTHxM6ddsEsKZTu90jp8V9FHVgC2h1UirQyqoqLiKwl+Zg=="], "youtubei.js": ["youtubei.js@17.2.0", "", { "dependencies": { "@bufbuild/protobuf": "^2.0.0", "fflate": "^0.8.2", "meriyah": "^6.1.4" } }, "sha512-XLNsgRKO1h7t4i9tIMWSQSeWdD7Ujkk5v1m5YCaumaHMhu/xuLqtO3M0Hq7CXNup9HlJ1NGrT1Y+HLIHnL6Ujg=="],
"dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], "dom-serializer/entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="],

View File

@ -3,4 +3,4 @@
"useCompanion": true, "useCompanion": true,
"maxVideoSize": 100, "maxVideoSize": 100,
"companionIp": "" "companionIp": ""
} }

View File

@ -1,6 +1,7 @@
import express from 'express'; import express from 'express';
import * as cheerio from 'cheerio'; import * as cheerio from 'cheerio';
import * as fs from 'node:fs' import * as fs from 'node:fs'
import path from 'node:path'
import { EnabledTrackTypes } from 'googlevideo/utils'; import { EnabledTrackTypes } from 'googlevideo/utils';
import { import {
@ -16,6 +17,7 @@ import { fetchChannelVideos, getVideoThumbnails, parseViewCount, relativeTimeToT
const ffmpeg = require('fluent-ffmpeg') const ffmpeg = require('fluent-ffmpeg')
const app = express(); const app = express();
app.use(express.json());
require('express-ws')(app) require('express-ws')(app)
ffmpeg.setFfmpegPath('/usr/local/bin/ffmpeg') ffmpeg.setFfmpegPath('/usr/local/bin/ffmpeg')
@ -152,6 +154,30 @@ app.get('/videos/:id', async (req, res) => {
return res.json(false); return res.json(false);
} }
}) })
app.post('/whitelist', async (req, res) => {
try {
const id = req.body?.id || req.body?.videoId || req.query?.id;
if (!id || typeof id !== 'string') {
return res.status(400).json({ success: false, message: 'Missing or invalid video id' });
}
const configPath = path.resolve(import.meta.dirname, 'config.json');
const config: Config = await Bun.file(configPath).json();
if (!Array.isArray(config.whitelist)) {
config.whitelist = [];
}
if (!config.whitelist.includes(id)) {
config.whitelist.push(id);
await Bun.write(configPath, JSON.stringify(config, null, 2) + '\n');
}
return res.json({ success: true, message: `Added video ${id} to size whitelist`, whitelist: config.whitelist });
} catch (error: any) {
return res.status(500).json({ success: false, message: `Failed to update whitelist: ${error.message}` });
}
});
interface Config { interface Config {
whitelist: string[] whitelist: string[]

View File

@ -20,6 +20,6 @@
"fluent-ffmpeg": "^2.1.3", "fluent-ffmpeg": "^2.1.3",
"googlevideo": "^4.0.4", "googlevideo": "^4.0.4",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
"youtubei.js": "^17.0.1" "youtubei.js": "^17.2.0"
} }
} }

View File

@ -45,7 +45,7 @@ export function serializeProto(obj: any): Uint8Array {
continue; continue;
} }
const parts = key.split(':'); const parts = key.split(':');
const fieldNum = parseInt(parts[0], 10); const fieldNum = parseInt(parts[0] || '0', 10);
const type = parts[1]; const type = parts[1];
if (isNaN(fieldNum)) { if (isNaN(fieldNum)) {
@ -191,9 +191,9 @@ function decodeLengthSeconds(lengthText: string): number {
let seconds = 0; let seconds = 0;
if (parts.length === 2) { if (parts.length === 2) {
seconds = parts[0] * 60 + parts[1]; seconds = (parts[0] ?? 0) * 60 + (parts[1] ?? 0);
} else if (parts.length === 3) { } else if (parts.length === 3) {
seconds = parts[0] * 3600 + parts[1] * 60 + parts[2]; seconds = (parts[0] ?? 0) * 3600 + (parts[1] ?? 0) * 60 + (parts[2] ?? 0);
} }
return seconds; return seconds;
} }
@ -727,7 +727,7 @@ function shortTextToNumber(shortText: string): number {
if (!shortText) return 0; if (!shortText) return 0;
const match = shortText.match(/(\d+(?:\.\d+)?)\s*([mMkKbB]?)/i); const match = shortText.match(/(\d+(?:\.\d+)?)\s*([mMkKbB]?)/i);
if (!match) return 0; if (!match) return 0;
let number = parseFloat(match[1]); let number = parseFloat(match[1] || '0');
const suffix = match[2]?.toLowerCase(); const suffix = match[2]?.toLowerCase();
switch (suffix) { switch (suffix) {
case 'k': number *= 1000; break; case 'k': number *= 1000; break;