diff --git a/.env.production b/.env.production index bdc7d75..551c698 100644 --- a/.env.production +++ b/.env.production @@ -1 +1,3 @@ -DB_URL=mongodb://127.0.0.1:27017/test \ No newline at end of file +DB_URL=mongodb://127.0.0.1:27017/test +DEEP_SEEK_URL=https://api.deepseek.com +DEEP_SEEK_API_KEY= \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 5eab6fc..2f99232 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,6 @@ { "cSpell.words": [ + "deepseek", "Segs", "uuidv" ] diff --git a/middleware/auth.js b/middleware/auth.js index e6b6bb0..121c76b 100644 --- a/middleware/auth.js +++ b/middleware/auth.js @@ -11,12 +11,14 @@ const auth = function (req, res, next) { if ( // TODO: This array should be a global array or a array in a global file ([ + "/deepseek", "/logic/login", "/test", "/grab", "/user/", "/youdao/", "/translation/content", + "/cron" ].indexOf(req.originalUrl) > -1 && (req.method === "POST" || req.method === "GET")) || rule.test(req.originalUrl) || diff --git a/package.json b/package.json index b7153b2..b0a7989 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "cheerio": "1.0.0-rc.12", "cookie-parser": "~1.4.4", "cors": "^2.8.5", + "cron": "^3.5.0", "debug": "~2.6.9", "dotenv": "^16.4.5", "express": "~4.16.1", @@ -29,6 +30,7 @@ "mongodb": "^5.6.0", "mongoose": "^7.3.1", "morgan": "~1.9.1", + "openai": "^4.83.0", "pm2": "^5.4.2", "pug": "2.0.0-beta11", "qrcode": "^1.5.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 147320f..0fa1956 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ importers: cors: specifier: ^2.8.5 version: 2.8.5 + cron: + specifier: ^3.5.0 + version: 3.5.0 debug: specifier: ~2.6.9 version: 2.6.9 @@ -71,6 +74,9 @@ importers: morgan: specifier: ~1.9.1 version: 1.9.1 + openai: + specifier: ^4.83.0 + version: 4.83.0 pm2: specifier: ^5.4.2 version: 5.4.2 @@ -208,12 +214,21 @@ packages: '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + '@types/luxon@3.4.2': + resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} + '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/node-fetch@2.6.12': + resolution: {integrity: sha512-8nneRWKCg3rMtF69nLQJnOYUcbafYeFSjqkw3jCRLsqkWFlHaoQrr5mXmofFGOx3DKn7UfmBMyov8ySvLRVldA==} + '@types/node@12.20.55': resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + '@types/node@18.19.75': + resolution: {integrity: sha512-UIksWtThob6ZVSyxcOqCLOUNg/dyO1Qvx4McgeuhrEtHTLFTf7BBhEazaE4K806FGTPtzd/2sE90qn4fVr7cyw==} + '@types/node@20.16.11': resolution: {integrity: sha512-y+cTCACu92FyA5fgQSAI8A1H429g7aSK2HsO7K4XYUWc4dY5IUz55JSDIYT6/VsOLfGy8vmvQYC2hfb0iF16Uw==} @@ -241,6 +256,10 @@ packages: '@types/xml2js@0.4.14': resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==} + abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + accepts@1.3.8: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} @@ -262,6 +281,10 @@ packages: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} + agentkeepalive@4.6.0: + resolution: {integrity: sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==} + engines: {node: '>= 8.0.0'} + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -532,6 +555,9 @@ packages: resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} engines: {node: '>= 0.10'} + cron@3.5.0: + resolution: {integrity: sha512-0eYZqCnapmxYcV06uktql93wNWdlTmmBFP2iYz+JPVcQqlyFYcn1lFuIk4R54pkOmE7mcldTAPZv6X5XA4Q46A==} + croner@4.1.97: resolution: {integrity: sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==} @@ -750,6 +776,10 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + eventemitter2@0.4.14: resolution: {integrity: sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==} @@ -821,10 +851,17 @@ packages: forever-agent@0.6.1: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + form-data-encoder@1.7.2: + resolution: {integrity: sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A==} + form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} + formdata-node@4.4.1: + resolution: {integrity: sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==} + engines: {node: '>= 12.20'} + forwarded@0.2.0: resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} engines: {node: '>= 0.6'} @@ -956,6 +993,9 @@ packages: resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} engines: {node: '>=10.17.0'} + humanize-ms@1.2.1: + resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} + iconv-lite@0.4.23: resolution: {integrity: sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==} engines: {node: '>=0.10.0'} @@ -1183,6 +1223,10 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + md5@2.3.0: resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} @@ -1295,6 +1339,10 @@ packages: resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} engines: {node: '>= 0.4.0'} + node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + node-fetch@2.7.0: resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} engines: {node: 4.x || >=6.0.0} @@ -1353,6 +1401,18 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + openai@4.83.0: + resolution: {integrity: sha512-fmTsqud0uTtRKsPC7L8Lu55dkaTwYucqncDHzVvO64DKOpNTuiYwjbR/nVgpapXuYy8xSnhQQPUm+3jQaxICgw==} + hasBin: true + peerDependencies: + ws: ^8.18.0 + zod: ^3.23.8 + peerDependenciesMeta: + ws: + optional: true + zod: + optional: true + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -1797,6 +1857,9 @@ packages: uglify-to-browserify@1.0.2: resolution: {integrity: sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==} + undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} @@ -1852,6 +1915,10 @@ packages: resolution: {integrity: sha512-qZKX4RnBzH2ugr8Lxa7x+0V6XD9Sb/ouARtiasEQCHB1EVU4NXtmHsDDrx1dO4ne5fc3J6EW05BP1Dl0z0iung==} engines: {node: '>=0.10.0'} + web-streams-polyfill@4.0.0-beta.3: + resolution: {integrity: sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==} + engines: {node: '>= 14'} + webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} @@ -2173,10 +2240,21 @@ snapshots: '@types/http-errors@2.0.4': {} + '@types/luxon@3.4.2': {} + '@types/mime@1.3.5': {} + '@types/node-fetch@2.6.12': + dependencies: + '@types/node': 22.7.5 + form-data: 4.0.0 + '@types/node@12.20.55': {} + '@types/node@18.19.75': + dependencies: + undici-types: 5.26.5 + '@types/node@20.16.11': dependencies: undici-types: 6.19.8 @@ -2211,6 +2289,10 @@ snapshots: dependencies: '@types/node': 22.7.5 + abort-controller@3.0.0: + dependencies: + event-target-shim: 5.0.1 + accepts@1.3.8: dependencies: mime-types: 2.1.35 @@ -2230,6 +2312,10 @@ snapshots: transitivePeerDependencies: - supports-color + agentkeepalive@4.6.0: + dependencies: + humanize-ms: 1.2.1 + ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -2540,6 +2626,11 @@ snapshots: object-assign: 4.1.1 vary: 1.1.2 + cron@3.5.0: + dependencies: + '@types/luxon': 3.4.2 + luxon: 3.5.0 + croner@4.1.97: {} cross-env@7.0.3: @@ -2729,6 +2820,8 @@ snapshots: etag@1.8.1: {} + event-target-shim@5.0.1: {} + eventemitter2@0.4.14: {} eventemitter2@5.0.1: {} @@ -2835,12 +2928,19 @@ snapshots: forever-agent@0.6.1: {} + form-data-encoder@1.7.2: {} + form-data@4.0.0: dependencies: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 + formdata-node@4.4.1: + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 4.0.0-beta.3 + forwarded@0.2.0: {} fresh@0.5.2: {} @@ -2986,6 +3086,10 @@ snapshots: human-signals@2.1.0: {} + humanize-ms@1.2.1: + dependencies: + ms: 2.1.3 + iconv-lite@0.4.23: dependencies: safer-buffer: 2.1.2 @@ -3186,6 +3290,8 @@ snapshots: lru-cache@7.18.3: {} + luxon@3.5.0: {} + md5@2.3.0: dependencies: charenc: 0.0.2 @@ -3287,6 +3393,8 @@ snapshots: netmask@2.0.2: {} + node-domexception@1.0.0: {} + node-fetch@2.7.0: dependencies: whatwg-url: 5.0.0 @@ -3332,6 +3440,18 @@ snapshots: dependencies: mimic-fn: 2.1.0 + openai@4.83.0: + dependencies: + '@types/node': 18.19.75 + '@types/node-fetch': 2.6.12 + abort-controller: 3.0.0 + agentkeepalive: 4.6.0 + form-data-encoder: 1.7.2 + formdata-node: 4.4.1 + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -3886,6 +4006,8 @@ snapshots: uglify-to-browserify@1.0.2: optional: true + undici-types@5.26.5: {} + undici-types@6.19.8: {} universalify@0.2.0: {} @@ -3930,6 +4052,8 @@ snapshots: void-elements@2.0.1: {} + web-streams-polyfill@4.0.0-beta.3: {} + webidl-conversions@3.0.1: {} webidl-conversions@7.0.0: {} diff --git a/routes/article.js b/routes/article.js index bf7f968..2885084 100644 --- a/routes/article.js +++ b/routes/article.js @@ -1,25 +1,19 @@ const express = require("express"); const router = express.Router(); const rt = require("../schemas/articleSchema"); +const { + theGuardianModel, +} = require("../schemas/supportedWebsite/theGuardianSchema"); +const { wordGroupModel } = require("../schemas/wordGroupSchema"); const { articleModel } = rt; const ut = require("../utils/utils"); -const { generateResponse } = ut; +const { generateResponse, generateBadResponse } = ut; const axios = require("axios").default; const cheerio = require("cheerio"); const { newsInLevelsModel, } = require("../schemas/supportedWebsite/newsInLevelsSchema"); -// Get article detail -router.get("/:id", async function (req, res, next) { - try { - let t = await articleModel.findById(req.params.id).exec(); - res.json(generateResponse(t)); - } catch (error) { - res.json(generateResponse("", 400, "fail")); - } -}); - router.get("/youtube/detail/:youtubeId", async function (req, res, next) { const u = req.tUser; const r = await articleModel.find({ @@ -223,4 +217,103 @@ router.post("/parse/newsinlevels", async function (req, res, next) { res.json(generateResponse()); }); +router.post("/guardian", async function (req, res, next) { + console.log("sdjfasldjfalsd;f"); + const { title, summary, originalUrl, content, groupId } = req.body; + const userId = req.tUser._id; + const existGuardianList = await theGuardianModel.find( + { + groupId, + author: userId, + }, + "_id title" + ); + if (existGuardianList.length > 0) { + res.json(existGuardianList[0]); + } else { + if (title && content && groupId && originalUrl && req.tUser) { + const t = await theGuardianModel.create({ + title, + summary, + content, + groupId, + author: userId, + originalUrl, + }); + res.json(generateResponse(t)); + } else { + res.json(generateBadResponse()); + } + } +}); + +router.get("/guardian", async function (req, res, next) { + const userId = req.tUser._id; + // const r = await theGuardianModel.find({ author: userId }, "_id title questions").exec(); + const r = await theGuardianModel.aggregate([ + { + // 添加一个新的字段 'date',仅包含日期部分 + $addFields: { + date: { + $dateToString: { format: "%Y-%m-%d", date: "$createdAt" }, + }, + }, + }, + { + // 筛选需要的字段 + $project: { + date: 1, + title: 1, + author: 1, + summary: 1, + questions: 1, + _id: 1, + createdAt: 1, + }, + }, + { + // 按照 'date' 字段进行分组 + $group: { + _id: "$date", + count: { $sum: 1 }, // 计算每个日期的文档数量 + documents: { + $push: { + _id: "$_id", + title: "$title", + author: "$author", + questions: "$questions", + summary: "$summary", + }, + }, + }, + }, + { + // 按日期升序排序 + $sort: { _id: 1 }, + }, + ]); + + res.json(generateResponse(r)); +}); + +router.get("/guardian/:id", async function (req, res, next) { + const id = req.params.id; + const t = await theGuardianModel.findById(id); + if (t) { + res.json(generateResponse(t)); + } else { + res.json(generateBadResponse()); + } +}); + +// Get article detail +// 这个路由会与/article/guardian这样的路由冲突 +router.get("/:id", async function (req, res, next) { + try { + let t = await articleModel.findById(req.params.id).exec(); + res.json(generateResponse(t)); + } catch (error) { + res.json(generateResponse("", 400, "fail")); + } +}); module.exports = router; diff --git a/routes/index.js b/routes/index.js index f233688..9f6ed81 100644 --- a/routes/index.js +++ b/routes/index.js @@ -9,6 +9,25 @@ const qrcode = require("qrcode"); const cheerio = require("cheerio"); const Parser = require("@postlight/parser"); const { default: axios } = require("axios"); +const { default: OpenAI } = require("openai"); +const { CronJob } = require("cron"); +const { articleModel } = require("../schemas/articleSchema"); +const { + theGuardianModel, +} = require("../schemas/supportedWebsite/theGuardianSchema"); + +router.get("/cron", async function (req, res, next) { + const job = new CronJob( + "* * * * * *", // cronTime + function () { + console.log("You will see this message every second"); + }, // onTick + null, // onComplete + true, // start + "America/Los_Angeles" // timeZone + ); + res.json(generateResponse()); +}); router.get("/index", async function (req, res, next) { qrcode.toDataURL( @@ -23,7 +42,7 @@ router.get("/index", async function (req, res, next) { router.get("/newsinlevel", async function (req, res, next) { const url = `https://www.newsinlevels.com/products/what-people-ate-during-world-war-ii-level-1/#/`; const d = await axios({ url }); - console.log(d.data) + console.log(d.data); res.json(generateResponse()); }); @@ -99,4 +118,56 @@ router.get("/test", async function (req, res, next) { res.send(generateResponse(r)); }); +router.post("/deepseek", async function (req, res, next) { + const openai = new OpenAI({ + baseURL: process.env.DEEP_SEEK_URL, + apiKey: process.env.DEEP_SEEK_API_KEY, + }); + const { articleId } = req.body; + if (!articleId) { + res.json(generateBadResponse()); + return; + } + const article = await theGuardianModel.findById(articleId).exec(); + const questions = article.questions; + const answers = article.answers; + if (questions && answers) { + res.json(generateResponse(article)); + return; + } + const content = article.content.join(""); + // console.log(content); + try { + const completion = await openai.chat.completions.create({ + messages: [ + { + role: "system", + content: `请根据这篇文章的内容,帮我出5个阅读理解题目,每个题目提供4个选项,题目和选项使用英文。答案和解析使用中文进行分析,答案和解析统一在所有题目后提供,问题和答案之间使用三个感叹号进行分隔。下是文章内容: ${content}`, + // content: "你好", + }, + ], + model: "deepseek-chat", + }); + + // console.log(completion); + // console.log(completion.choices[0].message.content); + // console.log(typeof completion.choices[0].message.content); + const replyContent = completion.choices[0].message.content; + const questionList = replyContent.split("!!!")[0]; + const answerList = replyContent.split("!!!")[1]; + console.log(questionList); + console.log(answerList); + article.questions = questionList; + article.answers = answerList; + await article.save(); + res.json( + generateResponse({ content: completion.choices[0].message.content }) + ); + } catch (error) { + console.log("deepseek error."); + console.log(error); + res.json(generateBadResponse()); + } +}); + module.exports = router; diff --git a/schemas/supportedWebsite/theGuardianSchema.js b/schemas/supportedWebsite/theGuardianSchema.js new file mode 100644 index 0000000..ef82596 --- /dev/null +++ b/schemas/supportedWebsite/theGuardianSchema.js @@ -0,0 +1,25 @@ +const mongoose = require("mongoose"); + +const { Schema } = mongoose; +const coverSchema = new Schema({ url: String }); +const theGuardianSchema = new Schema( + { + title: String, + author: mongoose.ObjectId, + groupId: mongoose.ObjectId, + cover: [coverSchema], + summary: String, + content: [String], + originalUrl: String, + questions: String, + answers: String, + }, + + { + timestamps: true, + } +); + +const theGuardianModel = mongoose.model("TheGuardian", theGuardianSchema); + +module.exports = { theGuardianModel }; diff --git a/utils/cron.js b/utils/cron.js new file mode 100644 index 0000000..1124f3b --- /dev/null +++ b/utils/cron.js @@ -0,0 +1,13 @@ +export class CronTask{ + constructor(){ + this.tasks = []; + } + + addTask(task){ + this.tasks.push(task); + } + + runTasks(){ + this.tasks.forEach(task => task()); + } +} \ No newline at end of file