import { Database } from "bun:sqlite"; function escapeHtml(str: string): string { return str .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } function homeHtml() { return ` strings

strings

minimal pastebin

+ New Paste

API

# Create a paste (basic auth required)
curl -u user:pass -X POST https://strings.witcc.dev/api/paste \\
  -H "Content-Type: text/plain" \\
  -H "X-Filename: example.py" \\
  -d 'print("hello world")'

# With custom slug
curl -u user:pass -X POST https://strings.witcc.dev/api/paste \\
  -H "Content-Type: application/json" \\
  -d '{"content": "print(1)", "filename": "test.py", "slug": "my-snippet"}'

# Pipe a file
cat myfile.rs | curl -u user:pass -X POST https://strings.witcc.dev/api/paste \\
  -H "X-Filename: myfile.rs" \\
  --data-binary @-
`; } function errorPage(message: string) { const escaped = escapeHtml(message); return ` Error - strings

${escaped}

← back home
`; } function renderPaste(paste: Paste) { const lang = paste.language || "plaintext"; const filename = paste.filename ? escapeHtml(paste.filename) : paste.id; const title = `${filename} - strings`; const content = escapeHtml(paste.content); return ` ${title}
strings / ${filename} · ${lang}
raw + new
${content}
`; } function newPastePage(error?: string) { const errorHtml = error ? `
${escapeHtml(error)}
` : ""; return ` New Paste - strings

strings / new

${errorHtml}
`; } type Paste = { id: string; content: string; filename: string | null; language: string | null; created_at: number; }; // Config from environment const PORT = parseInt(process.env.PORT || "3000"); const DB_PATH = process.env.DB_PATH || "./strings.db"; const USERNAME = process.env.AUTH_USERNAME || "admin"; // Load auth password from file or env async function loadPassword(): Promise { if (process.env.AUTH_PASSWORD_FILE) { try { const file = Bun.file(process.env.AUTH_PASSWORD_FILE); return (await file.text()).trim(); } catch (e) { console.error("Failed to read AUTH_PASSWORD_FILE:", e); process.exit(1); } } return process.env.AUTH_PASSWORD || "changeme"; } const PASSWORD = await loadPassword(); // Initialize database const db = new Database(DB_PATH); db.run(` CREATE TABLE IF NOT EXISTS pastes ( id TEXT PRIMARY KEY, content TEXT NOT NULL, filename TEXT, language TEXT, created_at INTEGER DEFAULT (unixepoch()) ) `); // Generate random ID function generateId(length = 8): string { const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789"; let result = ""; for (let i = 0; i < length; i++) { result += chars[Math.floor(Math.random() * chars.length)]; } return result; } // Validate custom slug function isValidSlug(slug: string): boolean { return /^[a-zA-Z0-9_-]{1,64}$/.test(slug); } // Check if ID exists function idExists(id: string): boolean { const row = db.query("SELECT 1 FROM pastes WHERE id = ?").get(id); return row !== null; } // Infer language from filename function inferLanguage(filename?: string): string | undefined { if (!filename) return undefined; const ext = filename.split(".").pop()?.toLowerCase(); const langMap: Record = { js: "javascript", ts: "typescript", jsx: "javascript", tsx: "typescript", py: "python", rb: "ruby", rs: "rust", go: "go", java: "java", c: "c", cpp: "cpp", h: "c", hpp: "cpp", cs: "csharp", php: "php", swift: "swift", kt: "kotlin", scala: "scala", sh: "bash", bash: "bash", zsh: "bash", fish: "fish", ps1: "powershell", sql: "sql", html: "html", css: "css", scss: "scss", sass: "sass", less: "less", json: "json", yaml: "yaml", yml: "yaml", toml: "toml", xml: "xml", md: "markdown", markdown: "markdown", nix: "nix", dockerfile: "dockerfile", makefile: "makefile", cmake: "cmake", ex: "elixir", exs: "elixir", erl: "erlang", hs: "haskell", lua: "lua", r: "r", jl: "julia", vim: "vim", tf: "hcl", }; return ext ? langMap[ext] : undefined; } // Basic auth helper function checkAuth(req: Request): boolean { const authHeader = req.headers.get("Authorization"); if (!authHeader || !authHeader.startsWith("Basic ")) { return false; } const base64Credentials = authHeader.slice(6); const credentials = atob(base64Credentials); const [username, password] = credentials.split(":"); return username === USERNAME && password === PASSWORD; } function unauthorizedResponse(): Response { return new Response("Unauthorized", { status: 401, headers: { "WWW-Authenticate": 'Basic realm="Secure Area"', }, }); } function getOrCreateId(customSlug?: string): string { if (customSlug) { if (!isValidSlug(customSlug)) { throw new Error("Invalid slug. Use 1-64 alphanumeric characters, hyphens, or underscores."); } if (idExists(customSlug)) { throw new Error("Slug already taken"); } return customSlug; } let id: string; do { id = generateId(); } while (idExists(id)); return id; } // Router async function handleRequest(req: Request): Promise { const url = new URL(req.url); const path = url.pathname; const method = req.method; // Create paste - API if (method === "POST" && path === "/api/paste") { if (!checkAuth(req)) return unauthorizedResponse(); const contentType = req.headers.get("Content-Type") || ""; let content: string; let filename: string | undefined; let language: string | undefined; let customSlug: string | undefined; if (contentType.includes("application/json")) { const body = await req.json(); content = body.content; filename = body.filename; language = body.language; customSlug = body.slug; } else { content = await req.text(); filename = req.headers.get("X-Filename") || undefined; language = req.headers.get("X-Language") || undefined; customSlug = req.headers.get("X-Slug") || undefined; } if (!content) { return Response.json({ error: "Content is required" }, { status: 400 }); } let id: string; try { id = getOrCreateId(customSlug); } catch (e: any) { const status = e.message.includes("taken") ? 409 : 400; return Response.json({ error: e.message }, { status }); } if (!language && filename) { language = inferLanguage(filename); } db.run( "INSERT INTO pastes (id, content, filename, language) VALUES (?, ?, ?, ?)", [id, content, filename || null, language || null] ); const baseUrl = process.env.BASE_URL || `http://localhost:${PORT}`; return Response.json({ id, url: `${baseUrl}/${id}`, raw: `${baseUrl}/${id}/raw`, }); } // Create paste - Form submission if (method === "POST" && path === "/new") { if (!checkAuth(req)) return unauthorizedResponse(); const form = await req.formData(); const content = form.get("content") as string; const filename = (form.get("filename") as string) || undefined; const language = (form.get("language") as string) || undefined; const customSlug = (form.get("slug") as string) || undefined; if (!content) { return new Response(newPastePage("Content is required"), { status: 400, headers: { "Content-Type": "text/html" }, }); } let id: string; try { id = getOrCreateId(customSlug); } catch (e: any) { const status = e.message.includes("taken") ? 409 : 400; return new Response(newPastePage(e.message), { status, headers: { "Content-Type": "text/html" }, }); } const inferredLang = language || inferLanguage(filename || undefined); db.run( "INSERT INTO pastes (id, content, filename, language) VALUES (?, ?, ?, ?)", [id, content, filename || null, inferredLang || null] ); return Response.redirect(`${url.origin}/${id}`, 302); } // New paste form if (method === "GET" && path === "/new") { if (!checkAuth(req)) return unauthorizedResponse(); return new Response(newPastePage(), { headers: { "Content-Type": "text/html" }, }); } // Delete paste if (method === "DELETE" && path.match(/^\/[^/]+$/)) { if (!checkAuth(req)) return unauthorizedResponse(); const id = path.slice(1); const result = db.run("DELETE FROM pastes WHERE id = ?", [id]); if (result.changes === 0) { return Response.json({ error: "Paste not found" }, { status: 404 }); } return Response.json({ deleted: true }); } // Get raw paste if (method === "GET" && path.match(/^\/[^/]+\/raw$/)) { const id = path.slice(1, -4); const paste = db.query("SELECT * FROM pastes WHERE id = ?").get(id) as Paste | null; if (!paste) { return new Response("Paste not found", { status: 404 }); } return new Response(paste.content, { headers: { "Content-Type": "text/plain; charset=utf-8" }, }); } // Get paste (HTML view) if (method === "GET" && path.match(/^\/[^/]+$/)) { const id = path.slice(1); if (id === "new" || id === "api") { return new Response(errorPage("Not found"), { status: 404, headers: { "Content-Type": "text/html" }, }); } const paste = db.query("SELECT * FROM pastes WHERE id = ?").get(id) as Paste | null; if (!paste) { return new Response(errorPage("Paste not found"), { status: 404, headers: { "Content-Type": "text/html" }, }); } return new Response(renderPaste(paste), { headers: { "Content-Type": "text/html" }, }); } // Home page if (method === "GET" && path === "/") { return new Response(homeHtml(), { headers: { "Content-Type": "text/html" }, }); } return new Response(errorPage("Not found"), { status: 404, headers: { "Content-Type": "text/html" }, }); } console.log(`strings running on http://localhost:${PORT}`); export default { port: PORT, fetch: handleRequest, };