diff --git a/.env.example b/.env.example index acf4c6c..570f73b 100644 --- a/.env.example +++ b/.env.example @@ -21,7 +21,4 @@ REQUEST_TIMEOUT=6000 USE_LOG_FILE=true # RSS Mode -RSS_MODE=false - -# Puppeteer -USE_PUPPETEER=false \ No newline at end of file +RSS_MODE=false \ No newline at end of file diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index b8d65a8..db50546 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -43,7 +43,7 @@ jobs: imsyy/dailyhot-api ghcr.io/${{ github.repository }} - - name: Build and push regular image (no Puppeteer) + - name: Build and push regular image uses: docker/build-push-action@v5 with: context: . @@ -54,18 +54,3 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - - - name: Build and push Puppeteer image (with Puppeteer) - uses: docker/build-push-action@v5 - with: - context: . - file: ./Dockerfile - platforms: | - linux/amd64 - linux/arm64 - push: true - tags: imsyy/dailyhot-api:web-latest - build-args: | - USE_PUPPETEER=true - labels: ${{ steps.meta.outputs.labels }} - diff --git a/Dockerfile b/Dockerfile index 6eb0096..ffe2acf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,24 +2,6 @@ FROM node:20-alpine AS base ENV NODE_ENV=docker -# 安装 Puppeteer 所需的依赖库 -RUN apk add --no-cache \ - libc6-compat \ - nss \ - freetype \ - harfbuzz \ - ca-certificates - -# 判断是否需要安装 Chromium -ARG USE_PUPPETEER=false -RUN if [ "$USE_PUPPETEER" = "true" ]; then \ - apk add --no-cache chromium; \ - fi - -# 配置 Chromium -ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true -ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium-browser - # 清理缓存 RUN rm -rf /var/cache/apk/* @@ -33,12 +15,10 @@ COPY package*json tsconfig.json pnpm-lock.yaml .env.example ./ COPY src ./src COPY public ./public -# add .env.example to .env +# 复制环境变量 RUN [ ! -e ".env" ] && cp .env.example .env || true -RUN if [ "$USE_PUPPETEER" = "true" ]; then \ - sed -i 's/^USE_PUPPETEER=false/USE_PUPPETEER=true/' .env; \ - fi +# 安装依赖 RUN pnpm install RUN pnpm build RUN pnpm prune --production diff --git a/README.md b/README.md index c1c187d..4cc7a4c 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@
查看全部接口 -> 实例站点运行于海外服务器,部分国内站点可能存在访问异常,请以实际情况为准 +> 示例站点运行于海外服务器,部分国内站点可能存在访问异常,请以实际情况为准 | **站点** | **类别** | **调用名称** | **状态** | | ---------------- | ------------ | -------------- | --------------------------------------------------------------------------------------------------------------------------- | @@ -41,6 +41,7 @@ | 知乎日报 | 推荐榜 | zhihu-daily | ![](https://img.shields.io/website.svg?label=zhihu-daily&url=https://api-hot.imsyy.top/zhihu-daily&cacheSeconds=7200) | | 百度 | 热搜榜 | baidu | ![](https://img.shields.io/website.svg?label=baidu&url=https://api-hot.imsyy.top/baidu&cacheSeconds=7200) | | 抖音 | 热点榜 | douyin | ![](https://img.shields.io/website.svg?label=douyin&url=https://api-hot.imsyy.top/douyin&cacheSeconds=7200) | +| 快手 | 热点榜 | kuaishou | ![](https://img.shields.io/website.svg?label=kuaishou&url=https://api-hot.imsyy.top/kuaishou&cacheSeconds=7200) | | 豆瓣电影 | 新片榜 | douban-movie | ![](https://img.shields.io/website.svg?label=douban-movie&url=https://api-hot.imsyy.top/douban-movie&cacheSeconds=7200) | | 豆瓣讨论小组 | 讨论精选 | douban-group | ![](https://img.shields.io/website.svg?label=douban-group&url=https://api-hot.imsyy.top/douban-group&cacheSeconds=7200) | | 百度贴吧 | 热议榜 | tieba | ![](https://img.shields.io/website.svg?label=tieba&url=https://api-hot.imsyy.top/tieba&cacheSeconds=7200) | @@ -48,6 +49,7 @@ | IT之家 | 热榜 | ithome | ![](https://img.shields.io/website.svg?label=ithome&url=https://api-hot.imsyy.top/ithome&cacheSeconds=7200) | | IT之家「喜加一」 | 最新动态 | ithome-xijiayi | ![](https://img.shields.io/website.svg?label=ithome-xijiayi&url=https://api-hot.imsyy.top/ithome-xijiayi&cacheSeconds=7200) | | 简书 | 热门推荐 | jianshu | ![](https://img.shields.io/website.svg?label=jianshu&url=https://api-hot.imsyy.top/jianshu&cacheSeconds=7200) | +| 果壳 | 热门文章 | guokr | ![](https://img.shields.io/website.svg?label=guokr&url=https://api-hot.imsyy.top/guokr&cacheSeconds=7200) | | 澎湃新闻 | 热榜 | thepaper | ![](https://img.shields.io/website.svg?label=thepaper&url=https://api-hot.imsyy.top/thepaper&cacheSeconds=7200) | | 今日头条 | 热榜 | toutiao | ![](https://img.shields.io/website.svg?label=toutiao&url=https://api-hot.imsyy.top/toutiao&cacheSeconds=7200) | | 36 氪 | 热榜 | 36kr | ![](https://img.shields.io/website.svg?label=36kr&url=https://api-hot.imsyy.top/36kr&cacheSeconds=7200) | @@ -66,7 +68,7 @@ | 虎扑 | 步行街热帖 | hupu | ![](https://img.shields.io/website.svg?label=hupu&url=https://api-hot.imsyy.top/hupu&cacheSeconds=7200) | | 爱范儿 | 快讯 | ifanr | ![](https://img.shields.io/website.svg?label=ifanr&url=https://api-hot.imsyy.top/ifanr&cacheSeconds=7200) | | 英雄联盟 | 更新公告 | lol | ![](https://img.shields.io/website.svg?label=lol&url=https://api-hot.imsyy.top/lol&cacheSeconds=7200) | -| 米游社 | 最新消息 | miyoushe | ![](https://img.shields.io/website.svg?label=miyoushe&url=https://api-hot.imsyy.top/miyoushe&cacheSeconds=7200) | +| 米游社 | 最新消息 | miyoushe | ![](https://img.shields.io/website.svg?label=miyoushe&url=https://api-hot.imsyy.top/miyoushe&cacheSeconds=7200) | | 原神 | 最新消息 | genshin | ![](https://img.shields.io/website.svg?label=genshin&url=https://api-hot.imsyy.top/genshin&cacheSeconds=7200) | | 崩坏3 | 最新动态 | honkai | ![](https://img.shields.io/website.svg?label=honkai&url=https://api-hot.imsyy.top/honkai&cacheSeconds=7200) | | 崩坏:星穹铁道 | 最新动态 | starrail | ![](https://img.shields.io/website.svg?label=starrail&url=https://api-hot.imsyy.top/starrail&cacheSeconds=7200) | @@ -103,8 +105,6 @@ serveHotApi(3000); ## ⚙️ 部署 -由于部分接口无法通过接口调用等方式获取数据,故采用 `Puppeteer` 来实现,但由于使用后会造成 **内存占用过大或镜像过大**,可选择性开启,详情请参考下方说明。 - 具体使用说明可参考 [我的博客](https://blog.imsyy.top/posts/2024/0408),下方仅讲解基础操作: ### Docker 部署 @@ -116,8 +116,6 @@ serveHotApi(3000); ```bash # 构建 docker build -t dailyhot-api . -# 构建 Puppeteer 版 -docker build --build-arg USE_PUPPETEER=true -t dailyhot-api . # 运行 docker run --restart always -p 6688:6688 -d dailyhot-api @@ -130,8 +128,6 @@ docker-compose up -d ```bash # 拉取 docker pull imsyy/dailyhot-api:latest -# 拉取 Puppeteer 版 -docker pull imsyy/dailyhot-api:web-latest # 运行 docker run --restart always -p 6688:6688 -d imsyy/dailyhot-api:latest @@ -139,7 +135,7 @@ docker run --restart always -p 6688:6688 -d imsyy/dailyhot-api:latest ### 手动部署 -最直接的方式,您可以按照以下步骤将 DailyHotApi 部署在您的电脑、服务器或者其他任何地方 +最直接的方式,您可以按照以下步骤将 `DailyHotApi` 部署在您的电脑、服务器或者其他任何地方 #### 安装 @@ -159,10 +155,7 @@ npm install #### 开发 ```bash -# 标准运行 npm run dev -# 采用 Puppeteer 运行 -npm run dev:web ``` 成功启动后程序会在控制台输出可访问的地址 @@ -171,11 +164,7 @@ npm run dev:web ```bash npm run build - -# 标准运行 npm run start -# 采用 Puppeteer 运行 -npm run start:web ``` 成功启动后程序会在控制台输出可访问的地址 diff --git a/package.json b/package.json index 43d22a4..cd32022 100644 --- a/package.json +++ b/package.json @@ -30,11 +30,9 @@ "format": "prettier --write .", "lint": "eslint .", "dev": "cross-env NODE_ENV=development tsx watch --no-cache src/index.ts", - "dev:web": "cross-env NODE_ENV=development USE_PUPPETEER=true tsx watch --no-cache src/index.ts", "dev:cache": "cross-env NODE_ENV=development tsx watch src/index.ts", "build": "tsc --project tsconfig.json", - "start": "cross-env NODE_ENV=development tsx dist/index.js", - "start:web": "cross-env NODE_ENV=development USE_PUPPETEER=true tsx dist/index.js" + "start": "cross-env NODE_ENV=development tsx dist/index.js" }, "type": "module", "dependencies": { @@ -46,18 +44,18 @@ "dotenv": "^16.4.6", "feed": "^4.2.2", "hono": "^4.6.12", + "iconv-lite": "^0.6.3", "md5": "^2.3.0", "node-cache": "^5.1.2", - "puppeteer": "^23.10.0", - "puppeteer-cluster": "^0.24.0", "rss-parser": "^3.13.0", - "winston": "^3.17.0", - "xml2js": "^0.6.2" + "user-agents": "^1.1.379", + "winston": "^3.17.0" }, "devDependencies": { "@eslint/js": "^9.16.0", "@types/md5": "^2.3.5", "@types/node": "^22.10.1", + "@types/user-agents": "^1.0.4", "@types/xml2js": "^0.4.14", "@typescript-eslint/eslint-plugin": "^8.17.0", "@typescript-eslint/parser": "^8.17.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e08a49d..9b85d44 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -32,27 +32,24 @@ importers: hono: specifier: ^4.6.12 version: 4.6.12 + iconv-lite: + specifier: ^0.6.3 + version: 0.6.3 md5: specifier: ^2.3.0 version: 2.3.0 node-cache: specifier: ^5.1.2 version: 5.1.2 - puppeteer: - specifier: ^23.10.0 - version: 23.10.0(typescript@5.7.2) - puppeteer-cluster: - specifier: ^0.24.0 - version: 0.24.0(puppeteer@23.10.0(typescript@5.7.2)) rss-parser: specifier: ^3.13.0 version: 3.13.0 + user-agents: + specifier: ^1.1.379 + version: 1.1.379 winston: specifier: ^3.17.0 version: 3.17.0 - xml2js: - specifier: ^0.6.2 - version: 0.6.2 devDependencies: '@eslint/js': specifier: ^9.16.0 @@ -63,6 +60,9 @@ importers: '@types/node': specifier: ^22.10.1 version: 22.10.1 + '@types/user-agents': + specifier: ^1.0.4 + version: 1.0.4 '@types/xml2js': specifier: ^0.4.14 version: 0.4.14 @@ -96,14 +96,6 @@ importers: packages: - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - '@colors/colors@1.6.0': resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} engines: {node: '>=0.1.90'} @@ -327,14 +319,6 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} - '@puppeteer/browsers@2.5.0': - resolution: {integrity: sha512-6TQAc/5uRILE6deixJ1CR8rXyTbzXIXNgO1D0Woi9Bqicz2FV5iKP3BHYEg6o4UATCMcbQQ0jbmeaOkn/HQk2w==} - engines: {node: '>=18'} - hasBin: true - - '@tootallnate/quickjs-emscripten@0.23.0': - resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} - '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} @@ -350,12 +334,12 @@ packages: '@types/triple-beam@1.3.5': resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/user-agents@1.0.4': + resolution: {integrity: sha512-AjeFc4oX5WPPflgKfRWWJfkEk7Wu82fnj1rROPsiqFt6yElpdGFg8Srtm/4PU4rA9UiDUZlruGPgcwTMQlwq4w==} + '@types/xml2js@0.4.14': resolution: {integrity: sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==} - '@types/yauzl@2.10.3': - resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} - '@typescript-eslint/eslint-plugin@8.17.0': resolution: {integrity: sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -428,17 +412,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - agent-base@7.1.1: - resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} - engines: {node: '>= 14'} - ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - ansi-styles@4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} @@ -446,10 +422,6 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - ast-types@0.13.4: - resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} - engines: {node: '>=4'} - async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} @@ -459,34 +431,9 @@ packages: axios@1.7.8: resolution: {integrity: sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==} - b4a@1.6.7: - resolution: {integrity: sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==} - balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - bare-events@2.5.0: - resolution: {integrity: sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==} - - bare-fs@2.3.5: - resolution: {integrity: sha512-SlE9eTxifPDJrT6YgemQ1WGFleevzwY+XAP1Xqgl56HtcrisC2CHCZ2tq6dBpcH2TnNxwUEUGhweo+lrQtYuiw==} - - bare-os@2.4.4: - resolution: {integrity: sha512-z3UiI2yi1mK0sXeRdc4O1Kk8aOa/e+FNWZcTiPB/dfTWyLypuE99LibgRaQki914Jq//yAWylcAt+mknKdixRQ==} - - bare-path@2.1.3: - resolution: {integrity: sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==} - - bare-stream@2.4.2: - resolution: {integrity: sha512-XZ4ln/KV4KT+PXdIWTKjsLY+quqCaEtqqtgGJVPw9AoM73By03ij64YjepK0aQvHSWDb6AfAZwqKaFu68qkrdA==} - - base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - basic-ftp@5.0.5: - resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} - engines: {node: '>=10.0.0'} - boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} @@ -500,12 +447,6 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} - buffer-crc32@0.2.13: - resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} - - buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} @@ -528,15 +469,6 @@ packages: resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==} engines: {node: '>=18.17'} - chromium-bidi@0.8.0: - resolution: {integrity: sha512-uJydbGdTw0DEUjhoogGveneJVWX/9YuqkWePzMmkBYwtdAqo5d3J/ovNKFr+/2hWXYmYCr6it8mSSTIj6SS6Ug==} - peerDependencies: - devtools-protocol: '*' - - cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - clone@2.1.2: resolution: {integrity: sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==} engines: {node: '>=0.8'} @@ -570,15 +502,6 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - cosmiconfig@9.0.0: - resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - cross-env@7.0.3: resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} @@ -598,10 +521,6 @@ packages: resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} engines: {node: '>= 6'} - data-uri-to-buffer@6.0.2: - resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} - engines: {node: '>= 14'} - dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} @@ -617,17 +536,10 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - degenerator@5.0.1: - resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} - engines: {node: '>= 14'} - delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - devtools-protocol@0.0.1367902: - resolution: {integrity: sha512-XxtPuC3PGakY6PD7dG66/o8KwJ/LkH2/EKe19Dcw58w53dv4/vSQEkn/SzuyhHE2q4zPgCkxQBxus3VV4ql+Pg==} - dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -645,18 +557,12 @@ packages: resolution: {integrity: sha512-JhcR/+KIjkkjiU8yEpaB/USlzVi3i5whwOjpIRNGi9svKEXZSe+Qp6IWAjFjv+2GViAoDRCUv/QLNziQxsLqDg==} engines: {node: '>=12'} - emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - enabled@2.0.0: resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} encoding-sniffer@0.2.0: resolution: {integrity: sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==} - end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - entities@2.2.0: resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} @@ -664,31 +570,15 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - esbuild@0.23.1: resolution: {integrity: sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==} engines: {node: '>=18'} hasBin: true - escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - escape-string-regexp@4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - escodegen@2.1.0: - resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} - engines: {node: '>=6.0'} - hasBin: true - eslint-scope@8.2.0: resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -715,11 +605,6 @@ packages: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} @@ -736,17 +621,9 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} - extract-zip@2.0.1: - resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} - engines: {node: '>= 10.17.0'} - hasBin: true - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - fast-fifo@1.3.2: - resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -760,9 +637,6 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - fd-slicer@1.1.0: - resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} - fecha@4.2.3: resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} @@ -805,30 +679,14 @@ packages: resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} engines: {node: '>= 6'} - fs-extra@11.2.0: - resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} - engines: {node: '>=14.14'} - fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] - get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - - get-stream@5.2.0: - resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} - engines: {node: '>=8'} - get-tsconfig@4.8.1: resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} - get-uri@6.0.3: - resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==} - engines: {node: '>= 14'} - glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -845,9 +703,6 @@ packages: resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} engines: {node: '>=18'} - graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - graphemer@1.4.0: resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} @@ -862,21 +717,10 @@ packages: htmlparser2@9.1.0: resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} - http-proxy-agent@7.0.2: - resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} - engines: {node: '>= 14'} - - https-proxy-agent@7.0.5: - resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} - engines: {node: '>= 14'} - iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} - ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -892,13 +736,6 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - - is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -909,10 +746,6 @@ packages: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} - is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - is-glob@4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} @@ -928,31 +761,19 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true - jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -963,13 +784,13 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} - lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - locate-path@6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + lodash.clonedeep@4.5.0: + resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} @@ -977,10 +798,6 @@ packages: resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} engines: {node: '>= 12.0.0'} - lru-cache@7.18.3: - resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} - engines: {node: '>=12'} - md5@2.3.0: resolution: {integrity: sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==} @@ -1007,19 +824,12 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} - mitt@3.0.1: - resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} - ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - netmask@2.0.2: - resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} - engines: {node: '>= 0.4.0'} - node-cache@5.1.2: resolution: {integrity: sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==} engines: {node: '>= 8.0.0'} @@ -1027,9 +837,6 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - one-time@1.0.0: resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} @@ -1045,22 +852,10 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} - pac-proxy-agent@7.0.2: - resolution: {integrity: sha512-BFi3vZnO9X5Qt6NRz7ZOaPja3ic0PhlsmCRYLOpN11+mWBCR6XJDqW5RF3j8jm4WGGQZtBA+bTfxYzeKW73eHg==} - engines: {node: '>= 14'} - - pac-resolver@7.0.1: - resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} - engines: {node: '>= 14'} - parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} - parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - parse5-htmlparser2-tree-adapter@7.1.0: resolution: {integrity: sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==} @@ -1078,12 +873,6 @@ packages: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} - pend@1.2.0: - resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - - picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} @@ -1097,52 +886,20 @@ packages: engines: {node: '>=14'} hasBin: true - progress@2.0.3: - resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} - engines: {node: '>=0.4.0'} - - proxy-agent@6.4.0: - resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==} - engines: {node: '>= 14'} - proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - pump@3.0.2: - resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} - punycode@2.3.1: resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} engines: {node: '>=6'} - puppeteer-cluster@0.24.0: - resolution: {integrity: sha512-zHPoNsrwkFLKFtgJJv2aC13EbMASQsE048uZd7CyikEXcl+sc1Nf6PMFb9kMoZI7/zMYxvuP658o2mw079ZZyQ==} - peerDependencies: - puppeteer: '>=22.0.0' - - puppeteer-core@23.10.0: - resolution: {integrity: sha512-7pv6kFget4Iki0RLBDowi35vaccz73XpC6/FAnfCrYa2IXVUlBHfZw+HGWzlvvTGwM9HHd32rgCrIDzil3kj+w==} - engines: {node: '>=18'} - - puppeteer@23.10.0: - resolution: {integrity: sha512-vLpEvUM8POKBX4j6y/yyD4oGRhS1oBAbMn3lYpz1yeakhRsA8IhF5QmjXwAIQYGdR/INxyFiY6kQDoUtLGDP3g==} - engines: {node: '>=18'} - hasBin: true - queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - queue-tick@1.0.1: - resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} - readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} - require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} @@ -1189,42 +946,12 @@ packages: simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - - socks-proxy-agent@8.0.4: - resolution: {integrity: sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==} - engines: {node: '>= 14'} - - socks@2.8.3: - resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - - source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - - sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - stack-trace@0.0.10: resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} - streamx@2.20.2: - resolution: {integrity: sha512-aDGDLU+j9tJcUdPGOaHmVF1u/hhI+CsGkT02V3OKlHDV7IukOI+nTWAGkiZEKCO35rWN1wIr4tS7YFr1f4qSvA==} - - string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -1233,21 +960,9 @@ packages: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} - tar-fs@3.0.6: - resolution: {integrity: sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==} - - tar-stream@3.1.7: - resolution: {integrity: sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==} - - text-decoder@1.2.1: - resolution: {integrity: sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==} - text-hex@1.0.0: resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} - through@2.3.8: - resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -1262,9 +977,6 @@ packages: peerDependencies: typescript: '>=4.2.0' - tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - tsx@4.19.2: resolution: {integrity: sha512-pOUl6Vo2LUq/bSa8S5q7b91cgNSjctn9ugq/+Mvow99qW6x/UZYwzxy/3NmqoT66eHYfCVvFvACC58UBPFf28g==} engines: {node: '>=18.0.0'} @@ -1274,9 +986,6 @@ packages: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} - typed-query-selector@2.12.0: - resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==} - typescript-eslint@8.17.0: resolution: {integrity: sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1292,9 +1001,6 @@ packages: engines: {node: '>=14.17'} hasBin: true - unbzip2-stream@1.4.3: - resolution: {integrity: sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==} - undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} @@ -1302,15 +1008,11 @@ packages: resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==} engines: {node: '>=18.17'} - universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - urlpattern-polyfill@10.0.0: - resolution: {integrity: sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==} + user-agents@1.1.379: + resolution: {integrity: sha512-f5W4mw2SraLUnaiRBxL+FKqL7kuQtJGdUz9BoRUcKRIKuHL9eYeigT7Idit/SRDMR7bJ7fd2HGqfWzHnmhgPZw==} util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -1340,25 +1042,6 @@ packages: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} - wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - - wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - ws@8.18.0: - resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - xml-js@1.6.11: resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==} hasBin: true @@ -1367,46 +1050,16 @@ packages: resolution: {integrity: sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==} engines: {node: '>=4.0.0'} - xml2js@0.6.2: - resolution: {integrity: sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==} - engines: {node: '>=4.0.0'} - xmlbuilder@11.0.1: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'} - y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - - yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - - yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - - yauzl@2.10.0: - resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} - yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - snapshots: - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - - '@babel/helper-validator-identifier@7.25.9': {} - '@colors/colors@1.6.0': {} '@dabh/diagnostics@2.0.3': @@ -1555,21 +1208,6 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.17.1 - '@puppeteer/browsers@2.5.0': - dependencies: - debug: 4.3.7 - extract-zip: 2.0.1 - progress: 2.0.3 - proxy-agent: 6.4.0 - semver: 7.6.3 - tar-fs: 3.0.6 - unbzip2-stream: 1.4.3 - yargs: 17.7.2 - transitivePeerDependencies: - - supports-color - - '@tootallnate/quickjs-emscripten@0.23.0': {} - '@types/estree@1.0.6': {} '@types/json-schema@7.0.15': {} @@ -1582,15 +1220,12 @@ snapshots: '@types/triple-beam@1.3.5': {} + '@types/user-agents@1.0.4': {} + '@types/xml2js@0.4.14': dependencies: '@types/node': 22.10.1 - '@types/yauzl@2.10.3': - dependencies: - '@types/node': 22.10.1 - optional: true - '@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2)': dependencies: '@eslint-community/regexpp': 4.12.1 @@ -1679,12 +1314,6 @@ snapshots: acorn@8.14.0: {} - agent-base@7.1.1: - dependencies: - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - ajv@6.12.6: dependencies: fast-deep-equal: 3.1.3 @@ -1692,18 +1321,12 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 - ansi-regex@5.0.1: {} - ansi-styles@4.3.0: dependencies: color-convert: 2.0.1 argparse@2.0.1: {} - ast-types@0.13.4: - dependencies: - tslib: 2.8.1 - async@3.2.6: {} asynckit@0.4.0: {} @@ -1716,37 +1339,8 @@ snapshots: transitivePeerDependencies: - debug - b4a@1.6.7: {} - balanced-match@1.0.2: {} - bare-events@2.5.0: - optional: true - - bare-fs@2.3.5: - dependencies: - bare-events: 2.5.0 - bare-path: 2.1.3 - bare-stream: 2.4.2 - optional: true - - bare-os@2.4.4: - optional: true - - bare-path@2.1.3: - dependencies: - bare-os: 2.4.4 - optional: true - - bare-stream@2.4.2: - dependencies: - streamx: 2.20.2 - optional: true - - base64-js@1.5.1: {} - - basic-ftp@5.0.5: {} - boolbase@1.0.0: {} brace-expansion@1.1.11: @@ -1762,13 +1356,6 @@ snapshots: dependencies: fill-range: 7.1.1 - buffer-crc32@0.2.13: {} - - buffer@5.7.1: - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - callsites@3.1.0: {} chalk@4.1.2: @@ -1803,19 +1390,6 @@ snapshots: undici: 6.21.0 whatwg-mimetype: 4.0.0 - chromium-bidi@0.8.0(devtools-protocol@0.0.1367902): - dependencies: - devtools-protocol: 0.0.1367902 - mitt: 3.0.1 - urlpattern-polyfill: 10.0.0 - zod: 3.23.8 - - cliui@8.0.1: - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - clone@2.1.2: {} color-convert@1.9.3: @@ -1851,15 +1425,6 @@ snapshots: concat-map@0.0.1: {} - cosmiconfig@9.0.0(typescript@5.7.2): - dependencies: - env-paths: 2.2.1 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - optionalDependencies: - typescript: 5.7.2 - cross-env@7.0.3: dependencies: cross-spawn: 7.0.6 @@ -1882,8 +1447,6 @@ snapshots: css-what@6.1.0: {} - data-uri-to-buffer@6.0.2: {} - dayjs@1.11.13: {} debug@4.3.7: @@ -1892,16 +1455,8 @@ snapshots: deep-is@0.1.4: {} - degenerator@5.0.1: - dependencies: - ast-types: 0.13.4 - escodegen: 2.1.0 - esprima: 4.0.1 - delayed-stream@1.0.0: {} - devtools-protocol@0.0.1367902: {} - dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -1922,8 +1477,6 @@ snapshots: dotenv@16.4.6: {} - emoji-regex@8.0.0: {} - enabled@2.0.0: {} encoding-sniffer@0.2.0: @@ -1931,20 +1484,10 @@ snapshots: iconv-lite: 0.6.3 whatwg-encoding: 3.1.1 - end-of-stream@1.4.4: - dependencies: - once: 1.4.0 - entities@2.2.0: {} entities@4.5.0: {} - env-paths@2.2.1: {} - - error-ex@1.3.2: - dependencies: - is-arrayish: 0.2.1 - esbuild@0.23.1: optionalDependencies: '@esbuild/aix-ppc64': 0.23.1 @@ -1972,18 +1515,8 @@ snapshots: '@esbuild/win32-ia32': 0.23.1 '@esbuild/win32-x64': 0.23.1 - escalade@3.2.0: {} - escape-string-regexp@4.0.0: {} - escodegen@2.1.0: - dependencies: - esprima: 4.0.1 - estraverse: 5.3.0 - esutils: 2.0.3 - optionalDependencies: - source-map: 0.6.1 - eslint-scope@8.2.0: dependencies: esrecurse: 4.3.0 @@ -2038,8 +1571,6 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.14.0) eslint-visitor-keys: 4.2.0 - esprima@4.0.1: {} - esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -2052,20 +1583,8 @@ snapshots: esutils@2.0.3: {} - extract-zip@2.0.1: - dependencies: - debug: 4.3.7 - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.3 - transitivePeerDependencies: - - supports-color - fast-deep-equal@3.1.3: {} - fast-fifo@1.3.2: {} - fast-glob@3.3.2: dependencies: '@nodelib/fs.stat': 2.0.5 @@ -2082,10 +1601,6 @@ snapshots: dependencies: reusify: 1.0.4 - fd-slicer@1.1.0: - dependencies: - pend: 1.2.0 - fecha@4.2.3: {} feed@4.2.2: @@ -2122,34 +1637,13 @@ snapshots: combined-stream: 1.0.8 mime-types: 2.1.35 - fs-extra@11.2.0: - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - fsevents@2.3.3: optional: true - get-caller-file@2.0.5: {} - - get-stream@5.2.0: - dependencies: - pump: 3.0.2 - get-tsconfig@4.8.1: dependencies: resolve-pkg-maps: 1.0.0 - get-uri@6.0.3: - dependencies: - basic-ftp: 5.0.5 - data-uri-to-buffer: 6.0.2 - debug: 4.3.7 - fs-extra: 11.2.0 - transitivePeerDependencies: - - supports-color - glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -2162,8 +1656,6 @@ snapshots: globals@15.13.0: {} - graceful-fs@4.2.11: {} - graphemer@1.4.0: {} has-flag@4.0.0: {} @@ -2177,26 +1669,10 @@ snapshots: domutils: 3.1.0 entities: 4.5.0 - http-proxy-agent@7.0.2: - dependencies: - agent-base: 7.1.1 - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - - https-proxy-agent@7.0.5: - dependencies: - agent-base: 7.1.1 - debug: 4.3.7 - transitivePeerDependencies: - - supports-color - iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 - ieee754@1.2.1: {} - ignore@5.3.2: {} import-fresh@3.3.0: @@ -2208,21 +1684,12 @@ snapshots: inherits@2.0.4: {} - ip-address@9.0.5: - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - - is-arrayish@0.2.1: {} - is-arrayish@0.3.2: {} is-buffer@1.1.6: {} is-extglob@2.1.1: {} - is-fullwidth-code-point@3.0.0: {} - is-glob@4.0.3: dependencies: is-extglob: 2.1.1 @@ -2233,28 +1700,16 @@ snapshots: isexe@2.0.0: {} - js-tokens@4.0.0: {} - js-yaml@4.1.0: dependencies: argparse: 2.0.1 - jsbn@1.1.0: {} - json-buffer@3.0.1: {} - json-parse-even-better-errors@2.3.1: {} - json-schema-traverse@0.4.1: {} json-stable-stringify-without-jsonify@1.0.1: {} - jsonfile@6.1.0: - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -2266,12 +1721,12 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 - lines-and-columns@1.2.4: {} - locate-path@6.0.0: dependencies: p-locate: 5.0.0 + lodash.clonedeep@4.5.0: {} + lodash.merge@4.6.2: {} logform@2.7.0: @@ -2283,8 +1738,6 @@ snapshots: safe-stable-stringify: 2.5.0 triple-beam: 1.4.1 - lru-cache@7.18.3: {} - md5@2.3.0: dependencies: charenc: 0.0.2 @@ -2312,14 +1765,10 @@ snapshots: dependencies: brace-expansion: 2.0.1 - mitt@3.0.1: {} - ms@2.1.3: {} natural-compare@1.4.0: {} - netmask@2.0.2: {} - node-cache@5.1.2: dependencies: clone: 2.1.2 @@ -2328,10 +1777,6 @@ snapshots: dependencies: boolbase: 1.0.0 - once@1.4.0: - dependencies: - wrappy: 1.0.2 - one-time@1.0.0: dependencies: fn.name: 1.1.0 @@ -2353,35 +1798,10 @@ snapshots: dependencies: p-limit: 3.1.0 - pac-proxy-agent@7.0.2: - dependencies: - '@tootallnate/quickjs-emscripten': 0.23.0 - agent-base: 7.1.1 - debug: 4.3.7 - get-uri: 6.0.3 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.5 - pac-resolver: 7.0.1 - socks-proxy-agent: 8.0.4 - transitivePeerDependencies: - - supports-color - - pac-resolver@7.0.1: - dependencies: - degenerator: 5.0.1 - netmask: 2.0.2 - parent-module@1.0.1: dependencies: callsites: 3.1.0 - parse-json@5.2.0: - dependencies: - '@babel/code-frame': 7.26.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - parse5-htmlparser2-tree-adapter@7.1.0: dependencies: domhandler: 5.0.3 @@ -2399,86 +1819,24 @@ snapshots: path-key@3.1.1: {} - pend@1.2.0: {} - - picocolors@1.1.1: {} - picomatch@2.3.1: {} prelude-ls@1.2.1: {} prettier@3.4.1: {} - progress@2.0.3: {} - - proxy-agent@6.4.0: - dependencies: - agent-base: 7.1.1 - debug: 4.3.7 - http-proxy-agent: 7.0.2 - https-proxy-agent: 7.0.5 - lru-cache: 7.18.3 - pac-proxy-agent: 7.0.2 - proxy-from-env: 1.1.0 - socks-proxy-agent: 8.0.4 - transitivePeerDependencies: - - supports-color - proxy-from-env@1.1.0: {} - pump@3.0.2: - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - punycode@2.3.1: {} - puppeteer-cluster@0.24.0(puppeteer@23.10.0(typescript@5.7.2)): - dependencies: - debug: 4.3.7 - puppeteer: 23.10.0(typescript@5.7.2) - transitivePeerDependencies: - - supports-color - - puppeteer-core@23.10.0: - dependencies: - '@puppeteer/browsers': 2.5.0 - chromium-bidi: 0.8.0(devtools-protocol@0.0.1367902) - debug: 4.3.7 - devtools-protocol: 0.0.1367902 - typed-query-selector: 2.12.0 - ws: 8.18.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - - puppeteer@23.10.0(typescript@5.7.2): - dependencies: - '@puppeteer/browsers': 2.5.0 - chromium-bidi: 0.8.0(devtools-protocol@0.0.1367902) - cosmiconfig: 9.0.0(typescript@5.7.2) - devtools-protocol: 0.0.1367902 - puppeteer-core: 23.10.0 - typed-query-selector: 2.12.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - typescript - - utf-8-validate - queue-microtask@1.2.3: {} - queue-tick@1.0.1: {} - readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - require-directory@2.1.1: {} - resolve-from@4.0.0: {} resolve-pkg-maps@1.0.0: {} @@ -2514,76 +1872,20 @@ snapshots: dependencies: is-arrayish: 0.3.2 - smart-buffer@4.2.0: {} - - socks-proxy-agent@8.0.4: - dependencies: - agent-base: 7.1.1 - debug: 4.3.7 - socks: 2.8.3 - transitivePeerDependencies: - - supports-color - - socks@2.8.3: - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - - source-map@0.6.1: - optional: true - - sprintf-js@1.1.3: {} - stack-trace@0.0.10: {} - streamx@2.20.2: - dependencies: - fast-fifo: 1.3.2 - queue-tick: 1.0.1 - text-decoder: 1.2.1 - optionalDependencies: - bare-events: 2.5.0 - - string-width@4.2.3: - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - strip-ansi@6.0.1: - dependencies: - ansi-regex: 5.0.1 - strip-json-comments@3.1.1: {} supports-color@7.2.0: dependencies: has-flag: 4.0.0 - tar-fs@3.0.6: - dependencies: - pump: 3.0.2 - tar-stream: 3.1.7 - optionalDependencies: - bare-fs: 2.3.5 - bare-path: 2.1.3 - - tar-stream@3.1.7: - dependencies: - b4a: 1.6.7 - fast-fifo: 1.3.2 - streamx: 2.20.2 - - text-decoder@1.2.1: {} - text-hex@1.0.0: {} - through@2.3.8: {} - to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -2594,8 +1896,6 @@ snapshots: dependencies: typescript: 5.7.2 - tslib@2.8.1: {} - tsx@4.19.2: dependencies: esbuild: 0.23.1 @@ -2607,8 +1907,6 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typed-query-selector@2.12.0: {} - typescript-eslint@8.17.0(eslint@9.16.0)(typescript@5.7.2): dependencies: '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2))(eslint@9.16.0)(typescript@5.7.2) @@ -2622,22 +1920,17 @@ snapshots: typescript@5.7.2: {} - unbzip2-stream@1.4.3: - dependencies: - buffer: 5.7.1 - through: 2.3.8 - undici-types@6.20.0: {} undici@6.21.0: {} - universalify@2.0.1: {} - uri-js@4.4.1: dependencies: punycode: 2.3.1 - urlpattern-polyfill@10.0.0: {} + user-agents@1.1.379: + dependencies: + lodash.clonedeep: 4.5.0 util-deprecate@1.0.2: {} @@ -2673,16 +1966,6 @@ snapshots: word-wrap@1.2.5: {} - wrap-ansi@7.0.0: - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - - wrappy@1.0.2: {} - - ws@8.18.0: {} - xml-js@1.6.11: dependencies: sax: 1.4.1 @@ -2692,32 +1975,6 @@ snapshots: sax: 1.4.1 xmlbuilder: 11.0.1 - xml2js@0.6.2: - dependencies: - sax: 1.4.1 - xmlbuilder: 11.0.1 - xmlbuilder@11.0.1: {} - y18n@5.0.8: {} - - yargs-parser@21.1.1: {} - - yargs@17.7.2: - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - - yauzl@2.10.0: - dependencies: - buffer-crc32: 0.2.13 - fd-slicer: 1.1.0 - yocto-queue@0.1.0: {} - - zod@3.23.8: {} diff --git a/src/app.tsx b/src/app.tsx index 36892bc..37f70b9 100644 --- a/src/app.tsx +++ b/src/app.tsx @@ -59,7 +59,7 @@ app.get("/", (c) => c.html()); app.notFound((c) => c.html(, 404)); // error app.onError((err, c) => { - logger.error(`出现致命错误:${err}`); + logger.error(`❌ [ERROR] ${err?.message}`); return c.html(, 500); }); diff --git a/src/config.ts b/src/config.ts index 39b4af3..7c293df 100644 --- a/src/config.ts +++ b/src/config.ts @@ -12,15 +12,12 @@ export type Config = { ALLOWED_HOST: string; USE_LOG_FILE: boolean; RSS_MODE: boolean; - USE_PUPPETEER: boolean; }; // 验证并提取环境变量 const getEnvVariable = (key: string): string | undefined => { const value = process.env[key]; - if (value === undefined) { - return undefined; - } + if (value === undefined) return undefined; return value; }; @@ -28,9 +25,7 @@ const getEnvVariable = (key: string): string | undefined => { const getNumericEnvVariable = (key: string, defaultValue: number): number => { const value = getEnvVariable(key) ?? String(defaultValue); const parsedValue = parseInt(value, 10); - if (isNaN(parsedValue)) { - return defaultValue; - } + if (isNaN(parsedValue)) return defaultValue; return parsedValue; }; @@ -45,10 +40,9 @@ export const config: Config = { PORT: getNumericEnvVariable("PORT", 6688), DISALLOW_ROBOT: getBooleanEnvVariable("DISALLOW_ROBOT", true), CACHE_TTL: getNumericEnvVariable("CACHE_TTL", 3600), - REQUEST_TIMEOUT: getNumericEnvVariable("CACHE_TTL", 6000), + REQUEST_TIMEOUT: getNumericEnvVariable("REQUEST_TIMEOUT", 6000), ALLOWED_DOMAIN: getEnvVariable("ALLOWED_DOMAIN") || "*", ALLOWED_HOST: getEnvVariable("ALLOWED_HOST") || "imsyy.top", USE_LOG_FILE: getBooleanEnvVariable("USE_LOG_FILE", true), RSS_MODE: getBooleanEnvVariable("RSS_MODE", false), - USE_PUPPETEER: getBooleanEnvVariable("USE_PUPPETEER", false), }; diff --git a/src/index.ts b/src/index.ts index 7d1fc20..8f86b63 100644 --- a/src/index.ts +++ b/src/index.ts @@ -10,8 +10,7 @@ const serveHotApi: (port?: number) => void = (port: number = config.PORT) => { fetch: app.fetch, port, }); - logger.info(`🔥 DailyHot API 成功在端口 ${port} 上运行`); - logger.info(`💻 Puppeteer: ${config.USE_PUPPETEER}`); + logger.info(`🔥 DailyHot API successfully runs on port ${port}`); logger.info(`🔗 Local: 👉 http://localhost:${port}`); return apiServer; } catch (error) { diff --git a/src/router.types.d.ts b/src/router.types.d.ts index 1eb4569..755832e 100644 --- a/src/router.types.d.ts +++ b/src/router.types.d.ts @@ -315,14 +315,31 @@ export type RouterType = { message: string; replynum: number; }; - nodeseek: { - guid: { - _: string; - }[]; + xueqiu: { + pic: string; + tag: string; + id: number; + hot: number; + content: string; + }; + guokr: { + id: number; title: string; - description: string | string[]; - "dc:creator": string; - pubDate: string[]; - link: string[]; + summary: string; + author: { + nickname: string; + }; + date_modified: string; + small_image: string; + }; + kuaishou: { + id: string; + name: string; + hotValue: string; + iconUrl: string; + poster:string; + photoIds: { + json: string[]; + }; }; }; diff --git a/src/routes/52pojie.ts b/src/routes/52pojie.ts index da504fd..d29e76e 100644 --- a/src/routes/52pojie.ts +++ b/src/routes/52pojie.ts @@ -1,24 +1,27 @@ import type { RouterData, ListContext, Options, RouterResType } from "../types.js"; -import { web } from "../utils/getData.js"; -import { extractRss, parseRSS } from "../utils/parseRSS.js"; +import { get } from "../utils/getData.js"; import { getTime } from "../utils/getTime.js"; +import { parseRSS } from "../utils/parseRSS.js"; +import iconv from "iconv-lite"; + +const typeMap: Record = { + digest: "最新精华", + hot: "最新热门", + new: "最新回复", + newthread: "最新发表", +}; export const handleRoute = async (c: ListContext, noCache: boolean) => { - const type = c.req.query("type") || "hot"; + const type = c.req.query("type") || "digest"; const listData = await getList({ type }, noCache); const routeData: RouterData = { name: "52pojie", title: "吾爱破解", - type: "榜单", + type: typeMap[type], params: { type: { name: "榜单分类", - type: { - tech: "新鲜出炉", - newthread: "技术分享", - hot: "人气热门", - digest: "精华采撷", - }, + type: typeMap, }, }, link: "https://www.52pojie.cn/", @@ -31,28 +34,27 @@ export const handleRoute = async (c: ListContext, noCache: boolean) => { const getList = async (options: Options, noCache: boolean): Promise => { const { type } = options; const url = `https://www.52pojie.cn/forum.php?mod=guide&view=${type}&rss=1`; - const result = await web({ + const result = await get({ url, noCache, - userAgent: - "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36", + responseType: "arraybuffer", + headers: { + userAgent: + "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36", + }, }); - const parseData = async () => { - if (typeof result?.data !== "string") return []; - const rssContent = extractRss(result.data); - if (!rssContent) return []; - return await parseRSS(rssContent); - }; - const list = await parseData(); + // 转码 + const utf8Data = iconv.decode(result.data, "gbk"); + const list = await parseRSS(utf8Data); return { ...result, data: list.map((v, i) => ({ id: v.guid || i, title: v.title || "", - desc: v.content || "", - author: v.author || "", + desc: v.content?.trim() || "", + author: v.author, timestamp: getTime(v.pubDate || 0), - hot: 0, + hot: undefined, url: v.link || "", mobileUrl: v.link || "", })), diff --git a/src/routes/guokr.ts b/src/routes/guokr.ts new file mode 100644 index 0000000..41de9f8 --- /dev/null +++ b/src/routes/guokr.ts @@ -0,0 +1,45 @@ +import type { RouterData } from "../types.js"; +import type { RouterType } from "../router.types.js"; +import { get } from "../utils/getData.js"; +import { getTime } from "../utils/getTime.js"; + +export const handleRoute = async (_: undefined, noCache: boolean) => { + const listData = await getList(noCache); + const routeData: RouterData = { + name: "guokr", + title: "果壳", + type: "热门文章", + description: "科技有意思", + link: "https://www.guokr.com/", + total: listData.data?.length || 0, + ...listData, + }; + return routeData; +}; + +const getList = async (noCache: boolean) => { + const url = `https://www.guokr.com/beta/proxy/science_api/articles?limit=30`; + const result = await get({ + url, + noCache, + headers: { + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0", + }, + }); + const list = result.data; + return { + ...result, + data: list.map((v: RouterType["guokr"]) => ({ + id: v.id, + title: v.title, + desc: v.summary, + cover: v.small_image, + author: v.author?.nickname, + hot: undefined, + timestamp: getTime(v.date_modified), + url: `https://www.guokr.com/article/${v.id}`, + mobileUrl: `https://m.guokr.com/article/${v.id}`, + })), + }; +}; diff --git a/src/routes/hostloc.ts b/src/routes/hostloc.ts index 1319cc4..b76250a 100644 --- a/src/routes/hostloc.ts +++ b/src/routes/hostloc.ts @@ -1,6 +1,6 @@ import type { RouterData, ListContext, Options } from "../types.js"; -import { web } from "../utils/getData.js"; -import { extractRss, parseRSS } from "../utils/parseRSS.js"; +import { get } from "../utils/getData.js"; +import { parseRSS } from "../utils/parseRSS.js"; import { getTime } from "../utils/getTime.js"; const typeMap: Record = { @@ -33,19 +33,15 @@ export const handleRoute = async (c: ListContext, noCache: boolean) => { const getList = async (options: Options, noCache: boolean) => { const { type } = options; const url = `https://hostloc.com/forum.php?mod=guide&view=${type}&rss=1`; - const result = await web({ + const result = await get({ url, noCache, - userAgent: - "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36", + headers: { + userAgent: + "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36", + }, }); - const parseData = async () => { - if (typeof result?.data !== "string") return []; - const rssContent = extractRss(result.data); - if (!rssContent) return []; - return await parseRSS(rssContent); - }; - const list = await parseData(); + const list = await parseRSS(result.data); return { ...result, data: list.map((v, i) => ({ diff --git a/src/routes/ifanr.ts b/src/routes/ifanr.ts index 6ae8c65..62d8377 100644 --- a/src/routes/ifanr.ts +++ b/src/routes/ifanr.ts @@ -29,8 +29,8 @@ const getList = async (noCache: boolean) => { desc: v.post_content, timestamp: getTime(v.created_at), hot: v.like_count || v.comment_count, - url: v.buzz_original_url || `https://www.ifanr.com/${v.id}`, - mobileUrl: v.buzz_original_url || `https://www.ifanr.com/digest/${v.id}`, + url: v.buzz_original_url || `https://www.ifanr.com/${v.post_id}`, + mobileUrl: v.buzz_original_url || `https://www.ifanr.com/digest/${v.post_id}`, })), }; }; diff --git a/src/routes/kuaishou.ts b/src/routes/kuaishou.ts new file mode 100644 index 0000000..def47ca --- /dev/null +++ b/src/routes/kuaishou.ts @@ -0,0 +1,59 @@ +import type { RouterType } from "../router.types.js"; +import type { ListItem, RouterData } from "../types.js"; +import { get } from "../utils/getData.js"; +import { parseChineseNumber } from "../utils/getNum.js"; +import UserAgent from "user-agents"; + +export const handleRoute = async (_: undefined, noCache: boolean) => { + const listData = await getList(noCache); + const routeData: RouterData = { + name: "kuaishou", + title: "快手", + type: "热榜", + description: "快手,拥抱每一种生活", + link: "https://www.kuaishou.com/", + total: listData.data?.length || 0, + ...listData, + }; + return routeData; +}; + +const getList = async (noCache: boolean) => { + const url = `https://www.kuaishou.com/?isHome=1`; + const userAgent = new UserAgent({ + deviceCategory: "desktop", + }); + const result = await get({ + url, + noCache, + headers: { + "User-Agent": userAgent.toString(), + }, + }); + const listData: ListItem[] = []; + // 获取主要内容 + const pattern = /window.__APOLLO_STATE__=(.*);\(function\(\)/s; + const matchResult = result.data?.match(pattern); + const jsonObject = JSON.parse(matchResult[1])["defaultClient"]; + // 获取所有分类 + const allItems = jsonObject['$ROOT_QUERY.visionHotRank({"page":"home"})']["items"]; + // 获取全部热榜 + allItems?.forEach((item: { id: string }) => { + // 基础数据 + const hotItem: RouterType["kuaishou"] = jsonObject[item.id]; + const id = hotItem.photoIds?.json?.[0]; + listData.push({ + id: hotItem.id, + title: hotItem.name, + cover: decodeURIComponent(hotItem.poster), + hot: parseChineseNumber(hotItem.hotValue), + timestamp: undefined, + url: `https://www.kuaishou.com/short-video/${id}`, + mobileUrl: `https://www.kuaishou.com/short-video/${id}`, + }); + }); + return { + ...result, + data: listData, + }; +}; diff --git a/src/routes/nodeseek.ts b/src/routes/nodeseek.ts index 2301a04..20c9d31 100644 --- a/src/routes/nodeseek.ts +++ b/src/routes/nodeseek.ts @@ -1,8 +1,7 @@ import type { RouterData } from "../types.js"; -import type { RouterType } from "../router.types.js"; import { get } from "../utils/getData.js"; -import { parseStringPromise } from "xml2js"; import { getTime } from "../utils/getTime.js"; +import { parseRSS } from "../utils/parseRSS.js"; export const handleRoute = async (_: undefined, noCache: boolean) => { const listData = await getList(noCache); @@ -28,19 +27,18 @@ export const handleRoute = async (_: undefined, noCache: boolean) => { const getList = async (noCache: boolean) => { const url = `https://rss.nodeseek.com/`; const result = await get({ url, noCache }); - const rssData = await parseStringPromise(result.data); - const list = rssData.rss.channel[0].item; + const list = await parseRSS(result.data); return { ...result, - data: list.map((v: RouterType["nodeseek"]) => ({ - id: v.guid[0]._, - title: v.title[0], - desc: v.description ? v.description[0] : "", - author: v["dc:creator"] ? v["dc:creator"][0] : "unknown", - timestamp: getTime(v.pubDate[0]), + data: list.map((v, i) => ({ + id: v.guid || i, + title: v.title || "", + desc: v.content?.trim() || "", + author: v.author, + timestamp: getTime(v.pubDate || 0), hot: undefined, - url: v.link[0], - mobileUrl: v.link[0], + url: v.link || "", + mobileUrl: v.link || "", })), }; }; diff --git a/src/routes/xueqiu.ts b/src/routes/xueqiu.ts new file mode 100644 index 0000000..ca13b44 --- /dev/null +++ b/src/routes/xueqiu.ts @@ -0,0 +1,44 @@ +import type { RouterData } from "../types.js"; +import type { RouterType } from "../router.types.js"; +import { get } from "../utils/getData.js"; + +export const handleRoute = async (_: undefined, noCache: boolean) => { + const listData = await getList(noCache); + const routeData: RouterData = { + name: "xueqiu", + title: "雪球", + type: "热门话题", + description: "聪明的投资者都在这里", + link: "https://xueqiu.com/", + total: listData.data?.length || 0, + ...listData, + }; + return routeData; +}; + +const getList = async (noCache: boolean) => { + const url = `https://xueqiu.com/hot_event/list.json`; + const result = await get({ + url, + noCache, + headers: { + "User-Agent": + "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/605.1.15", + }, + }); + const list = result.data.list; + return { + ...result, + data: list.map((v: RouterType["xueqiu"]) => ({ + id: v.id, + title: v.tag?.startsWith("#") && v.tag?.endsWith("#") ? v.tag.slice(1, -1) : v.tag, + desc: v.content, + cover: v.pic, + author: undefined, + hot: v.hot, + timestamp: undefined, + url: undefined, + mobileUrl: undefined, + })), + }; +}; diff --git a/src/types.d.ts b/src/types.d.ts index 3a1b0ea..145ebfa 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,4 +1,5 @@ import type { Context } from "hono"; +import type { ResponseType } from "axios"; // Context export type ListContext = Context; @@ -44,6 +45,7 @@ export interface Get { noCache?: boolean; ttl?: number; originaInfo?: boolean; + responseType?: ResponseType; } export interface Post { @@ -56,14 +58,6 @@ export interface Post { originaInfo?: boolean; } -export interface Web { - url: string; - timeout?: number; - noCache?: boolean; - ttl?: number; - userAgent?: string; -} - // 参数类型 export interface Options { [key: string]: string | number | undefined; diff --git a/src/utils/cache.ts b/src/utils/cache.ts index 9e80047..59b55d3 100644 --- a/src/utils/cache.ts +++ b/src/utils/cache.ts @@ -27,7 +27,7 @@ export const getCache = (key: string): GetCache | undefined => { // 将数据写入缓存 export const setCache = (key: string, value: T, ttl: number = config.CACHE_TTL) => { const success = cache.set(key, value, ttl); - if (logger) logger.info("数据缓存成功", { url: key }); + if (logger) logger.info(`💾 [CHCHE] ${key} has been cached`); return success; }; diff --git a/src/utils/getData.ts b/src/utils/getData.ts index 05137db..155b6cd 100644 --- a/src/utils/getData.ts +++ b/src/utils/getData.ts @@ -1,8 +1,6 @@ -import type { Get, Post, Web } from "../types.js"; -import type { Page } from "puppeteer"; +import type { Get, Post } from "../types.js"; import { config } from "../config.js"; import { getCache, setCache, delCache } from "./cache.js"; -import { Cluster } from "puppeteer-cluster"; import logger from "./logger.js"; import axios from "axios"; @@ -13,69 +11,6 @@ const request = axios.create({ withCredentials: true, }); -// Puppeteer Cluster -let cluster: Cluster | null = null; - -/** - * 创建 Puppeteer Cluster - * @returns {Promise} Puppeteer Cluster - */ -export const createCluster = async (): Promise => { - if (cluster) return cluster; - try { - cluster = await Cluster.launch({ - concurrency: Cluster.CONCURRENCY_BROWSER, - maxConcurrency: 5, - puppeteerOptions: { - headless: true, - args: [ - "--no-sandbox", - "--disable-gpu", - "--disable-setuid-sandbox", - "--disable-dev-shm-usage", - ], - }, - }); - logger.info("Puppeteer Cluster 已成功初始化"); - } catch (error) { - logger.warn("启动 Puppeteer Cluster 失败,可能是没有 Chromium 安装", error); - cluster = null; - } - return cluster; -}; - -/** - * 处理任务 - * @param page 页面 - * @param data 数据 - * @returns - */ -const taskHandler = async ({ - page, - data: { url, userAgent }, -}: { - page: Page; - data: { url: string; userAgent?: string }; -}): Promise => { - // 用户代理 - if (userAgent) await page.setUserAgent(userAgent); - // 请求拦截 - await page.setRequestInterception(true); - // 拦截非必要资源 - page.on("request", (request) => { - const type = request.resourceType(); - if (type === "document" || type === "script") { - request.continue(); - } else { - request.abort(); - } - }); - // 加载页面 - await page.goto(url, { waitUntil: "networkidle0", timeout: config.REQUEST_TIMEOUT }); - // 返回页面内容 - return page.content(); -}; - // 请求拦截 request.interceptors.request.use( (request) => { @@ -84,7 +19,7 @@ request.interceptors.request.use( return request; }, (error) => { - logger.error("请求失败,请稍后重试"); + logger.error("❌ [ERROR] request failed"); return Promise.reject(error); }, ); @@ -102,31 +37,38 @@ request.interceptors.response.use( // GET export const get = async (options: Get) => { - const { url, headers, params, noCache, ttl = config.CACHE_TTL, originaInfo = false } = options; - logger.info("发起 GET 请求", options); + const { + url, + headers, + params, + noCache, + ttl = config.CACHE_TTL, + originaInfo = false, + responseType = "json", + } = options; + logger.info(`🌐 [GET] ${url}`); try { // 检查缓存 if (noCache) delCache(url); else { const cachedData = getCache(url); if (cachedData) { - logger.info("采用缓存", { url }); + logger.info("💾 [CHCHE] The request is cached"); return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; } } // 缓存不存在时请求接口 - logger.info("请求接口", { url }); - const response = await request.get(url, { headers, params }); + const response = await request.get(url, { headers, params, responseType }); const responseData = response?.data || response; // 存储新获取的数据到缓存 const updateTime = new Date().toISOString(); const data = originaInfo ? response : responseData; setCache(url, { data, updateTime }, ttl); // 返回数据 - logger.info("接口调用成功", { status: response?.statusText }); + logger.info(`✅ [${response?.statusText}] request was successful`); return { fromCache: false, data, updateTime }; } catch (error) { - logger.error("GET 请求出错", error); + logger.error("❌ [ERROR] request failed"); throw error; } }; @@ -134,19 +76,18 @@ export const get = async (options: Get) => { // POST export const post = async (options: Post) => { const { url, headers, body, noCache, ttl = config.CACHE_TTL, originaInfo = false } = options; - logger.info("发起 POST 请求", options); + logger.info(`🌐 [POST] ${url}`); try { // 检查缓存 if (noCache) delCache(url); else { const cachedData = getCache(url); if (cachedData) { - logger.info("采用缓存", { url }); + logger.info("💾 [CHCHE] The request is cached"); return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; } } // 缓存不存在时请求接口 - logger.info("请求接口", { url }); const response = await request.post(url, body, { headers }); const responseData = response?.data || response; // 存储新获取的数据到缓存 @@ -156,68 +97,10 @@ export const post = async (options: Post) => { setCache(url, { data, updateTime }, ttl); } // 返回数据 - logger.info("接口调用成功", { status: response?.statusText }); + logger.info(`✅ [${response?.statusText}] request was successful`); return { fromCache: false, data, updateTime }; } catch (error) { - logger.error("POST 请求出错", error); + logger.error("❌ [ERROR] request failed"); throw error; } }; - -// WEB - Puppeteer -export const web = async (options: Web) => { - const { url, noCache, ttl = config.CACHE_TTL, userAgent } = options; - logger.info("使用 Puppeteer 发起页面请求", options); - if (config.USE_PUPPETEER === false) { - return { - fromCache: false, - data: [], - message: "Puppeteer is not enabled, please set USE_PUPPETEER=true", - updateTime: 0, - }; - } - // 初始化 Cluster - const clusterInstance = await createCluster(); - if (!clusterInstance) { - logger.error("Cluster 初始化失败,无法继续"); - throw new Error("Cluster 初始化失败"); - } - try { - // 检查缓存 - if (noCache) { - delCache(url); - } else { - const cachedData = getCache(url); - if (cachedData) { - logger.info("采用缓存", { url }); - return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; - } - } - // 缓存不存在时使用 Puppeteer 请求页面 - logger.info("启动浏览器请求页面", { url }); - const pageContent = await clusterInstance.execute({ url, userAgent }, taskHandler); - // 存储新获取的数据到缓存 - const updateTime = new Date().toISOString(); - setCache(url, { data: pageContent, updateTime }, ttl); - // 返回数据 - logger.info("页面内容获取成功"); - return { fromCache: false, data: pageContent, updateTime }; - } catch (error) { - logger.error("Puppeteer 请求出错", error); - throw error; - } -}; - -/** - * 关闭 Cluster - */ -export const closeCluster = async () => { - if (cluster) { - try { - await cluster.close(); - logger.info("Puppeteer Cluster 已成功关闭"); - } catch (error) { - logger.error("关闭 Puppeteer Cluster 时出错", error); - } - } -}; diff --git a/src/utils/getRSS.ts b/src/utils/getRSS.ts index a1fe91f..2ea8313 100644 --- a/src/utils/getRSS.ts +++ b/src/utils/getRSS.ts @@ -35,7 +35,8 @@ const getRSS = (data: RouterData) => { const rssData = feed.rss2(); return rssData; } catch (error) { - logger.error("RSS 生成失败:", error); + logger.error("❌ [ERROR] getRSS failed"); + throw error; } }; diff --git a/src/utils/parseRSS.ts b/src/utils/parseRSS.ts index 184ccae..33e2a33 100644 --- a/src/utils/parseRSS.ts +++ b/src/utils/parseRSS.ts @@ -47,7 +47,7 @@ export const parseRSS = async (rssContent: string) => { // 返回解析数据 return items; } catch (error) { - logger.error("解析 RSS 内容时出错:", error); - return []; + logger.error("❌ [ERROR] An error occurred while parsing RSS content"); + throw error; } };