Add app auth, dashboard, scheduler, video management, and new scrapers

- JWT-based app authentication with user roles, folder/route access control
- Dashboard with storage stats, health checks, and recent activity
- Auto-download/scrape scheduler (12h interval) with per-user and per-job configs
- Video upload, tagging, HLS transcoding, and detail pages
- New scrapers: LeakGallery, Mega (megajs), yt-dlp
- FlareSolverr integration for Cloudflare-protected sites
- Gallery: advanced filtering (date, size, search), sort modes, equal-mix shuffle
- Forum sites management with stored cookies/auth
- GridWall/GridCell components for responsive media grid
- Media API with folder-access permissions

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Trey T
2026-04-16 07:48:10 -05:00
parent 4903b84aef
commit 236f36aae6
54 changed files with 9986 additions and 420 deletions
+34
View File
@@ -1,19 +1,28 @@
import express from 'express';
import https from 'https';
import cors from 'cors';
import cookieParser from 'cookie-parser';
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'fs';
import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { initRules } from './signing.js';
import authRouter, { requireAuth, checkRoutePermission } from './auth.js';
import proxyRouter from './proxy.js';
import downloadRouter from './download.js';
import galleryRouter from './gallery.js';
import hlsRouter from './hls.js';
import settingsRouter from './settings.js';
import scrapeRouter from './scrape.js';
import flareSolverrRouter from './flaresolverr.js';
import drmStreamRouter from './drm-stream.js';
import healthRouter from './health.js';
import dashboardRouter from './dashboard.js';
import videosRouter from './videos.js';
import videoHlsRouter from './video-hls.js';
import mediaApiRouter from './media-api.js';
import { scanMediaFiles } from './gallery.js';
import { startScheduler } from './scheduler.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
@@ -23,11 +32,28 @@ const PORT = process.env.PORT || 3001;
const HTTPS_PORT = process.env.HTTPS_PORT || 3443;
app.use(cors());
app.use(cookieParser());
// Parse DRM license request bodies as raw binary BEFORE global JSON parser
// (express.json can interfere with reading the raw body stream)
app.use('/api/drm-license', express.raw({ type: '*/*', limit: '1mb' }));
app.use(express.json());
// Auth routes (public endpoints like login/setup must be before requireAuth)
app.use(authRouter);
// Apply auth middleware globally (after auth routes)
app.use('/api', (req, res, next) => {
// Skip auth for app-auth public endpoints
if (req.path.startsWith('/app-auth/')) return next();
// Skip auth for internal DRM license requests from pywidevine subprocess
if (req.path.startsWith('/drm-license') && ['127.0.0.1', '::1', '::ffff:127.0.0.1'].includes(req.ip)) return next();
requireAuth(req, res, next);
});
app.use('/api', (req, res, next) => {
if (req.path.startsWith('/app-auth/')) return next();
checkRoutePermission(req, res, next);
});
// API routes
app.use(proxyRouter);
app.use(downloadRouter);
@@ -35,7 +61,13 @@ app.use(galleryRouter);
app.use(hlsRouter);
app.use(settingsRouter);
app.use(scrapeRouter);
app.use(flareSolverrRouter);
app.use(drmStreamRouter);
app.use(healthRouter);
app.use(dashboardRouter);
app.use(videosRouter);
app.use(videoHlsRouter);
app.use(mediaApiRouter);
// Serve static client build in production
const clientDist = join(__dirname, '..', 'client', 'dist');
@@ -70,6 +102,8 @@ async function start() {
console.error('[server] Media scan failed:', err.message);
}
});
// Start auto-download/scrape scheduler
startScheduler();
});
// Start HTTPS server for DRM/EME support (requires secure context)