From 755654cf9d803fdb4032391045ff099748dc01f0 Mon Sep 17 00:00:00 2001 From: VityaSchel <59040542+VityaSchel@users.noreply.github.com> Date: Mon, 2 Oct 2023 18:54:26 +0400 Subject: [PATCH] Added last update, cache strategy, telegram fail notifications, teachers photos --- .example.env | 3 +- README.md | 11 +- package.json | 4 + pnpm-lock.yaml | 452 ++++++++++++++++++++++---- public/teachers/larionova.jpg | Bin 0 -> 4332 bytes public/teachers/амукова.jpg | Bin 0 -> 4093 bytes public/teachers/арефьев.jpg | Bin 0 -> 4084 bytes src/app/agregator/schedule.ts | 3 + src/app/logger.ts | 18 + src/entities/last-update-at/index.tsx | 14 + src/features/add-group/1925.png | Bin 0 -> 25928 bytes src/features/add-group/index.tsx | 63 ++++ src/pages/[group].tsx | 28 +- src/shared/data/teachers.ts | 6 +- src/widgets/navbar/index.tsx | 9 +- src/widgets/schedule/day.tsx | 14 +- src/widgets/schedule/index.tsx | 6 +- src/widgets/schedule/lesson.tsx | 6 +- tailwind.config.js | 66 ++-- 19 files changed, 579 insertions(+), 124 deletions(-) create mode 100644 public/teachers/larionova.jpg create mode 100644 public/teachers/амукова.jpg create mode 100644 public/teachers/арефьев.jpg create mode 100644 src/app/logger.ts create mode 100644 src/entities/last-update-at/index.tsx create mode 100644 src/features/add-group/1925.png create mode 100644 src/features/add-group/index.tsx diff --git a/.example.env b/.example.env index 1de21b4..a39ad2b 100644 --- a/.example.env +++ b/.example.env @@ -1 +1,2 @@ -PROXY_HOST= \ No newline at end of file +PROXY_HOST= +PARSING_FAILURE_NOTIFICATIONS_TELEGRAM_BOTAPI_TOKEN= \ No newline at end of file diff --git a/README.md b/README.md index 3cfa22d..1e791fd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # Schedule for колледж связи пгути +- [Schedule for колледж связи пгути](#schedule-for-колледж-связи-пгути) + - [Tech stack](#tech-stack) + - [Hire me!](#hire-me) + + Reskin of https://lk.ks.psuti.ru/ since it lacks mobile support and is generally ugly. ![TODO: screenshot](TODO: screenshot) @@ -9,12 +14,14 @@ Reskin of https://lk.ks.psuti.ru/ since it lacks mobile support and is generally ## Tech stack - React with Next.js v13.5 (pages router) -- Tailwind CSS +- Tailwind CSS. This is my first project using it, after using SCSS Modules for many years - @shadcn/ui components (built with Radix UI) - node-html-parser for scraping, rehydration strategy for cache - TypeScript with types for each package +- Telegram Bot API (via [node-telegram-bot-api]) for parsing failure notifications +- Custom [js parser for teachers' photos](https://gist.github.com/VityaSchel/28f1a360ee7798511765910b39c6086c) -Built in 1 day. Tools used: pnpm, eslint, react-icons. +Built under 1 day. Tools used: pnpm, eslint, react-icons. ## Hire me! diff --git a/package.json b/package.json index 9035da1..c1adee5 100644 --- a/package.json +++ b/package.json @@ -20,21 +20,25 @@ "classnames": "^2.3.2", "clsx": "^2.0.0", "content-type": "^1.0.5", + "date-fns": "^2.30.0", "jsdom": "^22.1.0", "lucide-react": "^0.279.0", "next": "latest", "next-themes": "^0.2.1", "node-html-parser": "^6.1.10", + "node-telegram-bot-api": "^0.63.0", "react": "latest", "react-dom": "latest", "react-icons": "^4.11.0", "sharp": "^0.32.6", "tailwind-merge": "^1.14.0", + "tailwind-scrollbar-hide": "^1.1.7", "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@types/jsdom": "^21.1.3", "@types/node": "latest", + "@types/node-telegram-bot-api": "^0.61.8", "@types/react": "latest", "@types/react-dom": "latest", "@typescript-eslint/eslint-plugin": "^6.7.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4270e20..2938e38 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -38,6 +38,9 @@ dependencies: content-type: specifier: ^1.0.5 version: 1.0.5 + date-fns: + specifier: ^2.30.0 + version: 2.30.0 jsdom: specifier: ^22.1.0 version: 22.1.0 @@ -53,6 +56,9 @@ dependencies: node-html-parser: specifier: ^6.1.10 version: 6.1.10 + node-telegram-bot-api: + specifier: ^0.63.0 + version: 0.63.0 react: specifier: latest version: 18.2.0 @@ -68,6 +74,9 @@ dependencies: tailwind-merge: specifier: ^1.14.0 version: 1.14.0 + tailwind-scrollbar-hide: + specifier: ^1.1.7 + version: 1.1.7 tailwindcss-animate: specifier: ^1.0.7 version: 1.0.7(tailwindcss@3.3.3) @@ -79,6 +88,9 @@ devDependencies: '@types/node': specifier: latest version: 20.8.0 + '@types/node-telegram-bot-api': + specifier: ^0.61.8 + version: 0.61.8 '@types/react': specifier: latest version: 18.2.24 @@ -986,6 +998,10 @@ packages: engines: {node: '>= 10'} dev: false + /@types/caseless@0.12.3: + resolution: {integrity: sha512-ZD/NsIJYq/2RH+hY7lXmstfp/v9djGt9ah+xRQ3pcgR79qiKsG4pLl25AI7IcXxVO8dH9GiBE5rAknC0ePntlw==} + dev: true + /@types/content-type@1.1.6: resolution: {integrity: sha512-WFHg/KFLCdUQl3m27WSQu0NEaLzoHGmgZHlsSYr0Y0iIvItMcBq7opZc6AGXPXqf+btIM6vTBJyLvuDAihB+zQ==} dev: false @@ -1006,6 +1022,14 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true + /@types/node-telegram-bot-api@0.61.8: + resolution: {integrity: sha512-WKGyH3gKvWx7+a19oVZOyJLXjiptSG5PZkNbAHi4CvcRSLwCYBqJpxhERnt2oJuMuNR3oPmpFxv81cM4224cYA==} + dependencies: + '@types/node': 20.8.0 + '@types/request': 2.48.9 + eventemitter3: 3.1.2 + dev: true + /@types/node@20.8.0: resolution: {integrity: sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ==} dev: true @@ -1025,6 +1049,15 @@ packages: '@types/scheduler': 0.16.4 csstype: 3.1.2 + /@types/request@2.48.9: + resolution: {integrity: sha512-4mi2hYsvPAhe8RXjk5DKB09sAUzbK68T2XjORehHdWyxFoX2zUnfi1VQ5wU4Md28H/5+uB4DkxY9BS4B87N/0A==} + dependencies: + '@types/caseless': 0.12.3 + '@types/node': 20.8.0 + '@types/tough-cookie': 4.0.3 + form-data: 2.5.1 + dev: true + /@types/scheduler@0.16.4: resolution: {integrity: sha512-2L9ifAGl7wmXwP4v3pN4p2FLhD0O1qsJpvKmNin5VA8+UvNVb447UDaAEV6UdrkA+m/Xs58U1RFps44x6TFsVQ==} @@ -1201,7 +1234,6 @@ packages: fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: true /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} @@ -1250,7 +1282,6 @@ packages: dependencies: call-bind: 1.0.2 is-array-buffer: 3.0.2 - dev: true /array-includes@3.1.7: resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} @@ -1268,6 +1299,15 @@ packages: engines: {node: '>=8'} dev: true + /array.prototype.findindex@2.2.2: + resolution: {integrity: sha512-fnTMT+Xq/VloVDsroPW9JLL1M5UxNTVfoNxU4KeyDcH5C/Jmjikf5+KDH5207wWMC8MBlSOn7kZkkys8XnqWNg==} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.1 + es-abstract: 1.22.2 + es-shim-unscopables: 1.0.0 + dev: false + /array.prototype.findlastindex@1.2.3: resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} engines: {node: '>= 0.4'} @@ -1320,7 +1360,17 @@ packages: get-intrinsic: 1.2.1 is-array-buffer: 3.0.2 is-shared-array-buffer: 1.0.2 - dev: true + + /asn1@0.2.6: + resolution: {integrity: sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /assert-plus@1.0.0: + resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==} + engines: {node: '>=0.8'} + dev: false /ast-types-flow@0.0.7: resolution: {integrity: sha512-eBvWn1lvIApYMhzQMsu9ciLfkBY499mFZlNqG+/9WR7PVlroQw0vG30cOQQbaKz3sCEc44TAOu2ykzqXSNnwag==} @@ -1334,7 +1384,6 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: false /autoprefixer@10.4.16(postcss@8.4.31): resolution: {integrity: sha512-7vd3UC6xKp0HLfua5IjZlcXvGAGy7cBAXTg2lyQ/8WpNhd6SiZ8Be+xm3FyBSYJx5GKcpRCzBh7RH4/0dnY+uQ==} @@ -1355,7 +1404,14 @@ packages: /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} - dev: true + + /aws-sign2@0.7.0: + resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} + dev: false + + /aws4@1.12.0: + resolution: {integrity: sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==} + dev: false /axe-core@4.8.2: resolution: {integrity: sha512-/dlp0fxyM3R8YW7MFzaHWXrf4zzbr0vaYb23VBFCl83R7nWNPg/yaQw2Dc8jzCMmDVLhSdzH8MjrsuIUuvX+6g==} @@ -1379,10 +1435,23 @@ packages: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: false + /bcrypt-pbkdf@1.0.2: + resolution: {integrity: sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==} + dependencies: + tweetnacl: 0.14.5 + dev: false + /binary-extensions@2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} + /bl@1.2.3: + resolution: {integrity: sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==} + dependencies: + readable-stream: 2.3.8 + safe-buffer: 5.2.1 + dev: false + /bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} dependencies: @@ -1391,6 +1460,10 @@ packages: readable-stream: 3.6.2 dev: false + /bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + dev: false + /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} dev: false @@ -1437,7 +1510,6 @@ packages: dependencies: function-bind: 1.1.1 get-intrinsic: 1.2.1 - dev: true /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -1451,6 +1523,10 @@ packages: /caniuse-lite@1.0.30001541: resolution: {integrity: sha512-bLOsqxDgTqUBkzxbNlSBt8annkDpQB9NdzdTbO2ooJ+eC/IQcvDspDc058g84ejCelF7vHUx57KIOjEecOHXaw==} + /caseless@0.12.0: + resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} + dev: false + /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1525,7 +1601,6 @@ packages: engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - dev: false /commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} @@ -1539,6 +1614,14 @@ packages: engines: {node: '>= 0.6'} dev: false + /core-util-is@1.0.2: + resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==} + dev: false + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1582,6 +1665,13 @@ packages: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} dev: true + /dashdash@1.14.1: + resolution: {integrity: sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==} + engines: {node: '>=0.10'} + dependencies: + assert-plus: 1.0.0 + dev: false + /data-urls@4.0.0: resolution: {integrity: sha512-/mMTei/JXPqvFqQtfyTowxmJVwr2PVAeCcDxyFf6LhoOu/09TX2OX3kb2wzi4DMXcfj4OItwDOnhl5oziPnT6g==} engines: {node: '>=14'} @@ -1591,6 +1681,13 @@ packages: whatwg-url: 12.0.1 dev: false + /date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + dependencies: + '@babel/runtime': 7.23.1 + dev: false + /debug@3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -1600,7 +1697,6 @@ packages: optional: true dependencies: ms: 2.1.3 - dev: true /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -1640,7 +1736,6 @@ packages: get-intrinsic: 1.2.1 gopd: 1.0.1 has-property-descriptors: 1.0.0 - dev: true /define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} @@ -1649,12 +1744,10 @@ packages: define-data-property: 1.1.0 has-property-descriptors: 1.0.0 object-keys: 1.1.1 - dev: true /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: false /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} @@ -1731,6 +1824,13 @@ packages: domhandler: 5.0.3 dev: false + /ecc-jsbn@0.1.2: + resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} + dependencies: + jsbn: 0.1.1 + safer-buffer: 2.1.2 + dev: false + /electron-to-chromium@1.4.537: resolution: {integrity: sha512-W1+g9qs9hviII0HAwOdehGYkr+zt7KKdmCcJcjH0mYg6oL8+ioT3Skjmt7BLoAQqXhjf40AXd+HlR4oAWMlXjA==} dev: true @@ -1800,7 +1900,6 @@ packages: typed-array-length: 1.0.4 unbox-primitive: 1.0.2 which-typed-array: 1.1.11 - dev: true /es-iterator-helpers@1.0.15: resolution: {integrity: sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==} @@ -1828,13 +1927,11 @@ packages: get-intrinsic: 1.2.1 has: 1.0.3 has-tostringtag: 1.0.0 - dev: true /es-shim-unscopables@1.0.0: resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} dependencies: has: 1.0.3 - dev: true /es-to-primitive@1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} @@ -1843,7 +1940,6 @@ packages: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 - dev: true /escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} @@ -2129,14 +2225,25 @@ packages: engines: {node: '>=0.10.0'} dev: true + /eventemitter3@3.1.2: + resolution: {integrity: sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==} + /expand-template@2.0.3: resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} engines: {node: '>=6'} dev: false + /extend@3.0.2: + resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==} + dev: false + + /extsprintf@1.3.0: + resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} + engines: {'0': node >=0.6.0} + dev: false + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true /fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} @@ -2154,7 +2261,6 @@ packages: /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} @@ -2172,6 +2278,11 @@ packages: flat-cache: 3.1.0 dev: true + /file-type@3.9.0: + resolution: {integrity: sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==} + engines: {node: '>=0.10.0'} + dev: false + /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -2203,6 +2314,27 @@ packages: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} dependencies: is-callable: 1.2.7 + + /forever-agent@0.6.1: + resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} + dev: false + + /form-data@2.3.3: + resolution: {integrity: sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /form-data@2.5.1: + resolution: {integrity: sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==} + engines: {node: '>= 0.12'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 dev: true /form-data@4.0.0: @@ -2243,11 +2375,9 @@ packages: define-properties: 1.2.1 es-abstract: 1.22.2 functions-have-names: 1.2.3 - dev: true /functions-have-names@1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} - dev: true /get-intrinsic@1.2.1: resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} @@ -2256,7 +2386,6 @@ packages: has: 1.0.3 has-proto: 1.0.1 has-symbols: 1.0.3 - dev: true /get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} @@ -2269,7 +2398,6 @@ packages: dependencies: call-bind: 1.0.2 get-intrinsic: 1.2.1 - dev: true /get-tsconfig@4.7.2: resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} @@ -2277,6 +2405,12 @@ packages: resolve-pkg-maps: 1.0.0 dev: true + /getpass@0.1.7: + resolution: {integrity: sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==} + dependencies: + assert-plus: 1.0.0 + dev: false + /github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} dev: false @@ -2341,7 +2475,6 @@ packages: engines: {node: '>= 0.4'} dependencies: define-properties: 1.2.1 - dev: true /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} @@ -2359,7 +2492,6 @@ packages: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} dependencies: get-intrinsic: 1.2.1 - dev: true /graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2368,9 +2500,22 @@ packages: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} dev: true + /har-schema@2.0.0: + resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} + engines: {node: '>=4'} + dev: false + + /har-validator@5.1.5: + resolution: {integrity: sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==} + engines: {node: '>=6'} + deprecated: this library is no longer supported + dependencies: + ajv: 6.12.6 + har-schema: 2.0.0 + dev: false + /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - dev: true /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} @@ -2381,24 +2526,20 @@ packages: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: get-intrinsic: 1.2.1 - dev: true /has-proto@1.0.1: resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} engines: {node: '>= 0.4'} - dev: true /has-symbols@1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} engines: {node: '>= 0.4'} - dev: true /has-tostringtag@1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 - dev: true /has@1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} @@ -2429,6 +2570,15 @@ packages: - supports-color dev: false + /http-signature@1.2.0: + resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} + engines: {node: '>=0.8', npm: '>=1.3.7'} + dependencies: + assert-plus: 1.0.0 + jsprim: 1.4.2 + sshpk: 1.17.0 + dev: false + /https-proxy-agent@5.0.1: resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} engines: {node: '>= 6'} @@ -2488,7 +2638,6 @@ packages: get-intrinsic: 1.2.1 has: 1.0.3 side-channel: 1.0.4 - dev: true /invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} @@ -2502,7 +2651,6 @@ packages: call-bind: 1.0.2 get-intrinsic: 1.2.1 is-typed-array: 1.1.12 - dev: true /is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -2519,7 +2667,6 @@ packages: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: has-bigints: 1.0.2 - dev: true /is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} @@ -2533,12 +2680,10 @@ packages: dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 - dev: true /is-callable@1.2.7: resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} engines: {node: '>= 0.4'} - dev: true /is-core-module@2.13.0: resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==} @@ -2550,7 +2695,6 @@ packages: engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 - dev: true /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} @@ -2582,14 +2726,12 @@ packages: /is-negative-zero@2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} - dev: true /is-number-object@1.0.7: resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 - dev: true /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} @@ -2610,7 +2752,6 @@ packages: dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 - dev: true /is-set@2.0.2: resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} @@ -2620,28 +2761,28 @@ packages: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: call-bind: 1.0.2 - dev: true /is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 - dev: true /is-symbol@1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 - dev: true /is-typed-array@1.1.12: resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} engines: {node: '>= 0.4'} dependencies: which-typed-array: 1.1.11 - dev: true + + /is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + dev: false /is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} @@ -2651,7 +2792,6 @@ packages: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.2 - dev: true /is-weakset@2.0.2: resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} @@ -2660,14 +2800,21 @@ packages: get-intrinsic: 1.2.1 dev: true + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: false + /isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} - dev: true /isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} dev: true + /isstream@0.1.2: + resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} + dev: false + /iterator.prototype@1.1.2: resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==} dependencies: @@ -2692,6 +2839,10 @@ packages: argparse: 2.0.1 dev: true + /jsbn@0.1.1: + resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} + dev: false + /jsdom@22.1.0: resolution: {integrity: sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==} engines: {node: '>=16'} @@ -2736,12 +2887,19 @@ packages: /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true + + /json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + dev: false /json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: false + /json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true @@ -2749,6 +2907,16 @@ packages: minimist: 1.2.8 dev: true + /jsprim@1.4.2: + resolution: {integrity: sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==} + engines: {node: '>=0.6.0'} + dependencies: + assert-plus: 1.0.0 + extsprintf: 1.3.0 + json-schema: 0.4.0 + verror: 1.10.0 + dev: false + /jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -2801,6 +2969,10 @@ packages: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -2835,13 +3007,17 @@ packages: /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: false /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true dev: false /mimic-response@3.1.0: @@ -2866,7 +3042,6 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - dev: true /mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} @@ -2962,6 +3137,23 @@ packages: resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} dev: true + /node-telegram-bot-api@0.63.0: + resolution: {integrity: sha512-SssDLHZ+Qi7Ygwt2iKur2BBZUjRBBDxC98+ydyVZo/arUJlXz3nA6dUEYP3pjNLWW4qQJdf7OsptaUDrKTTHlg==} + engines: {node: '>=0.12'} + dependencies: + array.prototype.findindex: 2.2.2 + bl: 1.2.3 + debug: 3.2.7 + eventemitter3: 3.1.2 + file-type: 3.9.0 + mime: 1.6.0 + pump: 2.0.1 + request: 2.88.2 + request-promise: 4.2.6(request@2.88.2) + transitivePeerDependencies: + - supports-color + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2981,6 +3173,10 @@ packages: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: false + /oauth-sign@0.9.0: + resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} + dev: false + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -2991,12 +3187,10 @@ packages: /object-inspect@1.12.3: resolution: {integrity: sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==} - dev: true /object-keys@1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} - dev: true /object.assign@4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} @@ -3006,7 +3200,6 @@ packages: define-properties: 1.2.1 has-symbols: 1.0.3 object-keys: 1.1.1 - dev: true /object.entries@1.1.7: resolution: {integrity: sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==} @@ -3116,6 +3309,10 @@ packages: engines: {node: '>=8'} dev: true + /performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + dev: false + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} @@ -3227,6 +3424,10 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: false + /prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} dependencies: @@ -3239,6 +3440,13 @@ packages: resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} dev: false + /pump@2.0.1: + resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + /pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} dependencies: @@ -3250,6 +3458,11 @@ packages: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} + /qs@6.5.3: + resolution: {integrity: sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==} + engines: {node: '>=0.6'} + dev: false + /querystringify@2.2.0: resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} dev: false @@ -3357,6 +3570,18 @@ packages: dependencies: pify: 2.3.0 + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: false + /readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -3394,7 +3619,57 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 set-function-name: 2.0.1 - dev: true + + /request-promise-core@1.1.4(request@2.88.2): + resolution: {integrity: sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==} + engines: {node: '>=0.10.0'} + peerDependencies: + request: ^2.34 + dependencies: + lodash: 4.17.21 + request: 2.88.2 + dev: false + + /request-promise@4.2.6(request@2.88.2): + resolution: {integrity: sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ==} + engines: {node: '>=0.10.0'} + deprecated: request-promise has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142 + peerDependencies: + request: ^2.34 + dependencies: + bluebird: 3.7.2 + request: 2.88.2 + request-promise-core: 1.1.4(request@2.88.2) + stealthy-require: 1.1.1 + tough-cookie: 2.5.0 + dev: false + + /request@2.88.2: + resolution: {integrity: sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==} + engines: {node: '>= 6'} + deprecated: request has been deprecated, see https://github.com/request/request/issues/3142 + dependencies: + aws-sign2: 0.7.0 + aws4: 1.12.0 + caseless: 0.12.0 + combined-stream: 1.0.8 + extend: 3.0.2 + forever-agent: 0.6.1 + form-data: 2.3.3 + har-validator: 5.1.5 + http-signature: 1.2.0 + is-typedarray: 1.0.0 + isstream: 0.1.2 + json-stringify-safe: 5.0.1 + mime-types: 2.1.35 + oauth-sign: 0.9.0 + performance-now: 2.1.0 + qs: 6.5.3 + safe-buffer: 5.2.1 + tough-cookie: 2.5.0 + tunnel-agent: 0.6.0 + uuid: 3.4.0 + dev: false /requires-port@1.0.0: resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} @@ -3454,7 +3729,10 @@ packages: get-intrinsic: 1.2.1 has-symbols: 1.0.3 isarray: 2.0.5 - dev: true + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -3466,7 +3744,6 @@ packages: call-bind: 1.0.2 get-intrinsic: 1.2.1 is-regex: 1.1.4 - dev: true /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -3504,7 +3781,6 @@ packages: define-data-property: 1.1.0 functions-have-names: 1.2.3 has-property-descriptors: 1.0.0 - dev: true /sharp@0.32.6: resolution: {integrity: sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==} @@ -3539,7 +3815,6 @@ packages: call-bind: 1.0.2 get-intrinsic: 1.2.1 object-inspect: 1.12.3 - dev: true /simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} @@ -3568,6 +3843,27 @@ packages: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} + /sshpk@1.17.0: + resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} + engines: {node: '>=0.10.0'} + hasBin: true + dependencies: + asn1: 0.2.6 + assert-plus: 1.0.0 + bcrypt-pbkdf: 1.0.2 + dashdash: 1.14.1 + ecc-jsbn: 0.1.2 + getpass: 0.1.7 + jsbn: 0.1.1 + safer-buffer: 2.1.2 + tweetnacl: 0.14.5 + dev: false + + /stealthy-require@1.1.1: + resolution: {integrity: sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==} + engines: {node: '>=0.10.0'} + dev: false + /streamsearch@1.1.0: resolution: {integrity: sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==} engines: {node: '>=10.0.0'} @@ -3601,7 +3897,6 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true /string.prototype.trimend@1.0.7: resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} @@ -3609,7 +3904,6 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true /string.prototype.trimstart@1.0.7: resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} @@ -3617,7 +3911,12 @@ packages: call-bind: 1.0.2 define-properties: 1.2.1 es-abstract: 1.22.2 - dev: true + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: false /string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -3696,6 +3995,10 @@ packages: resolution: {integrity: sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==} dev: false + /tailwind-scrollbar-hide@1.1.7: + resolution: {integrity: sha512-X324n9OtpTmOMqEgDUEA/RgLrNfBF/jwJdctaPZDzB3mppxJk7TLIDmOreEDm1Bq4R9LSPu4Epf8VSdovNU+iA==} + dev: false + /tailwindcss-animate@1.0.7(tailwindcss@3.3.3): resolution: {integrity: sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==} peerDependencies: @@ -3796,6 +4099,14 @@ packages: dependencies: is-number: 7.0.0 + /tough-cookie@2.5.0: + resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} + engines: {node: '>=0.8'} + dependencies: + psl: 1.9.0 + punycode: 2.3.0 + dev: false + /tough-cookie@4.1.3: resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} engines: {node: '>=6'} @@ -3844,6 +4155,10 @@ packages: safe-buffer: 5.2.1 dev: false + /tweetnacl@0.14.5: + resolution: {integrity: sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==} + dev: false + /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -3863,7 +4178,6 @@ packages: call-bind: 1.0.2 get-intrinsic: 1.2.1 is-typed-array: 1.1.12 - dev: true /typed-array-byte-length@1.0.0: resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} @@ -3873,7 +4187,6 @@ packages: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 - dev: true /typed-array-byte-offset@1.0.0: resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} @@ -3884,7 +4197,6 @@ packages: for-each: 0.3.3 has-proto: 1.0.1 is-typed-array: 1.1.12 - dev: true /typed-array-length@1.0.4: resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} @@ -3892,7 +4204,6 @@ packages: call-bind: 1.0.2 for-each: 0.3.3 is-typed-array: 1.1.12 - dev: true /typescript@5.2.2: resolution: {integrity: sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==} @@ -3907,7 +4218,6 @@ packages: has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 - dev: true /universalify@0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} @@ -3929,7 +4239,6 @@ packages: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.0 - dev: true /url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} @@ -3972,6 +4281,21 @@ packages: /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + /uuid@3.4.0: + resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} + deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. + hasBin: true + dev: false + + /verror@1.10.0: + resolution: {integrity: sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==} + engines: {'0': node >=0.6.0} + dependencies: + assert-plus: 1.0.0 + core-util-is: 1.0.2 + extsprintf: 1.3.0 + dev: false + /w3c-xmlserializer@4.0.0: resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} engines: {node: '>=14'} @@ -4020,7 +4344,6 @@ packages: is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.4 - dev: true /which-builtin-type@1.1.3: resolution: {integrity: sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==} @@ -4058,7 +4381,6 @@ packages: for-each: 0.3.3 gopd: 1.0.1 has-tostringtag: 1.0.0 - dev: true /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} diff --git a/public/teachers/larionova.jpg b/public/teachers/larionova.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1af045881e8851e0ca6f5cfebe1b1d0cbc08901a GIT binary patch literal 4332 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 literal 0 HcmV?d00001 diff --git a/public/teachers/амукова.jpg b/public/teachers/амукова.jpg new file mode 100644 index 0000000000000000000000000000000000000000..849f6fde6b9a2e1dde3d1b326c9d21c830508ea3 GIT binary patch literal 4093 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 F_a6uLPAC8X literal 0 HcmV?d00001 diff --git a/public/teachers/арефьев.jpg b/public/teachers/арефьев.jpg new file mode 100644 index 0000000000000000000000000000000000000000..30023a3f0b2d4f3d4d7e795ff0f6a05d7eb83573 GIT binary patch literal 4084 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 F{TDs&Or`(; literal 0 HcmV?d00001 diff --git a/src/app/agregator/schedule.ts b/src/app/agregator/schedule.ts index 7ba4523..c9def7b 100644 --- a/src/app/agregator/schedule.ts +++ b/src/app/agregator/schedule.ts @@ -4,6 +4,7 @@ import contentTypeParser from 'content-type' // import { parse } from 'node-html-parser' import { JSDOM } from 'jsdom' import { content as mockContent } from './mock' +import { reportParserError } from '@/app/logger' // ПС-7: 146 export async function getSchedule(groupID: number, groupName: string): Promise { @@ -17,11 +18,13 @@ export async function getSchedule(groupID: number, groupName: string): Promise 500 ? content.slice(0, 500 - 3) + '...' : content) + reportParserError(new Date().toISOString(), 'Не удалось получить страницу для группы', groupName) throw new Error('Error while fetching lk.ks.psuti.ru') } } \ No newline at end of file diff --git a/src/app/logger.ts b/src/app/logger.ts new file mode 100644 index 0000000..4ca759a --- /dev/null +++ b/src/app/logger.ts @@ -0,0 +1,18 @@ +import TelegramBot from 'node-telegram-bot-api' + +const token = process.env.PARSING_FAILURE_NOTIFICATIONS_TELEGRAM_BOTAPI_TOKEN +const ownerID = process.env.PARSING_FAILURE_NOTIFICATIONS_TELEGRAM_CHAT_ID + +let bot: TelegramBot +if (!token || !ownerID) { + console.warn('Telegram Token is not specified. This means you won\'t get any notifications about parsing failures.') +} else { + bot = new TelegramBot(token, { polling: false }) +} + + +export async function reportParserError(...text: string[]) { + if (!token || !ownerID) return + + await bot.sendMessage(ownerID, text.join(' ')) +} \ No newline at end of file diff --git a/src/entities/last-update-at/index.tsx b/src/entities/last-update-at/index.tsx new file mode 100644 index 0000000..84daf09 --- /dev/null +++ b/src/entities/last-update-at/index.tsx @@ -0,0 +1,14 @@ +import { formatDistanceStrict } from 'date-fns' +import { ru as dateFnsRuLocale } from 'date-fns/locale' + +export function LastUpdateAt({ date }: { + date: Date +}) { + return ( +
+ + Последнее обновление:{'\n'}{formatDistanceStrict(date, Date.now(), { locale: dateFnsRuLocale, addSuffix: true })} + +
+ ) +} \ No newline at end of file diff --git a/src/features/add-group/1925.png b/src/features/add-group/1925.png new file mode 100644 index 0000000000000000000000000000000000000000..e7f345a4f90701e44ac0d3d45e3ff9bd83b0480e GIT binary patch literal 25928 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 { + setPopupVisible(true) + } + + return ( + <> + + setPopupVisible(false)} /> + + ) +} + +function Popup({ open, onClose }: { + open: boolean + onClose: () => any +}) { + return ( + !isOpen && onClose()}> + + + Добавить группу + + + Если вы хотите добавить свою группу на сайт, скиньтесь всей группой и задонатьте мне 500 ₽ + + + На сайте не только появится ваше расписание, но оно будет обновляться каждую неделю. А если во время парсинга произойдет ошибка — я сразу получу об этом уведомление в телеграм, потому что у меня настроен бот. + + + Для меня добавить вашу группу это даже не одна строка кода, а одно нажатие клавиши, но я хочу чтобы этот сайт был доступен только самым лучшим и избранным, достойных престижа + + + + + + + + + + + + ) +} \ No newline at end of file diff --git a/src/pages/[group].tsx b/src/pages/[group].tsx index 6929b18..71289bd 100644 --- a/src/pages/[group].tsx +++ b/src/pages/[group].tsx @@ -4,22 +4,27 @@ import { GetServerSidePropsContext, GetServerSidePropsResult } from 'next' import { getSchedule } from '@/app/agregator/schedule' import { NextSerialized, nextDeserializer, nextSerialized } from '@/app/utils/date-serializer' import { NavBar } from '@/widgets/navbar' +import { LastUpdateAt } from '@/entities/last-update-at' type PageProps = NextSerialized<{ schedule: Day[] + parsedAt: Date }> export default function HomePage(props: PageProps) { - const { schedule } = nextDeserializer(props) + const { schedule, parsedAt } = nextDeserializer(props) return ( <> + ) } +const cachedSchedules = new Map() +const maxCacheDurationInMS = 1000 * 60 * 60 export async function getServerSideProps(context: GetServerSidePropsContext<{ group: string }>): Promise> { const groups: { [group: string]: [number, string] } = { ps7: [146, 'ПС-7'], @@ -27,11 +32,24 @@ export async function getServerSideProps(context: GetServerSidePropsContext<{ gr } const group = context.params?.group if (group && Object.hasOwn(groups, group) && group in groups) { - const schedule = await getSchedule(...groups[group]) + let schedule + let parsedAt + + const cachedSchedule = cachedSchedules.get(group) + if (cachedSchedule?.lastFetched && Date.now() - cachedSchedule.lastFetched.getTime() < maxCacheDurationInMS) { + schedule = cachedSchedule.results + parsedAt = cachedSchedule.lastFetched + } else { + schedule = await getSchedule(...groups[group]) + parsedAt = new Date() + cachedSchedules.set(group, { lastFetched: new Date(), results: schedule }) + } + return { - props: { - schedule: nextSerialized(schedule) - } + props: nextSerialized({ + schedule: schedule, + parsedAt: parsedAt + }) } } else { return { diff --git a/src/shared/data/teachers.ts b/src/shared/data/teachers.ts index df99e36..8697edb 100644 --- a/src/shared/data/teachers.ts +++ b/src/shared/data/teachers.ts @@ -14,7 +14,7 @@ export const teachers = [ }, { name: 'Амукова Светлана Николаевна', - picture: 'https://ks.psuti.ru/images/stories/emp/', + picture: 'https://ks.psuti.ru/images/stories/emp/амукова.jpg', pronouns: 'she' }, { @@ -36,7 +36,7 @@ export const teachers = [ }, { name: 'Арефьев Андрей Андреевич', - picture: 'https://ks.psuti.ru/images/stories/ks-news/2016/prepodavateli-foto/%20class=', + picture: 'https://ks.psuti.ru/images/stories/ks-news/2016/prepodavateli-foto/арефьев.jpg', pronouns: 'he' }, { @@ -107,7 +107,7 @@ export const teachers = [ }, { name: 'Ларионова Софья Николаевна', - picture: 'https://ks.psuti.ru/images/stories/ks-news/2016/prepodavateli-foto/.jpg', + picture: 'https://ks.psuti.ru/images/stories/ks-news/2016/prepodavateli-foto/larionova.jpg', pronouns: 'she' }, { diff --git a/src/widgets/navbar/index.tsx b/src/widgets/navbar/index.tsx index 87948be..97c184a 100644 --- a/src/widgets/navbar/index.tsx +++ b/src/widgets/navbar/index.tsx @@ -1,19 +1,20 @@ +import { AddGroupButton } from '@/features/add-group' import { ThemeSwitcher } from '@/features/theme-switch' import { Button } from '@/shadcn/ui/button' import { useTheme } from 'next-themes' import Link from 'next/link' import { useRouter } from 'next/router' -import cx from 'classnames' export function NavBar() { - const { resolvedTheme } = useTheme() + const { resolvedTheme, theme } = useTheme() return (
-