Rewrite frontend as single self-contained HTML file — all CSS/JS inline, no external files to fail loading
This commit is contained in:
2
dist/server/routes/auth.d.ts
vendored
Normal file
2
dist/server/routes/auth.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const router: import("express-serve-static-core").Router;
|
||||
export default router;
|
||||
30
dist/server/routes/auth.js
vendored
Normal file
30
dist/server/routes/auth.js
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const router = (0, express_1.Router)();
|
||||
router.post('/login', (req, res) => {
|
||||
const { username, password } = req.body;
|
||||
const serverUser = process.env.SERVER_USERNAME || 'admin';
|
||||
const serverPass = process.env.SERVER_PASSWORD || 'aidio2024';
|
||||
if (username === serverUser && password === serverPass) {
|
||||
const token = Buffer.from(`${username}:${password}`).toString('base64');
|
||||
res.json({ authenticated: true, token, username });
|
||||
}
|
||||
else {
|
||||
res.status(401).json({ authenticated: false, error: 'Invalid credentials' });
|
||||
}
|
||||
});
|
||||
router.get('/check', (req, res) => {
|
||||
const authHeader = req.headers.authorization;
|
||||
if (!authHeader || !authHeader.startsWith('Basic ')) {
|
||||
res.json({ authenticated: false });
|
||||
return;
|
||||
}
|
||||
const credentials = Buffer.from(authHeader.slice(6), 'base64').toString('utf-8');
|
||||
const [username, password] = credentials.split(':');
|
||||
const serverUser = process.env.SERVER_USERNAME || 'admin';
|
||||
const serverPass = process.env.SERVER_PASSWORD || 'aidio2024';
|
||||
res.json({ authenticated: username === serverUser && password === serverPass, username });
|
||||
});
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=auth.js.map
|
||||
1
dist/server/routes/auth.js.map
vendored
Normal file
1
dist/server/routes/auth.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/server/routes/auth.ts"],"names":[],"mappings":";;AAAA,qCAAoD;AAEpD,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACpD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;IACxC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,WAAW,CAAC;IAE9D,IAAI,QAAQ,KAAK,UAAU,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QACvD,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,IAAI,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxE,GAAG,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrD,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAC,CAAC;IAC/E,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACnD,MAAM,UAAU,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IAC7C,IAAI,CAAC,UAAU,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,GAAG,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACjF,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,OAAO,CAAC;IAC1D,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,WAAW,CAAC;IAE9D,GAAG,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,QAAQ,KAAK,UAAU,IAAI,QAAQ,KAAK,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC5F,CAAC,CAAC,CAAC;AAEH,kBAAe,MAAM,CAAC"}
|
||||
2
dist/server/routes/config.d.ts
vendored
Normal file
2
dist/server/routes/config.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const router: import("express-serve-static-core").Router;
|
||||
export default router;
|
||||
23
dist/server/routes/config.js
vendored
Normal file
23
dist/server/routes/config.js
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const jobStore_1 = require("../db/jobStore");
|
||||
const router = (0, express_1.Router)();
|
||||
router.get('/', (_req, res) => {
|
||||
const config = (0, jobStore_1.getAllConfig)();
|
||||
res.json({ config });
|
||||
});
|
||||
router.put('/', (req, res) => {
|
||||
const updates = req.body;
|
||||
if (typeof updates !== 'object' || updates === null) {
|
||||
res.status(400).json({ error: 'Body must be a JSON object of key-value pairs' });
|
||||
return;
|
||||
}
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
(0, jobStore_1.setConfigValue)(key, String(value));
|
||||
}
|
||||
const config = (0, jobStore_1.getAllConfig)();
|
||||
res.json({ config });
|
||||
});
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=config.js.map
|
||||
1
dist/server/routes/config.js.map
vendored
Normal file
1
dist/server/routes/config.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/server/routes/config.ts"],"names":[],"mappings":";;AAAA,qCAAoD;AACpD,6CAA8D;AAE9D,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;IAC/C,MAAM,MAAM,GAAG,IAAA,uBAAY,GAAE,CAAC;IAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IAC9C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC;IACzB,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;QACpD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,+CAA+C,EAAE,CAAC,CAAC;QACjF,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACnD,IAAA,yBAAc,EAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACrC,CAAC;IACD,MAAM,MAAM,GAAG,IAAA,uBAAY,GAAE,CAAC;IAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC;AAEH,kBAAe,MAAM,CAAC"}
|
||||
2
dist/server/routes/files.d.ts
vendored
Normal file
2
dist/server/routes/files.d.ts
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
declare const router: import("express-serve-static-core").Router;
|
||||
export default router;
|
||||
87
dist/server/routes/files.js
vendored
Normal file
87
dist/server/routes/files.js
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const express_1 = require("express");
|
||||
const multer_1 = __importDefault(require("multer"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const ytDlp_1 = require("../services/ytDlp");
|
||||
const UPLOADS_DIR = path_1.default.resolve('./uploads');
|
||||
const storage = multer_1.default.diskStorage({
|
||||
destination: (_req, _file, cb) => {
|
||||
if (!fs_1.default.existsSync(UPLOADS_DIR)) {
|
||||
fs_1.default.mkdirSync(UPLOADS_DIR, { recursive: true });
|
||||
}
|
||||
cb(null, UPLOADS_DIR);
|
||||
},
|
||||
filename: (_req, file, cb) => {
|
||||
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1e9);
|
||||
cb(null, uniqueSuffix + path_1.default.extname(file.originalname));
|
||||
}
|
||||
});
|
||||
const upload = (0, multer_1.default)({
|
||||
storage,
|
||||
fileFilter: (_req, file, cb) => {
|
||||
const allowedMimes = [
|
||||
'video/mp4', 'video/webm', 'video/x-matroska', 'video/quicktime',
|
||||
'video/x-msvideo', 'video/mpeg', 'video/x-ms-wmv', 'video/x-flv'
|
||||
];
|
||||
if (allowedMimes.includes(file.mimetype) || file.originalname.match(/\.(mp4|mkv|webm|mov|avi|mpg|mpeg|wmv|flv)$/i)) {
|
||||
cb(null, true);
|
||||
}
|
||||
else {
|
||||
cb(new Error('Invalid file type. Only video files are allowed.'));
|
||||
}
|
||||
},
|
||||
limits: { fileSize: 10 * 1024 * 1024 * 1024 } // 10GB
|
||||
});
|
||||
const router = (0, express_1.Router)();
|
||||
router.post('/upload', upload.single('video'), (req, res) => {
|
||||
if (!req.file) {
|
||||
res.status(400).json({ error: 'No video file uploaded' });
|
||||
return;
|
||||
}
|
||||
res.json({
|
||||
filePath: req.file.path,
|
||||
filename: req.file.originalname,
|
||||
size: req.file.size
|
||||
});
|
||||
});
|
||||
router.get('/', (_req, res) => {
|
||||
if (!fs_1.default.existsSync(UPLOADS_DIR)) {
|
||||
res.json({ files: [] });
|
||||
return;
|
||||
}
|
||||
const entries = fs_1.default.readdirSync(UPLOADS_DIR, { withFileTypes: true });
|
||||
const files = entries
|
||||
.filter(e => e.isFile())
|
||||
.map(e => ({
|
||||
filename: e.name,
|
||||
filePath: path_1.default.join(UPLOADS_DIR, e.name),
|
||||
size: fs_1.default.statSync(path_1.default.join(UPLOADS_DIR, e.name)).size
|
||||
}))
|
||||
.sort((a, b) => b.filePath.localeCompare(a.filePath));
|
||||
res.json({ files });
|
||||
});
|
||||
router.post('/youtube', (req, res) => {
|
||||
if (!(0, ytDlp_1.isYtDlpAvailable)()) {
|
||||
res.status(400).json({ error: 'yt-dlp is not installed or not in PATH' });
|
||||
return;
|
||||
}
|
||||
const { url } = req.body;
|
||||
if (!url) {
|
||||
res.status(400).json({ error: 'URL is required' });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const result = (0, ytDlp_1.downloadVideo)(url, UPLOADS_DIR);
|
||||
res.json(result);
|
||||
}
|
||||
catch (err) {
|
||||
res.status(500).json({ error: `Failed to download: ${err.message}` });
|
||||
}
|
||||
});
|
||||
exports.default = router;
|
||||
//# sourceMappingURL=files.js.map
|
||||
1
dist/server/routes/files.js.map
vendored
Normal file
1
dist/server/routes/files.js.map
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"files.js","sourceRoot":"","sources":["../../../src/server/routes/files.ts"],"names":[],"mappings":";;;;;AAAA,qCAAoD;AACpD,oDAA4B;AAC5B,gDAAwB;AACxB,4CAAoB;AACpB,6CAAoE;AAEpE,MAAM,WAAW,GAAG,cAAI,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;AAE9C,MAAM,OAAO,GAAG,gBAAM,CAAC,WAAW,CAAC;IACjC,WAAW,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAC/B,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAChC,YAAE,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACjD,CAAC;QACD,EAAE,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;IACxB,CAAC;IACD,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;QAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;QACxE,EAAE,CAAC,IAAI,EAAE,YAAY,GAAG,cAAI,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,IAAA,gBAAM,EAAC;IACpB,OAAO;IACP,UAAU,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE;QAC7B,MAAM,YAAY,GAAG;YACnB,WAAW,EAAE,YAAY,EAAE,kBAAkB,EAAE,iBAAiB;YAChE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,aAAa;SACjE,CAAC;QACF,IAAI,YAAY,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,6CAA6C,CAAC,EAAE,CAAC;YACnH,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC,OAAO;CACtD,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,IAAA,gBAAM,GAAE,CAAC;AAExB,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IAC7E,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACd,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wBAAwB,EAAE,CAAC,CAAC;QAC1D,OAAO;IACT,CAAC;IACD,GAAG,CAAC,IAAI,CAAC;QACP,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;QACvB,QAAQ,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY;QAC/B,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,IAAI;KACpB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAa,EAAE,GAAa,EAAE,EAAE;IAC/C,IAAI,CAAC,YAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;QACxB,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,YAAE,CAAC,WAAW,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,KAAK,GAAG,OAAO;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;SACvB,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACT,QAAQ,EAAE,CAAC,CAAC,IAAI;QAChB,QAAQ,EAAE,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC;QACxC,IAAI,EAAE,YAAE,CAAC,QAAQ,CAAC,cAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;KACvD,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IACxD,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACtD,IAAI,CAAC,IAAA,wBAAgB,GAAE,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,wCAAwC,EAAE,CAAC,CAAC;QAC1E,OAAO;IACT,CAAC;IAED,MAAM,EAAE,GAAG,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC;IACzB,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC,CAAC;QACnD,OAAO;IACT,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAA,qBAAa,EAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACnB,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,uBAAuB,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,kBAAe,MAAM,CAAC"}
|
||||
3
dist/server/routes/jobs.d.ts
vendored
Normal file
3
dist/server/routes/jobs.d.ts
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
import { Router } from 'express';
|
||||
import { JobManager } from '../services/jobManager';
|
||||
export declare function createJobsRouter(jobManager: JobManager): Router;
|
||||
164
dist/server/routes/jobs.js
vendored
Normal file
164
dist/server/routes/jobs.js
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
"use strict";
|
||||
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createJobsRouter = createJobsRouter;
|
||||
const express_1 = require("express");
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const fs_1 = __importDefault(require("fs"));
|
||||
const jobStore_1 = require("../db/jobStore");
|
||||
function getParam(req, name) {
|
||||
const val = req.params[name];
|
||||
return Array.isArray(val) ? val[0] : val;
|
||||
}
|
||||
function createJobsRouter(jobManager) {
|
||||
const router = (0, express_1.Router)();
|
||||
router.get('/', (_req, res) => {
|
||||
const jobs = jobManager.listJobs();
|
||||
res.json({ jobs });
|
||||
});
|
||||
router.post('/', (req, res) => {
|
||||
const { videoPath, config, outputOptions } = req.body;
|
||||
if (!videoPath) {
|
||||
res.status(400).json({ error: 'videoPath is required' });
|
||||
return;
|
||||
}
|
||||
if (!fs_1.default.existsSync(videoPath)) {
|
||||
res.status(400).json({ error: `Video file not found: ${videoPath}` });
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const job = jobManager.createJob(videoPath, config || {}, outputOptions || {});
|
||||
res.status(201).json({ job });
|
||||
}
|
||||
catch (err) {
|
||||
res.status(500).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
router.get('/:id', (req, res) => {
|
||||
const job = (0, jobStore_1.getJob)(getParam(req, 'id'));
|
||||
if (!job) {
|
||||
res.status(404).json({ error: 'Job not found' });
|
||||
return;
|
||||
}
|
||||
res.json({ job });
|
||||
});
|
||||
router.post('/:id/start', async (req, res) => {
|
||||
try {
|
||||
await jobManager.startJob(getParam(req, 'id'));
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
res.status(400).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
router.post('/:id/pause', async (req, res) => {
|
||||
try {
|
||||
await jobManager.pauseJob(getParam(req, 'id'));
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
res.status(400).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
router.post('/:id/restart', async (req, res) => {
|
||||
try {
|
||||
await jobManager.restartJob(getParam(req, 'id'));
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
res.status(400).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
router.post('/:id/cancel', async (req, res) => {
|
||||
try {
|
||||
await jobManager.cancelJob(getParam(req, 'id'));
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
res.status(400).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
router.delete('/:id', (req, res) => {
|
||||
try {
|
||||
jobManager.deleteJob(getParam(req, 'id'));
|
||||
res.json({ success: true });
|
||||
}
|
||||
catch (err) {
|
||||
res.status(400).json({ error: err.message });
|
||||
}
|
||||
});
|
||||
router.get('/:id/progress', (req, res) => {
|
||||
res.setHeader('Content-Type', 'text/event-stream');
|
||||
res.setHeader('Cache-Control', 'no-cache');
|
||||
res.setHeader('Connection', 'keep-alive');
|
||||
res.setHeader('X-Accel-Buffering', 'no');
|
||||
const sendProgress = (data) => {
|
||||
res.write(`data: ${JSON.stringify(data)}\n\n`);
|
||||
};
|
||||
const initialJob = (0, jobStore_1.getJob)(getParam(req, 'id'));
|
||||
if (initialJob) {
|
||||
sendProgress({
|
||||
id: initialJob.id,
|
||||
status: initialJob.status,
|
||||
progress: initialJob.progress,
|
||||
currentIndex: initialJob.current_index,
|
||||
totalUnits: initialJob.total_units,
|
||||
segments: JSON.parse(initialJob.segments),
|
||||
error: initialJob.error,
|
||||
output_audio: initialJob.output_audio,
|
||||
output_subtitles_srt: initialJob.output_subtitles_srt,
|
||||
output_subtitles_vtt: initialJob.output_subtitles_vtt,
|
||||
output_muxed: initialJob.output_muxed
|
||||
});
|
||||
}
|
||||
const unsubscribe = jobManager.onJobProgress(getParam(req, 'id'), (data) => {
|
||||
if (data.status === 'completed' || data.status === 'failed' || data.status === 'cancelled') {
|
||||
sendProgress(data);
|
||||
res.end();
|
||||
unsubscribe();
|
||||
return;
|
||||
}
|
||||
sendProgress(data);
|
||||
});
|
||||
req.on('close', () => {
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
router.get('/:id/download/:type', (req, res) => {
|
||||
const job = (0, jobStore_1.getJob)(getParam(req, 'id'));
|
||||
if (!job) {
|
||||
res.status(404).json({ error: 'Job not found' });
|
||||
return;
|
||||
}
|
||||
const type = getParam(req, 'type');
|
||||
let filePath = null;
|
||||
let filename = '';
|
||||
switch (type) {
|
||||
case 'audio':
|
||||
filePath = job.output_audio;
|
||||
filename = `${path_1.default.basename(job.video_filename, path_1.default.extname(job.video_filename))}_description.mp3`;
|
||||
break;
|
||||
case 'subtitles':
|
||||
const format = req.query.format || 'srt';
|
||||
filePath = format === 'vtt' ? job.output_subtitles_vtt : job.output_subtitles_srt;
|
||||
filename = `${path_1.default.basename(job.video_filename, path_1.default.extname(job.video_filename))}_description.${format}`;
|
||||
break;
|
||||
case 'muxed':
|
||||
filePath = job.output_muxed;
|
||||
filename = `${path_1.default.basename(job.video_filename, path_1.default.extname(job.video_filename))}_described.mkv`;
|
||||
break;
|
||||
default:
|
||||
res.status(400).json({ error: 'Invalid download type' });
|
||||
return;
|
||||
}
|
||||
if (!filePath || !fs_1.default.existsSync(filePath)) {
|
||||
res.status(404).json({ error: 'Output file not found' });
|
||||
return;
|
||||
}
|
||||
res.download(filePath, filename);
|
||||
});
|
||||
return router;
|
||||
}
|
||||
//# sourceMappingURL=jobs.js.map
|
||||
1
dist/server/routes/jobs.js.map
vendored
Normal file
1
dist/server/routes/jobs.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user