diff --git a/.dockerignore b/.dockerignore index 2810f834..f793643e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,15 +1,37 @@ -node_modules -npm-debug.log +# folders +.devcontainer +.github +.husky +.idea +.vscode Dockerfile* -docker-compose* +LICENSE +Procfile +node_modules +test + +# files +.codecov.yml .dockerignore -.git -.github +.editorconfig +.eslint* .gitignore -README.md -LICENSE -.vscode -dist -build -images -script \ No newline at end of file +.gitpod.yml +.markdownlint.jsonc +.prettier* +.(yarn|npm|nvm)rc +*.md +app.json +docker-compose* +fly.toml +jsconfig.json +npm-debug.log +process.json +package-lock.json +vercel.json + +# git but keep the git commit hash +.git/logs +.git/index +.git/info +.git/hooks diff --git a/.env b/.env index 0fa82a27..69a7f4d1 100644 --- a/.env +++ b/.env @@ -1,5 +1,20 @@ # 服务端口 -PORT=6688 +PORT = 6688 # 允许的域名 -ALLOWED_DOMAIN = '*' \ No newline at end of file +ALLOWED_DOMAIN = "*" + +# ROBOT +DISALLOW_ROBOT = true + +# 缓存时长( 秒 ) +CACHE_TTL = 3600 + +# 请求超时( 毫秒 ) +REQUEST_TIMEOUT = 6000 + +# 是否输出日志 +USE_LOG_FILE = true + +# RSS Mode +RSS_MODE = false \ No newline at end of file diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..1048a96e --- /dev/null +++ b/.eslintignore @@ -0,0 +1,5 @@ +.vscode +docker-compose.yml +dist +logs +!/.github diff --git a/.eslintrc.json b/.eslintrc.json index 1eb3e021..380b4171 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,17 +3,12 @@ "browser": true, "es2021": true }, - "extends": ["eslint:recommended", "plugin:vue/vue3-essential"], + "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], + "parser": "@typescript-eslint/parser", "parserOptions": { "ecmaVersion": "latest", "sourceType": "module" }, - "plugins": ["vue"], - "rules": {}, - "globals": { - "require": true, - "module": true, - "process": true, - "__dirname": true - } + "plugins": ["@typescript-eslint"], + "rules": {} } diff --git a/.gitignore b/.gitignore index 8f636f48..a307e94f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,13 +10,8 @@ lerna-debug.log* node_modules .DS_Store dist -dist-ssr -coverage *.local -/cypress/videos/ -/cypress/screenshots/ - # Editor directories and files .vscode/* !.vscode/extensions.json @@ -25,6 +20,4 @@ coverage *.ntvs* *.njsproj *.sln -*.sw? - -test.md +*.sw? \ No newline at end of file diff --git a/.hintrc b/.hintrc deleted file mode 100644 index f301c617..00000000 --- a/.hintrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": [ - "development" - ], - "hints": { - "meta-viewport": "off", - "disown-opener": "off", - "button-type": "off", - "axe/aria": "off", - "no-inline-styles": "off", - "axe/text-alternatives": "off" - } -} \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 00000000..c1a54614 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +dist +node_modules +pnpm-lock.yaml +LICENSE.md +# tsconfig.json +# tsconfig.*.json diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 00000000..e452526e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,84 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our community include: + +- Demonstrating empathy and kindness toward other people +- Being respectful of differing opinions, viewpoints, and experiences +- Giving and gracefully accepting constructive feedback +- Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience +- Focusing on what is best not just for us as individuals, but for the overall community + +Examples of unacceptable behavior include: + +- The use of sexualized language or imagery, and sexual attention or + advances of any kind +- Trolling, insulting or derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or email + address, without their explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at . All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of actions. + +**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the project community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0, +available at . + +Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity). + +[homepage]: https://www.contributor-covenant.org + +For answers to common questions about this code of conduct, see the FAQ at +. Translations are available at . diff --git a/Dockerfile b/Dockerfile index 73b5fa32..4472f48b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,41 @@ -FROM node:18-alpine +FROM node:20-alpine AS base + +FROM base AS builder + +RUN apk add --no-cache libc6-compat +RUN npm install -g pnpm WORKDIR /app -COPY package*.json ./ -RUN npm install --production +COPY package*json tsconfig.json pnpm-lock.yaml .env ./ +COPY src ./src +COPY public ./public + +RUN pnpm install && \ + pnpm build && \ + pnpm prune --production + +FROM base AS runner +WORKDIR /app -COPY . . +# 创建用户和组 +RUN addgroup --system --gid 114514 nodejs +RUN adduser --system --uid 114514 hono +# 创建日志目录 +RUN mkdir -p /app/logs && chown -R hono:nodejs /app/logs + +# 复制文件 +COPY --from=builder --chown=hono:nodejs /app/node_modules /app/node_modules +COPY --from=builder --chown=hono:nodejs /app/dist /app/dist +COPY --from=builder /app/public /app/public +COPY --from=builder /app/.env /app/.env +COPY --from=builder /app/package.json /app/package.json + +# 切换用户 +USER hono + +# 暴露端口 EXPOSE 6688 -CMD ["npm", "start"] \ No newline at end of file + +# 运行 +CMD ["node", "/app/dist/index.js"] \ No newline at end of file diff --git a/LICENSE b/LICENSE index 8e2b10d5..a4c2bf96 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 底层用户 +Copyright (c) 2023 imsyy Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6e7b7aa7..87d5e385 100644 --- a/README.md +++ b/README.md @@ -4,117 +4,63 @@

一个聚合热门数据的 API 接口

