From eabc75c8de4ea39fe48af5b1f9248c96af4a5992 Mon Sep 17 00:00:00 2001 From: Pin Lin Date: Sun, 19 Oct 2025 01:59:17 +0800 Subject: [PATCH] Create simple template renderer --- docker-compose.yml | 1 + example.env | 1 + index.js | 71 ++++++++++++----------------------- templates/index.html | 25 ++++++++++++ templates/login-fail.html | 22 +++++++++++ templates/login.html | 20 ++++++++++ templates/wakeup-fail.html | 22 +++++++++++ templates/wakeup-success.html | 21 +++++++++++ utils/templates.jsm | 28 ++++++++++++++ 9 files changed, 165 insertions(+), 46 deletions(-) create mode 100644 templates/index.html create mode 100644 templates/login-fail.html create mode 100644 templates/login.html create mode 100644 templates/wakeup-fail.html create mode 100644 templates/wakeup-success.html create mode 100644 utils/templates.jsm diff --git a/docker-compose.yml b/docker-compose.yml index 3e7e665..93aa896 100755 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -3,6 +3,7 @@ services: build: . image: pinlin/wakeup3770:latest environment: + - NODE_ENV=production - PORT=3000 - MAC_ADDRESS=12:34:56:78:90:AB - OIDC_WELL_KNOWN_URL= diff --git a/example.env b/example.env index 04f3014..06c6344 100644 --- a/example.env +++ b/example.env @@ -1,3 +1,4 @@ +NODE_ENV=production PORT=3000 MAC_ADDRESS=12:34:56:78:90:AB OIDC_WELL_KNOWN_URL= diff --git a/index.js b/index.js index a87a51f..05e2808 100755 --- a/index.js +++ b/index.js @@ -2,38 +2,27 @@ const express = require("express"); const session = require("express-session"); const { Issuer } = require("openid-client"); const wol = require("wake_on_lan"); +const { createTemplateRenderer } = require("./utils/templates.jsm"); -require('dotenv').config(); +require("dotenv").config(); + +const PORT = process.env.PORT || 3000; +const REDIRECT_URI = + process.env.REDIRECT_URI || "http://127.0.0.1:3000/callback"; const app = express(); -const PORT = process.env.PORT || 3000; -const REDIRECT_URI = process.env.REDIRECT_URI || "http://127.0.0.1:3000/callback"; +app.use( + session({ + secret: process.env.COOKIE_SECRET, + saveUninitialized: false, + cookie: { maxAge: 10 * 60 * 1000 }, + }) +); -app.use(session({ - secret: process.env.COOKIE_SECRET, - saveUninitialized: false, - cookie: { maxAge: 10 * 60 * 1000 } -})); - -function expandHtml(body) { - return ` - - - - - - - - - ${body} - - - ` -} +const renderHtml = createTemplateRenderer({ + useCache: process.env.NODE_ENV === "production", +}); let client; @@ -43,32 +32,21 @@ let client; client_id: process.env.CLIENT_ID, client_secret: process.env.CLIENT_SECRET, redirect_uris: [REDIRECT_URI], - response_types: ["code"] + response_types: ["code"], }); app.get("/", (req, res) => { if (req.session.user) { - res.send(expandHtml(` -

喚醒 PinLin3770

-

已登入為身分 ${req.session.user.sub}

-
- -
-
- 喚醒 PinLin3770 - `)); + res.send(renderHtml("index.html", { USERNAME: req.session.user.sub })); } else { - res.send(expandHtml(` -

喚醒 PinLin3770

- 點此登入 - `)); + res.send(renderHtml("login.html")); } }); app.get("/login", (req, res) => { const url = client.authorizationUrl({ scope: "openid profile", - redirect_uri: REDIRECT_URI + redirect_uri: REDIRECT_URI, }); res.redirect(url); }); @@ -81,8 +59,8 @@ let client; req.session.user = userinfo; res.redirect("/"); - } catch (err) { - res.send(expandHtml(`

⚠️ 登入失敗

${err}

回首頁`)); + } catch (error) { + res.send(renderHtml("login-fail.html", { error })); } }); @@ -91,9 +69,10 @@ let client; wol.wake(process.env.MAC_ADDRESS, (error) => { if (error) { - return res.send(expandHtml(`

⚠️ 發送魔法封包失敗

${error}

回首頁`)); + res.send(renderHtml("wakeup-fail.html", { error })); + } else { + res.send(renderHtml("wakeup-success.html")); } - res.send(expandHtml(`

✅ 已經發送魔法封包

回首頁`)); }); }); diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..4afd512 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,25 @@ + + + + + + 喚醒 PinLin3770 + + + +

喚醒 PinLin3770

+

已登入為身分 {{USERNAME}}

+
+ +
+
+ 喚醒 PinLin3770 + + diff --git a/templates/login-fail.html b/templates/login-fail.html new file mode 100644 index 0000000..b41e459 --- /dev/null +++ b/templates/login-fail.html @@ -0,0 +1,22 @@ + + + + + + 登入失敗 | 喚醒 PinLin3770 + + + +

喚醒 PinLin3770

+

⚠️ 登入失敗

+

{{error}}

+ 回首頁 + + diff --git a/templates/login.html b/templates/login.html new file mode 100644 index 0000000..3bb1bcd --- /dev/null +++ b/templates/login.html @@ -0,0 +1,20 @@ + + + + + + 登入 | 喚醒 PinLin3770 + + + +

喚醒 PinLin3770

+ 點此登入 + + diff --git a/templates/wakeup-fail.html b/templates/wakeup-fail.html new file mode 100644 index 0000000..69ce998 --- /dev/null +++ b/templates/wakeup-fail.html @@ -0,0 +1,22 @@ + + + + + + 喚醒失敗 | 喚醒 PinLin3770 + + + +

喚醒 PinLin3770

+

⚠️ 發送魔法封包失敗

+

{{error}}

+ 回首頁 + + diff --git a/templates/wakeup-success.html b/templates/wakeup-success.html new file mode 100644 index 0000000..8da5c33 --- /dev/null +++ b/templates/wakeup-success.html @@ -0,0 +1,21 @@ + + + + + + 喚醒成功 | 喚醒 PinLin3770 + + + +

喚醒 PinLin3770

+

✅ 已經發送魔法封包

+ 回首頁 + + diff --git a/utils/templates.jsm b/utils/templates.jsm new file mode 100644 index 0000000..8725f18 --- /dev/null +++ b/utils/templates.jsm @@ -0,0 +1,28 @@ +import fs from "fs"; +import path from "path"; + +export function createTemplateRenderer({ + baseDir = path.resolve("templates"), + useCache = true, +} = {}) { + const cache = {}; + + return function render(fileName, vars = {}) { + const filePath = path.join(baseDir, fileName); + let template; + + if (useCache && cache[filePath]) { + template = cache[filePath]; + } else { + template = fs.readFileSync(filePath, "utf8"); + if (useCache) cache[filePath] = template; + } + + let html = template; + for (const [key, value] of Object.entries(vars)) { + html = html.replace(new RegExp(`{{${key}}}`, "g"), value); + } + + return html; + }; +}