Pārlūkot izejas kodu

:construction: save work

Song 5 gadi atpakaļ
vecāks
revīzija
615ff93d6b

+ 4 - 1
.gitignore

@@ -1,4 +1,7 @@
 .idea
 node_modules
 package-lock.json
-.env
+.env
+data.db
+data.db-journal
+.vscode

+ 4 - 2
app.js

@@ -5,8 +5,9 @@ const logger = require("morgan");
 const http = require("http");
 require("dotenv").config();
 
-const indexRouter = require("./routes");
-const requestToken = require("./utils").requestToken;
+const indexRouter = require("./routers/index");
+const messageRouter = require("./routers/message");
+const requestToken = require("./utils/wechat").requestToken;
 
 const app = express();
 
@@ -26,6 +27,7 @@ app.use(cookieParser());
 app.use(express.static(path.join(__dirname, "public")));
 
 app.use("/", indexRouter);
+app.use("/message", messageRouter);
 
 const server = http.createServer(app);
 

+ 22 - 0
knexfile.js

@@ -0,0 +1,22 @@
+module.exports = {
+  development: {
+    client: "sqlite3",
+    connection: {
+      filename: "./data.db",
+    },
+  },
+
+  staging: {
+    client: "sqlite3",
+    connection: {
+      filename: "./data.db",
+    },
+  },
+
+  production: {
+    client: "sqlite3",
+    connection: {
+      filename: "./data.db",
+    },
+  },
+};

+ 13 - 0
migrations/20200913222330_initialize_database.js

@@ -0,0 +1,13 @@
+exports.up = function (knex) {
+  return knex.schema.createTable("messages", (tableBuilder) => {
+    tableBuilder.uuid("id").primary();
+    tableBuilder.string("title");
+    tableBuilder.string("status");
+    tableBuilder.string("created_by");
+    tableBuilder.string("created_time");
+    tableBuilder.string("description");
+    tableBuilder.text("content");
+  });
+};
+
+exports.down = function (knex) {};

+ 19 - 0
models/message.js

@@ -0,0 +1,19 @@
+const db = require("../utils/database").db;
+const { v4: uuid } = require("uuid");
+
+class Message {
+  create(message) {
+    message.id = uuid();
+    return db("messages").insert(message);
+  }
+
+  getById(id) {
+    return db("messages").where("id", id);
+  }
+
+  deleteById(id) {
+    return db("messages").where("id", id).del();
+  }
+}
+
+module.exports.Message = new Message();

+ 5 - 1
package.json

@@ -12,7 +12,11 @@
     "dotenv": "^8.2.0",
     "ejs": "^3.1.5",
     "express": "~4.16.1",