-> [!TIP] -> ### 目前正基于 `Hono` 和 `typescript` 重构该项目,敬请期待 +--- +- 极快响应,便于开发 +- 支持 RSS 模式和 JSON 模式 +- 支持多种部署方式 +- 简明的路由目录,便于新增 ## 示例 -> 这里是使用该 API 的示例站点 +> 这里是使用该 API 的示例站点 +> 示例站点可能由于访问量或者长久未维护而访问异常 +> 若您也使用了本 API 搭建了网站,欢迎提交您的站点链接 - [今日热榜 - https://hot.imsyy.top/](https://hot.imsyy.top/) ## 总览 -> 🟢 状态正常 -> 🟠 可能失效 -> ❌ 无法使用 - -| **站点** | **类别** | **调用名称** | **状态** | -| ------------ | -------- | --------------------- | -------- | -| 哔哩哔哩 | 热门榜 | bilibili | 🟢 | -| 微博 | 热搜榜 | weibo | 🟢 | -| 知乎 | 热榜 | zhihu | 🟢 | -| 百度 | 热搜榜 | baidu | 🟢 | -| 抖音 | 热点榜 | douyin / douyin_new | 🟢 | -| 抖音 | 热歌榜 | douyin_music | 🟢 | -| 豆瓣 | 新片榜 | douban_new | 🟢 | -| 豆瓣讨论小组 | 讨论精选 | douban_group | 🟢 | -| 百度贴吧 | 热议榜 | tieba | 🟢 | -| 少数派 | 热榜 | sspai | 🟢 | -| IT 之家 | 热榜 | ithome | 🟠 | -| 澎湃新闻 | 热榜 | thepaper | 🟢 | -| 今日头条 | 热榜 | toutiao | 🟢 | -| 36 氪 | 热榜 | 36kr | 🟢 | -| 稀土掘金 | 热榜 | juejin | 🟢 | -| 腾讯新闻 | 热点榜 | newsqq | 🟢 | -| 网易新闻 | 热点榜 | netease | 🟢 | -| 英雄联盟 | 更新公告 | lol | 🟢 | -| 原神 | 最新消息 | genshin | 🟢 | -| 微信读书 | 飙升榜 | weread | 🟢 | -| 快手 | 热榜 | kuaishou | 🟢 | -| 网易云音乐 | 排行榜 | netease_music_toplist | 🟢 | -| QQ音乐 | 排行榜 | qq_music_toplist | 🟢 | -| NGA | 热帖 | ngabbs | 🟢 | -| Github | Trending | github | 🟢 | -| V2EX | 热榜 | v2ex | 🟠 | -| 历史上的今天 | 指定日期 | calendar | 🟢 | - -### 特殊接口说明 - -#### 网易云音乐 - -调用网易云音乐排行榜需要传入指定榜单类别 - -| 参数名 | 参数值 | 说明 | -| ------ | ------ | ------ | -| type | 1 | 飙升榜 | -| type | 2 | 新歌榜 | -| type | 3 | 原创榜 | -| type | 4 | 热歌榜 | - -```http -GET https://example.com/netease_music_toplist?type=1 -``` - -#### QQ音乐 - -调用QQ音乐排行榜需要传入指定榜单类别 - -| 参数名 | 参数值 | 说明 | -| ------ | ------ | ---------------- | -| type | 1 | 飙升榜 | -| type | 2 | 热歌榜 | -| type | 3 | 新歌榜 | -| type | 4 | 流行指数榜 | -| type | 5 | 腾讯音乐人原创榜 | -| type | 6 | 听歌识曲榜 | - -```http -GET https://example.com/qq_music_toplist?type=1 -``` - -#### 获取全部接口信息 - -获取除了下方特殊接口外的全部接口列表 - -```http -GET https://example.com/all -``` - -#### 历史上的今天(指定日期) - -将指定的月份和日期传入即可得到当天数据,请注意格式 - -```http -GET https://example.com/calendar/date?month=06&day=01 -``` +> 🟢 状态正常 / 🟠 可能失效 / ❌ 无法使用 + +| **站点** | **类别** | **调用名称** | **状态** | +| -------------- | -------- | ------------ | -------- | +| 哔哩哔哩 | 热门榜 | bilibili | 🟢 | +| AcFun | 排行榜 | acfun | 🟢 | +| 微博 | 热搜榜 | weibo | 🟢 | +| 知乎 | 热榜 | zhihu | 🟢 | +| 知乎日报 | 推荐榜 | zhihu-daily | 🟢 | +| 百度 | 热搜榜 | baidu | 🟢 | +| 抖音 | 热点榜 | douyin | 🟢 | +| 豆瓣电影 | 新片榜 | douban-movie | 🟢 | +| 豆瓣讨论小组 | 讨论精选 | douban-group | 🟢 | +| 百度贴吧 | 热议榜 | tieba | 🟢 | +| 少数派 | 热榜 | sspai | 🟢 | +| IT 之家 | 热榜 | ithome | 🟠 | +| 简书 | 热门推荐 | jianshu | 🟠 | +| 澎湃新闻 | 热榜 | thepaper | 🟢 | +| 今日头条 | 热榜 | toutiao | 🟢 | +| 36 氪 | 热榜 | 36kr | 🟢 | +| 稀土掘金 | 热榜 | juejin | 🟢 | +| 腾讯新闻 | 热点榜 | qq-news | 🟢 | +| 网易新闻 | 热点榜 | netease-news | 🟢 | +| 英雄联盟 | 更新公告 | lol | 🟢 | +| 原神 | 最新消息 | genshin | 🟢 | +| 崩坏3 | 最新动态 | honkai | 🟢 | +| 崩坏:星穹铁道 | 最新动态 | starrail | 🟢 | +| 微信读书 | 飙升榜 | weread | 🟢 | +| NGA | 热帖 | ngabbs | 🟢 | +| HelloGitHub | Trending | github | 🟢 | ## 部署 -```bash -# 安装依赖 -pnpm install - -# 运行 -pnpm start -``` +具体使用说明可参考 [我的博客](https://blog.imsyy.top/posts/2024/0408),下方仅讲解基础操作: -## Docker 部署 +### Docker 部署 > 安装及配置 Docker 将不在此处说明,请自行解决 -### 本地构建 +#### 本地构建 ```bash # 构建 @@ -125,7 +71,7 @@ docker run -p 6688:6688 -d dailyhot-api docker-compose up -d ``` -### 在线部署 +#### 在线部署 ```bash # 拉取 @@ -134,133 +80,57 @@ docker pull imsyy/dailyhot-api:latest docker run -p 6688:6688 -d imsyy/dailyhot-api:latest ``` -## Vercel 部署 +### 手动部署 -现已支持 Vercel 部署,无需服务器 +最直接的方式,您可以按照以下步骤将 DailyHotApi 部署在您的电脑、服务器或者其他任何地方 -### 操作方法 +#### 安装 -1. fork 本项目 -2. 在 `Vercel` 官网点击 `New Project` -3. 点击 `Import Git Repository` 并选择你 fork 的此项目并点击 `import` -4. `PROJECT NAME`自己填,`FRAMEWORK PRESET` 选 `Other` 然后直接点 `Deploy` 接着等部署完成即可 +```bash +git clone https://github.com/imsyy/DailyHotApi.git +cd DailyHotApi +``` -## 调用 +然后再执行安装依赖 -### 获取榜单数据 +```bash +npm install +``` -> 获取数据只需在域名后面加上上方列表中的调用名称即可 +#### 开发 -```http -GET https://api-hot.imsyy.top/bilibili/ +```bash +npm run dev ``` -
-调用示例 - -```json -{ - "code": 200, - "message": "获取成功", - "title": "哔哩哔哩", // 榜单名称 - "subtitle": "热门榜", // 榜单类别 - "from": "server", // 此处返回是最新数据还是缓存 - "total": 100, // 数据总数 - "updateTime": "2023-03-14T07:40:51.846Z", // 数据获取时间 - "data": [ - { - "id": "BV1E84y1A7z2", - "title": "假如我的校园是一款RPG游戏!", - "desc": "所有取景都是在学校里面拍的,都是真实存在的场景哦!", - "pic": "http://i2.hdslb.com/bfs/archive/a24e442d0aae6d488db023c4ddcb450e9f2bf5f3.jpg", - "owner": { - "mid": 424658638, - "name": "四夕小田木_已黑化_", - "face": "https://i1.hdslb.com/bfs/face/afd9ba47933edc4842ccbeba2891a25465d1cf77.jpg" - }, - "data": { - "aid": 610872610, - "view": 4178745, - "danmaku": 4229, - "reply": 5317, - "favorite": 91020, - "coin": 133596, - "share": 46227, - "now_rank": 0, - "his_rank": 1, - "like": 616519, - "dislike": 0, - "vt": 0, - "vv": 0 - }, - "url": "https://b23.tv/BV1E84y1A7z2", - "mobileUrl": "https://m.bilibili.com/video/BV1E84y1A7z2" - }, - ... - ] -} +成功启动后程序会在控制台输出可访问的地址 + +#### 编译运行 + +```bash +npm run build +npm run start ``` -
+成功启动后程序会在控制台输出可访问的地址 -### 获取榜单最新数据 +### Railway 部署 -> 获取最新数据只需在原链接后面加上 `/new`,这样就会直接从服务端拉取最新数据,不会从本地缓存中读取 +本项目支持使用 [Railway](https://railway.app/) 一键部署,请先将本项目 fork 到您的仓库中,即可使用一键部署。 -```http -GET https://api-hot.imsyy.top/bilibili/new -``` +### Zeabur 部署 -
-调用示例 - -```json -{ - "code": 200, - "message": "获取成功", - "title": "哔哩哔哩", // 榜单名称 - "subtitle": "热门榜", // 榜单类别 - "total": 100, // 数据总数 - "updateTime": "2023-03-14T07:40:51.846Z", // 数据获取时间 - "data": [ - { - "id": "BV1E84y1A7z2", - "title": "假如我的校园是一款RPG游戏!", - "desc": "所有取景都是在学校里面拍的,都是真实存在的场景哦!", - "pic": "http://i2.hdslb.com/bfs/archive/a24e442d0aae6d488db023c4ddcb450e9f2bf5f3.jpg", - "owner": { - "mid": 424658638, - "name": "四夕小田木_已黑化_", - "face": "https://i1.hdslb.com/bfs/face/afd9ba47933edc4842ccbeba2891a25465d1cf77.jpg" - }, - "data": { - "aid": 610872610, - "view": 4178745, - "danmaku": 4229, - "reply": 5317, - "favorite": 91020, - "coin": 133596, - "share": 46227, - "now_rank": 0, - "his_rank": 1, - "like": 616519, - "dislike": 0, - "vt": 0, - "vv": 0 - }, - "url": "https://b23.tv/BV1E84y1A7z2", - "mobileUrl": "https://m.bilibili.com/video/BV1E84y1A7z2" - }, - ... - ] -} -``` +本项目支持使用 [Zeabur](https://zeabur.com/) 一键部署,请先将本项目 fork 到您的仓库中,即可使用一键部署。 + +### Vercel 部署 + +> 🚧 Vercel 部署支持正在修复中 -
+若您目前仅能通过 `Vercel` 进行部署,那么请暂时不要使用最新版本 ## 其他 -- 本项目为了避免频繁请求官方数据,默认对数据做了缓存处理,默认为 `30` 分钟,如需更改,请自行前往 `utils\cacheData.js` 文件修改 +- 本项目为了避免频繁请求官方数据,默认对数据做了缓存处理,默认为 `60` 分钟,如需更改,请自行修改配置 - 本项目部分接口使用了 **页面爬虫**,若违反对应页面的相关规则,请 **及时通知我去除该接口** ## 免责声明 diff --git a/docker-compose.yml b/docker-compose.yml index a616ddb3..15bfe6c2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,12 +1,15 @@ +version: "3.8" + services: DailyhotApi: build: context: . - image: dailyhot-api - container_name: dailyhot-api - volumes: - - /etc/localtime:/etc/localtime:ro - - /etc/timezone:/etc/timezone:ro + target: runner ports: - - 6688:6688 + - "6688:6688" + volumes: + - "./logs:/app/logs" + environment: + - PORT=6688 + user: "114514" restart: always diff --git a/index.js b/index.js deleted file mode 100644 index ace1a095..00000000 --- a/index.js +++ /dev/null @@ -1,99 +0,0 @@ -require("dotenv").config(); -const Koa = require("koa"); -const bodyParser = require("koa-bodyparser"); -const cors = require("koa2-cors"); -const serve = require("koa-static"); -const views = require("koa-views"); - -const app = new Koa(); -const net = require("net"); -const router = require("./routes"); - -// 配置信息 -let domain = process.env.ALLOWED_DOMAIN || "*"; -let port = process.env.PORT || 6688; - -// 解析请求体 -app.use(bodyParser()); - -// 静态文件目录 -app.use(serve(__dirname + "/public")); -app.use(views(__dirname + "/public")); - -// 跨域 -app.use( - cors({ - origin: domain, - }), -); - -// CORS -app.use(async (ctx, next) => { - ctx.set("Access-Control-Allow-Origin", domain); - ctx.set("Access-Control-Allow-Methods", "GET, OPTIONS"); - ctx.set("Access-Control-Allow-Headers", "Content-Type, Authorization"); - ctx.set("Access-Control-Allow-Credentials", "true"); - // 处理预检请求 - if (ctx.method === "OPTIONS") { - ctx.status = 200; - } else { - if (domain === "*") { - await next(); - } else { - if (ctx.headers.origin === domain || ctx.headers.referer === domain) { - await next(); - } else { - ctx.status = 403; - ctx.body = { - code: 403, - message: "请通过正确的域名访问", - }; - } - } - } -}); - -// 使用路由中间件 -app.use(router.routes()); -app.use(router.allowedMethods()); - -// 启动应用程序并监听端口 -const startApp = (port) => { - app.listen(port, () => { - console.info(`成功在 ${port} 端口上运行`); - }); -}; - -// 检测端口是否被占用 -const checkPort = (port) => { - return new Promise((resolve, reject) => { - const server = net - .createServer() - .once("error", (err) => { - if (err.code === "EADDRINUSE") { - console.info(`端口 ${port} 已被占用, 正在尝试其他端口...`); - server.close(); - resolve(false); - } else { - reject(err); - } - }) - .once("listening", () => { - server.close(); - resolve(true); - }) - .listen(port); - }); -}; - -// 尝试启动应用程序 -const tryStartApp = async (port) => { - let isPortAvailable = await checkPort(port); - while (!isPortAvailable) { - port++; - isPortAvailable = await checkPort(port); - } - startApp(port); -}; - -tryStartApp(port); diff --git a/package.json b/package.json index 6b631a4b..e783ef2a 100644 --- a/package.json +++ b/package.json @@ -1,32 +1,51 @@ { "name": "dailyhot_api", - "version": "1.0.8", - "description": "An api on Today's Hot list", - "main": "index.js", + "version": "2.0.0", + "description": "An Api on Today's Hot list", + "keywords": [ + "API", + "RSS" + ], + "homepage": "https://github.com/imsyy/DailyHotApi#readme", + "bugs": { + "url": "https://github.com/imsyy/DailyHotApi/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/DIYgod/RSSHub.git" + }, + "license": "MIT", + "author": "imsyy", + "main": "src/index.ts", "scripts": { "format": "prettier --write .", - "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix", - "start": "node index.js", - "dev": "npx nodemon index.js", - "prd": "pm2 start index.js", - "build": "node index.js" + "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix", + "dev": "tsx watch --no-cache src/index.ts", + "dev:cache": "tsx watch src/index.ts", + "build": "tsc --project tsconfig.json", + "start": "tsx src/index.ts" }, - "author": "imsyy", - "license": "MIT", + "type": "module", "dependencies": { - "axios": "^1.6.3", + "@hono/node-server": "^1.9.1", + "axios": "^1.6.8", "cheerio": "1.0.0-rc.12", - "dotenv": "^16.3.1", - "eslint": "^8.56.0", - "eslint-plugin-vue": "^9.19.2", - "koa": "^2.15.0", - "koa-bodyparser": "^4.4.1", - "koa-router": "^12.0.1", - "koa-static": "^5.0.0", - "koa-views": "^8.1.0", - "koa2-cors": "^2.0.6", + "dotenv": "^16.4.5", + "feed": "^4.2.2", + "hono": "^4.2.2", "node-cache": "^5.1.2", - "nodemon": "^2.0.22", - "prettier": "^3.1.1" + "winston": "^3.13.0" + }, + "devDependencies": { + "@types/node": "^20.12.5", + "@typescript-eslint/eslint-plugin": "^7.5.0", + "@typescript-eslint/parser": "^7.5.0", + "eslint": "^8.57.0", + "prettier": "^3.2.5", + "tsx": "^3.14.0", + "typescript": "^5.4.4" + }, + "engines": { + "node": ">=20" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b592e9e0..c25c2a89 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5,70 +5,286 @@ settings: excludeLinksFromLockfile: false dependencies: + '@hono/node-server': + specifier: ^1.9.1 + version: 1.9.1 axios: - specifier: ^1.6.3 - version: 1.6.3 + specifier: ^1.6.8 + version: 1.6.8 cheerio: specifier: 1.0.0-rc.12 version: 1.0.0-rc.12 dotenv: - specifier: ^16.3.1 - version: 16.3.1 - eslint: - specifier: ^8.56.0 - version: 8.56.0 - eslint-plugin-vue: - specifier: ^9.19.2 - version: 9.19.2(eslint@8.56.0) - koa: - specifier: ^2.15.0 - version: 2.15.0 - koa-bodyparser: - specifier: ^4.4.1 - version: 4.4.1 - koa-router: - specifier: ^12.0.1 - version: 12.0.1 - koa-static: - specifier: ^5.0.0 - version: 5.0.0 - koa-views: - specifier: ^8.1.0 - version: 8.1.0 - koa2-cors: - specifier: ^2.0.6 - version: 2.0.6 + specifier: ^16.4.5 + version: 16.4.5 + feed: + specifier: ^4.2.2 + version: 4.2.2 + hono: + specifier: ^4.2.2 + version: 4.2.2 node-cache: specifier: ^5.1.2 version: 5.1.2 - nodemon: - specifier: ^2.0.22 - version: 2.0.22 + winston: + specifier: ^3.13.0 + version: 3.13.0 + +devDependencies: + '@types/node': + specifier: ^20.12.5 + version: 20.12.5 + '@typescript-eslint/eslint-plugin': + specifier: ^7.5.0 + version: 7.5.0(@typescript-eslint/parser@7.5.0)(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/parser': + specifier: ^7.5.0 + version: 7.5.0(eslint@8.57.0)(typescript@5.4.4) + eslint: + specifier: ^8.57.0 + version: 8.57.0 prettier: - specifier: ^3.1.1 - version: 3.1.1 + specifier: ^3.2.5 + version: 3.2.5 + tsx: + specifier: ^3.14.0 + version: 3.14.0 + typescript: + specifier: ^5.4.4 + version: 5.4.4 packages: /@aashutoshrathi/word-wrap@1.2.6: resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} engines: {node: '>=0.10.0'} + dev: true + + /@colors/colors@1.6.0: + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + dev: false + + /@dabh/diagnostics@2.0.3: + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 dev: false - /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0): resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 dependencies: - eslint: 8.56.0 + eslint: 8.57.0 eslint-visitor-keys: 3.4.3 - dev: false + dev: true /@eslint-community/regexpp@4.10.0: resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: false + dev: true /@eslint/eslintrc@2.1.4: resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} @@ -78,202 +294,44 @@ packages: debug: 4.3.4 espree: 9.6.1 globals: 13.24.0 - ignore: 5.3.0 + ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color - dev: false + dev: true - /@eslint/js@8.56.0: - resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} + /@eslint/js@8.57.0: + resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@hono/node-server@1.9.1: + resolution: {integrity: sha512-XBru0xbtRlTZJyAiFJLn7XDKbCVXBaRhVQAQhB9TwND2gwj8jf9SDWIj/7VxVtNAjURJf7Ofcz58DRA6DPYiWA==} + engines: {node: '>=18.14.1'} dev: false - /@humanwhocodes/config-array@0.11.13: - resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} engines: {node: '>=10.10.0'} dependencies: - '@humanwhocodes/object-schema': 2.0.1 + '@humanwhocodes/object-schema': 2.0.3 debug: 4.3.4 minimatch: 3.1.2 transitivePeerDependencies: - supports-color - dev: false + dev: true /@humanwhocodes/module-importer@1.0.1: resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} - dev: false + dev: true - /@humanwhocodes/object-schema@2.0.1: - resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} - dev: false - - /@isaacs/cliui@8.0.2: - resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} - engines: {node: '>=12'} - dependencies: - string-width: 5.1.2 - string-width-cjs: /string-width@4.2.3 - strip-ansi: 7.1.0 - strip-ansi-cjs: /strip-ansi@6.0.1 - wrap-ansi: 8.1.0 - wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: false - - /@ladjs/consolidate@1.0.3: - resolution: {integrity: sha512-zyUeV5nkEFz7FH88pz+moVeMMOygTx1zL5bjXGHCVX5MMpmAtFf5piaQlBDk3nClGoUs8vjYI9TKsbXldGv0VA==} - engines: {node: '>=14'} - peerDependencies: - '@babel/core': ^7.22.5 - arc-templates: ^0.5.3 - atpl: '>=0.7.6' - bracket-template: ^1.1.5 - coffee-script: ^1.12.7 - dot: ^1.1.3 - dust: ^0.3.0 - dustjs-helpers: ^1.7.4 - dustjs-linkedin: ^2.7.5 - eco: ^1.1.0-rc-3 - ect: ^0.5.9 - ejs: ^3.1.5 - haml-coffee: ^1.14.1 - hamlet: ^0.3.3 - hamljs: ^0.6.2 - handlebars: ^4.7.6 - hogan.js: ^3.0.2 - htmling: ^0.0.8 - jazz: ^0.0.18 - jqtpl: ~1.1.0 - just: ^0.1.8 - liquid-node: ^3.0.1 - liquor: ^0.0.5 - lodash: ^4.17.20 - mote: ^0.2.0 - mustache: ^4.0.1 - nunjucks: ^3.2.2 - plates: ~0.4.11 - pug: ^3.0.0 - qejs: ^3.0.5 - ractive: ^1.3.12 - react: '>=16.13.1' - react-dom: '>=16.13.1' - slm: ^2.0.0 - swig: ^1.4.2 - swig-templates: ^2.0.3 - teacup: ^2.0.0 - templayed: '>=0.2.3' - then-pug: '*' - tinyliquid: ^0.2.34 - toffee: ^0.3.6 - twig: ^1.15.2 - twing: ^5.0.2 - underscore: ^1.11.0 - vash: ^0.13.0 - velocityjs: ^2.0.1 - walrus: ^0.10.1 - whiskers: ^0.4.0 - peerDependenciesMeta: - '@babel/core': - optional: true - arc-templates: - optional: true - atpl: - optional: true - bracket-template: - optional: true - coffee-script: - optional: true - dot: - optional: true - dust: - optional: true - dustjs-helpers: - optional: true - dustjs-linkedin: - optional: true - eco: - optional: true - ect: - optional: true - ejs: - optional: true - haml-coffee: - optional: true - hamlet: - optional: true - hamljs: - optional: true - handlebars: - optional: true - hogan.js: - optional: true - htmling: - optional: true - jazz: - optional: true - jqtpl: - optional: true - just: - optional: true - liquid-node: - optional: true - liquor: - optional: true - lodash: - optional: true - mote: - optional: true - mustache: - optional: true - nunjucks: - optional: true - plates: - optional: true - pug: - optional: true - qejs: - optional: true - ractive: - optional: true - react: - optional: true - react-dom: - optional: true - slm: - optional: true - swig: - optional: true - swig-templates: - optional: true - teacup: - optional: true - templayed: - optional: true - then-pug: - optional: true - tinyliquid: - optional: true - toffee: - optional: true - twig: - optional: true - twing: - optional: true - underscore: - optional: true - vash: - optional: true - velocityjs: - optional: true - walrus: - optional: true - whiskers: - optional: true - dev: false + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + dev: true /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -281,52 +339,174 @@ packages: dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 - dev: false + dev: true /@nodelib/fs.stat@2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} - dev: false + dev: true /@nodelib/fs.walk@1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.16.0 - dev: false + fastq: 1.17.1 + dev: true - /@one-ini/wasm@0.1.1: - resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} - dev: false + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true - /@pkgjs/parseargs@0.11.0: - resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} - engines: {node: '>=14'} - requiresBuild: true - dev: false - optional: true + /@types/node@20.12.5: + resolution: {integrity: sha512-BD+BjQ9LS/D8ST9p5uqBxghlN+S42iuNxjsUGjeZobe/ciXzk2qb1B6IXc6AnRLS+yFJRpN2IPEHMzwspfDJNw==} + dependencies: + undici-types: 5.26.5 + dev: true - /@ungap/structured-clone@1.2.0: - resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: false + /@types/semver@7.5.8: + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + dev: true - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + /@types/triple-beam@1.3.5: + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} dev: false - /abbrev@2.0.0: - resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - dev: false + /@typescript-eslint/eslint-plugin@7.5.0(@typescript-eslint/parser@7.5.0)(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 7.5.0(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/scope-manager': 7.5.0 + '@typescript-eslint/type-utils': 7.5.0(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/utils': 7.5.0(eslint@8.57.0)(typescript@5.4.4) + '@typescript-eslint/visitor-keys': 7.5.0 + debug: 4.3.4 + eslint: 8.57.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.4) + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true - /accepts@1.3.8: - resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} - engines: {node: '>= 0.6'} + /@typescript-eslint/parser@7.5.0(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true dependencies: - mime-types: 2.1.35 - negotiator: 0.6.3 - dev: false + '@typescript-eslint/scope-manager': 7.5.0 + '@typescript-eslint/types': 7.5.0 + '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.4.4) + '@typescript-eslint/visitor-keys': 7.5.0 + debug: 4.3.4 + eslint: 8.57.0 + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@7.5.0: + resolution: {integrity: sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.5.0 + '@typescript-eslint/visitor-keys': 7.5.0 + dev: true + + /@typescript-eslint/type-utils@7.5.0(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.4.4) + '@typescript-eslint/utils': 7.5.0(eslint@8.57.0)(typescript@5.4.4) + debug: 4.3.4 + eslint: 8.57.0 + ts-api-utils: 1.3.0(typescript@5.4.4) + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@7.5.0: + resolution: {integrity: sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg==} + engines: {node: ^18.18.0 || >=20.0.0} + dev: true + + /@typescript-eslint/typescript-estree@7.5.0(typescript@5.4.4): + resolution: {integrity: sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 7.5.0 + '@typescript-eslint/visitor-keys': 7.5.0 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.6.0 + ts-api-utils: 1.3.0(typescript@5.4.4) + typescript: 5.4.4 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@7.5.0(eslint@8.57.0)(typescript@5.4.4): + resolution: {integrity: sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 7.5.0 + '@typescript-eslint/types': 7.5.0 + '@typescript-eslint/typescript-estree': 7.5.0(typescript@5.4.4) + eslint: 8.57.0 + semver: 7.6.0 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@7.5.0: + resolution: {integrity: sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA==} + engines: {node: ^18.18.0 || >=20.0.0} + dependencies: + '@typescript-eslint/types': 7.5.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true /acorn-jsx@5.3.2(acorn@8.11.3): resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -334,13 +514,13 @@ packages: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: acorn: 8.11.3 - dev: false + dev: true /acorn@8.11.3: resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} engines: {node: '>=0.4.0'} hasBin: true - dev: false + dev: true /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -349,54 +529,41 @@ packages: fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 - dev: false + dev: true /ansi-regex@5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} - dev: false - - /ansi-regex@6.0.1: - resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} - engines: {node: '>=12'} - dev: false + dev: true /ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} dependencies: color-convert: 2.0.1 - dev: false - - /ansi-styles@6.2.1: - resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} - engines: {node: '>=12'} - dev: false - - /any-promise@1.3.0: - resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} - dev: false - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: false + dev: true /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} dev: false /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: false - /axios@1.6.3: - resolution: {integrity: sha512-fWyNdeawGam70jXSVlKl+SUNVcL6j6W79CuSIPfi6HnDUmSCH6gyUys/HrqHeA/wU0Az41rRgean494d0Jb+ww==} + /axios@1.6.8: + resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==} dependencies: - follow-redirects: 1.15.4 + follow-redirects: 1.15.6 form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -405,12 +572,7 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - dev: false - - /binary-extensions@2.2.0: - resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} - engines: {node: '>=8'} - dev: false + dev: true /boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -421,46 +583,29 @@ packages: dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 - dev: false + dev: true /brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} dependencies: balanced-match: 1.0.2 - dev: false + dev: true /braces@3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} dependencies: fill-range: 7.0.1 - dev: false - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: false + dev: true - /cache-content-type@1.0.1: - resolution: {integrity: sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==} - engines: {node: '>= 6.0.0'} - dependencies: - mime-types: 2.1.35 - ylru: 1.3.2 - dev: false - - /call-bind@1.0.5: - resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} - dependencies: - function-bind: 1.1.2 - get-intrinsic: 1.2.2 - set-function-length: 1.1.1 - dev: false + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: false + dev: true /chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} @@ -468,7 +613,7 @@ packages: dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 - dev: false + dev: true /cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -494,38 +639,15 @@ packages: parse5-htmlparser2-tree-adapter: 7.0.0 dev: false - /chokidar@3.5.3: - resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.2 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: false - /clone@2.1.2: resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} engines: {node: '>=0.8'} dev: false - /co-body@6.1.0: - resolution: {integrity: sha512-m7pOT6CdLN7FuXUcpuz/8lfQ/L77x8SchHCF4G0RBTJO20Wzmhn5Sp4/5WsKy8OSpifBSUrmg83qEqaDHdyFuQ==} + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: - inflation: 2.1.0 - qs: 6.11.2 - raw-body: 2.5.2 - type-is: 1.6.18 - dev: false - - /co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + color-name: 1.1.3 dev: false /color-convert@2.0.1: @@ -533,67 +655,46 @@ packages: engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} dev: false /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: false - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} + /color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} dependencies: - delayed-stream: 1.0.0 - dev: false - - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: false - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - dev: false - - /condense-newlines@0.2.1: - resolution: {integrity: sha512-P7X+QL9Hb9B/c8HI5BFFKmjgBu2XpQuF98WZ9XkO+dBGgk5XgwiQz7o1SmpglNWId3581UcS0SFAWfoIhMHPfg==} - engines: {node: '>=0.10.0'} - dependencies: - extend-shallow: 2.0.1 - is-whitespace: 0.3.0 - kind-of: 3.2.2 + color-name: 1.1.4 + simple-swizzle: 0.2.2 dev: false - /config-chain@1.1.13: - resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + /color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} dependencies: - ini: 1.3.8 - proto-list: 1.2.4 + color-convert: 1.9.3 + color-string: 1.9.1 dev: false - /content-disposition@0.5.4: - resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} - engines: {node: '>= 0.6'} + /colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} dependencies: - safe-buffer: 5.2.1 - dev: false - - /content-type@1.0.5: - resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} - engines: {node: '>= 0.6'} + color: 3.2.1 + text-hex: 1.0.0 dev: false - /cookies@0.9.1: - resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} dependencies: - depd: 2.0.0 - keygrip: 1.1.0 + delayed-stream: 1.0.0 dev: false - /copy-to@2.0.1: - resolution: {integrity: sha512-3DdaFaU/Zf1AnpLiFDeNCD4TOWe3Zl2RZaTzUvWiIk5ERzcCodOE20Vqq4fzCbNoHURFHT4/us/Lfq+S2zyY4w==} - dev: false + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} @@ -602,7 +703,7 @@ packages: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 - dev: false + dev: true /css-select@5.1.0: resolution: {integrity: sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==} @@ -619,24 +720,6 @@ packages: engines: {node: '>= 6'} dev: false - /cssesc@3.0.0: - resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} - engines: {node: '>=4'} - hasBin: true - dev: false - - /debug@3.2.7(supports-color@5.5.0): - resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - supports-color: 5.5.0 - dev: false - /debug@4.3.4: resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} engines: {node: '>=6.0'} @@ -647,55 +730,30 @@ packages: optional: true dependencies: ms: 2.1.2 - dev: false - - /deep-equal@1.0.1: - resolution: {integrity: sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==} - dev: false + dev: true /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: false - - /define-data-property@1.1.1: - resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.2 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 - dev: false + dev: true /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} dev: false - /delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: false - - /depd@1.1.2: - resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} - engines: {node: '>= 0.6'} - dev: false - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: false - - /destroy@1.2.0: - resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - dev: false + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true /doctrine@3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} dependencies: esutils: 2.0.3 - dev: false + dev: true /dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -724,41 +782,13 @@ packages: domhandler: 5.0.3 dev: false - /dotenv@16.3.1: - resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} dev: false - /eastasianwidth@0.2.0: - resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: false - - /editorconfig@1.0.4: - resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} - engines: {node: '>=14'} - hasBin: true - dependencies: - '@one-ini/wasm': 0.1.1 - commander: 10.0.1 - minimatch: 9.0.1 - semver: 7.5.4 - dev: false - - /ee-first@1.1.1: - resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - dev: false - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - dev: false - - /emoji-regex@9.2.2: - resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: false - - /encodeurl@1.0.2: - resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} - engines: {node: '>= 0.8'} + /enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} dev: false /entities@4.5.0: @@ -766,32 +796,40 @@ packages: engines: {node: '>=0.12'} dev: false - /escape-html@1.0.3: - resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} - dev: false + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: true /escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - dev: false - - /eslint-plugin-vue@9.19.2(eslint@8.56.0): - resolution: {integrity: sha512-CPDqTOG2K4Ni2o4J5wixkLVNwgctKXFu6oBpVJlpNq7f38lh9I80pRTouZSJ2MAebPJlINU/KTFSXyQfBUlymA==} - engines: {node: ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) - eslint: 8.56.0 - natural-compare: 1.4.0 - nth-check: 2.1.1 - postcss-selector-parser: 6.0.15 - semver: 7.5.4 - vue-eslint-parser: 9.3.2(eslint@8.56.0) - xml-name-validator: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: false + dev: true /eslint-scope@7.2.2: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} @@ -799,23 +837,23 @@ packages: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 - dev: false + dev: true /eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: false + dev: true - /eslint@8.56.0: - resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} + /eslint@8.57.0: + resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@eslint-community/regexpp': 4.10.0 '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.56.0 - '@humanwhocodes/config-array': 0.11.13 + '@eslint/js': 8.57.0 + '@humanwhocodes/config-array': 0.11.14 '@humanwhocodes/module-importer': 1.0.1 '@nodelib/fs.walk': 1.2.8 '@ungap/structured-clone': 1.2.0 @@ -836,7 +874,7 @@ packages: glob-parent: 6.0.2 globals: 13.24.0 graphemer: 1.4.0 - ignore: 5.3.0 + ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -851,7 +889,7 @@ packages: text-table: 0.2.0 transitivePeerDependencies: - supports-color - dev: false + dev: true /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} @@ -860,55 +898,70 @@ packages: acorn: 8.11.3 acorn-jsx: 5.3.2(acorn@8.11.3) eslint-visitor-keys: 3.4.3 - dev: false + dev: true /esquery@1.5.0: resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} engines: {node: '>=0.10'} dependencies: estraverse: 5.3.0 - dev: false + dev: true /esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} dependencies: estraverse: 5.3.0 - dev: false + dev: true /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} - dev: false + dev: true /esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - dev: false - - /extend-shallow@2.0.1: - resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} - engines: {node: '>=0.10.0'} - dependencies: - is-extendable: 0.1.1 - dev: false + dev: true /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: false + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true /fast-json-stable-stringify@2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: false + dev: true /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: false + dev: true - /fastq@1.16.0: - resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==} + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} dependencies: reusify: 1.0.4 + dev: true + + /fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + dev: false + + /feed@4.2.2: + resolution: {integrity: sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==} + engines: {node: '>=0.4.0'} + dependencies: + xml-js: 1.6.11 dev: false /file-entry-cache@6.0.1: @@ -916,14 +969,14 @@ packages: engines: {node: ^10.12.0 || >=12.0.0} dependencies: flat-cache: 3.2.0 - dev: false + dev: true /fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 - dev: false + dev: true /find-up@5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} @@ -931,23 +984,27 @@ packages: dependencies: locate-path: 6.0.0 path-exists: 4.0.0 - dev: false + dev: true /flat-cache@3.2.0: resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: - flatted: 3.2.9 + flatted: 3.3.1 keyv: 4.5.4 rimraf: 3.0.2 - dev: false + dev: true - /flatted@3.2.9: - resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + /flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + dev: true + + /fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} dev: false - /follow-redirects@1.15.4: - resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==} + /follow-redirects@1.15.6: + resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -956,14 +1013,6 @@ packages: optional: true dev: false - /foreground-child@3.1.1: - resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} - engines: {node: '>=14'} - dependencies: - cross-spawn: 7.0.3 - signal-exit: 4.1.0 - dev: false - /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -973,68 +1022,37 @@ packages: mime-types: 2.1.35 dev: false - /fresh@0.5.2: - resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} - engines: {node: '>= 0.6'} - dev: false - /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - dev: false + dev: true /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true - dev: false + dev: true optional: true - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: false - - /get-intrinsic@1.2.2: - resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} - dependencies: - function-bind: 1.1.2 - has-proto: 1.0.1 - has-symbols: 1.0.3 - hasown: 2.0.0 - dev: false - - /get-paths@0.0.7: - resolution: {integrity: sha512-0wdJt7C1XKQxuCgouqd+ZvLJ56FQixKoki9MrFaO4EriqzXOiH9gbukaDE1ou08S8Ns3/yDzoBAISNPqj6e6tA==} - engines: {node: '>=6.4'} + /get-tsconfig@4.7.3: + resolution: {integrity: sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==} dependencies: - pify: 4.0.1 - dev: false + resolve-pkg-maps: 1.0.0 + dev: true /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 - dev: false + dev: true /glob-parent@6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 - dev: false - - /glob@10.3.10: - resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} - engines: {node: '>=16 || 14 >=14.17'} - hasBin: true - dependencies: - foreground-child: 3.1.1 - jackspeak: 2.3.6 - minimatch: 9.0.3 - minipass: 7.0.4 - path-scurry: 1.10.1 - dev: false + dev: true /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} @@ -1045,63 +1063,39 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: false + dev: true /globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 - dev: false + dev: true - /gopd@1.0.1: - resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} dependencies: - get-intrinsic: 1.2.2 - dev: false + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.1 + merge2: 1.4.1 + slash: 3.0.0 + dev: true /graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: false - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: false + dev: true /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: false - - /has-property-descriptors@1.0.1: - resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} - dependencies: - get-intrinsic: 1.2.2 - dev: false - - /has-proto@1.0.1: - resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} - engines: {node: '>= 0.4'} - dev: false - - /has-symbols@1.0.3: - resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} - engines: {node: '>= 0.4'} - dev: false - - /has-tostringtag@1.0.0: - resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.0.3 - dev: false + dev: true - /hasown@2.0.0: - resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 + /hono@4.2.2: + resolution: {integrity: sha512-mDmjBHF6uBNN3TASdAbDCFsN9FLbrlgXyFZkhLEkU7hUgk0+T9hcsUrL/nho4qV+Xk0RDHx7gop4Q1gelZZVRw==} + engines: {node: '>=16.0.0'} dev: false /htmlparser2@8.0.2: @@ -1113,61 +1107,10 @@ packages: entities: 4.5.0 dev: false - /http-assert@1.5.0: - resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==} - engines: {node: '>= 0.8'} - dependencies: - deep-equal: 1.0.1 - http-errors: 1.8.1 - dev: false - - /http-errors@1.6.3: - resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} - engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.3 - setprototypeof: 1.1.0 - statuses: 1.5.0 - dev: false - - /http-errors@1.8.1: - resolution: {integrity: sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==} - engines: {node: '>= 0.6'} - dependencies: - depd: 1.1.2 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 1.5.0 - toidentifier: 1.0.1 - dev: false - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: false - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: false - - /ignore-by-default@1.0.1: - resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} - dev: false - - /ignore@5.3.0: - resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + /ignore@5.3.1: + resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - dev: false + dev: true /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} @@ -1175,312 +1118,85 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: false + dev: true /imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - dev: false - - /inflation@2.1.0: - resolution: {integrity: sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==} - engines: {node: '>= 0.8.0'} - dev: false + dev: true /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} dependencies: once: 1.4.0 wrappy: 1.0.2 - dev: false - - /inherits@2.0.3: - resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} - dev: false + dev: true /inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - dev: false - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - dev: false - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.2.0 - dev: false - - /is-buffer@1.1.6: - resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} - dev: false - /is-extendable@0.1.1: - resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} - engines: {node: '>=0.10.0'} + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} dev: false /is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - dev: false - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - dev: false - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.0 - dev: false + dev: true /is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 - dev: false + dev: true /is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - dev: false + dev: true /is-path-inside@3.0.3: - resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} - engines: {node: '>=8'} - dev: false - - /is-whitespace@0.3.0: - resolution: {integrity: sha512-RydPhl4S6JwAyj0JJjshWJEFG6hNye3pZFBRZaTUfZFwGHxzppNaNOVgQuS/E/SlhrApuMXrpnK1EEIXfdo3Dg==} - engines: {node: '>=0.10.0'} - dev: false - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - dev: false - - /jackspeak@2.3.6: - resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} - engines: {node: '>=14'} - dependencies: - '@isaacs/cliui': 8.0.2 - optionalDependencies: - '@pkgjs/parseargs': 0.11.0 - dev: false - - /js-beautify@1.14.11: - resolution: {integrity: sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw==} - engines: {node: '>=14'} - hasBin: true - dependencies: - config-chain: 1.1.13 - editorconfig: 1.0.4 - glob: 10.3.10 - nopt: 7.2.0 - dev: false - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: false - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: false - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: false - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: false - - /keygrip@1.1.0: - resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} - engines: {node: '>= 0.6'} - dependencies: - tsscmp: 1.0.6 - dev: false - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: false - - /kind-of@3.2.2: - resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} - engines: {node: '>=0.10.0'} - dependencies: - is-buffer: 1.1.6 - dev: false - - /koa-bodyparser@4.4.1: - resolution: {integrity: sha512-kBH3IYPMb+iAXnrxIhXnW+gXV8OTzCu8VPDqvcDHW9SQrbkHmqPQtiZwrltNmSq6/lpipHnT7k7PsjlVD7kK0w==} - engines: {node: '>=8.0.0'} - dependencies: - co-body: 6.1.0 - copy-to: 2.0.1 - type-is: 1.6.18 - dev: false - - /koa-compose@4.1.0: - resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} - dev: false - - /koa-convert@2.0.0: - resolution: {integrity: sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==} - engines: {node: '>= 10'} - dependencies: - co: 4.6.0 - koa-compose: 4.1.0 - dev: false - - /koa-router@12.0.1: - resolution: {integrity: sha512-gaDdj3GtzoLoeosacd50kBBTnnh3B9AYxDThQUo4sfUyXdOhY6ku1qyZKW88tQCRgc3Sw6ChXYXWZwwgjOxE0w==} - engines: {node: '>= 12'} - dependencies: - debug: 4.3.4 - http-errors: 2.0.0 - koa-compose: 4.1.0 - methods: 1.1.2 - path-to-regexp: 6.2.1 - transitivePeerDependencies: - - supports-color - dev: false + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true - /koa-send@5.0.1: - resolution: {integrity: sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==} - engines: {node: '>= 8'} - dependencies: - debug: 4.3.4 - http-errors: 1.8.1 - resolve-path: 1.4.0 - transitivePeerDependencies: - - supports-color + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} dev: false - /koa-static@5.0.0: - resolution: {integrity: sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==} - engines: {node: '>= 7.6.0'} - dependencies: - debug: 3.2.7(supports-color@5.5.0) - koa-send: 5.0.1 - transitivePeerDependencies: - - supports-color - dev: false + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true - /koa-views@8.1.0: - resolution: {integrity: sha512-sIkZeplf7YKg1+OjYuzxU5zQvzbfdwFKzD8XNLKFHRMFZXWBTW+S/WQwQ32fzZiJp1lPxz0QlzNJkkGu0NVIdg==} - deprecated: This package is deprecated, please use the new fork @ladjs/koa-views. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/koa-views for updates and release changelog - peerDependencies: - '@types/koa': ^2.13.1 - peerDependenciesMeta: - '@types/koa': - optional: true + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true dependencies: - '@ladjs/consolidate': 1.0.3 - debug: 4.3.4 - get-paths: 0.0.7 - koa-send: 5.0.1 - mz: 2.7.0 - pretty: 2.0.0 - resolve-path: 1.4.0 - transitivePeerDependencies: - - '@babel/core' - - arc-templates - - atpl - - bracket-template - - coffee-script - - dot - - dust - - dustjs-helpers - - dustjs-linkedin - - eco - - ect - - ejs - - haml-coffee - - hamlet - - hamljs - - handlebars - - hogan.js - - htmling - - jazz - - jqtpl - - just - - liquid-node - - liquor - - lodash - - mote - - mustache - - nunjucks - - plates - - pug - - qejs - - ractive - - react - - react-dom - - slm - - supports-color - - swig - - swig-templates - - teacup - - templayed - - then-pug - - tinyliquid - - toffee - - twig - - twing - - underscore - - vash - - velocityjs - - walrus - - whiskers - dev: false + argparse: 2.0.1 + dev: true - /koa2-cors@2.0.6: - resolution: {integrity: sha512-JRCcSM4lamM+8kvKGDKlesYk2ASrmSTczDtGUnIadqMgnHU4Ct5Gw7Bxt3w3m6d6dy3WN0PU4oMP43HbddDEWg==} - engines: {node: '>= 7.6.0'} - dev: false + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true - /koa@2.15.0: - resolution: {integrity: sha512-KEL/vU1knsoUvfP4MC4/GthpQrY/p6dzwaaGI6Rt4NQuFqkw3qrvsdYF5pz3wOfi7IGTvMPHC9aZIcUKYFNxsw==} - engines: {node: ^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4} + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} dependencies: - accepts: 1.3.8 - cache-content-type: 1.0.1 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookies: 0.9.1 - debug: 4.3.4 - delegates: 1.0.0 - depd: 2.0.0 - destroy: 1.2.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - fresh: 0.5.2 - http-assert: 1.5.0 - http-errors: 1.8.1 - is-generator-function: 1.0.10 - koa-compose: 4.1.0 - koa-convert: 2.0.0 - on-finished: 2.4.1 - only: 0.0.2 - parseurl: 1.3.3 - statuses: 1.5.0 - type-is: 1.6.18 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color + json-buffer: 3.0.1 + dev: true + + /kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} dev: false /levn@0.4.1: @@ -1489,26 +1205,29 @@ packages: dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 - dev: false + dev: true /locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} dependencies: p-locate: 5.0.0 - dev: false + dev: true /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: false + dev: true - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: false - - /lru-cache@10.1.0: - resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} - engines: {node: 14 || >=16.14} + /logform@2.6.0: + resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==} + engines: {node: '>= 12.0.0'} + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.3 + safe-stable-stringify: 2.4.3 + triple-beam: 1.4.1 dev: false /lru-cache@6.0.0: @@ -1516,17 +1235,20 @@ packages: engines: {node: '>=10'} dependencies: yallist: 4.0.0 - dev: false + dev: true - /media-typer@0.3.0: - resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} - engines: {node: '>= 0.6'} - dev: false + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true - /methods@1.1.2: - resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} - engines: {node: '>= 0.6'} - dev: false + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} @@ -1544,51 +1266,26 @@ packages: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} dependencies: brace-expansion: 1.1.11 - dev: false - - /minimatch@9.0.1: - resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: false + dev: true /minimatch@9.0.3: resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 - dev: false - - /minipass@7.0.4: - resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} - engines: {node: '>=16 || 14 >=14.17'} - dev: false + dev: true /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: false + dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: false - /mz@2.7.0: - resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - dependencies: - any-promise: 1.3.0 - object-assign: 4.1.1 - thenify-all: 1.6.0 - dev: false - /natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: false - - /negotiator@0.6.3: - resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} - engines: {node: '>= 0.6'} - dev: false + dev: true /node-cache@5.1.2: resolution: {integrity: sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==} @@ -1597,73 +1294,22 @@ packages: clone: 2.1.2 dev: false - /nodemon@2.0.22: - resolution: {integrity: sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==} - engines: {node: '>=8.10.0'} - hasBin: true - dependencies: - chokidar: 3.5.3 - debug: 3.2.7(supports-color@5.5.0) - ignore-by-default: 1.0.1 - minimatch: 3.1.2 - pstree.remy: 1.1.8 - semver: 5.7.2 - simple-update-notifier: 1.1.0 - supports-color: 5.5.0 - touch: 3.1.0 - undefsafe: 2.0.5 - dev: false - - /nopt@1.0.10: - resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: false - - /nopt@7.2.0: - resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} - engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - hasBin: true - dependencies: - abbrev: 2.0.0 - dev: false - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: false - /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: boolbase: 1.0.0 dev: false - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: false - - /object-inspect@1.13.1: - resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} - dev: false - - /on-finished@2.4.1: - resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} - engines: {node: '>= 0.8'} - dependencies: - ee-first: 1.1.1 - dev: false - /once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - dev: false + dev: true - /only@0.0.2: - resolution: {integrity: sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==} + /one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + dependencies: + fn.name: 1.1.0 dev: false /optionator@0.9.3: @@ -1676,28 +1322,28 @@ packages: levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 - dev: false + dev: true /p-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 - dev: false + dev: true /p-locate@5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} dependencies: p-limit: 3.1.0 - dev: false + dev: true /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: false + dev: true /parse5-htmlparser2-tree-adapter@7.0.0: resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} @@ -1712,254 +1358,155 @@ packages: entities: 4.5.0 dev: false - /parseurl@1.3.3: - resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} - engines: {node: '>= 0.8'} - dev: false - /path-exists@4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} - dev: false + dev: true /path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} - dev: false + dev: true /path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - dev: false - - /path-scurry@1.10.1: - resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - lru-cache: 10.1.0 - minipass: 7.0.4 - dev: false + dev: true - /path-to-regexp@6.2.1: - resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==} - dev: false + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true /picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - dev: false - - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: false - - /postcss-selector-parser@6.0.15: - resolution: {integrity: sha512-rEYkQOMUCEMhsKbK66tbEU9QVIxbhN18YiniAwA7XQYTVBqrBy+P2p5JcdqsHgKM2zWylp8d7J6eszocfds5Sw==} - engines: {node: '>=4'} - dependencies: - cssesc: 3.0.0 - util-deprecate: 1.0.2 - dev: false + dev: true /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - dev: false + dev: true - /prettier@3.1.1: - resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} engines: {node: '>=14'} hasBin: true - dev: false - - /pretty@2.0.0: - resolution: {integrity: sha512-G9xUchgTEiNpormdYBl+Pha50gOUovT18IvAe7EYMZ1/f9W/WWMPRn+xI68yXNMUk3QXHDwo/1wV/4NejVNe1w==} - engines: {node: '>=0.10.0'} - dependencies: - condense-newlines: 0.2.1 - extend-shallow: 2.0.1 - js-beautify: 1.14.11 - dev: false - - /proto-list@1.2.4: - resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} - dev: false + dev: true /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} dev: false - /pstree.remy@1.1.8: - resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} - dev: false - /punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - dev: false - - /qs@6.11.2: - resolution: {integrity: sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.4 - dev: false + dev: true /queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: false - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: false + dev: true - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} dependencies: - picomatch: 2.3.1 + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 dev: false /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: false + dev: true - /resolve-path@1.4.0: - resolution: {integrity: sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==} - engines: {node: '>= 0.8'} - dependencies: - http-errors: 1.6.3 - path-is-absolute: 1.0.1 - dev: false + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: false + dev: true /rimraf@3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: glob: 7.2.3 - dev: false + dev: true /run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 - dev: false + dev: true /safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} dev: false - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - dev: false - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true + /safe-stable-stringify@2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} dev: false - /semver@7.0.0: - resolution: {integrity: sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==} - hasBin: true + /sax@1.3.0: + resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} dev: false - /semver@7.5.4: - resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + /semver@7.6.0: + resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==} engines: {node: '>=10'} hasBin: true dependencies: lru-cache: 6.0.0 - dev: false - - /set-function-length@1.1.1: - resolution: {integrity: sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.1 - get-intrinsic: 1.2.2 - gopd: 1.0.1 - has-property-descriptors: 1.0.1 - dev: false - - /setprototypeof@1.1.0: - resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} - dev: false - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: false + dev: true /shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 - dev: false + dev: true /shebang-regex@3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - dev: false + dev: true - /side-channel@1.0.4: - resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} dependencies: - call-bind: 1.0.5 - get-intrinsic: 1.2.2 - object-inspect: 1.13.1 + is-arrayish: 0.3.2 dev: false - /signal-exit@4.1.0: - resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} - engines: {node: '>=14'} - dev: false + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true - /simple-update-notifier@1.1.0: - resolution: {integrity: sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==} - engines: {node: '>=8.10.0'} + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} dependencies: - semver: 7.0.0 - dev: false - - /statuses@1.5.0: - resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} - engines: {node: '>= 0.6'} - dev: false + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: false + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 + /stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} dev: false - /string-width@5.1.2: - resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} - engines: {node: '>=12'} + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} dependencies: - eastasianwidth: 0.2.0 - emoji-regex: 9.2.2 - strip-ansi: 7.1.0 + safe-buffer: 5.2.1 dev: false /strip-ansi@6.0.1: @@ -1967,182 +1514,142 @@ packages: engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 - dev: false - - /strip-ansi@7.1.0: - resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} - engines: {node: '>=12'} - dependencies: - ansi-regex: 6.0.1 - dev: false + dev: true /strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - dev: false - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: false + dev: true /supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} dependencies: has-flag: 4.0.0 + dev: true + + /text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} dev: false /text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: false - - /thenify-all@1.6.0: - resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} - engines: {node: '>=0.8'} - dependencies: - thenify: 3.3.1 - dev: false - - /thenify@3.3.1: - resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - dependencies: - any-promise: 1.3.0 - dev: false + dev: true /to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 - dev: false + dev: true - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} + /triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} dev: false - /touch@3.1.0: - resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} - hasBin: true + /ts-api-utils@1.3.0(typescript@5.4.4): + resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} + engines: {node: '>=16'} + peerDependencies: + typescript: '>=4.2.0' dependencies: - nopt: 1.0.10 - dev: false + typescript: 5.4.4 + dev: true - /tsscmp@1.0.6: - resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} - engines: {node: '>=0.6.x'} - dev: false + /tsx@3.14.0: + resolution: {integrity: sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==} + hasBin: true + dependencies: + esbuild: 0.18.20 + get-tsconfig: 4.7.3 + source-map-support: 0.5.21 + optionalDependencies: + fsevents: 2.3.3 + dev: true /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 - dev: false + dev: true /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} - dev: false - - /type-is@1.6.18: - resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} - engines: {node: '>= 0.6'} - dependencies: - media-typer: 0.3.0 - mime-types: 2.1.35 - dev: false + dev: true - /undefsafe@2.0.5: - resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} - dev: false + /typescript@5.4.4: + resolution: {integrity: sha512-dGE2Vv8cpVvw28v8HCPqyb08EzbBURxDpuhJvTrusShUfGnhHBafDsLdS1EhhxyL6BJQE+2cT3dDPAv+MQ6oLw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: false + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.1 - dev: false + dev: true /util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} dev: false - /vary@1.1.2: - resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} - engines: {node: '>= 0.8'} - dev: false - - /vue-eslint-parser@9.3.2(eslint@8.56.0): - resolution: {integrity: sha512-q7tWyCVaV9f8iQyIA5Mkj/S6AoJ9KBN8IeUSf3XEmBrOtxOZnfTg5s4KClbZBCK3GtnT/+RyCLZyDHuZwTuBjg==} - engines: {node: ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: '>=6.0.0' - dependencies: - debug: 4.3.4 - eslint: 8.56.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.5.0 - lodash: 4.17.21 - semver: 7.5.4 - transitivePeerDependencies: - - supports-color - dev: false - /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true dependencies: isexe: 2.0.0 - dev: false + dev: true - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} + /winston-transport@4.7.0: + resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==} + engines: {node: '>= 12.0.0'} dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 + logform: 2.6.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 dev: false - /wrap-ansi@8.1.0: - resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} - engines: {node: '>=12'} + /winston@3.13.0: + resolution: {integrity: sha512-rwidmA1w3SE4j0E5MuIufFhyJPBDG7Nu71RkZor1p2+qHvJSZ9GYDA81AyleQcZbh/+V6HjeBdfnTZJm9rSeQQ==} + engines: {node: '>= 12.0.0'} dependencies: - ansi-styles: 6.2.1 - string-width: 5.1.2 - strip-ansi: 7.1.0 + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.5 + is-stream: 2.0.1 + logform: 2.6.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.4.3 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.7.0 dev: false /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: false + dev: true - /xml-name-validator@4.0.0: - resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} - engines: {node: '>=12'} + /xml-js@1.6.11: + resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==} + hasBin: true + dependencies: + sax: 1.3.0 dev: false /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - dev: false - - /ylru@1.3.2: - resolution: {integrity: sha512-RXRJzMiK6U2ye0BlGGZnmpwJDPgakn6aNQ0A7gHRbD4I0uvK4TW6UqkK1V0pp9jskjJBAXd3dRrbzWkqJ+6cxA==} - engines: {node: '>= 4.0.0'} - dev: false + dev: true /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - dev: false + dev: true diff --git a/public/404.html b/public/404.html deleted file mode 100644 index 103595d9..00000000 --- a/public/404.html +++ /dev/null @@ -1,189 +0,0 @@ - - - - - 404 | DailyHot API - - - - - -
-
-
404 Not Found
-
请检查您的路径
-
- -
-
- - - - diff --git a/public/favicon.svg b/public/favicon.svg deleted file mode 100644 index c0df2a12..00000000 --- a/public/favicon.svg +++ /dev/null @@ -1,11 +0,0 @@ - - favicon-svg - - - - - - - \ No newline at end of file diff --git a/public/ico/error.png b/public/ico/error.png new file mode 100644 index 00000000..e67369df Binary files /dev/null and b/public/ico/error.png differ diff --git a/public/ico/favicon.png b/public/ico/favicon.png new file mode 100644 index 00000000..e74ac2ff Binary files /dev/null and b/public/ico/favicon.png differ diff --git a/public/ico/powered-by-vercel.svg b/public/ico/powered-by-vercel.svg new file mode 100644 index 00000000..87782868 --- /dev/null +++ b/public/ico/powered-by-vercel.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/index.html b/public/index.html deleted file mode 100644 index c1b6c7c3..00000000 --- a/public/index.html +++ /dev/null @@ -1,195 +0,0 @@ - - - - - DailyHot API - - - - - -
-
-
DailyHot API
-
服务已正常运行
-
- - -
-
- - - - diff --git a/routes/36kr.js b/routes/36kr.js deleted file mode 100644 index 1003997e..00000000 --- a/routes/36kr.js +++ /dev/null @@ -1,138 +0,0 @@ -const Router = require("koa-router"); -const krRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "36kr", - title: "36氪", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "krData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://gateway.36kr.com/api/mis/nav/home/nav/rank/hot"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.itemId, - title: v.templateMaterial.widgetTitle, - pic: v.templateMaterial.widgetImage, - owner: v.templateMaterial.authorName, - hot: v.templateMaterial.statRead, - data: v.templateMaterial, - url: `https://www.36kr.com/p/${v.itemId}`, - mobileUrl: `https://www.36kr.com/p/${v.itemId}`, - }; - }); -}; - -// 36氪热榜 -krRouter.get("/36kr", async (ctx) => { - console.log("获取36氪热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取36氪热榜"); - // 从服务器拉取数据 - const response = await axios.post(url, { - partner_id: "wap", - param: { - siteId: 1, - platformId: 2, - }, - timestamp: new Date().getTime(), - }); - data = getData(response.data.data.hotRankList); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 36氪热榜 - 获取最新数据 -krRouter.get("/36kr/new", async (ctx) => { - console.log("获取36氪热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.post(url, { - partner_id: "wap", - param: { - siteId: 1, - platformId: 2, - }, - timestamp: new Date().getTime(), - }); - const newData = getData(response.data.data.hotRankList); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取36氪热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -krRouter.info = routerInfo; -module.exports = krRouter; diff --git a/routes/baidu.js b/routes/baidu.js deleted file mode 100644 index c02bad11..00000000 --- a/routes/baidu.js +++ /dev/null @@ -1,135 +0,0 @@ -const Router = require("koa-router"); -const baiduRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { name: "baidu", title: "百度", subtitle: "热搜榜" }; - -// 缓存键名 -const cacheKey = "baiduData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://top.baidu.com/board?tab=realtime"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - const dataList = []; - try { - const pattern = //s; - const matchResult = data.match(pattern); - const jsonObject = JSON.parse(matchResult[1]).cards[0].content; - jsonObject.forEach((v) => { - dataList.push({ - title: v.query, - desc: v.desc, - pic: v.img, - hot: Number(v.hotScore), - url: `https://www.baidu.com/s?wd=${encodeURIComponent(v.query)}`, - mobileUrl: v.url, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// 百度热搜 -baiduRouter.get("/baidu", async (ctx) => { - console.log("获取百度热搜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取百度热搜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - message: "获取失败", - }; - } -}); - -// 百度热搜 - 获取最新数据 -baiduRouter.get("/baidu/new", async (ctx) => { - console.log("获取百度热搜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取百度热搜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -baiduRouter.info = routerInfo; -module.exports = baiduRouter; diff --git a/routes/bilibili.js b/routes/bilibili.js deleted file mode 100644 index cee725e5..00000000 --- a/routes/bilibili.js +++ /dev/null @@ -1,125 +0,0 @@ -const Router = require("koa-router"); -const bilibiliRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "bilibili", - title: "哔哩哔哩", - subtitle: "热门榜", -}; - -// 缓存键名 -const cacheKey = "bilibiliData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://api.bilibili.com/x/web-interface/ranking/v2"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.bvid, - title: v.title, - desc: v.desc, - pic: v.pic.replace(/http:/, "https:"), - owner: v.owner, - data: v.stat, - hot: v.stat.view, - url: v.short_link_v2 || `https://b23.tv/${v.bvid}`, - mobileUrl: `https://m.bilibili.com/video/${v.bvid}`, - }; - }); -}; - -// 哔哩哔哩热门榜 -bilibiliRouter.get("/bilibili", async (ctx) => { - console.log("获取哔哩哔哩热门榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取哔哩哔哩热门榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data.list); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 哔哩哔哩热门榜 - 获取最新数据 -bilibiliRouter.get("/bilibili/new", async (ctx) => { - console.log("获取哔哩哔哩热门榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data.list); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取哔哩哔哩热门榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -bilibiliRouter.info = routerInfo; -module.exports = bilibiliRouter; diff --git a/routes/calendar.js b/routes/calendar.js deleted file mode 100644 index 8d693e4d..00000000 --- a/routes/calendar.js +++ /dev/null @@ -1,125 +0,0 @@ -const Router = require("koa-router"); -const calendarRouter = new Router(); -const axios = require("axios"); -const { get, set } = require("../utils/cacheData"); - -// 缓存键名 -const cacheKey = "calendarData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 获取月份 -const month = (new Date().getMonth() + 1).toString().padStart(2, "0"); - -// 获取天数 -const day = new Date().getDate().toString().padStart(2, "0"); - -// 调用路径 -const url = `https://baike.baidu.com/cms/home/eventsOnHistory/${month}.json`; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - year: v.year, - title: v.title.replace(/<[^>]+>/g, ""), - desc: v.desc.replace(/<[^>]+>/g, ""), - pic: v?.pic_share || v?.pic_index, - avatar: v?.pic_calendar, - type: v.type, - url: v.link, - mobileUrl: v.link, - }; - }); -}; - -// 历史上的今天 -calendarRouter.get("/calendar", async (ctx) => { - console.log("获取历史上的今天"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取历史上的今天"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data[month][month + day]); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - title: "历史上的今天", - subtitle: month + "-" + day, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - title: "历史上的今天", - subtitle: month + "-" + day, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - message: "获取失败", - }; - } -}); - -// 历史上的今天 - 获取指定日期 -calendarRouter.get("/calendar/date", async (ctx) => { - console.log("获取历史上的今天 - 指定日期"); - try { - // 获取参数 - const { month, day } = ctx.query; - if (!month || !day) { - ctx.body = { code: 400, message: "参数不完整" }; - return false; - } - if (month.length == 1 || day.length == 1) { - ctx.body = { code: 400, message: "参数格式错误" }; - return false; - } - // 从服务器拉取最新数据 - const response = await axios.get( - `https://baike.baidu.com/cms/home/eventsOnHistory/${month}.json`, - ); - const newData = getData(response.data[month][month + day]); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取历史上的今天"); - // 返回数据 - ctx.body = { - code: 200, - message: "获取成功", - title: "历史上的今天", - subtitle: month + "-" + day, - total: newData.length, - updateTime, - data: newData, - }; - } catch (error) { - // 返回错误信息 - ctx.body = { - code: 500, - title: "历史上的今天", - subtitle: month + "-" + day, - message: "获取失败", - }; - } -}); - -module.exports = calendarRouter; diff --git a/routes/douban_group.js b/routes/douban_group.js deleted file mode 100644 index f0841625..00000000 --- a/routes/douban_group.js +++ /dev/null @@ -1,181 +0,0 @@ -/** - * @author: x-dr - * @date: 2023-12-26 - * @customEditors: imsyy - * @lastEditTime: 2024-01-02 - */ - -const Router = require("koa-router"); -const doubanGroupNewRouter = new Router(); -const axios = require("axios"); -const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "douban_group", - title: "豆瓣讨论小组", - subtitle: "精选", -}; - -// 缓存键名 -const cacheKey = "doubanGroupData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -const url = "https://www.douban.com/group/explore"; - -const headers = { - accept: - "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7", - "accept-language": "zh-CN,zh;q=0.9,en;q=0.8", - "cache-control": "max-age=0", - "sec-ch-ua": '"Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"', - "sec-ch-ua-mobile": "?0", - "sec-ch-ua-platform": '"Windows"', - "sec-fetch-dest": "document", - "sec-fetch-mode": "navigate", - "sec-fetch-site": "none", - "sec-fetch-user": "?1", - "upgrade-insecure-requests": "1", - // "cookie": "bid=lLpb6D1JLuw; douban-fav-remind=1; _pk_id.100001.8cb4=e7d91ae46530fd1d.1680518589.; ll=\"118281\"; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1703602972%2C%22http%3A%2F%2Fnew.xianbao.fun%2F%22%5D; _pk_ses.100001.8cb4=1; ap_v=0,6.0" -}; - -// 数据处理 -const getData = (data) => { - if (!data) return false; - const dataList = []; - const $ = cheerio.load(data); - try { - $(`.channel-item`).each((i, e) => { - // console.log($(e).html()); - const item = cheerio.load($(e).html()); - const title = item("h3") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const url = item("h3 a").attr("href"); - const hot = item('div[class="likes"]') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const desc = item('div[class="block"]') - .text() - .replace(/(^\s*)|(\s*$|\n)/g, ""); - const source = item('div[class="source"] a') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - // const excerpt = item('.channel-item-desc').text().replace(/(^\s*)|(\s*$)/g, "") - // console.log(title); - // console.log(url); - dataList.push({ - title: title, - desc: desc, - url: url, - mobileUrl: url, - hot: hot, - source: source, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// trending -doubanGroupNewRouter.get("/douban_group", async (ctx) => { - console.log("获取豆瓣讨论小组精选"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新豆瓣讨论小组精选"); - // 从服务器拉取数据 - const response = await axios.get(url, { headers }); - // console.log(response.data); - data = getData(response.data); - - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 豆瓣新片榜 - 获取最新数据 -doubanGroupNewRouter.get("/douban_group/new", async (ctx) => { - console.log("获取豆瓣讨论小组精选 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新豆瓣讨论小组精选"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - updateTime, - total: newData.length, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -doubanGroupNewRouter.info = routerInfo; -module.exports = doubanGroupNewRouter; diff --git a/routes/douban_new.js b/routes/douban_new.js deleted file mode 100644 index 356d85a1..00000000 --- a/routes/douban_new.js +++ /dev/null @@ -1,159 +0,0 @@ -/* - * @author: MyFaith - * @date: 2023-09-06 - * @customEditors: imsyy - * @lastEditTime: 2023-09-06 - */ - -const Router = require("koa-router"); -const doubanNewRouter = new Router(); -const axios = require("axios"); -const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "douban_new", - title: "豆瓣", - subtitle: "新片榜", -}; - -// 缓存键名 -const cacheKey = "doubanNewData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://movie.douban.com/chart/"; -const headers = { - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1", -}; - -// 豆瓣新片榜单特殊处理 - 标题 -const replaceTitle = (title, score) => { - return `[★${score}] ` + title.replace(/\n/g, "").replace(/ /g, "").replace(/\//g, " / ").trim(); -}; - -// 数据处理 -const getData = (data) => { - if (!data) return false; - const dataList = []; - const $ = cheerio.load(data); - try { - $(".article .item").map((idx, item) => { - const id = $(item).find("a").attr("href").split("/").at(-2) ?? ""; - const score = $(item).find(".rating_nums").text() ?? ""; - - dataList.push({ - title: replaceTitle($(item).find("a").text(), score), - desc: $(item).find("p").text(), - score, - comments: $(item).find("span.pl").text().match(/\d+/)?.[0] ?? "", - pic: $(item).find("img").attr("src") ?? "", - url: $(item).find("a").attr("href") ?? "", - mobileUrl: `https://m.douban.com/movie/subject/${id}`, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// 豆瓣新片榜 -doubanNewRouter.get("/douban_new", async (ctx) => { - console.log("获取豆瓣新片榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取豆瓣新片榜"); - // 从服务器拉取数据 - const response = await axios.get(url, { headers }); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 豆瓣新片榜 - 获取最新数据 -doubanNewRouter.get("/douban_new/new", async (ctx) => { - console.log("获取豆瓣新片榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取豆瓣新片榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - updateTime, - total: newData.length, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -doubanNewRouter.info = routerInfo; -module.exports = doubanNewRouter; diff --git a/routes/douyin.js b/routes/douyin.js deleted file mode 100644 index 60f61b8a..00000000 --- a/routes/douyin.js +++ /dev/null @@ -1,183 +0,0 @@ -const Router = require("koa-router"); -const douyinRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "douyin", - title: "抖音", - subtitle: "热点榜", -}; - -// 缓存键名 -const cacheKey = "douyinHotData"; -const cacheCookieKey = "douyinCookieData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = - "https://www.douyin.com/aweme/v1/web/hot/search/list/?device_platform=webapp&aid=6383&channel=channel_pc_web&detail_list=1&round_trip_time=50"; - -// Token 获取路径 -const cookisUrl = "https://www.douyin.com/passport/general/login_guiding_strategy/?aid=6383"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - const dataList = []; - try { - const jsonObject = data.data.word_list; - jsonObject.forEach((v) => { - dataList.push({ - title: v.word, - pic: `${v.word_cover.url_list[0]}`, - hot: Number(v.hot_value), - url: `https://www.douyin.com/hot/${encodeURIComponent(v.sentence_id)}`, - mobileUrl: `https://www.douyin.com/hot/${encodeURIComponent(v.sentence_id)}`, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return []; - } -}; - -// 处理抖音 Cookis -const setDouyinCookies = (data) => { - if (!data) return null; - try { - const pattern = /passport_csrf_token=(.*); Path/s; - const matchResult = data.headers["set-cookie"][0].match(pattern); - const cookieData = matchResult[1]; - return cookieData; - } catch (error) { - console.error("获取抖音 Cookie 出错" + error); - return null; - } -}; - -// 获取抖音 Cookie数据 -const getDouyinCookie = async () => { - try { - let cookie = await get(cacheCookieKey); - if (!cookie) { - const cookisResponse = await axios.get(cookisUrl); - cookie = setDouyinCookies(cookisResponse); - console.log("抖音 Cookie 写入缓存", cookie); - await set(cacheCookieKey, cookie); - } - return cookie; - } catch (error) { - console.error("获取抖音 Cookie 出错", error); - return null; - } -}; - -// 抖音热点榜 -douyinRouter.get("/douyin", async (ctx) => { - console.log("获取抖音热点榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const cookie = await getDouyinCookie(); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取抖音热点榜"); - // 从服务器拉取数据 - const response = await axios.get(url, { - headers: { - Cookie: `passport_csrf_token=${cookie}`, - }, - }); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 抖音热点榜 - 获取最新数据 -douyinRouter.get("/douyin/new", async (ctx) => { - console.log("获取抖音热点榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const cookie = await getDouyinCookie(); - const response = await axios.get(url, { - headers: { - Cookie: `passport_csrf_token=${cookie}`, - }, - }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取抖音热点榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -douyinRouter.info = routerInfo; -module.exports = douyinRouter; diff --git a/routes/douyin_music.js b/routes/douyin_music.js deleted file mode 100644 index c00844e0..00000000 --- a/routes/douyin_music.js +++ /dev/null @@ -1,155 +0,0 @@ -/* - * @author: WangPeng - * @date: 2023-07-11 16:41:48 - * @customEditors: imsyy - * @lastEditTime: 2023-07-11 16:03:12 - */ - -const Router = require("koa-router"); -const douyinMusicRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "douyin_music", - title: "抖音", - subtitle: "热歌榜", -}; - -// 缓存键名 -const cacheKey = "douyinMusicData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://aweme.snssdk.com/aweme/v1/chart/music/list/"; -const HEADERS = { - "user-agent": "okhttp3", -}; -const QUERIES = { - device_platform: "android", - version_name: "13.2.0", - version_code: "130200", - aid: "1128", - chart_id: "6853972723954146568", - count: "100", -}; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - try { - return data.map((v) => { - const item = v.music_info; - return { - id: item.id, - title: item.title, - album: item.album, - artist: item.author, - pic: item?.cover_large.url_list[0], - lyric: item.lyric_url, - url: item.play_url.uri, - mobileUrl: item.play_url.uri, - // h5Url: item.matched_song?.h5_url, - }; - }); - } catch (error) { - console.error("数据处理出错" + error); - return []; - } -}; - -// 抖音热歌榜 -douyinMusicRouter.get("/douyin_music", async (ctx) => { - console.log("获取抖音热歌榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取抖音热歌榜"); - // 从服务器拉取数据 - const response = await axios.get(url, { - headers: HEADERS, - params: QUERIES, - }); - data = getData(response.data.music_list); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 抖音热歌榜 - 获取最新数据 -douyinMusicRouter.get("/douyin_music/new", async (ctx) => { - console.log("获取抖音热歌榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url, { - headers: HEADERS, - params: QUERIES, - }); - const newData = getData(response.data.word_list); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取抖音热歌榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -douyinMusicRouter.info = routerInfo; -module.exports = douyinMusicRouter; diff --git a/routes/douyin_new.js b/routes/douyin_new.js deleted file mode 100644 index 1c0edd47..00000000 --- a/routes/douyin_new.js +++ /dev/null @@ -1,149 +0,0 @@ -/* - * @author: WangPeng - * @date: 2023-07-10 16:56:01 - * @customEditors: imsyy - * @lastEditTime: 2023-07-11 16:54:38 - */ - -const Router = require("koa-router"); -const douyinNewRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "douyin", - title: "抖音", - subtitle: "热点榜", -}; - -// 缓存键名 -const cacheKey = "douyinHotNewData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://aweme.snssdk.com/aweme/v1/hot/search/list/"; -const HEADERS = { - "user-agent": "okhttp3", -}; -const QUERIES = { - device_platform: "android", - version_name: "13.2.0", - version_code: "130200", - aid: "1128", -}; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - try { - const jsonObject = data.data.word_list; - return jsonObject.map((v) => { - return { - title: v.word, - pic: `${v.word_cover.url_list[0]}`, - hot: Number(v.hot_value), - url: `https://www.douyin.com/hot/${encodeURIComponent(v.sentence_id)}`, - mobileUrl: `https://www.douyin.com/hot/${encodeURIComponent(v.sentence_id)}`, - }; - }); - } catch (error) { - console.error("数据处理出错" + error); - return []; - } -}; - -// 抖音热点榜 -douyinNewRouter.get("/douyin_new", async (ctx) => { - console.log("获取抖音热点榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取抖音热点榜"); - // 从服务器拉取数据 - const response = await axios.get(url, { - headers: HEADERS, - params: QUERIES, - }); - data = getData(response.data); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 抖音热点榜 - 获取最新数据 -douyinNewRouter.get("/douyin_new/new", async (ctx) => { - console.log("获取抖音热点榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url, { - headers: HEADERS, - params: QUERIES, - }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取抖音热点榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -douyinNewRouter.info = routerInfo; -module.exports = douyinNewRouter; diff --git a/routes/genshin.js b/routes/genshin.js deleted file mode 100644 index 023b9285..00000000 --- a/routes/genshin.js +++ /dev/null @@ -1,123 +0,0 @@ -const Router = require("koa-router"); -const genshinRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "genshin", - title: "原神", - subtitle: "最新信息", -}; - -// 缓存键名 -const cacheKey = "genshinData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = - "https://content-static.mihoyo.com/content/ysCn/getContentList?pageSize=50&pageNum=1&channelId=10"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.id, - title: v.title, - pic: v.ext[1]?.value[0]?.url, - start_time: v?.start_time, - url: `https://ys.mihoyo.com/main/news/detail/${v.id}`, - mobileUrl: `https://ys.mihoyo.com/main/m/news/detail/${v.id}`, - }; - }); -}; - -// 原神最新信息 -genshinRouter.get("/genshin", async (ctx) => { - console.log("获取原神最新信息"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取原神最新信息"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data.list); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 原神最新信息 - 获取最新数据 -genshinRouter.get("/genshin/new", async (ctx) => { - console.log("获取原神最新信息 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data.list); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取原神最新信息"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -genshinRouter.info = routerInfo; -module.exports = genshinRouter; diff --git a/routes/github.js b/routes/github.js deleted file mode 100644 index ad1b148d..00000000 --- a/routes/github.js +++ /dev/null @@ -1,174 +0,0 @@ -/* - * @author: x-dr - * @date: 2023-12-25 - * @customEditors: imsyy - * @lastEditTime: 2023-12-27 - */ - -const Router = require("koa-router"); -const githubNewRouter = new Router(); -const axios = require("axios"); -const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "github", - title: "Github", - subtitle: "trending", -}; - -// 缓存键名 -const cacheKey = "githubData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -const url = "https://github.com/trending"; - -const headers = { - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1", -}; - -// 数据处理 -const getData = (data) => { - if (!data) return false; - const dataList = []; - const $ = cheerio.load(data); - try { - $(`.Box-row`).each((i, e) => { - // console.log(getCheerio(e).html()); - const item = cheerio.load($(e).html()); - // console.log(item); - const title = item("h2 a").attr("href").replace("/", ""); - const url = `https://github.com/${title}`; - const excerpt = item("p") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const language = item('.f6 span[itemprop="programmingLanguage"]') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const stars = item(".f6 a:first") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const forks = item(".f6 a:eq(1)") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const starstoday = item(".f6 span:eq(4)") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - - dataList.push({ - title: title, - desc: excerpt, - url: url, - language: language, - stars: stars, - forks: forks, - starstoday: starstoday, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// trending -githubNewRouter.get("/github", async (ctx) => { - console.log("获取github trending"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新github trending"); - // 从服务器拉取数据 - const response = await axios.get(url, { headers }); - // console.log(response.data); - data = getData(response.data); - - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// trending - 获取最新数据 -githubNewRouter.get("/github/new", async (ctx) => { - console.log("获取github trending - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新github trending"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - updateTime, - total: newData.length, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -githubNewRouter.info = routerInfo; -module.exports = githubNewRouter; diff --git a/routes/index.js b/routes/index.js deleted file mode 100644 index 3c7a9a1a..00000000 --- a/routes/index.js +++ /dev/null @@ -1,70 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const Router = require("koa-router"); - -const router = new Router(); - -// 全部路由数据 -const allRouterInfo = { - name: "全部接口", - subtitle: "除了特殊接口外的全部接口列表", - total: 0, - data: [], -}; - -// 根目录 -router.get("/", async (ctx) => { - await ctx.render("index"); -}); - -// 遍历所有路由模块 -fs.readdirSync(__dirname) - .filter((filename) => filename.endsWith(".js") && filename !== "index.js") - .forEach((filename) => { - const routerPath = path.join(__dirname, filename); - const routerModule = require(routerPath); - // 自动注册路由 - if (routerModule instanceof Router) { - // 写入路由数据 - if (routerModule?.info) { - allRouterInfo.total++; - allRouterInfo.data.push({ - ...routerModule.info, - stack: routerModule.stack, - }); - } - // 引用路由 - router.use(routerModule.routes()); - } - }); - -// 全部接口路由 -router.get("/all", async (ctx) => { - console.log("获取全部接口路由"); - if (allRouterInfo.total > 0) { - ctx.body = { - code: 200, - message: "获取成功", - ...allRouterInfo, - }; - } else if (allRouterInfo.total === 0) { - ctx.body = { - code: 200, - message: "暂无接口,请添加", - ...allRouterInfo, - }; - } else { - ctx.body = { - code: 500, - message: "获取失败", - ...allRouterInfo, - }; - } -}); - -// 404 路由 -router.use(async (ctx) => { - await ctx.render("404"); -}); - -module.exports = router; diff --git a/routes/ithome.js b/routes/ithome.js deleted file mode 100644 index 04ee196d..00000000 --- a/routes/ithome.js +++ /dev/null @@ -1,163 +0,0 @@ -const Router = require("koa-router"); -const itHomeRouter = new Router(); -const axios = require("axios"); -const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "ithome", - title: "IT之家", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "itHomeData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://m.ithome.com/rankm/"; -const headers = { - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1", -}; - -// it之家特殊处理 - url -const replaceLink = (url) => { - const match = url.match(/[html|live]\/(\d+)\.htm/)[1]; - return `https://www.ithome.com/0/${match.slice(0, 3)}/${match.slice(3)}.htm`; -}; - -// 数据处理 -const getData = (data) => { - if (!data) return false; - const dataList = []; - const $ = cheerio.load(data); - try { - $(".rank-name").each(() => { - const type = $(this).data("rank-type"); - const newListHtml = $(this).next(".rank-box").html(); - cheerio - .load(newListHtml)(".placeholder") - .get() - .map((v) => { - dataList.push({ - title: $(v).find(".plc-title").text(), - img: $(v).find("img").attr("data-original"), - time: $(v).find(".post-time").text(), - type: $(this).text(), - typeName: type, - hot: Number($(v).find(".review-num").text().replace(/\D/g, "")), - url: replaceLink($(v).find("a").attr("href")), - mobileUrl: $(v).find("a").attr("href"), - }); - }); - // dataList[type] = { - // name: $(this).text(), - // total: newsList.length, - // list: newsList, - // }; - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// IT之家热榜 -itHomeRouter.get("/ithome", async (ctx) => { - console.log("获取IT之家热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取IT之家热榜"); - // 从服务器拉取数据 - const response = await axios.get(url, { headers }); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// IT之家热榜 - 获取最新数据 -itHomeRouter.get("/ithome/new", async (ctx) => { - console.log("获取IT之家热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取IT之家热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - updateTime, - total: newData.length, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -itHomeRouter.info = routerInfo; -module.exports = itHomeRouter; diff --git a/routes/juejin.js b/routes/juejin.js deleted file mode 100644 index 83103b58..00000000 --- a/routes/juejin.js +++ /dev/null @@ -1,121 +0,0 @@ -const Router = require("koa-router"); -const juejinRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "juejin", - title: "稀土掘金", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "juejinData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://api.juejin.cn/content_api/v1/content/article_rank?category_id=1&type=hot"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.content.content_id, - title: v.content.title, - hot: v.content_counter.hot_rank, - url: `https://juejin.cn/post/${v.content.content_id}`, - mobileUrl: `https://juejin.cn/post/${v.content.content_id}`, - }; - }); -}; - -// 掘金热榜 -juejinRouter.get("/juejin", async (ctx) => { - console.log("获取掘金热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取掘金热榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 掘金热榜 - 获取最新数据 -juejinRouter.get("/juejin/new", async (ctx) => { - console.log("获取掘金热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取掘金热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -juejinRouter.info = routerInfo; -module.exports = juejinRouter; diff --git a/routes/kuaishou.js b/routes/kuaishou.js deleted file mode 100644 index 00c48d43..00000000 --- a/routes/kuaishou.js +++ /dev/null @@ -1,162 +0,0 @@ -/* - * @author: MCBBC - * @date: 2023-07-17 - * @customEditors: imsyy - * @lastEditTime: 2023-07-17 - */ - -const Router = require("koa-router"); -const kuaishouRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "kuaishou", - title: "快手", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "kuaishouData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://www.kuaishou.com/?isHome=1"; - -// Unicode 解码 -const decodedString = (encodedString) => { - return encodedString.replace(/\\u([\d\w]{4})/gi, (match, grp) => - String.fromCharCode(parseInt(grp, 16)), - ); -}; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - const dataList = []; - try { - const pattern = /window.__APOLLO_STATE__=(.*);\(function\(\)/s; - const idPattern = /clientCacheKey=([A-Za-z0-9]+)/s; - const matchResult = data.match(pattern); - const jsonObject = JSON.parse(matchResult[1])["defaultClient"]; - - // 获取所有分类 - const allItems = jsonObject['$ROOT_QUERY.visionHotRank({"page":"home"})']["items"]; - // 遍历所有分类 - allItems.forEach((v) => { - // 基础数据 - const image = jsonObject[v.id]["poster"]; - const id = image.match(idPattern)[1]; - // 数据处理 - dataList.push({ - title: jsonObject[v.id]["name"], - pic: decodedString(image), - hot: jsonObject[v.id]["hotValue"], - url: `https://www.kuaishou.com/short-video/${id}`, - mobileUrl: `https://www.kuaishou.com/short-video/${id}`, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// 快手热榜 -kuaishouRouter.get("/kuaishou", async (ctx) => { - console.log("获取快手热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取快手热榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 快手热榜 - 获取最新数据 -kuaishouRouter.get("/kuaishou/new", async (ctx) => { - console.log("获取快手热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取快手热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -kuaishouRouter.info = routerInfo; -module.exports = kuaishouRouter; diff --git a/routes/lol.js b/routes/lol.js deleted file mode 100644 index 2b80e016..00000000 --- a/routes/lol.js +++ /dev/null @@ -1,139 +0,0 @@ -const Router = require("koa-router"); -const lolRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "lol", - title: "英雄联盟", - subtitle: "更新公告", -}; - -// 缓存键名 -const cacheKey = "lolData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = - "https://apps.game.qq.com/cmc/zmMcnTargetContentList?r0=jsonp&page=1&num=16&target=24&source=web_pc"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - const dataList = []; - try { - const match = data.match(/callback\((.*)\)/); - const jsonObject = JSON.parse(match[1]).data.result; - jsonObject.forEach((v) => { - dataList.push({ - title: v.sTitle, - desc: v.sAuthor, - pic: `https:${v.sIMG}`, - hot: Number(v.iTotalPlay), - url: `https://lol.qq.com/news/detail.shtml?docid=${encodeURIComponent(v.iDocID)}`, - mobileUrl: `https://lol.qq.com/news/detail.shtml?docid=${encodeURIComponent(v.iDocID)}`, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// 英雄联盟更新公告 -lolRouter.get("/lol", async (ctx) => { - console.log("获取英雄联盟更新公告"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取英雄联盟更新公告"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - message: "获取失败", - }; - } -}); - -// 英雄联盟更新公告 - 获取最新数据 -lolRouter.get("/lol/new", async (ctx) => { - console.log("获取英雄联盟更新公告 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取英雄联盟更新公告"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -lolRouter.info = routerInfo; -module.exports = lolRouter; diff --git a/routes/netease.js b/routes/netease.js deleted file mode 100644 index b0eff6b0..00000000 --- a/routes/netease.js +++ /dev/null @@ -1,130 +0,0 @@ -/* - * @author: MCBBC - * @date: 2023-07-17 - * @customEditors: imsyy - * @lastEditTime: 2023-07-17 - */ - -const Router = require("koa-router"); -const neteaseRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "netease", - title: "网易新闻", - subtitle: "热点榜", -}; - -// 缓存键名 -const cacheKey = "neteaseData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://m.163.com/fe/api/hot/news/flow"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.skipID, - title: v.title, - desc: v._keyword, - pic: v.imgsrc, - owner: v.source, - url: `https://www.163.com/dy/article/${v.skipID}.html`, - mobileUrl: v.url, - }; - }); -}; - -// 网易新闻热榜 -neteaseRouter.get("/netease", async (ctx) => { - console.log("获取网易新闻热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取网易新闻热榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data.list); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 网易新闻热榜 - 获取最新数据 -neteaseRouter.get("/netease/new", async (ctx) => { - console.log("获取网易新闻热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data.list); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取网易新闻热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -neteaseRouter.info = routerInfo; -module.exports = neteaseRouter; diff --git a/routes/netease_music_toplist.js b/routes/netease_music_toplist.js deleted file mode 100644 index 1772d275..00000000 --- a/routes/netease_music_toplist.js +++ /dev/null @@ -1,198 +0,0 @@ -/** - * @author: x-dr - * @date: 2023-12-27 - * @customEditors: imsyy - * @lastEditTime: 2024-01-02 - */ - -const URL = require("url"); -const Router = require("koa-router"); -const neteaseMusicRouter = new Router(); -const axios = require("axios"); -const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "netease_music_toplist", - title: "网易云音乐", - subtitle: "排行榜", -}; - -// 缓存键名 -const cacheKey = "neteasemusicToplistData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -const url = "https://music.163.com/discover/toplist?id="; - -const headers = { - authority: "music.163.com", - referer: "https://music.163.com/", -}; - -// 榜单类别 -const listType = { - 1: { - id: 19723756, - name: "飙升榜", - }, - 2: { - id: 3779629, - name: "新歌榜", - }, - 3: { - id: 2884035, - name: "原创榜", - }, - 4: { - id: 3778678, - name: "热歌榜", - }, -}; - -// 数据处理 -const getData = (data) => { - if (!data) return false; - const dataList = []; - const $ = cheerio.load(data); - try { - $(".m-sgitem").each((i, e) => { - const urlString = $(e).attr("href"); - const parsedUrl = URL.parse(urlString, true); - const urlidValue = parsedUrl.query.id; - const item = cheerio.load($(e).html()); - const author = item('div[class="f-thide sginfo"]') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const title = item('div[class="f-thide sgtl"]') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - dataList.push({ - title: title, - desc: author, - url: `https://music.163.com/#/song?id=${urlidValue}`, - mobileUrl: `https://music.163.com/m/song?id=${urlidValue}`, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// 网易云音乐排行榜 -neteaseMusicRouter.get("/netease_music_toplist", async (ctx) => { - console.log("获取网易云音乐排行榜"); - try { - // 获取参数 - const { type } = ctx.query; - const typeNum = Number(type); - if (!typeNum || typeNum > 4 || typeNum < 1) { - ctx.body = { code: 400, ...routerInfo, message: "参数不完整或不正确" }; - return false; - } - // 更改名称 - routerInfo.subtitle = listType[typeNum].name; - // 从缓存中获取数据 - let data = await get(cacheKey + listType[typeNum].id); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取网易云音乐排行榜"); - // 从服务器拉取数据 - const response = await axios.get(url + listType[typeNum].id, { headers }); - // console.log(response.data); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey + listType[typeNum].id, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 网易云音乐排行榜 - 获取最新数据 -neteaseMusicRouter.get("/netease_music_toplist/new", async (ctx) => { - console.log("获取网易云音乐排行榜 - 最新数据"); - try { - // 获取参数 - const { type } = ctx.query; - const typeNum = Number(type); - if (!typeNum || typeNum > 4 || typeNum < 1) { - ctx.body = { code: 400, ...routerInfo, message: "参数不完整或不正确" }; - return false; - } - // 更改名称 - routerInfo.subtitle = listType[typeNum].name; - // 从服务器拉取最新数据 - const response = await axios.get(url + listType[typeNum].id, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取网易云音乐排行榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - updateTime, - total: newData.length, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey + listType[typeNum].id); - // 将最新数据写入缓存 - await set(cacheKey + listType[typeNum].id, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -neteaseMusicRouter.info = routerInfo; -module.exports = neteaseMusicRouter; diff --git a/routes/newsqq.js b/routes/newsqq.js deleted file mode 100644 index 402b9781..00000000 --- a/routes/newsqq.js +++ /dev/null @@ -1,124 +0,0 @@ -const Router = require("koa-router"); -const newsqqRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "newsqq", - title: "腾讯新闻", - subtitle: "热点榜", -}; - -// 缓存键名 -const cacheKey = "newsqqData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://r.inews.qq.com/gw/event/hot_ranking_list?page_size=50"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.slice(1).map((v) => { - return { - id: v.id, - title: v.title, - desc: v.abstract, - descSm: v.nlpAbstract, - hot: v.readCount, - pic: v.miniProShareImage, - url: `https://new.qq.com/rain/a/${v.id}`, - mobileUrl: `https://view.inews.qq.com/a/${v.id}`, - }; - }); -}; - -// 腾讯热点榜 -newsqqRouter.get("/newsqq", async (ctx) => { - console.log("获取腾讯热点榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取腾讯热点榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.idlist[0].newslist); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 腾讯热点榜 - 获取最新数据 -newsqqRouter.get("/newsqq/new", async (ctx) => { - console.log("获取腾讯热点榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.idlist[0].newslist); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取腾讯热点榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -newsqqRouter.info = routerInfo; -module.exports = newsqqRouter; diff --git a/routes/ngabbs.js b/routes/ngabbs.js deleted file mode 100644 index da533f9b..00000000 --- a/routes/ngabbs.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @author: x-dr - * @date: 2023-12-25 - * @customEditors: imsyy - * @lastEditTime: 2024-01-02 - */ - -const Router = require("koa-router"); -const ngabbsRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { name: "ngabbs", title: "NGA", subtitle: "论坛热帖" }; - -// 缓存键名 -const cacheKey = "ngabbsData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -const url = - "https://ngabbs.com/nuke.php?__lib=load_topic&__act=load_topic_reply_ladder2&opt=1&all=1"; - -const headers = { - Host: "ngabbs.com", - "Content-Type": "application/x-www-form-urlencoded", - Accept: "*/*", - "Accept-Encoding": "gzip, deflate, br", - Connection: "keep-alive", - "Content-Length": "11", - "User-Agent": "NGA/7.3.1 (iPhone; iOS 17.2.1; Scale/3.00)", - "Accept-Language": "zh-Hans-CN;q=1", - Referer: "https://ngabbs.com/", - "X-User-Agent": "NGA_skull/7.3.1(iPhone13,2;iOS 17.2.1)", -}; -const postData = { __output: "14" }; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - const dataList = []; - try { - const result = data.result[0]; - result.forEach((result) => { - dataList.push({ - author: result.author, - title: result.subject, - parent: result.parent["2"], - tid: result.tid, - comments: Number(result.replies), - url: `https://bbs.nga.cn/read.php?tid=${result.tid}`, - mobileUrl: `https://bbs.nga.cn/read.php?tid=${result.tid}`, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// NGA论坛热帖 -ngabbsRouter.get("/ngabbs", async (ctx) => { - console.log("获取NGA论坛热帖"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取NGA论坛热帖"); - // 从服务器拉取数据 - const response = await axios.post(url, postData, { headers }); - data = getData(response.data); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - message: "获取失败", - }; - } -}); - -// NGA论坛热帖 - 获取最新数据 -ngabbsRouter.get("/ngabbs/new", async (ctx) => { - console.log("获取NGA论坛热帖 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.post(url, postData, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取NGA论坛热帖"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -ngabbsRouter.info = routerInfo; -module.exports = ngabbsRouter; diff --git a/routes/qq_music_toplist.js b/routes/qq_music_toplist.js deleted file mode 100644 index 3c577e65..00000000 --- a/routes/qq_music_toplist.js +++ /dev/null @@ -1,211 +0,0 @@ -/** - * @author: x-dr - * @date: 2023-12-27 - * @customEditors: imsyy - * @lastEditTime: 2024-01-02 - */ - -// const fs = require("fs"); -const Router = require("koa-router"); -const qqMusicRouter = new Router(); -const axios = require("axios"); -const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "qq_music_toplist", - title: "QQ音乐", - subtitle: "排行榜", -}; - -// 缓存键名 -const cacheKey = "qqmusicData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -const url = "https://y.qq.com/n/ryqq/toplist/"; - -const headers = { - authority: "y.qq.com", - referer: "https://www.google.com/", - "user-agent": - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", -}; - -// 榜单类别 -const listType = { - 1: { - id: 62, - name: "飙升榜", - }, - 2: { - id: 26, - name: "热歌榜", - }, - 3: { - id: 27, - name: "新歌榜", - }, - 4: { - id: 4, - name: "流行指数榜", - }, - 5: { - id: 52, - name: "腾讯音乐人原创榜", - }, - 6: { - id: 67, - name: "听歌识曲榜", - }, -}; - -// 数据处理 -const getData = (data) => { - if (!data) return false; - const dataList = []; - const $ = cheerio.load(data); - // fs.writeFileSync('qq.html', $.html()); - try { - $(".songlist__item").each((i, e) => { - const item = cheerio.load($(e).html()); - const title = item('a[class="songlist__cover"]').attr("title"); - const urlPath = item('a[class="songlist__cover"]').attr("href"); - const author = item('div[class="songlist__artist"]') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const songtime = item('div[class="songlist__time"]') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - // const title = item('div[class="f-thide sgtl"]').text().replace(/(^\s*)|(\s*$)/g, "") - dataList.push({ - title: title, - desc: author, - songtime: songtime, - url: `https://y.qq.com${urlPath}`, - mobileUrl: `https://y.qq.com${urlPath}`, - }); - }); - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// 获取QQ音乐排行榜 -qqMusicRouter.get("/qq_music_toplist", async (ctx) => { - console.log("获取QQ音乐排行榜"); - try { - // 获取参数 - const { type } = ctx.query; - const typeNum = Number(type); - if (!typeNum || typeNum > 6 || typeNum < 1) { - ctx.body = { code: 400, ...routerInfo, message: "参数不完整或不正确" }; - return false; - } - // 更改名称 - routerInfo.subtitle = listType[typeNum].name; - // 从缓存中获取数据 - let data = await get(cacheKey + listType[typeNum].id); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新QQ音乐排行榜"); - // 从服务器拉取数据 - const response = await axios.get(url + listType[typeNum].id, { headers }); - // console.log(response.data); - data = getData(response.data); - - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey + listType[typeNum].id, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 获取QQ音乐排行榜 - 获取最新数据 -qqMusicRouter.get("/qq_music_toplist/new", async (ctx) => { - console.log("获取QQ音乐排行榜 - 最新数据"); - try { - // 获取参数 - const { type } = ctx.query; - const typeNum = Number(type); - if (!typeNum || typeNum > 4 || typeNum < 1) { - ctx.body = { code: 400, ...routerInfo, message: "参数不完整或不正确" }; - return false; - } - // 更改名称 - routerInfo.subtitle = listType[typeNum].name; - // 从服务器拉取最新数据 - const response = await axios.get(url + listType[typeNum].id, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新QQ音乐排行榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - updateTime, - total: newData.length, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey + listType[typeNum].id); - // 将最新数据写入缓存 - await set(cacheKey + listType[typeNum].id, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -qqMusicRouter.info = routerInfo; -module.exports = qqMusicRouter; diff --git a/routes/sspai.js b/routes/sspai.js deleted file mode 100644 index 2ea520ad..00000000 --- a/routes/sspai.js +++ /dev/null @@ -1,124 +0,0 @@ -const Router = require("koa-router"); -const sspaiRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "sspai", - title: "少数派", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "sspaiData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = `https://sspai.com/api/v1/article/tag/page/get?limit=40&tag=热门文章`; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.id, - title: v.title, - desc: v.summary, - pic: `https://cdn.sspai.com/${v.banner}`, - owner: v.author, - hot: v.like_count, - url: `https://sspai.com/post/${v.id}`, - mobileUrl: `https://sspai.com/post/${v.itemId}`, - }; - }); -}; - -// 少数派热榜 -sspaiRouter.get("/sspai", async (ctx) => { - console.log("获取少数派热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取少数派热榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 少数派热榜 - 获取最新数据 -sspaiRouter.get("/sspai/new", async (ctx) => { - console.log("获取少数派热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取少数派热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -sspaiRouter.info = routerInfo; -module.exports = sspaiRouter; diff --git a/routes/thepaper.js b/routes/thepaper.js deleted file mode 100644 index 12760c56..00000000 --- a/routes/thepaper.js +++ /dev/null @@ -1,123 +0,0 @@ -const Router = require("koa-router"); -const thepaperRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "thepaper", - title: "澎湃新闻", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "thepaperData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://cache.thepaper.cn/contentapi/wwwIndex/rightSidebar"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.contId, - title: v.name, - pic: v.pic, - hot: v.praiseTimes, - time: v.pubTime, - url: `https://www.thepaper.cn/newsDetail_forward_${v.contId}`, - mobileUrl: `https://m.thepaper.cn/newsDetail_forward_${v.contId}`, - }; - }); -}; - -// 澎湃热榜 -thepaperRouter.get("/thepaper", async (ctx) => { - console.log("获取澎湃热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取澎湃热榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data.hotNews); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 澎湃热榜 - 获取最新数据 -thepaperRouter.get("/thepaper/new", async (ctx) => { - console.log("获取澎湃热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data.hotNews); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取澎湃热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -thepaperRouter.info = routerInfo; -module.exports = thepaperRouter; diff --git a/routes/tieba.js b/routes/tieba.js deleted file mode 100644 index 7c3db5d6..00000000 --- a/routes/tieba.js +++ /dev/null @@ -1,123 +0,0 @@ -const Router = require("koa-router"); -const tiebaRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "tieba", - title: "百度贴吧", - subtitle: "热议榜", -}; - -// 缓存键名 -const cacheKey = "tiebaData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://tieba.baidu.com/hottopic/browse/topicList"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.topic_id, - title: v.topic_name, - desc: v.topic_desc, - pic: v.topic_pic, - hot: v.discuss_num, - url: v.topic_url, - mobileUrl: v.topic_url, - }; - }); -}; - -// 贴吧热议榜 -tiebaRouter.get("/tieba", async (ctx) => { - console.log("获取贴吧热议榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取贴吧热议榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data.bang_topic.topic_list); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 贴吧热议榜 - 获取最新数据 -tiebaRouter.get("/tieba/new", async (ctx) => { - console.log("获取贴吧热议榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data.bang_topic.topic_list); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取贴吧热议榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -tiebaRouter.info = routerInfo; -module.exports = tiebaRouter; diff --git a/routes/toutiao.js b/routes/toutiao.js deleted file mode 100644 index 15ad5688..00000000 --- a/routes/toutiao.js +++ /dev/null @@ -1,122 +0,0 @@ -const Router = require("koa-router"); -const toutiaoRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "toutiao", - title: "今日头条", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "toutiaoData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - return { - id: v.ClusterId, - title: v.Title, - pic: v.Image.url, - hot: v.HotValue, - url: `https://www.toutiao.com/trending/${v.ClusterIdStr}/`, - mobileUrl: `https://api.toutiaoapi.com/feoffline/amos_land/new/html/main/index.html?topic_id=${v.ClusterIdStr}`, - }; - }); -}; - -// 头条热榜 -toutiaoRouter.get("/toutiao", async (ctx) => { - console.log("获取头条热榜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取头条热榜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data); - updateTime = new Date().toISOString(); - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 头条热榜 - 获取最新数据 -toutiaoRouter.get("/toutiao/new", async (ctx) => { - console.log("获取头条热榜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取头条热榜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -toutiaoRouter.info = routerInfo; -module.exports = toutiaoRouter; diff --git a/routes/v2ex.js b/routes/v2ex.js deleted file mode 100644 index 3a60b300..00000000 --- a/routes/v2ex.js +++ /dev/null @@ -1,175 +0,0 @@ -/** - * @author: x-dr - * @date: 2023-12-25 - * @customEditors: imsyy - * @lastEditTime: 2024-01-02 - */ - -const Router = require("koa-router"); -const v2exRouter = new Router(); -const axios = require("axios"); -const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "v2ex", - title: "V2EX", - subtitle: "hot", -}; - -// 缓存键名 -const cacheKey = "v2exData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -const url = "https://www.v2ex.com/?tab=hot"; - -const headers = { - "Content-Type": "application/json", - "User-Agent": - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36", - authority: "www.v2ex.com", - referer: "https://www.v2ex.com/", -}; - -// 数据处理 -const getData = (data) => { - if (!data) return false; - const dataList = []; - const $ = cheerio.load(data); - try { - $(`div[class="cell item"]`).each((i, e) => { - const item = cheerio.load($(e).html()); - const title = item('span[class="item_title"]') - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const href = item(".item_title a").attr("href"); - const url = `https://www.v2ex.com${href}`; - const comments = item(".count_livid") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const member = item(".topic_info strong a:first") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const node = item(".topic_info .node") - .text() - .replace(/(^\s*)|(\s*$)/g, ""); - const avatar_img = item(".avatar").attr("src"); - // console.log( url); - - dataList.push({ - title: title, - url: url, - mobileUrl: url, - comments: comments, - member: member, - node: node, - avatar: avatar_img, - }); - }); - - return dataList; - } catch (error) { - console.error("数据处理出错" + error); - return false; - } -}; - -// v2ex -v2exRouter.get("/v2ex", async (ctx) => { - console.log("获取v2ex"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取v2ex"); - // 从服务器拉取数据 - const response = await axios.get(url, { headers }); - // console.log(response.data); - data = getData(response.data); - - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// v2ex - 获取最新数据 -v2exRouter.get("/v2ex/new", async (ctx) => { - console.log("获取v2ex - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url, { headers }); - const newData = getData(response.data); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取v2ex"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - updateTime, - total: newData.length, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -v2exRouter.info = routerInfo; -module.exports = v2exRouter; diff --git a/routes/weibo.js b/routes/weibo.js deleted file mode 100644 index 262b3ba6..00000000 --- a/routes/weibo.js +++ /dev/null @@ -1,134 +0,0 @@ -const Router = require("koa-router"); -const weiboRouter = new Router(); -const axios = require("axios"); -// const cheerio = require("cheerio"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "weibo", - title: "微博", - subtitle: "热搜榜", -}; - -// 缓存键名 -const cacheKey = "weiboData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://weibo.com/ajax/side/hotSearch"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - // return data; - return data.map((v) => { - const key = v.word_scheme ? v.word_scheme : `#${v.word}`; - return { - title: v.word, - desc: key, - hot: v.raw_hot, - url: `https://s.weibo.com/weibo?q=${encodeURIComponent(key)}&t=31&band_rank=1&Refer=top`, - mobileUrl: `https://s.weibo.com/weibo?q=${encodeURIComponent( - key, - )}&t=31&band_rank=1&Refer=top`, - }; - }); -}; - -// 微博热搜 -weiboRouter.get("/weibo", async (ctx) => { - console.log("获取微博热搜"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取微博热搜"); - // 从服务器拉取数据 - const response = await axios.get(url); - data = getData(response.data.data.realtime); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } -}); - -// 微博热搜 - 获取最新数据 -weiboRouter.get("/weibo/new", async (ctx) => { - console.log("获取微博热搜 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.data.realtime); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取微博热搜"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -weiboRouter.info = routerInfo; -module.exports = weiboRouter; diff --git a/routes/weread.js b/routes/weread.js deleted file mode 100644 index 988752af..00000000 --- a/routes/weread.js +++ /dev/null @@ -1,138 +0,0 @@ -const Router = require("koa-router"); -const wereadRouter = new Router(); -const axios = require("axios"); -const getWereadID = require("../utils/getWereadID"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - name: "weread", - title: "微信读书", - subtitle: "飙升榜", -}; - -// 缓存键名 -const cacheKey = "wereadData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://weread.qq.com/web/bookListInCategory/rising?rank=1"; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - return data.map((v) => { - const book = v.bookInfo; - return { - id: book.bookId, - title: book.title, - desc: book.intro, - pic: book.cover.replace("s_", "t9_"), - hot: v.readingCount, - author: book.author, - url: `https://weread.qq.com/web/bookDetail/${getWereadID(book.bookId)}`, - mobileUrl: `https://weread.qq.com/web/bookDetail/${getWereadID(book.bookId)}`, - }; - }); -}; - -// 微信读书 -wereadRouter.get("/weread", async (ctx) => { - console.log("获取微信读书"); - try { - // 从缓存中获取数据 - let data = await get(cacheKey); - const from = data ? "cache" : "server"; - if (!data) { - // 如果缓存中不存在数据 - console.log("从服务端重新获取微信读书"); - // 从服务器拉取数据 - const response = await axios.get(url, { - Headers: { - "User-Agent": - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.67", - }, - }); - data = getData(response.data.books); - updateTime = new Date().toISOString(); - if (!data) { - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - return false; - } - // 将数据写入缓存 - await set(cacheKey, data); - } - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - from, - total: data.length, - updateTime, - data, - }; - } catch (error) { - console.error(error); - ctx.body = { - code: 500, - message: "获取失败", - }; - } -}); - -// 微信读书 - 获取最新数据 -wereadRouter.get("/weread/new", async (ctx) => { - console.log("获取微信读书 - 最新数据"); - try { - // 从服务器拉取最新数据 - const response = await axios.get(url); - const newData = getData(response.data.books); - updateTime = new Date().toISOString(); - console.log("从服务端重新获取微信读书"); - - // 返回最新数据 - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: newData.length, - updateTime, - data: newData, - }; - - // 删除旧数据 - await del(cacheKey); - // 将最新数据写入缓存 - await set(cacheKey, newData); - } catch (error) { - // 如果拉取最新数据失败,尝试从缓存中获取数据 - console.error(error); - const cachedData = await get(cacheKey); - if (cachedData) { - ctx.body = { - code: 200, - message: "获取成功", - ...routerInfo, - total: cachedData.length, - updateTime, - data: cachedData, - }; - } else { - // 如果缓存中也没有数据,则返回错误信息 - ctx.body = { - code: 500, - ...routerInfo, - message: "获取失败", - }; - } - } -}); - -wereadRouter.info = routerInfo; -module.exports = wereadRouter; diff --git a/routes/zhihu.js b/routes/zhihu.js deleted file mode 100644 index c057cc74..00000000 --- a/routes/zhihu.js +++ /dev/null @@ -1,143 +0,0 @@ -const Router = require("koa-router"); -const zhihuRouter = new Router(); -const axios = require("axios"); -const { get, set, del } = require("../utils/cacheData"); - -// 接口信息 -const routerInfo = { - title: "知乎", - subtitle: "热榜", -}; - -// 缓存键名 -const cacheKey = "zhihuData"; - -// 调用时间 -let updateTime = new Date().toISOString(); - -// 调用路径 -const url = "https://www.zhihu.com/hot"; -const headers = { - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1", -}; - -// 数据处理 -const getData = (data) => { - if (!data) return []; - const dataList = []; - try { - const pattern = / + `} + + ); +}; + +export default Error; diff --git a/src/views/Home.tsx b/src/views/Home.tsx new file mode 100644 index 00000000..9c89f46d --- /dev/null +++ b/src/views/Home.tsx @@ -0,0 +1,60 @@ +import type { FC } from "hono/jsx"; +import { html } from "hono/html"; +import Layout from "./Layout.js"; + +const Home: FC = () => { + return ( + +
+
+ logo +
+
+

