import { Hono } from "https://deno.land/x/hono@v4.2.5/mod.ts"; import { serveStatic, logger, } from "https://deno.land/x/hono@v4.2.5/middleware.ts"; const cache = await Deno.openKv(); const app = new Hono(); app.use(logger()); // .well-known for matrix app.get("/.well-known/matrix/client", (c) => c.json({ "m.homeserver": { base_url: "https://matrix.chat.tjo.space", }, }), ); app.get("/.well-known/matrix/server", (c) => c.json({ "m.server": "matrix.chat.tjo.space:443", }), ); app.get("/.well-known/matrix/support", (c) => c.json({ contacts: [ { matrix_id: "@tine:tjo.space", email_address: "tine@tjo.space", role: "m.role.admin", }, ], }), ); // .well-known for webfinger - tailscale app.get("/.well-known/webfinger", (c) => { console.log(c.req.query()); console.log(c.req.header()); const resource = c.req.query("resource"); if (!resource) { c.status(400); return c.json({ error: "Missing resource query parameter" }); } const [scheme] = resource.split(":"); if (scheme !== "acct") { c.status(400); return c.json({ error: "Only acct scheme is supported" }); } return c.json({ subject: resource, links: [ { rel: "http://openid.net/specs/connect/1.0/issuer", href: `https://id.tjo.space/application/o/tailscalecom/`, }, ], }); }); // Serve plausible analytics app.get("/js/script.js", async (c) => { c.header("Content-Type", "text/javascript"); // Check if we have the script cached const cachedScript = await cache.get(["plausible", "script"]); if (cachedScript.value) { return c.body(cachedScript.value); } const response = await fetch("https://plausible.io/js/plausible.js"); const script = await response.text(); // Cache for 24 hours if we got the script if (response.status === 200) { await cache.set(["plausible", "script"], script, { expireIn: 1000 * 60 * 60 * 24, }); } return c.body(script); }); app.get("/api/event", (c) => { const request = new Request(c.req.raw); request.headers.delete("Cookie"); request.headers.set("X-Forwarded-For", c.req.header("host") || ""); return fetch("https://plausible.io/api/event", request); }); // Serve website app.use("*", serveStatic({ root: "./web" })); // Start server Deno.serve({ port: 8080, hostname: "0.0.0.0" }, app.fetch);