From 3452ad4e20f2893df91a06e053d683435cb0fde8 Mon Sep 17 00:00:00 2001 From: L0510410 <87233125+L0510410@users.noreply.github.com> Date: Thu, 11 Aug 2022 14:42:08 +0800 Subject: [PATCH] change weekly.ts and fix many bugs (#1085) --- .github/workflows/deploy.yml | 2 +- README.md | 2 +- package.json | 2 +- src/index.ts | 2 +- src/routes/emails.ts | 11 +- src/routes/users.ts | 64 ++---- src/routes/weekly.ts | 378 +++++++++++++++++++---------------- tsconfig.json | 4 +- yarn.lock | 44 +--- 9 files changed, 239 insertions(+), 270 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6adb7dd5..0b72e8ad 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -16,7 +16,7 @@ jobs: - name: Use Node.js ${{matrix.node-version}} uses: actions/setup-node@v1 with: - node-version: "14.x" + node-version: "16.x" - name: get yarn cache path id: yarn-cache-dir-path diff --git a/README.md b/README.md index 1fd9cc3f..ab11f9eb 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ EESAST 后端 API ### 环境 -- node 14 / npm +- node 16 / npm - yarn - TypeScript - MongoDB diff --git a/package.json b/package.json index f4011e14..0e458bf3 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "morgan": "1.10.0", "multer": "1.4.4", "node-cron": "3.0.1", - "node-fetch": "3.2.10", + "node-fetch": "2.6.2", "nodemailer": "6.7.7" }, "devDependencies": { diff --git a/src/index.ts b/src/index.ts index 9a630859..d9b12739 100644 --- a/src/index.ts +++ b/src/index.ts @@ -47,7 +47,7 @@ db.once("open", () => { }); export const client = new GraphQLClient( - `${process.env.HASURA_URL}/v1/graphql`, + `${process.env.HASURA_GRAPHQL_ENDPOINT}/v1/graphql`, { headers: { "Content-Type": "application/json", diff --git a/src/routes/emails.ts b/src/routes/emails.ts index 2cfb4558..f71de512 100644 --- a/src/routes/emails.ts +++ b/src/routes/emails.ts @@ -1,19 +1,13 @@ import express from "express"; -import { GraphQLClient, gql } from "graphql-request"; +import { gql } from "graphql-request"; import { sendEmail } from "../helpers/email"; import { newMentorApplicationTemplate } from "../helpers/htmlTemplates"; import hasura from "../middlewares/hasura"; +import { client } from ".."; const router = express.Router(); router.post("/events", hasura, async (req, res) => { - const client = new GraphQLClient(`${process.env.HASURA_URL}/v1/graphql`, { - headers: { - "Content-Type": "application/json", - "x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET!, - }, - }); - const data = req.body?.event?.data?.new; const table = req.body?.table?.name; const op = req.body?.event?.op; @@ -84,7 +78,6 @@ router.post("/events", hasura, async (req, res) => { } return res.status(200).end(); - break; } catch (e) { console.error(e); res.status(500).end(); diff --git a/src/routes/users.ts b/src/routes/users.ts index c09ff980..20d2eb01 100644 --- a/src/routes/users.ts +++ b/src/routes/users.ts @@ -11,9 +11,10 @@ import { } from "../helpers/htmlTemplates"; import authenticate, { JwtPayload } from "../middlewares/authenticate"; import { validateEmail, validatePassword } from "../helpers/validate"; -import fetch from "node-fetch"; import hasura from "../middlewares/hasura"; import type { MongoError } from "mongodb"; +import { gql } from "graphql-request"; +import { client } from ".."; const router = express.Router(); @@ -305,25 +306,16 @@ router.post("/verify", async (req, res) => { return res.status(200).end(); } } else if (type === "regular") { - await fetch(`${process.env.API_URL}/v1/graphql`, { - method: "POST", - headers: { - "Content-Type": "application/json", - "x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET!, - }, - body: JSON.stringify({ - query: ` - mutation InsertUser($_id: String!) { - insert_user_one(object: {_id: $_id}) { - _id - } + await client.request( + gql` + mutation InsertUser($_id: String!) { + insert_user_one(object: {_id: $_id}) { + _id } - `, - variables: { - _id: user._id, - }, - }), - }); + } + `, + { _id: user._id } + ); user.update({ emailVerified: true }, null, (err) => { if (err) { @@ -447,30 +439,18 @@ router.post("/actions/user_by_role", hasura, async (req, res) => { try { const users = await User.find({ role }); - - const response = await fetch(`${process.env.API_URL}/v1/graphql`, { - method: "POST", - headers: { - "Content-Type": "application/json", - "x-hasura-admin-secret": process.env.HASURA_GRAPHQL_ADMIN_SECRET!, - }, - body: JSON.stringify({ - query: ` - query GetUsersByIds($ids: [String!]) { - user(where: {_id: {_in: $ids}}) { - _id - name - department - } + const usersByRole = await client.request( + gql` + query GetUsersByIds($ids: [String!]) { + user(where: {_id: {_in: $ids}}) { + _id + name + department } - `, - variables: { - ids: users.map((u) => u._id), - }, - }), - }); - - const usersByRole: any = await response.json(); + } + `, + { ids: users.map((u) => u._id) } + ) if (usersByRole?.data?.user) { return res.status(200).json(usersByRole?.data?.user); diff --git a/src/routes/weekly.ts b/src/routes/weekly.ts index 90fbb32c..bc3a142f 100644 --- a/src/routes/weekly.ts +++ b/src/routes/weekly.ts @@ -1,193 +1,223 @@ import express from "express"; -import sha1 from "../helpers/sha1"; -// import fetch from "node-fetch"; -// import cron from "node-cron"; -// import authenticate from "../middlewares/authenticate"; +import fetch from "node-fetch"; +import jwt from "jsonwebtoken"; const router = express.Router(); -// var access_token: string; -// var weeklys: any = []; -// var newest_article_id: string; -// var items: any = []; -// 微信公众平台验证 router.get("/", async (req, res) => { try { - const signature = req.query.signature; - const timestamp = req.query.timestamp; - const nonce = req.query.nonce; - const echostr = req.query.echostr; - const token = process.env.WX_TOKEN; - console.log(signature, timestamp, nonce, echostr); - if (!(signature && timestamp && nonce && echostr)) return res.status(401).send("401 Unauthorized: missing param"); - const list = [token, timestamp, nonce]; - list.sort(); - let str = list.join(""); - str = sha1(str); - if (str == signature) return res.status(200).send(echostr); - else return res.status(401).send("401 Unauthorized: authentication failure"); - } catch (err) { - console.log("Error occurs!\n" + err); - return res.status(500).send("500 Internal Server Error: " + err); - } -}); - -/* -// 获取图文列表 -router.post("/fetchall", authenticate(), async (req, res) => { - try { - let total_count: number; - let params = new URLSearchParams(); - params.append("access_token", access_token); - params.append("offset", "0"); - params.append("count", "1"); - params.append("no_content", "1"); - let response = await fetch( - "https://api.weixin.qq.com/cgi-bin/freepublish/batchget", - { method: "POST", body: params} - ); - let result = await response.json(); - if (result.ok && result.errcode == 0) { - total_count = result.total_count; + const authHeader = req.get("Authorization"); + if (!authHeader) { + return res.status(401).send("401 Unauthorized: Missing token"); } - else return res.status(500).send("500 Internal Server Error: fetch failed!"); - - let count = total_count; - while (1) { - params.set("offset", String(count - 1)); - response = await fetch( - "https://api.weixin.qq.com/cgi-bin/freepublish/batchget", - { method: "POST", body: params} + const token = authHeader.substring(7); + return jwt.verify(token, process.env.SECRET!, async (err, decoded) => { + if (err || !decoded) { + return res + .status(401) + .send("401 Unauthorized: Token expired or invalid"); + } + const response = await fetch( + req.body.url, + { method: "GET"} ); - result = await response.json(); - if (result.ok && result.errcode == 0) { - if (newest_article_id == result.item[0].article_id) { - console.log("up-to-date now"); - break; - } else { - items.push(result.item[0]); - for (let new_item of result.item[0].content.news_item) { - let i = 0; - if (new_item.title.search("SAST Weekly") != -1) { - weeklys.push({ - article_id: result.item[0].article_id, - title: new_item.title, - url: new_item.url, - update_time: result.item[0].update_time, - sequence: i - }); - } - i++; - } - count--; - } + if (response.ok) { + const text: string = await response.text(); + const match = text.match(/var msg_cdn_url.*1:1/); + if (match == null) throw(Error("capture failed!")); + const url1 = match[0].match(/http:\/\/.*=png/); + const url2 = match[0].match(/http:\/\/.*=jpeg/); + return res.status(200).send(url1 == null ? url2 : url1); } else return res.status(500).send("500 Internal Server Error: fetch failed!"); - } - - newest_article_id = items[items.length - 1].article_id; - return res.status(200).send({weeklys}); + }) } catch (err) { - console.log("Error occurs!\n" + err); return res.status(500).send("500 Internal Server Error: " + err); } }) -// 获取图文 -router.post("/fetch", authenticate(), async (req, res) => { - try { - let params = new URLSearchParams(); - params.append("access_token", access_token); - params.append("article_id", req.body.article_id); - let response = await fetch( - "https://api.weixin.qq.com/cgi-bin/freepublish/getarticle", - { method: "POST", body: params} - ); - let result = await response.json(); - if (result.ok && result.errcode == 0) { - return res.status(200).send(result.news_item[req.body.sequence]); - } - else return res.status(500).send("500 Internal Server Error: fetch failed!"); - } catch (err) { - console.log("Error occurs!\n" + err); - return res.status(500).send("500 Internal Server Error: " + err); - } -}) +export default router; -// 定时获取AccessToken -const weekly_cron = () => { - cron.schedule(`* ${Number(process.env.WX_EXPIRED_TIME)-5} * * * *`, async () => { - try { - const params = new URLSearchParams(); - params.append("grant_type", "client_credential"); - params.append("appid", `${process.env.WX_APPID}`); - params.append("secret", `${process.env.WX_APPSECRET}`); +// var access_token: string; +// var weeklys: any = []; +// var newest_article_id: string; +// var items: any = []; - const response = await fetch( - "https://api.weixin.qq.com/cgi-bin/token", - { method: "GET", body: params} - ); - const result = await response.json(); - if (result.ok && result.errcode == 0) { - access_token = result.access_token; - console.log("access token updated"); - } else { - console.log(result.errcode + result.errmsg); - } - } catch (err) { - console.log("Error occurs!\n" + err); - } - }) -} +// // 微信公众平台验证 +// router.get("/", async (req, res) => { +// try { +// const signature = req.query.signature; +// const timestamp = req.query.timestamp; +// const nonce = req.query.nonce; +// const echostr = req.query.echostr; +// const token = process.env.WX_TOKEN; +// console.log(signature, timestamp, nonce, echostr); +// if (!(signature && timestamp && nonce && echostr)) return res.status(401).send("401 Unauthorized: missing param"); +// const list = [token, timestamp, nonce]; +// list.sort(); +// let str = list.join(""); +// str = sha1(str); +// if (str == signature) return res.status(200).send(echostr); +// else return res.status(401).send("401 Unauthorized: authentication failure"); +// } catch (err) { +// console.log("Error occurs!\n" + err); +// return res.status(500).send("500 Internal Server Error: " + err); +// } +// }); -// 初始化获取全部weekly推送 -const weekly_init = async () => { - let offset = 0; - try { - while (1) { - const params = new URLSearchParams(); - params.append("access_token", access_token); - params.append("offset", String(offset)); - params.append("count", "20"); - params.append("no_content", "1"); - const response = await fetch( - "https://api.weixin.qq.com/cgi-bin/freepublish/batchget", - { method: "POST", body: params} - ); - const result = await response.json(); - if (result.ok && result.errcode == 0) { - if (result.item_count < 20) { - items.push(result.item); - newest_article_id = result.item[result.item.length - 1].article_id; - break; - } else { - items.push(result.item); - offset += 20; - } - } - else return console.log("fetch failed!"); - } - for (let item of items) { - for (let new_item of item.content.news_item) { - let i = 0; - if (new_item.title.search("SAST Weekly") != -1) { - weeklys.push({ - article_id: item.article_id, - title: new_item.title, - url: new_item.url, - update_time: item.update_time, - sequence: i - }); - } - i++; - } - } - } - catch (err) { - console.log("error!" + err); - } -} +// // 获取图文列表 +// router.post("/fetchall", authenticate(), async (req, res) => { +// try { +// let total_count: number; +// let params = new URLSearchParams(); +// params.append("access_token", access_token); +// params.append("offset", "0"); +// params.append("count", "1"); +// params.append("no_content", "1"); +// let response = await fetch( +// "https://api.weixin.qq.com/cgi-bin/freepublish/batchget", +// { method: "POST", body: params} +// ); +// let result: any = await response.json(); +// if (result.ok && result.errcode == 0) { +// total_count = result.total_count; +// } +// else return res.status(500).send("500 Internal Server Error: fetch failed!"); -export {router, weekly_cron, weekly_init}; -*/ -export default router; +// let count = total_count; +// while (1) { +// params.set("offset", String(count - 1)); +// response = await fetch( +// "https://api.weixin.qq.com/cgi-bin/freepublish/batchget", +// { method: "POST", body: params} +// ); +// result = await response.json(); +// if (result.ok && result.errcode == 0) { +// if (newest_article_id == result.item[0].article_id) { +// console.log("up-to-date now"); +// break; +// } else { +// items.push(result.item[0]); +// for (let new_item of result.item[0].content.news_item) { +// let i = 0; +// if (new_item.title.search("SAST Weekly") != -1) { +// weeklys.push({ +// article_id: result.item[0].article_id, +// title: new_item.title, +// url: new_item.url, +// update_time: result.item[0].update_time, +// sequence: i +// }); +// } +// i++; +// } +// count--; +// } +// } +// else return res.status(500).send("500 Internal Server Error: fetch failed!"); +// } + +// newest_article_id = items[items.length - 1].article_id; +// return res.status(200).send({weeklys}); +// } catch (err) { +// console.log("Error occurs!\n" + err); +// return res.status(500).send("500 Internal Server Error: " + err); +// } +// }) + +// // 获取图文 +// router.post("/fetch", authenticate(), async (req, res) => { +// try { +// let params = new URLSearchParams(); +// params.append("access_token", access_token); +// params.append("article_id", req.body.article_id); +// let response = await fetch( +// "https://api.weixin.qq.com/cgi-bin/freepublish/getarticle", +// { method: "POST", body: params} +// ); +// let result: any = await response.json(); +// if (result.ok && result.errcode == 0) { +// return res.status(200).send(result.news_item[req.body.sequence]); +// } +// else return res.status(500).send("500 Internal Server Error: fetch failed!"); +// } catch (err) { +// console.log("Error occurs!\n" + err); +// return res.status(500).send("500 Internal Server Error: " + err); +// } +// }) + +// // 定时获取AccessToken +// const weekly_cron = () => { +// cron.schedule(`* ${Number(process.env.WX_EXPIRED_TIME)-5} * * * *`, async () => { +// try { +// const params = new URLSearchParams(); +// params.append("grant_type", "client_credential"); +// params.append("appid", `${process.env.WX_APPID}`); +// params.append("secret", `${process.env.WX_APPSECRET}`); + +// const response = await fetch( +// "https://api.weixin.qq.com/cgi-bin/token", +// { method: "GET", body: params} +// ); +// const result: any = await response.json(); +// if (result.ok && result.errcode == 0) { +// access_token = result.access_token; +// console.log("access token updated"); +// } else { +// console.log(result.errcode + result.errmsg); +// } +// } catch (err) { +// console.log("Error occurs!\n" + err); +// } +// }) +// } + +// // 初始化获取全部weekly推送 +// const weekly_init = async () => { +// let offset = 0; +// try { +// while (1) { +// const params = new URLSearchParams(); +// params.append("access_token", access_token); +// params.append("offset", String(offset)); +// params.append("count", "20"); +// params.append("no_content", "1"); +// const response = await fetch( +// "https://api.weixin.qq.com/cgi-bin/freepublish/batchget", +// { method: "POST", body: params} +// ); +// const result: any = await response.json(); +// if (result.ok && result.errcode == 0) { +// if (result.item_count < 20) { +// items.push(result.item); +// newest_article_id = result.item[result.item.length - 1].article_id; +// break; +// } else { +// items.push(result.item); +// offset += 20; +// } +// } +// else return console.log("fetch failed!"); +// } +// for (let item of items) { +// for (let new_item of item.content.news_item) { +// let i = 0; +// if (new_item.title.search("SAST Weekly") != -1) { +// weeklys.push({ +// article_id: item.article_id, +// title: new_item.title, +// url: new_item.url, +// update_time: item.update_time, +// sequence: i +// }); +// } +// i++; +// } +// } +// } +// catch (err) { +// console.log("error!" + err); +// } +// } + +// export {router, weekly_cron, weekly_init}; diff --git a/tsconfig.json b/tsconfig.json index 63bb8ec8..75362370 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,8 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "lib": ["esnext"], - "module": "commonjs", - "moduleResolution": "node", + "module": "ES2020", + "moduleResolution": "Node16", "noEmit": true, "resolveJsonModule": true, "strict": true, diff --git a/yarn.lock b/yarn.lock index 0461f716..36bf366e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2132,11 +2132,6 @@ data-uri-to-buffer@3: resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-3.0.1.tgz#594b8973938c5bc2c33046535785341abc4f3636" integrity sha512-WboRycPNsVw3B3TL559F7kuBUM4d8CgMEvk6xEJlOp7OBPjt6G7z8WMWlD2rOFZLk6OYfFIUGsCOWzcQH9K2og== -data-uri-to-buffer@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz#b5db46aea50f6176428ac05b73be39a57701a64b" - integrity sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA== - dateformat@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-2.2.0.tgz#4065e2013cf9fb916ddfd82efb506ad4c6769062" @@ -2691,14 +2686,6 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fetch-blob@^3.1.2, fetch-blob@^3.1.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9" - integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ== - dependencies: - node-domexception "^1.0.0" - web-streams-polyfill "^3.0.3" - file-entry-cache@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" @@ -2777,13 +2764,6 @@ form-data@^3.0.0: combined-stream "^1.0.8" mime-types "^2.1.12" -formdata-polyfill@^4.0.10: - version "4.0.10" - resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423" - integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g== - dependencies: - fetch-blob "^3.1.2" - formstream@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/formstream/-/formstream-1.1.1.tgz#17259d2440c35ca9736db9f45fb3ba3f8669c750" @@ -3942,11 +3922,6 @@ node-cron@3.0.1: resolved "https://registry.yarnpkg.com/node-cron/-/node-cron-3.0.1.tgz#6a9d5a71513c7ee1eb9e64a673f6730084561d87" integrity sha512-RAWZTNn2M5KDIUV/389UX0EXsqvdFAwc9QwHQceh0Ga56dygqSRthqIjwpgZsoDspHGt2rkHdk9Z4RgfPMdALw== -node-domexception@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" - integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== - node-environment-flags@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -3955,6 +3930,11 @@ node-environment-flags@^1.0.5: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" +node-fetch@2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.2.tgz#986996818b73785e47b1965cc34eb093a1d464d0" + integrity sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA== + node-fetch@2.6.7, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -3962,15 +3942,6 @@ node-fetch@2.6.7, node-fetch@^2.6.7: dependencies: whatwg-url "^5.0.0" -node-fetch@3.2.10: - version "3.2.10" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.2.10.tgz#e8347f94b54ae18b57c9c049ef641cef398a85c8" - integrity sha512-MhuzNwdURnZ1Cp4XTazr69K0BTizsBroX7Zx3UgDSVcZYKF/6p0CBe4EUb/hLqmzVhl0UpYfgRljQ4yxE+iCxA== - dependencies: - data-uri-to-buffer "^4.0.0" - fetch-blob "^3.1.4" - formdata-polyfill "^4.0.10" - node-releases@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666" @@ -5291,11 +5262,6 @@ vm2@^3.9.8: acorn "^8.7.0" acorn-walk "^8.2.0" -web-streams-polyfill@^3.0.3: - version "3.2.1" - resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz#71c2718c52b45fd49dbeee88634b3a60ceab42a6" - integrity sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q== - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"