-    "morgan": "~1.9.1"
+    "knex": "^0.21.5",
+    "marked": "^1.1.1",
+    "morgan": "~1.9.1",
+    "sqlite3": "^5.0.0",
+    "uuid": "^8.3.0"
   },
   "devDependencies": {
     "prettier": "^2.1.1"

+ 3 - 19
routes.js → routers/index.js

@@ -2,20 +2,14 @@ const express = require("express");
 const router = express.Router();
 const crypto = require("crypto");
 const fs = require("fs");
-const pushMessage = require("./utils").pushMessage;
 
 router.all("/", (req, res, next) => {
   fs.promises
     .access("./.env")
     .then(() => {
-      res.render("message", {
-        message: "服务已在运行,本次访问已被记录。",
+      res.render("info", {
+        message: "服务已在运行。",
       });
-      pushMessage(
-        req,
-        res,
-        `请注意,ip 地址为 ${req.ip} 的用户访问了你的消息通知服务,如果非你本人,则你的私有消息通知服务可能已被泄露,当前版本无法阻止其他用户通过本系统向你发送消息。`
-      );
     })
     .catch(() => {
       res.render("configure");
@@ -47,7 +41,7 @@ router.post("/configure", (req, res, next) => {
           process.exit();
         })
         .catch((e) => {
-          res.render("message", {
+          res.render("info", {
             message: "在尝试写入 .env 文件时发生错误:" + e,
           });
         });
@@ -68,14 +62,4 @@ router.all("/verify", (req, res, next) => {
   }
 });
 
-router.all("/push", (req, res, next) => {
-  let content = req.query.content || req.body.content;
-  pushMessage(req, res, content);
-});
-
-router.all("/:content", (req, res, next) => {
-  let content = req.params.content;
-  pushMessage(req, res, content);
-});
-
 module.exports = router;

+ 59 - 0
routers/message.js

@@ -0,0 +1,59 @@
+const express = require("express");
+const lexer = require("marked").lexer;
+const parser = require("marked").parser;
+const Message = require("../models/message").Message;
+const pushWeChatMessage = require("../utils/wechat").pushWeChatMessage;
+const formatTime = require("../utils/utils").formatTime;
+
+const router = express.Router();
+
+function md2html(markdown) {
+  return parser(lexer(markdown));
+}
+
+router.get("/:description", (req, res, next) => {
+  req.query.description = req.params.description;
+  next();
+});
+
+router.all("/", (req, res) => {
+  let message = {
+    title: req.query.title || req.body.title || "无标题",
+    status: 1,
+    created_by: "系统", // TODO
+    created_time: formatTime(),
+    description: req.query.description || req.body.description,
+    content: md2html(req.query.content || req.body.content),
+  };
+
+  Message.create(message)
+    .then((value) => {
+      console.log(value);
+      pushWeChatMessage(message.description, message.link)
+        .then((response) => {
+          res.json(response);
+        })
+        .catch((reason) => {
+          res.json(reason);
+        });
+    })
+    .catch((reason) => {
+      res.json(reason);
+    });
+});
+
+router.get("/detail/:id", (req, res) => {
+  const id = req.params.id;
+  Message.getById(id)
+    .then((value) => {
+      console.log(value);
+      res.render("message", value[0]);
+    })
+    .catch((reason) => {
+      res.render("info", {
+        message: "获取该消息时发生了错误:" + reason,
+      });
+    });
+});
+
+module.exports = router;

+ 9 - 0
utils/database.js

@@ -0,0 +1,9 @@
+const knex = require("knex");
+const environment = process.env.NODE_ENV || "development";
+const configuration = require("../knexfile")[environment];
+
+const db = knex(configuration);
+
+module.exports = {
+  db: db,
+};

+ 33 - 0
utils/utils.js

@@ -0,0 +1,33 @@
+function formatTime(format) {
+  if (format === undefined) format = "yyyy-MM-dd hh:mm:ss";
+  const date = new Date();
+  const o = {
+    "M+": date.getMonth() + 1,
+    "d+": date.getDate(),
+    "h+": date.getHours(),
+    "m+": date.getMinutes(),
+    "s+": date.getSeconds(),
+    S: date.getMilliseconds(),
+  };
+
+  if (/(y+)/.test(format)) {
+    format = format.replace(
+      RegExp.$1,
+      (date.getFullYear() + "").substr(4 - RegExp.$1.length)
+    );
+  }
+
+  for (let k in o) {
+    if (new RegExp("(" + k + ")").test(format)) {
+      format = format.replace(
+        RegExp.$1,
+        RegExp.$1.length === 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
+      );
+    }
+  }
+  return format;
+}
+
+module.exports = {
+  formatTime,
+};

+ 8 - 17
utils.js → utils/wechat.js

@@ -12,6 +12,7 @@ module.exports = {
           console.log("Token requested.");
           token = res.data.access_token;
           app.locals.access_token = token;
+          process.env.access_token = token;
         } else {
           console.error(res.data);
         }
@@ -19,27 +20,17 @@ module.exports = {
     return token;
   },
 
-  pushMessage: function (req, res, content) {
+  pushWeChatMessage: function (description, link) {
     // Reference: https://mp.weixin.qq.com/debug/cgi-bin/readtmpl?t=tmplmsg/faq_tmpl
-    let access_token = req.app.locals.access_token;
+    let access_token = process.env.access_token;
     let request_data = {
       touser: process.env.OPEN_ID,
       template_id: process.env.TEMPLATE_ID,
     };
-    request_data.data = { text: { value: content } };
-    axios
-      .post(
-        `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${access_token}`,
-        request_data
-      )
-      .then((response) => {
-        if (response.data && response.data.errcode === "40001") {
-          requestToken(req.app);
-        }
-        res.json(response.data);
-      })
-      .catch((error) => {
-        res.json(error);
-      });
+    request_data.data = { text: { value: description } };
+    return axios.post(
+      `https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=${access_token}`,
+      request_data
+    );
   },
 };

+ 10 - 0
views/info.ejs

@@ -0,0 +1,10 @@
+<%- include('./header') %>
+<article class="message is-primary">
+    <div class="message-header">
+        <p>注意</p>
+    </div>
+    <div class="message-body">
+        <%= message %>
+    </div>
+</article>
+<%- include('./footer') %>

+ 2 - 2
views/message.ejs

@@ -1,10 +1,10 @@
 <%- include('./header') %>
-<article class="message is-primary">
+<article class="info is-primary">
     <div class="message-header">
         <p>注意</p>
     </div>
     <div class="message-body">
-        <%= message %>
+
     </div>
 </article>
 <%- include('./footer') %>