const assert = require("assert"); const fs = require("fs"); const path = require("path"); const { generateCommandPreview, findDynamicSegments, normalizePreviewText, previewParts } = require("../src/services/command-preview"); const { runAdvancedCommand } = require("../src/services/commands"); const { conditionMatches, selectRandomReply, validateRandomConfig } = require("../src/services/command-random"); const { DELAY_MS, issueConfirmation, consumeConfirmation, isDestructivePath } = require("../src/services/destructive-confirm"); const { db, migrate } = require("../src/services/db"); async function run() { migrate(); const columns = db.prepare("PRAGMA table_info(custom_commands)").all().map((row) => row.name); for (const column of [ "preview_text", "preview_status", "preview_error", "preview_generated_at", "preview_dynamic_segments", "description", "random_replies_json", "rng_enabled", "rng_min", "rng_max" ]) { assert(columns.includes(column), `Missing custom command preview column: ${column}`); } db.exec("SAVEPOINT verify_command_description"); try { const now = Date.now(); const trigger = `verify-description-${now}`; const inserted = db.prepare( "INSERT INTO custom_commands (trigger, description, response, created_at, updated_at) VALUES (?, ?, ?, ?, ?)" ).run(trigger, "Initial description", "Test reply", now, now); db.prepare("UPDATE custom_commands SET description = ? WHERE id = ?") .run("Updated description", inserted.lastInsertRowid); assert.equal( db.prepare("SELECT description FROM custom_commands WHERE id = ?") .get(inserted.lastInsertRowid).description, "Updated description" ); } finally { db.exec("ROLLBACK TO verify_command_description; RELEASE verify_command_description"); } const preview = await generateCommandPreview({ language: "js", code: ` function run(ctx) { ctx.reply("Hello " + ctx.user.username); return "Balance 1234, id " + ctx.user.id + ", date " + new Date().toISOString(); } ` }); assert.equal(preview.preview_status, "ready"); assert.match(preview.preview_text, /Hello some_user/); assert.equal(preview.preview_text.includes("Some User"), false); const segments = JSON.parse(preview.preview_dynamic_segments); for (const type of ["username", "number", "id", "date"]) { assert(segments.some((segment) => segment.type === type), `Missing ${type} dynamic segment`); } assert(previewParts(preview.preview_text, segments).some((part) => part.dynamic)); assert.equal(normalizePreviewText("Some User and some-user"), "some_user and some_user"); assert(findDynamicSegments("some_user 42 user_123 2026-01-02T12:34:56.000Z").length, 4); const punctuationPreview = "Fun fact for some_user:\nExample"; assert.equal( previewParts(punctuationPreview, findDynamicSegments(punctuationPreview)).map((part) => part.text).join(""), punctuationPreview ); const snippetPreview = await generateCommandPreview({ language: "js", code: 'return "Snippet for " + ctx.user.username;' }); assert.equal(snippetPreview.preview_status, "ready"); assert.equal(snippetPreview.preview_text, "Snippet for some_user"); const exportedPreview = await generateCommandPreview({ language: "js", code: 'module.exports = (ctx) => "Export for " + ctx.user.username;' }); assert.equal(exportedPreview.preview_status, "ready"); assert.equal(exportedPreview.preview_text, "Export for some_user"); const safeBuiltInsPreview = await generateCommandPreview({ language: "js", code: ` const facts = ["using a process called respiration"]; const selected = facts[Math.floor(Math.random() * facts.length)]; const url = new URL("https://example.com/facts?count=1"); return JSON.stringify({ selected, host: url.hostname, count: url.searchParams.get("count") }); ` }); assert.equal(safeBuiltInsPreview.preview_status, "ready"); assert.deepEqual(JSON.parse(safeBuiltInsPreview.preview_text), { selected: "using a process called respiration", host: "example.com", count: "1" }); for (const code of [ 'return Math.constructor.constructor("return pro" + "cess")().cwd();', 'return ctx.constructor.constructor("return pro" + "cess")().cwd();', 'return URL.constructor.constructor("return pro" + "cess")().cwd();' ]) { const constructorEscape = await generateCommandPreview({ language: "js", code }); assert.equal(constructorEscape.preview_status, "unavailable"); assert.match(constructorEscape.preview_error, /code generation from strings disallowed/i); } const pythonSnippetPreview = await generateCommandPreview({ language: "python", code: 'return "Python snippet"' }); assert.equal(pythonSnippetPreview.preview_status, "ready"); assert.equal(pythonSnippetPreview.preview_text, "Python snippet"); assert.equal(await runAdvancedCommand({ language: "js", code: 'return "wrapped";' }, {}), "wrapped"); const randomConfig = { replies: [ { text: "Low {{core.command.rng}}", weight: 1, condition: "<20" }, { text: "High", weight: 2, condition: ">=20" } ], rngEnabled: true, rngMin: 1, rngMax: 100 }; const rolls = [0.1, 0.9]; const selectedRandom = selectRandomReply(randomConfig, () => rolls.shift()); assert.equal(selectedRandom.rng, 11); assert.equal(selectedRandom.reply.text, "Low {{core.command.rng}}"); assert.equal(conditionMatches(">=10", 10), true); assert.equal(conditionMatches("<20", 20), false); assert.equal(validateRandomConfig({ replies: [{ text: "Hi", weight: 1000 }], rngMin: 1, rngMax: 100 }).ok, false); assert.equal(validateRandomConfig({ replies: [{ text: "Hi", weight: 1, condition: "maybe" }], rngEnabled: true }).ok, false); const noSideEffects = await generateCommandPreview({ language: "js", code: ` async function run(ctx) { await ctx.economy.add(ctx.user.id, 999999); await ctx.inventory.remove(ctx.user.id, "all"); await ctx.moderation.ban(ctx.user.id); await ctx.files.write("outside.txt", "blocked"); ctx.db.prepare("DELETE FROM users").run(); return "Balance " + await ctx.economy.getBalance(ctx.user.id); } ` }); assert.equal(noSideEffects.preview_status, "ready"); assert.equal(noSideEffects.preview_text, "Balance 1234"); const readOnlyFetch = await generateCommandPreview({ language: "js", code: ` async function run() { const response = await fetch("data:application/json,%7B%22message%22%3A%22preview%22%7D"); const data = await response.json(); return data.message; } ` }); assert.equal(readOnlyFetch.preview_status, "ready"); assert.equal(readOnlyFetch.preview_text, "preview"); const blockedNetworkFetch = await generateCommandPreview({ language: "js", code: ` async function run() { await fetch("http://127.0.0.1:3000/admin/settings"); return "no"; } ` }); assert.equal(blockedNetworkFetch.preview_status, "unavailable"); assert.match(blockedNetworkFetch.preview_error, /does not send external network requests/i); const blockedWriteFetch = await generateCommandPreview({ language: "js", code: ` async function run() { await fetch("data:text/plain,no", { method: "POST", body: "write" }); return "no"; } ` }); assert.equal(blockedWriteFetch.preview_status, "unavailable"); assert.match(blockedWriteFetch.preview_error, /read-only GET and HEAD/i); const blocked = await generateCommandPreview({ language: "js", code: "function run() { return process.cwd(); }" }); assert.equal(blocked.preview_status, "unavailable"); assert.match(blocked.preview_error, /blocks filesystem, process/i); const blockedImport = await generateCommandPreview({ language: "python", code: "import os\ndef run(ctx):\n return os.getcwd()" }); assert.equal(blockedImport.preview_status, "unavailable"); assert.match(blockedImport.preview_error, /blocks imports/i); const timedOut = await generateCommandPreview({ language: "js", code: "function run() { while (true) {} }" }); assert.equal(timedOut.preview_status, "unavailable"); assert.match(timedOut.preview_error, /timed out/i); const req = fakeRequest(); assert.equal(isDestructivePath("/admin/commands/1/delete"), true); assert.equal(isDestructivePath("/admin/commands/1/update"), false); const first = issueConfirmation(req, "/admin/commands/1/delete"); assert.equal(first.delay_seconds, DELAY_MS / 1000); assert.equal(consumeConfirmation(req, "/admin/commands/1/delete", first.token).reason, "too_early"); const second = issueConfirmation(req, "/admin/commands/1/delete"); req.session.destructive_confirmations[second.token].not_before = Date.now() - 1; assert.equal(consumeConfirmation(req, "/admin/pages/1/delete", second.token).reason, "action_mismatch"); const third = issueConfirmation(req, "/admin/commands/1/delete"); req.session.destructive_confirmations[third.token].not_before = Date.now() - 1; assert.equal(consumeConfirmation(req, "/admin/commands/1/delete", third.token).valid, true); assert.equal(consumeConfirmation(req, "/admin/commands/1/delete", third.token).valid, false); const appScript = fs.readFileSync(path.join(__dirname, "..", "src", "web", "public", "app.js"), "utf8"); const layout = fs.readFileSync(path.join(__dirname, "..", "src", "web", "views", "partials", "layout-bottom.ejs"), "utf8"); const commandView = fs.readFileSync(path.join(__dirname, "..", "src", "web", "views", "admin-commands.ejs"), "utf8"); const publicCommandView = fs.readFileSync(path.join(__dirname, "..", "src", "web", "views", "commands.ejs"), "utf8"); const publicCommandContent = fs.readFileSync(path.join(__dirname, "..", "src", "web", "views", "partials", "command-list-content.ejs"), "utf8"); assert(appScript.includes("${confirmLabel(form, submitter)} in ${remaining}")); assert(appScript.includes('button.disabled = remaining > 0')); assert(appScript.includes('fetch("/api/destructive-confirmations"')); assert(appScript.includes("destructiveToken: timedDestructiveToken")); assert(appScript.includes("destructiveFetch(action")); assert(appScript.includes('headers.set("X-Confirmation-Token", token)')); assert(appScript.includes("event.preventDefault();")); assert(appScript.includes("expiryTimer")); assert(appScript.includes("resetDestructive")); assert(layout.includes("data-destructive-modal")); assert(layout.includes("data-destructive-confirm disabled")); assert(commandView.includes("Preview unavailable")); assert(commandView.includes("preview-dynamic")); assert(commandView.includes('data-collapsed-label="Read more"')); assert(commandView.includes('data-expanded-label="Read less"')); assert.equal(commandView.includes("Full preview"), false); assert.equal(commandView.includes("command-preview-full"), false); assert(appScript.includes('[data-expand-text]')); assert(commandView.includes(">Static<")); assert(commandView.includes(">Random Reply<")); assert(commandView.includes(">Dynamic<")); assert(commandView.includes("random_weight")); assert(commandView.includes("{{core.command.rng}}")); assert(commandView.includes('name="description"')); assert(publicCommandView.includes('data-command-content-toggle')); assert(publicCommandView.includes('partials/command-list-content')); assert(publicCommandContent.includes("command.preview.parts")); assert(publicCommandContent.includes("data-command-content-description")); assert.equal(publicCommandContent.includes("Refresh preview"), false); assert(appScript.includes('row.style.display = expanded ? "table-row" : "none"')); assert(appScript.includes("[data-command-list-content]")); assert.equal(commandView.includes('"Advanced (" + command.language + ")"'), false); console.log("Command preview and destructive confirmation verification passed."); } function fakeRequest() { return { session: { user: { id: "admin-user", isAdmin: true } }, body: {}, get() { return null; } }; } run().catch((error) => { console.error(error); process.exitCode = 1; });