init
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
const express = require("express");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const { exec } = require("child_process");
|
||||
const crypto = require("crypto");
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
const DATA_FILE = path.join(__dirname, "commands.json");
|
||||
const CEC_TIMEOUT_MS = 15000;
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
app.use(express.static(path.join(__dirname, "public")));
|
||||
|
||||
function loadCommands() {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(DATA_FILE, "utf8"));
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function saveCommands(commands) {
|
||||
fs.writeFileSync(DATA_FILE, JSON.stringify(commands, null, 2) + "\n");
|
||||
}
|
||||
|
||||
// Alle gespeicherten Befehle
|
||||
app.get("/api/commands", (req, res) => {
|
||||
res.json(loadCommands());
|
||||
});
|
||||
|
||||
// Neuen Befehl anlegen
|
||||
app.post("/api/commands", (req, res) => {
|
||||
const name = (req.body.name || "").trim();
|
||||
const command = (req.body.command || "").trim();
|
||||
if (!name || !command) {
|
||||
return res.status(400).json({ error: "Name und Command dürfen nicht leer sein." });
|
||||
}
|
||||
const commands = loadCommands();
|
||||
const entry = { id: crypto.randomUUID(), name, command };
|
||||
commands.push(entry);
|
||||
saveCommands(commands);
|
||||
res.status(201).json(entry);
|
||||
});
|
||||
|
||||
// Befehl löschen
|
||||
app.delete("/api/commands/:id", (req, res) => {
|
||||
const commands = loadCommands();
|
||||
const remaining = commands.filter((c) => c.id !== req.params.id);
|
||||
if (remaining.length === commands.length) {
|
||||
return res.status(404).json({ error: "Befehl nicht gefunden." });
|
||||
}
|
||||
saveCommands(remaining);
|
||||
res.json({ ok: true });
|
||||
});
|
||||
|
||||
// Befehl als Shell-Kommando ausführen
|
||||
app.post("/api/commands/:id/run", (req, res) => {
|
||||
const entry = loadCommands().find((c) => c.id === req.params.id);
|
||||
if (!entry) {
|
||||
return res.status(404).json({ error: "Befehl nicht gefunden." });
|
||||
}
|
||||
|
||||
exec(entry.command, { timeout: CEC_TIMEOUT_MS }, (error, stdout, stderr) => {
|
||||
const output = (stdout + stderr).trim();
|
||||
|
||||
if (error?.killed) {
|
||||
return res.status(504).json({
|
||||
error: `Befehl wurde nach ${CEC_TIMEOUT_MS / 1000}s abgebrochen (${error.signal}).`,
|
||||
command: entry.command,
|
||||
output,
|
||||
});
|
||||
}
|
||||
|
||||
if (error && typeof error.code !== "number") {
|
||||
return res.status(500).json({
|
||||
error: `Befehl konnte nicht ausgeführt werden: ${error.message}`,
|
||||
command: entry.command,
|
||||
});
|
||||
}
|
||||
|
||||
const exitCode = error ? error.code : 0;
|
||||
res.json({ ok: exitCode === 0, exitCode, command: entry.command, output });
|
||||
});
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`CEC-Tool läuft auf http://localhost:${PORT}`);
|
||||
});
|
||||
Reference in New Issue
Block a user