DailyHot API

+ 服务已正常运行 +
+
+ + +
+
+ {html` + + `} +
+ ); +}; + +export default Home; diff --git a/src/views/Layout.tsx b/src/views/Layout.tsx new file mode 100644 index 00000000..48bf17e1 --- /dev/null +++ b/src/views/Layout.tsx @@ -0,0 +1,243 @@ +import type { FC } from "hono/jsx"; +import { css, Style } from "hono/css"; + +type LayoutProps = { + title: string; + children: JSX.Element | JSX.Element[]; +}; + +const Layout: FC = (props) => { + const globalClass = css` + :-hono-global { + * { + margin: 0; + padding: 0; + user-select: none; + box-sizing: border-box; + -webkit-user-drag: none; + } + :root { + --text-color: #000; + --text-color-gray: #cbcbcb; + --text-color-hover: #fff; + --icon-color: #444; + } + @media (prefers-color-scheme: dark) { + :root { + --text-color: #fff; + --text-color-gray: #cbcbcb; + --text-color-hover: #3c3c3c; + --icon-color: #cbcbcb; + } + } + a { + text-decoration: none; + color: var(--text-color); + } + body { + width: 100vw; + height: 100vh; + display: flex; + flex-direction: column; + justify-content: space-between; + align-items: center; + color: var(--text-color); + background-color: var(--text-color-hover); + font-family: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei"; + transition: + color 0.3s, + background-color 0.3s; + } + main { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 20px; + margin: 20px; + height: 100%; + } + .img { + width: 120px; + height: 120px; + margin-bottom: 20px; + } + .img img, + .img svg { + width: 100%; + height: 100%; + } + .title { + display: flex; + flex-direction: column; + align-items: center; + margin-bottom: 40px; + } + .title .title-text { + font-size: 28px; + font-weight: bold; + margin-bottom: 12px; + } + .title .title-tip { + font-size: 20px; + opacity: 0.8; + } + .title .content { + margin-top: 30px; + display: flex; + padding: 20px; + border-radius: 12px; + border: 1px dashed var(--text-color); + } + .control { + display: flex; + flex-direction: row; + align-items: center; + } + .control button { + display: flex; + flex-direction: row; + align-items: center; + color: var(--text-color); + border: var(--text-color) solid; + background-color: var(--text-color-hover); + border-radius: 8px; + padding: 8px 12px; + margin: 0 8px; + transition: + color 0.3s, + background-color 0.3s; + cursor: pointer; + } + .control button .btn-icon { + width: 22px; + height: 22px; + margin-right: 8px; + } + .control button .btn-text { + font-size: 14px; + } + .control button:hover { + border: var(--text-color) solid; + background: var(--text-color); + color: var(--text-color-hover); + } + .control button i { + margin-right: 6px; + } + footer { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + line-height: 30px; + padding: 20px; + } + .social { + display: flex; + flex-direction: row; + align-items: center; + margin-bottom: 8px; + } + .social .link { + display: flex; + flex-direction: row; + align-items: center; + margin: 0 4px; + } + .social .link::after { + content: ""; + width: 4px; + height: 4px; + border-radius: 50%; + background-color: var(--text-color); + opacity: 0.4; + margin-left: 8px; + } + .social .link:last-child::after { + display: none; + } + .social .link svg { + width: 22px; + height: 22px; + } + footer .power, + footer .icp { + font-size: 14px; + } + footer a { + color: var(--text-color-gray); + transition: color 0.3s; + } + footer a:hover { + color: var(--text-color); + } + } + `; + return ( + + + + + {props.title} + + + + + + {props.children} + + + + ); +}; + +export default Layout; diff --git a/src/views/NotFound.tsx b/src/views/NotFound.tsx new file mode 100644 index 00000000..e87d831f --- /dev/null +++ b/src/views/NotFound.tsx @@ -0,0 +1,44 @@ +import type { FC } from "hono/jsx"; +import { html } from "hono/html"; +import Layout from "./Layout.js"; + +const NotFound: FC = () => { + return ( + +
+
+ + + +
+
+

404 Not Found

+ 请检查您的路径 +
+
+ +
+
+ {html` + + `} +
+ ); +}; + +export default NotFound; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..f42512fe --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": false, + "types": ["node"], + "jsx": "react-jsx", + "jsxImportSource": "hono/jsx", + "outDir": "./dist" + }, + "exclude": ["node_modules", "*.test.*"] +} diff --git a/utils/cacheData.js b/utils/cacheData.js deleted file mode 100644 index 749e3e75..00000000 --- a/utils/cacheData.js +++ /dev/null @@ -1,41 +0,0 @@ -const NodeCache = require("node-cache"); - -const cache = new NodeCache({ - stdTTL: 1800, // 缓存默认过期时间(单位秒) - checkperiod: 60, // 定期检查过期缓存的时间(单位秒) -}); - -/** - * 从缓存中获取数据 - * @param {string} key 缓存键值 - * @return {Promise} 数据 - */ -const get = async (key) => { - return cache.get(key); -}; - -/** - * 将数据写入缓存 - * @param {string} key 缓存键值 - * @param {any} value 数据 - * @param {number} ttl 有效期,单位秒,默认为300秒 - * @return {Promise} 无返回值 - */ -const set = async (key, value, ttl = 300) => { - return cache.set(key, value, ttl); -}; - -/** - * 从缓存中删除数据 - * @param {string} key 缓存键值 - * @return {Promise} 无返回值 - */ -const del = async (key) => { - return cache.del(key); -}; - -module.exports = { - get, - set, - del, -}; diff --git a/vercel.json b/vercel.json deleted file mode 100644 index b7c63c4b..00000000 --- a/vercel.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": 2, - "builds": [ - { - "src": "./index.js", - "use": "@vercel/node" - } - ], - "routes": [ - { - "src": "/(.*)", - "dest": "/", - "headers": { - "Access-Control-Allow-Credentials": "true", - "Access-Control-Allow-Origin": "*", - "Access-Control-Allow-Methods": "GET,OPTIONS,PATCH,DELETE,POST,PUT", - "Access-Control-Allow-Headers": "X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version" - } - } - ] -}