From bb12119123c86a1206aa57722d4bd5b6f6479d16 Mon Sep 17 00:00:00 2001 From: Tony Date: Tue, 4 Aug 2026 09:00:41 +0800 Subject: [PATCH] refactor: enforce typecheck (#22917) * feat(types): add upvotes, downvotes, and comments to DataItem * refactor: fix TS2339 * refactor: fix TS2322 * refactor: fix TS2322 * refactor: fix TS2345 * refactor: fix TS2339 * refactor: fix TS2322 * refactor: fix TS2345 * refactor: fix TS2531/2532/18048/18047 * refactor: fix TS18046/TS2571 * refactor: fix TS2538 * refactor: fix TS2554/2769/2558 * refactor: fix TS2362/2363 * refactor: fix TS2353/TS2561 * refactor: fix TS2741/2739/2740 * refactor: fix TS2304 TS2307 TS2305 TS2614 TS2552 TS2551 * refactor: fix TS2352 * refactor: fix TS2604 TS17001 * refactor: fix TS2367 TS2366 * refactor: fix TS2493 * refactor: fix TS2454 * refactor: fix TS2790 * refactor: fix TS2488 * refactor: fix TS2677 * refactor: fix TS18048/18049/2532 * refactor: fix TS2322 * refactor: fix TS2344 * refactor: fix TS2339 * refactor: fix TS2339 * refactor: fix TS2365 * refactor: fix TS1117 * refactor: fix TS2561 * refactor: fix TS2555 * refactor: fix TS2503 * refactor: fix TS2339 mobile api no longer work * fix: clean slop * fix: use Context instead of any * fix: fix more typing after merge * fix: add void return for ctx.redirect in handler * chore: add type check to lint and husky * fix: remove ts ignore * chore: add oxlint rule * fix: suppress build artifact * fix: update getArticles to use cache * fix: codeql * fix(route/typeless): use async gunzip * fix: address review * fix: address review * fix: double quotes escape --- .github/workflows/lint.yml | 2 + .husky/pre-commit | 1 + .oxlintrc.json | 12 +- lib/api/follow/config.test.ts | 2 +- lib/api/radar/rules/one.test.ts | 4 +- lib/app-bootstrap.test.tsx | 2 +- lib/app.test.ts | 2 +- lib/container.ts | 6 +- lib/errors/index.test.ts | 9 +- lib/index.test.ts | 2 +- lib/middleware/anti-hotlink.test.ts | 7 +- lib/middleware/cache.test.ts | 7 +- lib/middleware/parameter.test.ts | 5 +- lib/middleware/parameter.ts | 6 +- lib/middleware/template.test.ts | 23 ++-- lib/middleware/trace.test.ts | 10 +- lib/pkg.test.ts | 6 +- lib/registry-dev.test.ts | 2 +- lib/registry.test.ts | 3 +- lib/registry.ts | 6 +- lib/routes/005/index.tsx | 28 ++--- lib/routes/0818tuan/index.ts | 14 +-- lib/routes/0x80/index.ts | 10 +- lib/routes/0xxx/index.ts | 18 +-- lib/routes/10000link/info.ts | 14 +-- lib/routes/10jqka/realtimenews.ts | 6 +- lib/routes/121/weather-live.tsx | 6 +- lib/routes/12306/zxdt.ts | 6 +- lib/routes/141jav/index.tsx | 26 ++--- lib/routes/141ppv/index.tsx | 28 ++--- lib/routes/163/dy2.ts | 10 +- lib/routes/163/music/djradio.tsx | 2 +- lib/routes/163/news/rank.ts | 23 ++-- lib/routes/163/open/vip.tsx | 4 +- lib/routes/163/renjian.ts | 14 +-- lib/routes/163/utils.tsx | 2 +- lib/routes/18comic/album.ts | 4 +- lib/routes/18comic/blogs.ts | 12 +- lib/routes/18comic/search.ts | 14 ++- lib/routes/18comic/utils.ts | 17 +-- lib/routes/199it/index.tsx | 14 +-- lib/routes/19lou/index.ts | 16 +-- lib/routes/1lou/index.ts | 36 +++--- lib/routes/1x/index.tsx | 18 +-- lib/routes/2048/index.tsx | 16 +-- lib/routes/21caijing/channel.ts | 12 +- lib/routes/2cycd/index.ts | 14 +-- lib/routes/36kr/utils.ts | 2 +- lib/routes/3dmgame/game.ts | 8 +- lib/routes/3dmgame/news-center.ts | 16 +-- lib/routes/3dmgame/utils.ts | 4 +- lib/routes/423down/index.ts | 36 +++--- lib/routes/4ksj/forum.tsx | 41 +++---- lib/routes/50forum/zhuanjia.ts | 18 +-- lib/routes/51cto/recommend.ts | 3 +- lib/routes/51read/article.ts | 4 +- lib/routes/56kog/util.tsx | 37 +++--- lib/routes/591/list.tsx | 16 +-- lib/routes/5music/index.ts | 4 +- lib/routes/69shu/article.ts | 2 +- lib/routes/6park/index.ts | 13 ++- lib/routes/6park/news.ts | 16 +-- lib/routes/6v123/index.ts | 12 +- lib/routes/78dm/index.ts | 38 +++---- lib/routes/7mmtv/index.tsx | 18 +-- lib/routes/81/81rc/index.ts | 20 ++-- lib/routes/8264/list.tsx | 18 +-- lib/routes/8world/index.ts | 18 +-- lib/routes/91porn/author.ts | 18 +-- lib/routes/91porn/index.ts | 18 +-- lib/routes/95mm/utils.tsx | 11 +- lib/routes/9to5/subsite.ts | 4 +- lib/routes/9to5/utils.ts | 2 +- lib/routes/a9vg/index.ts | 34 +++--- lib/routes/aa1/60s.ts | 6 +- lib/routes/aamacau/index.ts | 14 +-- lib/routes/abc/index.ts | 10 +- lib/routes/abc/templates/description.tsx | 4 +- lib/routes/accessbriefing/index.ts | 10 +- .../accessbriefing/templates/description.tsx | 2 +- lib/routes/acfun/article.ts | 2 +- lib/routes/acpaa/index.ts | 16 +-- lib/routes/acs/journal.tsx | 14 +-- lib/routes/adquan/case-library.ts | 12 +- lib/routes/adquan/index.ts | 12 +- lib/routes/aeaweb/index.tsx | 19 ++-- lib/routes/afdian/explore.ts | 1 + lib/routes/aflcio/blog.ts | 12 +- lib/routes/agefans/detail.ts | 6 +- lib/routes/agefans/update.ts | 12 +- lib/routes/agirls/topic-list.ts | 12 +- lib/routes/agirls/topic.ts | 10 +- lib/routes/agirls/z-index.ts | 10 +- lib/routes/agora0/index.ts | 14 +-- lib/routes/agora0/pen0.ts | 14 +-- lib/routes/agri/index.ts | 28 ++--- lib/routes/ahjzu/news.ts | 16 +-- lib/routes/aibase/daily.ts | 2 +- lib/routes/aibase/discover.ts | 2 +- lib/routes/aibase/news.ts | 2 +- lib/routes/aibase/topic.ts | 2 +- lib/routes/aijishu/utils.ts | 2 +- lib/routes/ainvest/article.ts | 4 +- lib/routes/ainvest/news.ts | 4 +- lib/routes/ainvest/utils.ts | 5 +- lib/routes/aip/journal-pupp.ts | 2 +- lib/routes/aip/journal.ts | 8 +- lib/routes/airchina/index.ts | 2 +- lib/routes/aisixiang/column.ts | 12 +- lib/routes/aisixiang/thinktank.ts | 12 +- lib/routes/aisixiang/toplist.ts | 14 +-- lib/routes/aisixiang/utils.ts | 2 +- lib/routes/aisixiang/zhuanti.ts | 12 +- lib/routes/ali213/news.ts | 12 +- lib/routes/ali213/zl.ts | 10 +- lib/routes/alicesoft/infomation.ts | 18 +-- lib/routes/alistapart/index.ts | 4 +- lib/routes/alistapart/topic.ts | 4 +- lib/routes/aliyun/database-month.ts | 2 +- lib/routes/aliyun/developer/group.ts | 14 +-- lib/routes/aliyun/notice.ts | 4 +- lib/routes/aljazeera/index.tsx | 4 +- lib/routes/ally/rail.ts | 19 ++-- lib/routes/alwayscontrol/news.ts | 10 +- lib/routes/amazfitwatchfaces/index.ts | 12 +- lib/routes/amazon/kindle-software-updates.tsx | 2 +- lib/routes/android/platform-tools-releases.ts | 12 +- lib/routes/annualreviews/index.ts | 20 ++-- lib/routes/anquanke/category.ts | 2 +- lib/routes/anthropic/red.ts | 8 +- lib/routes/anthropic/research.ts | 18 +-- lib/routes/anytxt/release-notes.ts | 8 +- lib/routes/apache/apisix/blog.ts | 2 +- lib/routes/apkpure/versions.ts | 12 +- lib/routes/apnews/mobile-api.ts | 2 +- lib/routes/apnews/rss.ts | 4 +- lib/routes/apnews/sitemap.ts | 6 +- lib/routes/apnews/topics.ts | 6 +- lib/routes/apnic/index.ts | 6 +- lib/routes/app-sales/index.ts | 4 +- lib/routes/app-sales/mostwanted.ts | 4 +- lib/routes/app-sales/util.tsx | 2 +- lib/routes/apple/apps.ts | 6 +- lib/routes/apple/exchange-repair.ts | 14 +-- lib/routes/apple/newsroom.ts | 6 +- lib/routes/apple/podcast.ts | 2 +- lib/routes/apple/security-releases.ts | 14 +-- lib/routes/appleinsider/index.ts | 14 +-- lib/routes/appstore/price.ts | 2 +- lib/routes/appstorrent/programs.tsx | 3 +- lib/routes/aqara/news.ts | 6 +- lib/routes/aqara/post.tsx | 4 +- lib/routes/aqara/region.ts | 2 +- lib/routes/aqicn/aqi.ts | 26 ++--- lib/routes/arcteryx/regear-new-arrivals.tsx | 2 +- lib/routes/arcteryx/utils.ts | 2 +- lib/routes/aschmelyun/blog.ts | 12 +- lib/routes/asiafruitchina/categories.ts | 12 +- lib/routes/asiafruitchina/news.ts | 12 +- lib/routes/asiantolick/index.ts | 26 ++--- lib/routes/asus/gpu-tweak.ts | 18 +-- lib/routes/atcoder/contest.ts | 12 +- lib/routes/atcoder/post.ts | 10 +- lib/routes/augmentcode/blog.tsx | 14 +-- lib/routes/auto-stats/index.ts | 16 +-- lib/routes/azul/packages.ts | 6 +- lib/routes/azurlane/news.ts | 2 +- lib/routes/backlinko/blog.ts | 8 +- lib/routes/bad/index.ts | 16 +-- lib/routes/baidu/search.tsx | 4 +- lib/routes/baidu/tieba/post.tsx | 2 +- lib/routes/baidu/top.tsx | 16 ++- lib/routes/bakamh/manga.ts | 10 +- lib/routes/bandcamp/live.ts | 16 +-- lib/routes/bandcamp/tag.ts | 2 +- lib/routes/bandisoft/history.ts | 8 +- lib/routes/bangumi.tv/calendar/today.tsx | 2 +- lib/routes/bangumi.tv/group/reply.ts | 2 +- lib/routes/bangumi.tv/group/topic.ts | 4 +- lib/routes/bangumi.tv/subject/comments.ts | 4 +- lib/routes/bangumi.tv/user/blog.ts | 16 +-- lib/routes/banshujiang/index.ts | 14 +-- lib/routes/banyuetan/index.ts | 14 +-- lib/routes/baobua/category.ts | 6 +- lib/routes/baobua/latest.ts | 6 +- lib/routes/baobua/search.ts | 4 +- lib/routes/baozimh/index.tsx | 8 +- lib/routes/barronschina/index.ts | 24 ++-- lib/routes/bast/index.ts | 20 ++-- lib/routes/bbc/sport.ts | 2 +- lib/routes/bbc/utils.tsx | 2 +- lib/routes/bbcnewslabs/news.ts | 10 +- lib/routes/bc3ts/list.tsx | 4 +- lib/routes/bdys/index.tsx | 14 +-- lib/routes/beijingprice/index.ts | 24 ++-- lib/routes/bendibao/news.ts | 28 ++--- lib/routes/bilibili/bangumi.ts | 4 +- lib/routes/bilibili/cache.ts | 6 +- lib/routes/bilibili/danmaku.ts | 2 +- lib/routes/bilibili/mall-new.ts | 2 +- lib/routes/bilibili/user-channel.ts | 6 +- lib/routes/bilibili/user-collection.ts | 6 +- lib/routes/bilibili/video-all.ts | 4 +- lib/routes/bilibili/video.ts | 6 +- lib/routes/bilibili/wasm-exec.ts | 3 +- lib/routes/bing/search.ts | 10 +- lib/routes/bioone/featured.ts | 14 +-- lib/routes/bioone/journal.ts | 15 +-- lib/routes/biquge/index.ts | 20 ++-- lib/routes/bit/cs/utils.ts | 2 +- lib/routes/bit/jwc/utils.ts | 2 +- lib/routes/bit/yjs.ts | 8 +- lib/routes/bjfu/grs.ts | 10 +- lib/routes/bjfu/it/utils.ts | 6 +- lib/routes/bjfu/jwc/utils.ts | 6 +- lib/routes/bjfu/kjc.ts | 8 +- lib/routes/bjfu/news/index.ts | 2 +- lib/routes/bjfu/news/utils.ts | 4 +- lib/routes/bjp/apod.ts | 16 +-- lib/routes/bjsk/index.ts | 16 +-- lib/routes/bjsk/keti.ts | 14 +-- lib/routes/bjwxdxh/index.ts | 18 +-- lib/routes/bjx/huanbao.ts | 13 ++- lib/routes/bjx/types.ts | 10 +- lib/routes/blizzard/news-cn.ts | 36 +++--- lib/routes/blockworks/index.ts | 5 +- lib/routes/blogread/index.ts | 10 +- lib/routes/bloomberg/authors.ts | 16 +-- lib/routes/bloomberg/templates/lede-media.tsx | 2 +- .../bloomberg/templates/video-media.tsx | 2 +- lib/routes/bloomberg/utils.ts | 35 +++--- lib/routes/bluearchive/news.ts | 2 +- lib/routes/bluestacks/release.ts | 16 +-- lib/routes/bmkg/earthquake.ts | 9 +- lib/routes/bmkg/news.ts | 14 +-- lib/routes/bnu/bs.ts | 14 +-- lib/routes/bnu/dwxgb.ts | 19 +--- lib/routes/bnu/fdy.ts | 16 +-- lib/routes/bnu/jwb.ts | 16 +-- lib/routes/bnu/lib.ts | 14 +-- lib/routes/bnu/mba.ts | 22 ++-- lib/routes/boc/whpj.ts | 16 +-- lib/routes/bookfere/category.ts | 12 +- lib/routes/bookwalker/search.tsx | 8 +- lib/routes/booru/mmda.ts | 16 +-- lib/routes/brave/latest.ts | 10 +- lib/routes/bt0/mv.ts | 2 +- lib/routes/btbtla/detail.ts | 5 +- lib/routes/btzj/index.tsx | 8 +- lib/routes/buaa/jiaowu.ts | 4 +- lib/routes/buaa/lib/space/newbook.tsx | 8 +- lib/routes/buaa/news/index.ts | 4 +- lib/routes/buaa/sme.ts | 4 +- lib/routes/buct/cist.ts | 16 +-- lib/routes/buct/gr.ts | 16 +-- lib/routes/buct/jwc.ts | 16 +-- lib/routes/bullionvault/gold-news.ts | 12 +- lib/routes/bupt/jwc.ts | 8 +- lib/routes/bupt/rczp.ts | 12 +- lib/routes/bupt/scss.ts | 8 +- lib/routes/bvisness/blog.ts | 8 +- lib/routes/byau/xinwen/index.ts | 10 +- lib/routes/c114/roll.ts | 27 +++-- lib/routes/caam/index.ts | 16 +-- lib/routes/caareviews/utils.tsx | 6 +- lib/routes/cags/edu/index.ts | 2 +- lib/routes/caixin/blog.ts | 8 +- lib/routes/caixin/category.ts | 2 +- lib/routes/caixin/database.ts | 12 +- lib/routes/caixin/utils-fulltext.ts | 2 +- lib/routes/caixin/utils.ts | 3 +- lib/routes/caixin/weekly.ts | 6 +- lib/routes/caixinglobal/latest.ts | 6 +- lib/routes/camchina/index.ts | 12 +- lib/routes/cankaoxiaoxi/index.tsx | 4 +- lib/routes/cara/portfolio.ts | 4 +- lib/routes/cara/utils.ts | 2 +- lib/routes/cartoonmad/comic.tsx | 10 +- lib/routes/cas/cg/index.ts | 14 +-- lib/routes/cas/genetics/index.ts | 24 ++-- lib/routes/cas/ia/yjs.ts | 8 +- lib/routes/cas/iee/kydt.ts | 10 +- lib/routes/cas/is/index.ts | 16 +-- lib/routes/cas/mesalab/kb.ts | 2 +- lib/routes/cas/sim/kyjz.ts | 17 +-- lib/routes/casssp/news.ts | 16 +-- lib/routes/cast/index.ts | 6 +- lib/routes/castanet/news.ts | 6 +- lib/routes/catti/news.ts | 6 +- lib/routes/cau/ele.ts | 8 +- lib/routes/cau/yjs.ts | 6 +- lib/routes/cbaigui/index.ts | 6 +- lib/routes/cbc/topics.ts | 6 +- lib/routes/cbndata/information.ts | 10 +- lib/routes/cbpanet/index.ts | 24 ++-- lib/routes/ccac/news.ts | 2 +- lib/routes/ccagm/index.ts | 12 +- lib/routes/cccmc/index.ts | 10 +- lib/routes/ccf/ccfcv/index.tsx | 14 +-- lib/routes/ccf/news.ts | 12 +- lib/routes/ccfa/index.tsx | 23 ++-- lib/routes/ccg/index.ts | 12 +- lib/routes/ccnu/career.ts | 6 +- lib/routes/ccnu/cs.ts | 12 +- lib/routes/ccnu/wu.ts | 8 +- lib/routes/ccnu/yjs.ts | 10 +- lib/routes/ccreports/index.ts | 22 ++-- lib/routes/cctv/jx.ts | 16 +-- lib/routes/cctv/utils/news.ts | 3 +- lib/routes/cde/index.ts | 4 +- lib/routes/cde/xxgk.tsx | 2 +- lib/routes/cde/zdyz.ts | 6 +- lib/routes/cdi/index.ts | 13 ++- lib/routes/cdu/cdrw.ts | 8 +- lib/routes/cdu/jwgg.ts | 8 +- lib/routes/cdu/tzggcdunews.ts | 8 +- lib/routes/ce/district.ts | 10 +- lib/routes/cebbank/all.tsx | 12 +- lib/routes/cebbank/history.tsx | 8 +- lib/routes/ceph/blog.ts | 10 +- lib/routes/cfachina/analygarden.ts | 2 +- lib/routes/cffex/announcement.ts | 12 +- lib/routes/cfmmc/index.ts | 6 +- lib/routes/chaincatcher/news.ts | 14 +-- lib/routes/changba/user.tsx | 8 +- lib/routes/chikubi/utils.ts | 4 +- lib/routes/china/finance/finance.ts | 6 +- lib/routes/china/news/highlights/news.ts | 12 +- lib/routes/china/news/military/news.ts | 10 +- lib/routes/chinacdc/index.ts | 10 +- lib/routes/chinadaily/language.ts | 16 +-- lib/routes/chinadegrees/province.tsx | 12 +- lib/routes/chinafactcheck/index.ts | 11 +- lib/routes/chinafactcheck/utils.ts | 14 +-- lib/routes/chinaisa/index.ts | 20 ++-- lib/routes/chinamoney/notice.ts | 12 +- lib/routes/chinanews/index.ts | 16 +-- lib/routes/chinania/index.ts | 24 ++-- lib/routes/chinaratings/credit-research.ts | 4 +- lib/routes/chinathinktanks/viewpoint.ts | 18 +-- lib/routes/chinatimes/index.ts | 16 +-- lib/routes/chinaventure/index.ts | 17 +-- lib/routes/chinawriter/index.ts | 28 ++--- lib/routes/chiphell/portal.ts | 8 +- lib/routes/chlinlearn/daily-blog.ts | 2 +- lib/routes/chnmuseum/xingnew.ts | 10 +- lib/routes/chnmuseum/xwzt.ts | 6 +- lib/routes/chocolatey/packages.ts | 10 +- lib/routes/chongdiantou/index.ts | 4 +- lib/routes/chsi/hotnews.ts | 6 +- lib/routes/chsi/kydt.ts | 16 +-- lib/routes/chsi/kyzx.ts | 12 +- lib/routes/chuanliu/nice.tsx | 6 +- lib/routes/ciidbnu/index.ts | 12 +- lib/routes/cisia/index.ts | 18 +-- lib/routes/civitai/discussions.ts | 4 +- lib/routes/ciweimao/chapter.ts | 18 +-- lib/routes/cjlu/yjsy/index.ts | 2 +- lib/routes/claude/blog.ts | 4 +- lib/routes/claude/code-changelog.ts | 6 +- lib/routes/cloudflarestatus/index.tsx | 8 +- lib/routes/cls/depth.ts | 24 ++-- lib/routes/cma/channel.tsx | 8 +- lib/routes/cmde/index.ts | 12 +- lib/routes/cmpxchg8b/articles.ts | 10 +- lib/routes/cmu/andypavlo/blog.ts | 2 +- lib/routes/cna/web/index.ts | 8 +- lib/routes/cnbc/rss.ts | 8 +- lib/routes/cnbeta/common.ts | 2 +- lib/routes/cnbeta/utils.ts | 2 +- lib/routes/cnblogs/common.ts | 12 +- lib/routes/cncf/index.ts | 16 +-- lib/routes/cncf/reports.ts | 8 +- lib/routes/cneb/yjxw.ts | 12 +- lib/routes/cngold/index.ts | 20 ++-- lib/routes/cnjxol/index.tsx | 6 +- lib/routes/cnki/debut.ts | 4 +- lib/routes/cnki/journals.ts | 8 +- lib/routes/cnljxh/index.ts | 12 +- lib/routes/cntheory/paper.tsx | 10 +- lib/routes/coindesk/news.ts | 2 +- lib/routes/comicat/search.ts | 4 +- lib/routes/comicskingdom/index.tsx | 10 +- lib/routes/consumer/index.ts | 12 +- lib/routes/consumer/shopping-guide.ts | 22 ++-- lib/routes/coolapk/hot.ts | 8 +- lib/routes/coolbuy/index.tsx | 6 +- lib/routes/copymanga/comic.tsx | 2 +- lib/routes/cosplaytele/category.ts | 2 +- lib/routes/cosplaytele/latest.ts | 2 +- lib/routes/cosplaytele/tag.ts | 2 +- lib/routes/costar/press-releases.ts | 12 +- lib/routes/counter-strike/news.ts | 4 +- lib/routes/cpcaauto/index.ts | 22 ++-- lib/routes/cpcey/index.ts | 8 +- lib/routes/cpta/handler.ts | 2 +- lib/routes/cpuid/news.ts | 14 +-- lib/routes/cqgas/tqtz.ts | 10 +- lib/routes/cqu/index.ts | 14 +-- lib/routes/crac/index.ts | 13 ++- lib/routes/creative-comic/book.tsx | 6 +- lib/routes/cs/index.ts | 18 +-- lib/routes/cs/video.ts | 8 +- lib/routes/csdn/blog.ts | 7 +- lib/routes/cssn/iolaw.ts | 8 +- lib/routes/cste/index.ts | 14 +-- lib/routes/csu/career.ts | 18 +-- lib/routes/csu/cse.ts | 13 ++- lib/routes/ctbu/xxgg.ts | 10 +- lib/routes/ctinews/topic.ts | 14 +-- lib/routes/cts/news.ts | 10 +- lib/routes/cuc/yz.ts | 10 +- lib/routes/cuilingmag/index.ts | 26 ++--- lib/routes/cw/author.ts | 4 +- lib/routes/cw/master.ts | 4 +- lib/routes/cw/sub.ts | 4 +- lib/routes/cw/today.ts | 4 +- lib/routes/cw/utils.ts | 12 +- lib/routes/cyzone/util.ts | 9 +- lib/routes/cztv/daily.tsx | 8 +- lib/routes/cztv/zjxwlb.tsx | 12 +- lib/routes/dahecube/index.ts | 4 +- lib/routes/daily/discussed.ts | 4 +- lib/routes/daily/popular.ts | 4 +- lib/routes/daily/source.ts | 4 +- lib/routes/daily/squads.ts | 4 +- lib/routes/daily/upvoted.ts | 4 +- lib/routes/daily/user.ts | 4 +- lib/routes/daoxuan/rss.ts | 10 +- lib/routes/dapenti/utils.ts | 4 +- lib/routes/darwinawards/index.ts | 12 +- lib/routes/dayanzai/index.ts | 18 +-- lib/routes/dbaplus/new.ts | 16 +-- lib/routes/dcard/section.ts | 2 +- lib/routes/dcard/utils.ts | 4 +- lib/routes/dcfever/news.ts | 6 +- lib/routes/dcfever/reviews.ts | 6 +- lib/routes/dcfever/trading-search.ts | 10 +- lib/routes/dcfever/trading.ts | 8 +- lib/routes/dcfever/utils.tsx | 6 +- lib/routes/ddosi/category.ts | 2 +- lib/routes/ddosi/index.ts | 2 +- lib/routes/deadbydaylight/index.ts | 2 +- lib/routes/deadline/posts.tsx | 14 +-- lib/routes/dealstreetasia/home.ts | 4 +- lib/routes/dealstreetasia/section.ts | 4 +- lib/routes/dedao/articles.ts | 2 +- lib/routes/dedao/list.ts | 12 +- lib/routes/deepl/blog.ts | 14 +-- lib/routes/deeplearning/the-batch.ts | 6 +- lib/routes/deepmind/blog.ts | 10 +- lib/routes/deepseek/news.ts | 2 +- lib/routes/dehenglaw/index.ts | 18 +-- lib/routes/devolverdigital/blog.ts | 4 +- lib/routes/devtrium/posts.ts | 4 +- lib/routes/dgjyw/index.ts | 22 ++-- lib/routes/dgtle/article.ts | 4 +- lib/routes/dgtle/feed.ts | 4 +- lib/routes/dgtle/news.ts | 4 +- lib/routes/dgtle/tag.ts | 4 +- lib/routes/dgtle/util.ts | 12 +- lib/routes/dgtle/video.ts | 10 +- lib/routes/dhu/jiaowu/news.ts | 8 +- lib/routes/dhu/xxgk/news.ts | 8 +- lib/routes/dhu/yjs/news.ts | 16 +-- lib/routes/dhu/yjs/zs.ts | 14 +-- lib/routes/diariofruticola/filtro.ts | 12 +- lib/routes/diershoubing/news.tsx | 2 +- lib/routes/digitalcameraworld/news.ts | 17 ++- .../digitalpolicyalert/activity-tracker.ts | 8 +- lib/routes/dingshao/share.ts | 2 +- lib/routes/discord/channel.ts | 26 +++-- lib/routes/discourse/notifications.ts | 2 +- lib/routes/discourse/official.ts | 6 +- lib/routes/discourse/posts.ts | 6 +- lib/routes/discuz/discuz.ts | 40 +++---- lib/routes/disinfo/publications.ts | 14 +-- lib/routes/diskanalyzer/whats-new.ts | 11 +- lib/routes/distill/index.ts | 14 +-- lib/routes/dlnews/category.tsx | 8 +- lib/routes/dlsite/campaign.ts | 4 +- lib/routes/dlsite/ci-en/article.ts | 14 +-- lib/routes/dlsite/new.ts | 4 +- lib/routes/dlsite/utils.ts | 24 ++-- lib/routes/dn/news.ts | 28 ++--- lib/routes/dnaindia/common.ts | 7 +- lib/routes/dockerhub/repositories.ts | 2 +- lib/routes/dockerhub/tag.ts | 4 +- lib/routes/dockerhub/utils.ts | 2 +- lib/routes/docschina/weekly.ts | 1 - lib/routes/dol/announce.ts | 12 +- lib/routes/domp4/detail.ts | 6 +- lib/routes/domp4/latest-movie-bt.ts | 8 +- lib/routes/domp4/latest.ts | 6 +- lib/routes/dorohedoro/news.ts | 14 +-- lib/routes/douban/commercialpress/latest.ts | 2 +- lib/routes/douban/other/celebrity.ts | 10 +- lib/routes/douban/other/discussion.ts | 16 +-- lib/routes/douban/other/doulist.ts | 2 +- lib/routes/douban/other/explore.tsx | 18 +-- lib/routes/douban/other/group.ts | 8 +- lib/routes/douban/other/list.ts | 2 +- lib/routes/douban/other/playing.ts | 4 +- lib/routes/douban/other/replied.ts | 10 +- lib/routes/douban/other/replies.ts | 18 +-- lib/routes/douban/people/status.ts | 8 +- lib/routes/douban/people/wish.ts | 8 +- lib/routes/douyin/hashtag.ts | 6 +- lib/routes/douyin/live.ts | 4 +- lib/routes/douyin/templates/embed.tsx | 2 +- lib/routes/dribbble/utils.tsx | 42 +++---- lib/routes/dtcj/datainsight.ts | 10 +- lib/routes/duckdb/news.ts | 14 +-- lib/routes/duozhi/index.ts | 14 +-- lib/routes/duozhi/templates/description.tsx | 1 + lib/routes/dut/index.ts | 19 ++-- lib/routes/dw/news.ts | 2 +- lib/routes/dw/rss.ts | 6 +- lib/routes/dx2025/index.ts | 14 +-- lib/routes/dxy/types.ts | 1 + lib/routes/dxy/utils.ts | 14 +-- lib/routes/dytt/index.ts | 12 +- lib/routes/e-hentai/index.tsx | 40 +++---- lib/routes/eagle/blog.ts | 6 +- lib/routes/eagle/changelog.ts | 10 +- lib/routes/earthquake/ceic.ts | 2 +- lib/routes/eastday/24.ts | 6 +- lib/routes/eastday/sh.ts | 2 +- lib/routes/eastmoney/report/index.tsx | 18 +-- lib/routes/ebc/realtime.ts | 6 +- lib/routes/ecnu/art.ts | 6 +- lib/routes/ecnu/bksy.ts | 6 +- lib/routes/ecnu/cee.ts | 6 +- lib/routes/ecnu/chem.ts | 6 +- lib/routes/ecnu/chinese.ts | 8 +- lib/routes/ecnu/comm.ts | 6 +- lib/routes/ecnu/contest.tsx | 2 +- lib/routes/ecnu/cs.ts | 6 +- lib/routes/ecnu/cxcy.ts | 6 +- lib/routes/ecnu/dase.ts | 6 +- lib/routes/ecnu/dx.ts | 6 +- lib/routes/ecnu/dxb.ts | 6 +- lib/routes/ecnu/ed.ts | 6 +- lib/routes/ecnu/geoai.ts | 6 +- lib/routes/ecnu/ghcollege.ts | 6 +- lib/routes/ecnu/history.ts | 6 +- lib/routes/ecnu/jiaoliu.ts | 6 +- lib/routes/ecnu/jwc.ts | 6 +- lib/routes/ecnu/mks.ts | 6 +- lib/routes/ecnu/mxcsy.ts | 6 +- lib/routes/ecnu/pharm.ts | 6 +- lib/routes/ecnu/philo.ts | 6 +- lib/routes/ecnu/phy.ts | 8 +- lib/routes/ecnu/psy.ts | 8 +- lib/routes/ecnu/sees.ts | 6 +- lib/routes/ecnu/sei.ts | 6 +- lib/routes/ecnu/spm.ts | 6 +- lib/routes/ecnu/stat.ts | 8 +- lib/routes/ecnu/tyxx.ts | 6 +- lib/routes/ecnu/yjs.ts | 10 +- lib/routes/economist/espresso.ts | 4 +- lib/routes/economist/full.ts | 10 +- lib/routes/ecust/gschool/yjs.ts | 8 +- lib/routes/ecust/jwc/notice.ts | 8 +- lib/routes/eeo/kuaixun.ts | 10 +- lib/routes/ehentai/ehapi.ts | 14 ++- lib/routes/ehentai/favorites.ts | 2 +- lib/routes/ehentai/search.ts | 4 +- lib/routes/ehentai/tag.ts | 2 +- lib/routes/ekantipur/issue.ts | 10 +- lib/routes/elasticsearch-cn/index.ts | 14 +-- lib/routes/elecfans/article.ts | 8 +- lib/routes/elecfans/soft.ts | 8 +- lib/routes/elsevier/issue.ts | 8 +- lib/routes/elsevier/journal.ts | 12 +- lib/routes/embassy/index.ts | 4 +- lib/routes/engineering/tag.ts | 8 +- lib/routes/enterprisecraftsmanship/index.ts | 8 +- lib/routes/eprice/rss.tsx | 32 +++--- lib/routes/eshukan/academic.ts | 30 ++--- lib/routes/espn/news.tsx | 10 +- lib/routes/esquirehk/tag.tsx | 16 +-- lib/routes/europechinese/latest.ts | 2 +- lib/routes/eventbrite/events.ts | 2 +- lib/routes/everia/category.ts | 2 +- lib/routes/everia/latest.ts | 2 +- lib/routes/everia/search.ts | 2 +- lib/routes/everia/tag.ts | 2 +- lib/routes/expats/czech-news.ts | 12 +- lib/routes/f-droid/apprelease.ts | 2 +- lib/routes/f95zone/thread.ts | 2 +- lib/routes/famitsu/category.tsx | 6 +- lib/routes/fangchan/list.tsx | 16 +-- lib/routes/fansly/post.ts | 4 +- lib/routes/fansly/tag.ts | 4 +- lib/routes/fantube/creator.tsx | 6 +- lib/routes/fanxinzhui/index.tsx | 53 ++++----- lib/routes/farmatters/index.tsx | 8 +- lib/routes/fashionnetwork/index.ts | 24 ++-- lib/routes/fastbull/express-news.ts | 8 +- lib/routes/fastbull/news.tsx | 12 +- lib/routes/fcbayern/news.ts | 4 +- lib/routes/fda/cdrh.ts | 16 +-- lib/routes/fediverse/timeline.ts | 2 +- lib/routes/feng/forum.tsx | 2 +- lib/routes/feng/utils.ts | 2 +- lib/routes/ff14/ff14-global.ts | 2 +- lib/routes/finviz/news.ts | 14 +-- lib/routes/firecore/index.ts | 8 +- lib/routes/firefox/breaches.ts | 14 +-- lib/routes/fishshell/index.ts | 6 +- lib/routes/fjdaily/index.ts | 2 +- lib/routes/fjksbm/index.ts | 14 +-- lib/routes/flyert/forum.ts | 2 +- lib/routes/flyert/preferential.ts | 18 +-- lib/routes/flyert/util.ts | 53 ++++----- lib/routes/flyert/utils.ts | 4 +- lib/routes/follow/profile.ts | 6 +- lib/routes/foreignaffairs/rss.ts | 6 +- lib/routes/foresightnews/article.ts | 4 +- lib/routes/foresightnews/column.ts | 4 +- lib/routes/foresightnews/index.ts | 4 +- lib/routes/foresightnews/news.ts | 4 +- lib/routes/foresightnews/util.tsx | 10 +- lib/routes/fortnite/news.ts | 16 +-- lib/routes/fortunechina/index.ts | 30 ++--- lib/routes/freewechat/profile.ts | 22 ++-- lib/routes/freexcomic/book.ts | 14 +-- lib/routes/ft/myft.ts | 6 +- lib/routes/ftchinese/channel.ts | 1 - lib/routes/ftchinese/utils.ts | 2 +- lib/routes/ftm/index.ts | 17 ++- lib/routes/furstar/archive.ts | 2 +- lib/routes/furstar/artists.ts | 4 +- lib/routes/furstar/index.ts | 2 +- lib/routes/furstar/utils.tsx | 8 +- lib/routes/futunn/live.ts | 4 +- lib/routes/fx-markets/channel.ts | 15 +-- lib/routes/fx678/kx.ts | 8 +- lib/routes/fxiaoke/crm.ts | 28 ++--- lib/routes/fzmtr/announcements.ts | 8 +- lib/routes/gameapps/index.tsx | 14 +-- lib/routes/gamebase/news.tsx | 6 +- lib/routes/gamegene/news.ts | 14 +-- lib/routes/gamer/gnn-index.ts | 20 ++-- lib/routes/gamer/hot.ts | 13 ++- lib/routes/gamersecret/index.ts | 14 +-- lib/routes/gamme/category.ts | 8 +- lib/routes/gamme/tag.ts | 14 +-- lib/routes/gaoyu/blog.ts | 16 +-- lib/routes/gcores/radio.tsx | 4 +- lib/routes/gcores/user-radios.ts | 6 +- lib/routes/gcores/user-talks.ts | 6 +- lib/routes/gcores/util.ts | 6 +- lib/routes/gdsrx/index.ts | 16 +-- lib/routes/gdut/oa-news.ts | 17 +-- lib/routes/gelonghui/hot-article.ts | 4 +- lib/routes/gelonghui/utils.ts | 2 +- lib/routes/getitfree/util.ts | 7 +- lib/routes/gettr/user.tsx | 4 +- lib/routes/gigazine/en.ts | 4 +- lib/routes/gihyo/group.ts | 4 +- lib/routes/gisreportsonline/index.ts | 13 ++- lib/routes/github/advisor.ts | 8 +- lib/routes/github/branches.ts | 2 +- lib/routes/github/comments.ts | 20 ++-- lib/routes/github/contributors.ts | 2 +- lib/routes/github/file.ts | 4 +- lib/routes/github/gist.ts | 4 +- lib/routes/github/issue.ts | 2 +- lib/routes/github/pulls.ts | 2 +- lib/routes/github/pulse.tsx | 2 +- lib/routes/github/topic.ts | 12 +- lib/routes/github/trending.tsx | 2 +- lib/routes/github/wiki.ts | 10 +- lib/routes/gitpod/blog.tsx | 16 +-- lib/routes/gitpod/changelog.ts | 18 +-- lib/routes/gitstar-ranking/index.tsx | 8 +- lib/routes/globallawreview/index.ts | 30 ++--- lib/routes/gmcmonline/chinacustoms.ts | 40 +++---- lib/routes/go/jihs/idwr.ts | 8 +- lib/routes/go/mhlw/pdf.ts | 14 +-- lib/routes/gogoanimehd/recent-releases.ts | 2 +- lib/routes/google/alerts.ts | 10 +- lib/routes/google/fonts.tsx | 4 +- lib/routes/google/news.tsx | 26 ++--- lib/routes/google/play.ts | 2 +- lib/routes/google/research.ts | 8 +- lib/routes/google/scholar.ts | 2 +- lib/routes/gov/ah/kjt.ts | 18 +-- lib/routes/gov/beijing/bjedu/gh.ts | 16 +-- lib/routes/gov/beijing/jw/tzgg.ts | 18 +-- lib/routes/gov/beijing/kw/index.ts | 18 +-- lib/routes/gov/caac/cjwt.tsx | 4 +- lib/routes/gov/ccdi/utils.ts | 12 +- lib/routes/gov/chinamine-safety/util.ts | 3 +- lib/routes/gov/chinamine-safety/xw.ts | 8 +- lib/routes/gov/chinamine-safety/zfxxgk.ts | 8 +- lib/routes/gov/chinatax/latest.ts | 16 +-- lib/routes/gov/chongqing/gzw.ts | 20 ++-- lib/routes/gov/chongqing/rsks.ts | 14 +-- lib/routes/gov/chongqing/sydwgkzp.ts | 14 +-- lib/routes/gov/cmse/fxrw.ts | 12 +- lib/routes/gov/cmse/index.ts | 17 +-- lib/routes/gov/cn/news/index.ts | 26 +++-- lib/routes/gov/cnnic/index.ts | 12 +- lib/routes/gov/csrc/auditstatus.ts | 6 +- lib/routes/gov/csrc/csrc.ts | 2 +- lib/routes/gov/csrc/news.tsx | 8 +- lib/routes/gov/customs/list.ts | 14 +-- lib/routes/gov/forestry/gjlckjdjt.ts | 26 ++--- lib/routes/gov/general/general.ts | 20 ++-- lib/routes/gov/gz/index.ts | 8 +- lib/routes/gov/hainan/iitb/tzgg.ts | 4 +- lib/routes/gov/hangzhou/zwfw.tsx | 56 ++++----- lib/routes/gov/hebei/czt.ts | 12 +- lib/routes/gov/huizhou/zwgk/index.ts | 20 ++-- lib/routes/gov/hunan/changsha/major-email.ts | 12 +- lib/routes/gov/jgjcndrc/index.ts | 14 +-- lib/routes/gov/jiangsu/wlt/index.tsx | 5 +- .../healthcommission/medical-exam-notice.ts | 6 +- lib/routes/gov/lswz/index.ts | 18 +-- lib/routes/gov/maonan/maonan.ts | 8 +- lib/routes/gov/mee/nnsa.ts | 12 +- lib/routes/gov/mee/ywdt.ts | 18 +-- lib/routes/gov/mem/sgcc.ts | 18 +-- lib/routes/gov/mem/zfxxgkpt.ts | 8 +- lib/routes/gov/mfa/wjdt.ts | 10 +- lib/routes/gov/miit/wjfb.ts | 8 +- lib/routes/gov/miit/wjgs.ts | 16 +-- lib/routes/gov/miit/yjzj.ts | 8 +- lib/routes/gov/miit/zcjd.ts | 16 +-- lib/routes/gov/miit/zcwj.ts | 6 +- lib/routes/gov/moa/gjs.ts | 12 +- lib/routes/gov/moa/moa.ts | 8 +- lib/routes/gov/moa/szcpxx.ts | 22 ++-- lib/routes/gov/moe/moe.ts | 14 +-- lib/routes/gov/moe/s78.ts | 12 +- lib/routes/gov/mof/bond.ts | 10 +- lib/routes/gov/mofcom/article.ts | 24 ++-- lib/routes/gov/moj/aac/news.ts | 20 ++-- lib/routes/gov/moj/lfyjzj.ts | 6 +- lib/routes/gov/mot/index.ts | 16 +-- lib/routes/gov/ndrc/fggz.ts | 14 +-- lib/routes/gov/ndrc/xwdt.ts | 20 ++-- lib/routes/gov/ndrc/zfxxgk.ts | 22 ++-- lib/routes/gov/nea/bureau.ts | 6 +- lib/routes/gov/nfra/index.ts | 4 +- lib/routes/gov/nifdc/index.ts | 20 ++-- lib/routes/gov/nmpa/generic.ts | 14 +-- lib/routes/gov/nopss/index.ts | 12 +- lib/routes/gov/npc/index.ts | 4 +- lib/routes/gov/nrta/dsj.ts | 14 +-- lib/routes/gov/nrta/news.ts | 13 ++- lib/routes/gov/nsfc/index.ts | 18 +-- lib/routes/gov/pbc/goutongjiaoliu.ts | 16 +-- lib/routes/gov/pbc/gzlw.ts | 2 +- lib/routes/gov/pbc/trade-announcement.ts | 16 +-- lib/routes/gov/pbc/zcyj.ts | 2 +- lib/routes/gov/safe/util.tsx | 9 +- lib/routes/gov/samr/xgzlyhd.tsx | 6 +- lib/routes/gov/sasac/generic.ts | 14 +-- lib/routes/gov/sh/fgw/index.tsx | 22 ++-- lib/routes/gov/sh/wgj/wgj.tsx | 12 +- lib/routes/gov/sh/wsjkw/yqtb/index.ts | 8 +- lib/routes/gov/sh/yjj/index.ts | 18 +-- lib/routes/gov/shaanxi/kjt.ts | 16 +-- lib/routes/gov/shenzhen/szlh/index.ts | 4 +- lib/routes/gov/shenzhen/xxgk/zfxxgj.ts | 14 +-- lib/routes/gov/shenzhen/zjj/index.ts | 6 +- .../gov/sichuan/deyang/govpublicinfo.tsx | 4 +- lib/routes/gov/sichuan/deyang/mztoday.tsx | 4 +- lib/routes/gov/stats/index.tsx | 24 ++-- lib/routes/gov/suzhou/doc.ts | 16 +-- lib/routes/gov/suzhou/fg.ts | 20 ++-- lib/routes/gov/suzhou/news.ts | 12 +- lib/routes/gov/taiyuan/rsj.ts | 6 +- lib/routes/gov/wuhan/whyw.ts | 14 +-- lib/routes/gov/xuzhou/hrss.ts | 16 +-- lib/routes/gov/zhejiang/gwy.ts | 20 ++-- lib/routes/gov/zhengce/govall.ts | 5 +- lib/routes/gov/zhengce/index.ts | 24 ++-- lib/routes/gov/zhengce/wenjian.ts | 14 +-- lib/routes/gq/news.ts | 6 +- lib/routes/grainoil/category.ts | 12 +- lib/routes/greasyfork/feedback.ts | 8 +- lib/routes/greasyfork/scripts.ts | 12 +- lib/routes/greasyfork/versions.ts | 8 +- lib/routes/grist/featured.ts | 10 +- lib/routes/grist/index.ts | 4 +- lib/routes/grist/series.ts | 4 +- lib/routes/grist/topic.ts | 4 +- lib/routes/grubstreet/utils.ts | 3 +- lib/routes/guancha/headline.ts | 12 +- lib/routes/guancha/index.ts | 18 +-- lib/routes/guancha/member.ts | 2 +- lib/routes/guancha/personalpage.ts | 8 +- lib/routes/guancha/topic.ts | 12 +- lib/routes/guangdiu/index.ts | 16 +-- lib/routes/guangdiu/rank.ts | 16 +-- lib/routes/guangdiu/search.ts | 18 +-- lib/routes/guangzhoumetro/news.ts | 8 +- lib/routes/guanhai/index.ts | 24 ++-- lib/routes/guduodata/daily.tsx | 2 +- lib/routes/guozaoke/index.ts | 6 +- lib/routes/gzhu/yjs.ts | 8 +- lib/routes/hackernews/index.ts | 34 +++--- lib/routes/hacking8/index.ts | 12 +- lib/routes/hacking8/search.ts | 12 +- lib/routes/hackyournews/index.ts | 2 +- lib/routes/hafu/utils.tsx | 7 +- lib/routes/hakkatv/news.ts | 4 +- lib/routes/hameln/chapter.ts | 8 +- lib/routes/hanime1/search.ts | 2 +- lib/routes/harvard/health/blog.ts | 12 +- lib/routes/hashnode/blog.tsx | 4 +- lib/routes/hbooker/chapter.ts | 12 +- lib/routes/hbr/topic.ts | 20 ++-- lib/routes/hdu/auto/utils.ts | 2 +- lib/routes/hdu/cs/notice.ts | 8 +- lib/routes/hdu/cs/pg.ts | 8 +- lib/routes/hebeimuseum/list.tsx | 14 +-- .../hebtv/nong-bo-shi-zai-xing-dong.tsx | 14 +-- lib/routes/hellobtc/information.ts | 14 ++- lib/routes/hellobtc/kepu.ts | 16 +-- lib/routes/hexun/index.ts | 4 +- lib/routes/hfut/hf/utils.ts | 10 +- lib/routes/hfut/xc/utils.ts | 10 +- lib/routes/hinatazaka46/news.ts | 12 +- lib/routes/hiring.cafe/jobs.tsx | 2 +- lib/routes/hit/hitgs.ts | 14 +-- lib/routes/hit/today.ts | 8 +- lib/routes/hitsz/article.ts | 6 +- lib/routes/hitsz/due-tzgg.ts | 4 +- lib/routes/hitwh/today.ts | 6 +- lib/routes/hkej/index.tsx | 18 +-- lib/routes/hkepc/index.ts | 11 +- lib/routes/hket/index.tsx | 25 +++-- lib/routes/hkjunkcall/index.ts | 14 +-- lib/routes/hko/earthquake.ts | 14 +-- lib/routes/hljucm/yjsy.ts | 10 +- lib/routes/hnrb/index.ts | 18 +-- lib/routes/hongkong/dh.ts | 14 +-- lib/routes/hostmonit/cloudflareyes.tsx | 6 +- lib/routes/hotukdeals/index.ts | 8 +- lib/routes/hoyolab/news.tsx | 1 + lib/routes/hpoi/info.ts | 3 +- lib/routes/hpoi/user.ts | 8 +- lib/routes/hpoi/utils.ts | 8 +- lib/routes/hrbeu/cec/list.ts | 8 +- lib/routes/hrbeu/gx/list.ts | 16 +-- lib/routes/hrbeu/job/calendar.ts | 2 +- lib/routes/hrbeu/job/list.ts | 14 +-- lib/routes/hrbeu/sec/list.ts | 10 +- lib/routes/hrbeu/uae/news.ts | 16 +-- lib/routes/hrbeu/ugs/news.ts | 12 +- lib/routes/hrbeu/yjsy/list.ts | 12 +- lib/routes/hrbust/cs.ts | 10 +- lib/routes/hrbust/gzc.ts | 13 ++- lib/routes/hrbust/jwzx.ts | 13 ++- lib/routes/hrbust/lib.ts | 13 ++- lib/routes/hrbust/news.ts | 10 +- lib/routes/hrbust/nic.ts | 10 +- lib/routes/huanqiu/index.ts | 8 +- .../huawei/developer/harmonyos/samplecode.ts | 6 +- lib/routes/hubu/index.ts | 16 +-- lib/routes/hubu/zhxy.ts | 16 +-- lib/routes/humanlayer/blog.ts | 4 +- lib/routes/hunanpea/rsks.ts | 12 +- lib/routes/hunau/gfxy/index.ts | 1 + lib/routes/hunau/ied.ts | 2 +- lib/routes/hunau/jwc.ts | 2 +- lib/routes/hunau/utils/common.ts | 24 +++- lib/routes/hunau/utils/news-content.ts | 2 +- lib/routes/hunau/xky/index.ts | 2 + lib/routes/hupu/all.tsx | 14 +-- lib/routes/hupu/bbs.tsx | 12 +- lib/routes/hupu/news.ts | 2 +- lib/routes/hust/aia/news.ts | 10 +- lib/routes/hust/aia/notice.ts | 10 +- lib/routes/hust/gs.ts | 16 +-- lib/routes/hust/mse.ts | 20 ++-- lib/routes/hust/yjs.ts | 8 +- lib/routes/huxiu/util.ts | 34 +++--- lib/routes/hypergryph/arknights/arktca.ts | 8 +- lib/routes/hypergryph/arknights/japan.ts | 4 +- lib/routes/hypergryph/arknights/news.ts | 8 +- lib/routes/hypergryph/endfield/news.ts | 4 +- lib/routes/ianspriggs/index.ts | 26 ++--- lib/routes/icac/news.ts | 8 +- lib/routes/idaily/index.tsx | 4 +- lib/routes/idolmaster/news.ts | 2 +- lib/routes/ieee-security/sp.ts | 10 +- lib/routes/iehou/index.ts | 18 +-- lib/routes/ielts/index.ts | 8 +- lib/routes/ifanr/digest.ts | 6 +- lib/routes/ifeng/feng.ts | 4 +- lib/routes/iguoguo/index.ts | 6 +- lib/routes/ikea/cn/family-offers.ts | 4 +- lib/routes/ikea/cn/new.ts | 4 +- lib/routes/ikea/gb/offer.ts | 24 ++-- lib/routes/iknowwhatyoudownload/daily.tsx | 6 +- lib/routes/imagemagick/changelog.ts | 8 +- lib/routes/imdb/chart.tsx | 2 +- lib/routes/imiker/jinghua.ts | 6 +- lib/routes/imop/tianshu.ts | 12 +- lib/routes/indianexpress/section.ts | 6 +- lib/routes/indiansinkuwait/latest.ts | 12 +- lib/routes/indienova/gamedb.ts | 8 +- lib/routes/indienova/usergames.ts | 16 +-- lib/routes/indienova/utils.ts | 8 +- lib/routes/inewsweek/index.ts | 8 +- lib/routes/infoq/presentations.ts | 32 +++--- lib/routes/informs/index.tsx | 18 +-- lib/routes/infzm/hot.ts | 3 +- lib/routes/infzm/index.ts | 3 +- lib/routes/infzm/utils.ts | 2 +- lib/routes/inoreader/rss.ts | 14 +-- lib/routes/instagram/private-api/index.ts | 2 +- lib/routes/instagram/templates/video.tsx | 1 + lib/routes/instagram/web-api/index.ts | 2 +- lib/routes/instagram/web-api/utils.ts | 6 +- lib/routes/instructables/projects.ts | 4 +- lib/routes/investor/index.ts | 12 +- lib/routes/iplaysoft/index.ts | 2 +- lib/routes/iqilu/program.ts | 24 ++-- lib/routes/iqiyi/album.tsx | 2 +- lib/routes/iqiyi/video.ts | 2 +- lib/routes/iqnew/latest.ts | 11 +- lib/routes/iresearch/report.ts | 8 +- lib/routes/iresearch/weekly.ts | 7 +- lib/routes/itch/devlog.ts | 18 +-- lib/routes/itch/index.ts | 16 +-- lib/routes/itch/posts.ts | 10 +- lib/routes/ithome/index.ts | 20 ++-- lib/routes/ithome/ranking.ts | 14 +-- lib/routes/ithome/tag.ts | 26 +++-- lib/routes/ithome/zt.tsx | 36 +++--- lib/routes/itsec/news.ts | 12 +- lib/routes/ixigua/user-video.tsx | 2 +- lib/routes/j-test/news.ts | 2 +- lib/routes/jandan/index.ts | 19 ++-- lib/routes/japanpost/track.tsx | 7 +- lib/routes/javbus/index.tsx | 17 +-- lib/routes/javdb/utils.ts | 9 +- lib/routes/javlibrary/utils.tsx | 21 ++-- lib/routes/javtiful/actress.ts | 4 +- lib/routes/javtiful/channel.ts | 4 +- lib/routes/jbma/report.ts | 8 +- lib/routes/jianshu/utils.ts | 4 +- lib/routes/jiemian/common.tsx | 8 +- lib/routes/jike/user.ts | 2 +- lib/routes/jike/utils.ts | 6 +- lib/routes/jingzhengu/news.ts | 4 +- lib/routes/jinse/catalogue.ts | 8 +- lib/routes/jinse/lives.ts | 6 +- lib/routes/jinse/timeline.ts | 8 +- lib/routes/jisilu/category.ts | 4 +- lib/routes/jisilu/explore.ts | 4 +- lib/routes/jisilu/people.ts | 9 +- lib/routes/jisilu/topic.ts | 4 +- lib/routes/jisilu/util.ts | 2 +- lib/routes/jjwxc/author.tsx | 6 +- lib/routes/jjwxc/book.ts | 26 ++--- lib/routes/joins/chinese.tsx | 24 ++-- lib/routes/joneslanglasalle/index.ts | 4 +- lib/routes/jpmorganchase/research.ts | 2 +- lib/routes/jpxgmn/search.ts | 16 +-- lib/routes/jpxgmn/tab.ts | 16 +-- lib/routes/jpxgmn/weekly.ts | 8 +- lib/routes/jseea/news.ts | 14 +-- lib/routes/jsu/cxzx.ts | 6 +- lib/routes/jsu/jwc.ts | 4 +- lib/routes/jsu/math.ts | 4 +- lib/routes/jsu/rjxy.ts | 4 +- lib/routes/jsu/universityindex.ts | 4 +- lib/routes/juejin/trending.ts | 2 +- lib/routes/juejin/utils.ts | 2 +- lib/routes/jumeili/home.ts | 2 +- lib/routes/jump/discount.tsx | 2 +- lib/routes/junhe/legal-updates.ts | 20 ++-- lib/routes/kadokawa/blog.ts | 24 ++-- lib/routes/kakuyomu/works.ts | 2 +- lib/routes/kamen-rider-official/news.ts | 6 +- lib/routes/kantarworldpanel/index.tsx | 28 ++--- lib/routes/kanxue/topic.ts | 6 +- lib/routes/kbs/news.ts | 18 +-- lib/routes/kbs/today.ts | 16 +-- lib/routes/kcna/news.tsx | 8 +- lib/routes/keep/user.tsx | 4 +- lib/routes/keepass/news.ts | 18 +-- lib/routes/kemono/index.tsx | 2 +- lib/routes/kemono/types.ts | 2 + lib/routes/kepu/live.tsx | 4 +- lib/routes/keylol/index.ts | 36 +++--- lib/routes/kimlaw/thesis.ts | 14 +-- lib/routes/kiro/blog.ts | 12 +- lib/routes/kiro/changelog.ts | 12 +- lib/routes/kisskiss/blog.ts | 8 +- lib/routes/koreaherald/index.ts | 2 +- lib/routes/kovidgoyal/kitty/changelog.ts | 6 +- lib/routes/koyso/index.tsx | 12 +- lib/routes/kpmg/insights.tsx | 2 +- lib/routes/kpopping/kpics.ts | 14 +-- lib/routes/kpopping/news.ts | 16 +-- lib/routes/kuaidi100/index.ts | 2 +- lib/routes/kuaidi100/utils.ts | 37 +++--- lib/routes/kuaishou/profile.ts | 2 +- lib/routes/kunchengblog/essay.ts | 10 +- lib/routes/kuwaitlocal/index.ts | 18 +-- lib/routes/kyodonews/index.tsx | 7 +- lib/routes/laimanhua/index.ts | 8 +- lib/routes/lang/room.tsx | 2 +- lib/routes/laohu8/personal.ts | 17 +-- lib/routes/last-origin/news.ts | 2 +- lib/routes/latepost/index.ts | 8 +- lib/routes/layoffs/index.ts | 2 +- lib/routes/learnblockchain/posts.ts | 2 +- lib/routes/learnku/topic.tsx | 6 +- lib/routes/leetcode/articles.ts | 12 +- lib/routes/leiphone/utils.ts | 3 +- lib/routes/lemonde/en.ts | 4 +- lib/routes/lemonde/index.ts | 4 +- lib/routes/lenovo/drive.tsx | 3 +- lib/routes/lephoceen/chrono.ts | 2 +- lib/routes/lfsyd/utils.tsx | 4 +- lib/routes/lhratings/research.ts | 23 ++-- lib/routes/line/utils.ts | 4 +- lib/routes/lineageos/changes.ts | 6 +- lib/routes/linkedin/cn/renderer.ts | 24 ++-- lib/routes/linkedin/cn/utils.tsx | 2 +- lib/routes/linkedin/jobs.ts | 10 +- lib/routes/linkedin/models.ts | 13 --- lib/routes/linkedin/utils.ts | 19 ++-- lib/routes/linkresearcher/index.tsx | 2 +- lib/routes/linovelib/novel.ts | 6 +- lib/routes/liquipedia/dota2-matches.ts | 16 +-- lib/routes/literotica/category.ts | 14 +-- lib/routes/literotica/new.ts | 16 +-- lib/routes/liulinblog/index.ts | 22 ++-- lib/routes/liulinblog/itnews.ts | 3 +- lib/routes/liveuamap/index.ts | 8 +- lib/routes/locals/feed.ts | 2 +- lib/routes/lofter/collection.ts | 2 +- lib/routes/lofter/tag.ts | 4 +- lib/routes/lofter/user.ts | 2 +- lib/routes/logclub/index.ts | 38 +++---- lib/routes/logclub/report.ts | 18 +-- lib/routes/logonews/index.tsx | 15 +-- lib/routes/logrocket/index.ts | 18 +-- lib/routes/lorientlejour/index.tsx | 4 +- lib/routes/lrepacks/index.ts | 32 +++--- lib/routes/lsnu/jiaowc/tzgg.ts | 2 +- lib/routes/ltaaa/article.ts | 14 +-- lib/routes/luogu/contest.ts | 20 +++- lib/routes/luogu/daily.ts | 2 +- lib/routes/luolei/index.tsx | 18 +-- lib/routes/lvv2/news.ts | 26 +++-- lib/routes/lvv2/top.ts | 24 ++-- lib/routes/lxixsxa/jsonp-helper.ts | 2 +- lib/routes/m4/index.ts | 16 +-- lib/routes/macfilos/blog.ts | 16 +-- lib/routes/macmenubar/recently.ts | 2 +- lib/routes/macupdate/app.ts | 4 +- lib/routes/magazinelib/latest-magazine.tsx | 15 +-- lib/routes/magnumphotos/magazine.ts | 8 +- lib/routes/mail/imap.ts | 14 +-- lib/routes/malaysiakini/index.ts | 8 +- lib/routes/manhuagui/comic.ts | 14 +-- lib/routes/manhuagui/subscribe.tsx | 2 +- lib/routes/mashiro/index.ts | 14 +-- lib/routes/mathpix/blog.tsx | 16 +-- lib/routes/mckinsey/cn/index.ts | 10 +- lib/routes/mdpi/journal.tsx | 4 +- lib/routes/medieval-china/post.ts | 2 +- lib/routes/medsci/index.ts | 14 +-- lib/routes/meishichina/index.ts | 18 +-- lib/routes/meituan/tech.ts | 8 +- lib/routes/metacritic/index.tsx | 19 +++- lib/routes/meteoblue/weathernews.ts | 4 +- lib/routes/mhlw/monthly-labour-survey.ts | 4 +- lib/routes/mi/crowdfunding.ts | 4 +- lib/routes/mi/types.ts | 1 + lib/routes/mihoyo/bbs/cache.ts | 2 +- lib/routes/mindmeister/example.tsx | 16 +-- lib/routes/mingpao/index.tsx | 18 +-- lib/routes/miniflux/entry.ts | 14 +-- lib/routes/miniflux/subscription.ts | 6 +- lib/routes/missav/new.tsx | 4 +- lib/routes/miui/community/user.ts | 2 +- lib/routes/mixi2/community.ts | 4 +- lib/routes/mixi2/user.ts | 4 +- lib/routes/modb/topic.ts | 4 +- lib/routes/modelscope/community.tsx | 2 +- lib/routes/modian/zhongchou.ts | 14 +-- lib/routes/mohw/clarification.ts | 14 +-- lib/routes/mox/index.ts | 41 ++++--- lib/routes/mpaypass/main.ts | 2 +- lib/routes/mpaypass/news.ts | 6 +- lib/routes/mrm/index.ts | 12 +- lib/routes/musify/index.ts | 2 +- lib/routes/musikguru/news.ts | 12 +- lib/routes/mwm/index.ts | 12 +- lib/routes/mycard520/news.ts | 12 +- lib/routes/mydrivers/cid.ts | 8 +- lib/routes/mydrivers/index.tsx | 18 +-- lib/routes/mydrivers/rank.ts | 12 +- lib/routes/mydrivers/util.ts | 9 +- lib/routes/myfans/post.tsx | 8 +- lib/routes/myfigurecollection/activity.tsx | 18 +-- lib/routes/myfigurecollection/index.tsx | 17 +-- lib/routes/mysql/release.ts | 12 +- lib/routes/nankai/ai-notice.ts | 4 +- lib/routes/nankai/cc-notice.ts | 8 +- lib/routes/nankai/graduate-notice.ts | 4 +- lib/routes/nankai/jwc.ts | 6 +- lib/routes/nankai/notice.ts | 8 +- lib/routes/nankai/yzb.ts | 6 +- lib/routes/natgeo/dailyphoto.tsx | 2 +- lib/routes/natgeo/dailyselection.ts | 2 +- .../nationalgeographic/latest-stories.tsx | 2 +- lib/routes/naturalism/new.ts | 10 +- lib/routes/nature/news.ts | 8 +- lib/routes/nature/siteindex.ts | 12 +- lib/routes/nature/utils.ts | 50 ++++----- lib/routes/nautil/topics.tsx | 10 +- lib/routes/nautiljon/manga-releases.ts | 10 +- lib/routes/naver/search.ts | 2 +- lib/routes/nbd/daily.ts | 2 +- lib/routes/nbd/index.ts | 12 +- lib/routes/nber/common.tsx | 2 +- lib/routes/ncc-cma/cmdp.tsx | 14 +-- lib/routes/ncepu/master/masterinfo.ts | 12 +- lib/routes/ncwu/notice.ts | 10 +- lib/routes/ndss-symposium/ndss.ts | 18 +-- lib/routes/neatdownloadmanager/download.ts | 12 +- lib/routes/neea/jlpt.ts | 10 +- lib/routes/nenu/sohac.ts | 14 +-- lib/routes/nenu/yjsy.ts | 18 +-- lib/routes/netflav/index.tsx | 2 +- lib/routes/netflix/newsroom.ts | 16 +-- lib/routes/neu/bmie.ts | 4 +- lib/routes/neu/news.ts | 14 +-- lib/routes/newrank/utils.ts | 21 ++-- lib/routes/newrank/wechat.ts | 2 +- lib/routes/news/xhsxw.ts | 6 +- lib/routes/newsmarket/index.ts | 13 +-- lib/routes/newzmz/index.ts | 6 +- lib/routes/newzmz/util.ts | 26 ++--- lib/routes/nextapple/realtime.ts | 4 +- lib/routes/nextjs/blog.ts | 2 +- lib/routes/nga/post.ts | 12 +- lib/routes/ngocn2/index.ts | 14 +-- lib/routes/nhentai/util.tsx | 4 +- lib/routes/nhk/news-web-easy.tsx | 8 +- lib/routes/nhk/news.tsx | 2 +- lib/routes/niaogebiji/cat.ts | 20 ++-- lib/routes/nicovideo/utils.tsx | 2 +- lib/routes/nifd/research.ts | 18 +-- lib/routes/nikkei/cn/index.ts | 12 +- lib/routes/nikkei/index.ts | 6 +- lib/routes/nikkei/news.tsx | 36 +++--- lib/routes/nintendo/direct.ts | 2 +- lib/routes/nintendo/eshop-cn.ts | 2 +- lib/routes/nintendo/eshop-hk.ts | 11 +- lib/routes/nintendo/eshop-us.ts | 4 +- lib/routes/nintendo/news-china.ts | 2 +- lib/routes/nintendo/system-update.ts | 10 +- lib/routes/nintendo/utils.ts | 2 +- lib/routes/njglyy/utils/index.ts | 15 +-- lib/routes/njit/jwc.ts | 10 +- lib/routes/njit/tzgg.ts | 6 +- lib/routes/njnu/jwc/utils.ts | 2 +- lib/routes/nju/admission.ts | 5 +- lib/routes/nju/dafls.ts | 8 +- lib/routes/nju/gra.ts | 14 +-- lib/routes/nju/hosptial.ts | 5 +- lib/routes/nju/hqjt.ts | 8 +- lib/routes/nju/itsc.ts | 15 +-- lib/routes/nju/jjc.ts | 10 +- lib/routes/nju/jw.ts | 4 +- lib/routes/nju/scit.ts | 8 +- lib/routes/nju/zbb.ts | 20 ++-- lib/routes/nju/zcc.ts | 4 +- lib/routes/njucm/utils/index.ts | 13 ++- lib/routes/njuferret/blog.ts | 6 +- lib/routes/njupt/jwc.ts | 8 +- lib/routes/njust/cwc.ts | 2 +- lib/routes/njust/dgxg.ts | 2 +- lib/routes/njust/eoe.ts | 2 +- lib/routes/njust/gs.ts | 6 +- lib/routes/njust/jwc.ts | 2 +- lib/routes/nlc/read.tsx | 20 ++-- lib/routes/nltimes/news.ts | 10 +- lib/routes/nmc/publish.ts | 16 +-- lib/routes/nmtv/column.tsx | 4 +- lib/routes/nodejs/blog.ts | 10 +- lib/routes/nosec/index.ts | 4 +- lib/routes/notateslaapp/update.ts | 8 +- lib/routes/notion/database.ts | 16 +-- lib/routes/now/news.ts | 6 +- lib/routes/nowcoder/discuss.ts | 2 +- lib/routes/nowcoder/experience.ts | 2 +- lib/routes/nowcoder/jobcenter.ts | 20 ++-- lib/routes/npr/full.ts | 10 +- lib/routes/ntdtv/channel.ts | 18 +-- lib/routes/nuaa/college/cae.ts | 7 +- lib/routes/nuaa/college/cs.ts | 7 +- lib/routes/nuaa/jwc/jwc.ts | 7 +- lib/routes/nuaa/yjsy/yjsy.ts | 7 +- lib/routes/nudt/yjszs.ts | 8 +- lib/routes/nuist/bulletin.ts | 4 +- lib/routes/nuist/cas.ts | 21 ++-- lib/routes/nuist/jwc.ts | 14 +-- lib/routes/nuist/library/lib.ts | 12 +- lib/routes/nuist/scs.ts | 16 +-- lib/routes/nuist/sese.ts | 16 +-- lib/routes/nuist/xgc.ts | 14 +-- lib/routes/nuist/yjs.ts | 14 +-- lib/routes/nwafu/all.ts | 24 ++-- lib/routes/nwnu/routes/college/csse.ts | 2 +- .../routes/department/academic-affairs.ts | 2 +- .../nwnu/routes/department/postgraduate.ts | 2 +- lib/routes/nyaa/main.ts | 16 +-- lib/routes/nytimes/book.ts | 2 +- lib/routes/nytimes/daily-briefing-chinese.tsx | 6 +- lib/routes/nytimes/index.ts | 10 +- lib/routes/nytimes/rss.ts | 9 +- lib/routes/nytimes/utils.ts | 5 +- lib/routes/obsidian/publish.ts | 4 +- lib/routes/oceanengine/arithmetic-index.tsx | 5 +- lib/routes/odaily/activity.ts | 2 +- lib/routes/odaily/user.ts | 2 +- lib/routes/oeeee/utils.ts | 4 +- lib/routes/oilchem/index.ts | 14 +-- lib/routes/oncc/index.tsx | 10 +- lib/routes/oncc/money18.ts | 8 +- lib/routes/onehu/common.ts | 10 +- lib/routes/onet/news.tsx | 12 +- lib/routes/oo-software/changelog.ts | 12 +- lib/routes/openai/cookbook.ts | 8 +- lib/routes/openwrt/releases.ts | 4 +- lib/routes/oreno3d/get-sec-page-data.ts | 8 +- lib/routes/oreno3d/main.tsx | 27 ++--- lib/routes/ornl/all-news.ts | 14 +-- lib/routes/oschina/column.ts | 16 +-- lib/routes/oschina/event.ts | 18 +-- lib/routes/oschina/topic.ts | 14 +-- lib/routes/oshwhub/explore.ts | 13 +-- lib/routes/osu/beatmaps/latest-ranked.tsx | 2 +- lib/routes/otobanana/cast.ts | 4 +- lib/routes/otobanana/livestream.ts | 4 +- lib/routes/otobanana/timeline.ts | 4 +- lib/routes/ouc/it-postgraduate.ts | 10 +- lib/routes/ouc/it-tx.ts | 16 +-- lib/routes/ouc/it.ts | 16 +-- lib/routes/ouc/jwc.ts | 16 +-- lib/routes/ouc/jwgl.ts | 16 +-- lib/routes/ouc/yjs.ts | 10 +- lib/routes/oup/index.tsx | 18 +-- lib/routes/outagereport/index.ts | 2 +- lib/routes/p-articles/contributors.ts | 6 +- lib/routes/p-articles/section.ts | 8 +- lib/routes/pacilution/latest.ts | 6 +- lib/routes/papers/category.ts | 8 +- lib/routes/papers/query.ts | 8 +- lib/routes/parliament.uk/petitions.tsx | 6 +- lib/routes/parliament/section77.ts | 30 ++--- lib/routes/patagonia/new-arrivals.tsx | 6 +- lib/routes/patreon/feed.tsx | 4 +- lib/routes/patreon/render-content-json.tsx | 4 +- lib/routes/paulgraham/article.ts | 14 +-- lib/routes/penguin-random-house/utils.tsx | 4 +- lib/routes/people/index.ts | 16 +-- lib/routes/people/liuyan.ts | 11 +- lib/routes/people/paper.ts | 88 ++++++--------- lib/routes/peopo/topic.ts | 16 +-- lib/routes/perplexity/blog.ts | 2 +- lib/routes/phoronix/index.ts | 14 ++- lib/routes/pianyuan/search.ts | 6 +- lib/routes/pianyuan/utils.ts | 4 +- lib/routes/picuki/profile.ts | 4 +- lib/routes/pikabu/community.ts | 8 +- lib/routes/pikabu/user.ts | 24 ++-- lib/routes/pincong/index.ts | 2 +- lib/routes/pincong/topic.ts | 2 +- lib/routes/pingwest/status.ts | 4 +- lib/routes/pingwest/user.ts | 2 +- lib/routes/pingwest/utils.ts | 2 +- lib/routes/pixabay/search.tsx | 4 +- lib/routes/pixelstech/index.ts | 12 +- lib/routes/pixiv/pixiv-got.ts | 6 +- lib/routes/piyao/jrpy.ts | 14 ++- lib/routes/pkmer/recent.ts | 12 +- lib/routes/pku/bbs/hot.ts | 4 +- lib/routes/pku/cls/announcement.ts | 14 +-- lib/routes/pku/eecs.ts | 14 +-- lib/routes/pku/hr.ts | 12 +- lib/routes/pku/nsd.ts | 8 +- lib/routes/pku/pkuyjs.ts | 10 +- lib/routes/pku/scc/recruit.ts | 14 +-- lib/routes/pku/ss/common.ts | 8 +- lib/routes/playno1/av.ts | 16 +-- lib/routes/playno1/st.ts | 14 +-- lib/routes/playno1/utils.ts | 2 +- lib/routes/playpcesor/rss.ts | 2 +- lib/routes/plurk/anonymous.ts | 6 +- lib/routes/plurk/topic.ts | 8 +- lib/routes/plurk/user.ts | 2 +- lib/routes/plurk/utils.ts | 40 ++++--- lib/routes/pnas/index.tsx | 18 +-- lib/routes/podwise/collections.ts | 8 +- lib/routes/podwise/episodes.ts | 19 ++-- lib/routes/polymarket/event.ts | 2 +- lib/routes/priconne-redive/news.ts | 20 ++-- lib/routes/producereport/index.ts | 12 +- lib/routes/producthunt/today.tsx | 2 +- lib/routes/ps/trophy.ts | 20 ++-- lib/routes/psnine/node.ts | 8 +- lib/routes/pts/curations.ts | 8 +- lib/routes/pts/index.ts | 14 +-- lib/routes/pts/projects.ts | 8 +- lib/routes/publico/items-processor.ts | 10 +- lib/routes/pubmed/trending.tsx | 12 +- lib/routes/pubscholar/utils.ts | 2 +- lib/routes/pumc/mdadmission.ts | 12 +- lib/routes/putty/changes.ts | 12 +- lib/routes/pwc/sustainability.ts | 4 +- lib/routes/python/release.ts | 14 +-- lib/routes/qbitai/category.ts | 8 +- lib/routes/qbitai/tag.ts | 4 +- lib/routes/qbittorrent/news.ts | 12 +- lib/routes/qdu/houqin.ts | 10 +- lib/routes/qdu/jwc.ts | 14 +-- lib/routes/qianp/news.ts | 16 +-- lib/routes/qianzhan/column.ts | 4 +- lib/routes/qianzhan/rank.ts | 4 +- lib/routes/qipamaijia/index.ts | 2 +- lib/routes/qlu/notice.ts | 16 +-- lib/routes/qm120/news.ts | 12 +- lib/routes/qoo-app/apps/card.ts | 18 +-- lib/routes/qoo-app/apps/comment.ts | 18 +-- lib/routes/qoo-app/apps/note.ts | 20 ++-- lib/routes/qoo-app/apps/post.ts | 20 ++-- lib/routes/qoo-app/news.ts | 4 +- lib/routes/qoo-app/notes/note.ts | 4 +- lib/routes/qoo-app/notes/topic.ts | 4 +- lib/routes/qoo-app/notes/user.ts | 4 +- lib/routes/qoo-app/user/app-comment.ts | 6 +- lib/routes/qoo-app/utils.ts | 14 +-- lib/routes/qq/ac/comic.ts | 8 +- lib/routes/qq/ac/utils.tsx | 11 +- lib/routes/qq/cfhd/index.ts | 16 +-- lib/routes/qq/lol/news.ts | 8 +- lib/routes/qq88/index.ts | 14 +-- lib/routes/qqorw/index.ts | 24 ++-- lib/routes/questmobile/report.ts | 8 +- lib/routes/quicker/qa.ts | 12 +- lib/routes/quicker/share.ts | 12 +- lib/routes/quicker/user.ts | 12 +- lib/routes/quicker/versions.ts | 8 +- lib/routes/qust/jw.ts | 2 +- lib/routes/qztc/sjxy/index.ts | 2 +- lib/routes/radio/templates/description.tsx | 2 +- lib/routes/rarehistoricalphotos/index.ts | 4 +- lib/routes/raspberrypi/magazine.ts | 12 +- lib/routes/rawkuma/manga.tsx | 18 +-- lib/routes/raycast/changelog.ts | 2 +- lib/routes/react/blog.ts | 2 +- lib/routes/reactiflux/transcripts.ts | 6 +- lib/routes/readhub/daily.ts | 6 +- lib/routes/readhub/index.ts | 4 +- lib/routes/readwise/list.ts | 4 +- lib/routes/remnote/changelog.ts | 4 +- lib/routes/researchgate/publications.ts | 18 +-- lib/routes/resonac/products.ts | 8 +- lib/routes/reuters/common.tsx | 5 +- lib/routes/reuters/investigates.ts | 16 +-- lib/routes/rfa/index.ts | 4 +- lib/routes/rfi/news.ts | 20 ++-- lib/routes/right/forum.ts | 12 +- lib/routes/rockthejvm/articles.ts | 16 +-- lib/routes/rodong/news.ts | 16 +-- lib/routes/routledge/book-series.tsx | 12 +- lib/routes/rsc/journal.tsx | 30 ++--- lib/routes/rsshub/routes.ts | 4 +- lib/routes/rsshub/transform/html.ts | 20 ++-- lib/routes/rsshub/transform/sitemap.ts | 6 +- lib/routes/ruancan/utils.ts | 15 +-- lib/routes/ruc/ai.ts | 11 +- lib/routes/ruc/hr.ts | 14 +-- lib/routes/sakurazaka46/blog.ts | 14 +-- lib/routes/sakurazaka46/news.ts | 14 +-- lib/routes/samd/news.ts | 2 +- lib/routes/samrdprc/index.ts | 12 +- lib/routes/sara/index.ts | 4 +- lib/routes/saraba1st/digest.tsx | 22 ++-- lib/routes/saraba1st/thread.ts | 2 +- lib/routes/sass/gs/index.ts | 7 +- lib/routes/scau/yjs.ts | 6 +- lib/routes/scau/yjsy.ts | 6 +- lib/routes/science/blogs.ts | 18 +-- lib/routes/science/cover.tsx | 22 ++-- lib/routes/science/current.ts | 4 +- lib/routes/science/early.ts | 4 +- lib/routes/science/utils.tsx | 12 +- lib/routes/sciencedirect/journal.ts | 6 +- lib/routes/sciencenet/blog.ts | 14 +-- lib/routes/sciencenet/user.ts | 12 +- lib/routes/scientificamerican/podcast.ts | 10 +- .../templates/description.tsx | 4 +- lib/routes/scmp/coronavirus.ts | 1 + lib/routes/scmp/index.ts | 4 +- lib/routes/scmp/topic.ts | 4 +- lib/routes/scnu/cs/match.ts | 8 +- lib/routes/scnu/jw.ts | 8 +- lib/routes/scnu/library.ts | 8 +- .../physics-school-announcements-and-news.ts | 11 +- lib/routes/scnu/ss.ts | 8 +- lib/routes/scnu/yjs.ts | 6 +- lib/routes/scoop/apps.tsx | 6 +- lib/routes/scpta/news.ts | 16 +-- lib/routes/sctv/programme.tsx | 6 +- lib/routes/scu/jwc/tzgg.ts | 8 +- lib/routes/scu/scupi/notice.ts | 6 +- lib/routes/scut/gzic/media.ts | 19 ++-- lib/routes/scut/gzic/news.ts | 20 ++-- lib/routes/scut/gzic/notice.ts | 19 ++-- lib/routes/scut/jwc/news.ts | 2 +- lib/routes/scut/jwc/notice.ts | 2 +- lib/routes/scut/jwc/school.ts | 2 +- lib/routes/scut/scet/notice.ts | 10 +- lib/routes/scut/seie/news-ccenter.ts | 16 +-- lib/routes/scut/smae/notice.ts | 14 +-- lib/routes/scut/yjs.ts | 8 +- lib/routes/scvtc/xygg.ts | 16 +-- lib/routes/sdo/ff14risingstones/posts.ts | 2 +- lib/routes/sdo/ff14risingstones/strats.ts | 2 +- .../sdo/ff14risingstones/user-dynamics.ts | 2 +- lib/routes/sdo/ff14risingstones/user-posts.ts | 2 +- .../sdo/ff14risingstones/user-resently.ts | 2 +- .../sdo/ff14risingstones/user-strats.ts | 2 +- lib/routes/sdu/cmse.ts | 16 +-- lib/routes/sdu/cs/index.ts | 18 +-- lib/routes/sdu/cs/yjsgz.ts | 16 +-- lib/routes/sdu/epe.ts | 14 +-- lib/routes/sdu/extractor/index.ts | 2 +- lib/routes/sdu/extractor/sdrj.ts | 2 +- lib/routes/sdu/extractor/view.ts | 2 +- lib/routes/sdu/extractor/wh/jwc.ts | 2 +- lib/routes/sdu/extractor/wh/news.ts | 2 +- lib/routes/sdu/gjsw.ts | 16 +-- lib/routes/sdu/mech.ts | 18 +-- lib/routes/sdu/qd/xszxqd.ts | 16 +-- lib/routes/sdu/qd/xyb.ts | 16 +-- lib/routes/sdu/sc.ts | 16 +-- lib/routes/sdu/wh/jwc.ts | 12 +- lib/routes/sdu/wh/news.ts | 12 +- lib/routes/sdu/ygb.ts | 16 +-- lib/routes/sdust/yjsy/zhaosheng.ts | 14 +-- lib/routes/sdzk/index.ts | 14 +-- lib/routes/secrss/author.ts | 2 +- lib/routes/secrss/category.ts | 2 +- lib/routes/seekingalpha/index.tsx | 4 +- lib/routes/sega/maimaidx.ts | 4 +- lib/routes/sehuatang/index.ts | 26 ++--- lib/routes/sehuatang/user.ts | 16 +-- lib/routes/semiconductors/index.ts | 14 +-- lib/routes/sensortower/blog.ts | 2 +- lib/routes/setn/index.ts | 18 +-- lib/routes/seu/cse/index.ts | 18 +-- lib/routes/seu/radio/academic.ts | 16 +-- lib/routes/seu/yjs.ts | 8 +- lib/routes/seu/yzb/index.ts | 16 +-- lib/routes/sfacg/novel-chapter.ts | 14 +-- lib/routes/shcstheatre/programs.tsx | 2 +- lib/routes/shiep/index.tsx | 12 +- lib/routes/shisu/en.ts | 4 +- lib/routes/shmeea/index.ts | 12 +- lib/routes/shmeea/self-study.ts | 2 +- lib/routes/shmtu/jwc.ts | 12 +- lib/routes/shmtu/www.ts | 10 +- lib/routes/shopback/store.ts | 10 +- lib/routes/shoppingdesign/posts.ts | 10 +- lib/routes/showstart/artist.ts | 2 +- lib/routes/showstart/brand.ts | 2 +- lib/routes/showstart/event.ts | 4 +- lib/routes/showstart/site.ts | 2 +- lib/routes/shu/jwb.ts | 6 +- lib/routes/sicau/dky.ts | 12 +- lib/routes/sicau/jk.ts | 2 +- lib/routes/sicau/yan.ts | 10 +- lib/routes/sicau/zsjy.ts | 12 +- lib/routes/sigsac/ccs.ts | 18 +-- lib/routes/simpleinfo/index.tsx | 20 ++-- lib/routes/sina/discovery.ts | 4 +- lib/routes/sina/sports.ts | 6 +- lib/routes/sina/utils.tsx | 10 +- lib/routes/sinchew/index.tsx | 18 +-- lib/routes/sis001/author.ts | 12 +- lib/routes/sis001/common.ts | 4 +- lib/routes/sis001/forum.ts | 10 +- lib/routes/sjtu/gs.ts | 14 +-- lib/routes/sjtu/jwc.ts | 4 +- lib/routes/sjtu/seiee/icisee.ts | 12 +- lib/routes/sjtu/seiee/index.ts | 16 +-- lib/routes/sjtu/yzb/zkxx.ts | 10 +- lib/routes/sketis/isabelle-dev/blog/index.ts | 3 +- lib/routes/skysports/news.ts | 12 +- lib/routes/slashdot/index.ts | 8 +- lib/routes/smashingmagazine/category.ts | 16 +-- lib/routes/smzdm/article.ts | 16 +-- lib/routes/smzdm/baoliao.ts | 14 +-- lib/routes/smzdm/haowen-fenlei.ts | 18 +-- lib/routes/smzdm/keyword.ts | 10 +- lib/routes/smzdm/product.ts | 6 +- lib/routes/smzdm/utils.ts | 2 +- lib/routes/snowpeak/us-new-arrivals.tsx | 61 +++++----- lib/routes/sobooks/utils.ts | 11 +- lib/routes/sohu/mobile.ts | 14 +-- lib/routes/sohu/mp.tsx | 8 +- lib/routes/solidot/_article.ts | 2 +- lib/routes/solidot/main.ts | 2 +- lib/routes/sony/downloads.ts | 4 +- lib/routes/sorrycc/index.ts | 8 +- lib/routes/soundofhope/channel.ts | 14 ++- lib/routes/soundon/podcast.ts | 4 +- lib/routes/sourceforge/index.ts | 2 +- lib/routes/springer/journal.tsx | 14 +-- lib/routes/sputniknews/index.ts | 14 +-- lib/routes/sqmc/www.ts | 8 +- lib/routes/sse/inquire.tsx | 2 +- lib/routes/sse/sselawsrules.ts | 16 +-- lib/routes/sspai/topics.ts | 27 ++--- lib/routes/sspu/jwc.ts | 12 +- lib/routes/sspu/pe.ts | 20 ++-- lib/routes/stanford/blog.ts | 4 +- lib/routes/startuplatte/index.ts | 12 +- lib/routes/stbu/jsjxy.ts | 12 +- lib/routes/stbu/xyxw.ts | 10 +- lib/routes/stcn/index.ts | 14 +-- lib/routes/stcn/kx.ts | 10 +- lib/routes/stcn/rank.ts | 10 +- lib/routes/steam/search.ts | 6 +- lib/routes/steam/sharefile-changelog.ts | 10 +- lib/routes/steam/workshop-search.tsx | 16 +-- lib/routes/stheadline/std/realtime.ts | 14 +-- lib/routes/stockedge/daily-news.ts | 4 +- lib/routes/storm/index.ts | 14 +-- lib/routes/storyfm/episodes.tsx | 16 +-- lib/routes/storyfm/index.ts | 4 +- lib/routes/stream-capital/search.ts | 8 +- lib/routes/studygolang/utils.ts | 19 ++-- lib/routes/subhd/index.ts | 18 +-- lib/routes/supchina/index.ts | 28 ++--- lib/routes/supchina/podcasts.ts | 13 ++- lib/routes/surfshark/blog.ts | 14 +-- lib/routes/sustainabilitymag/articles.ts | 4 +- lib/routes/sustech/bidding.ts | 6 +- lib/routes/sustech/newshub-zh.ts | 16 +-- lib/routes/swissinfo/index.ts | 14 +-- lib/routes/swjtu/jwc.ts | 3 +- lib/routes/swjtu/sports.ts | 2 +- lib/routes/swjtu/xg.ts | 2 +- lib/routes/swpu/bgw.ts | 4 +- lib/routes/swpu/cjxy.ts | 18 +-- lib/routes/swpu/dean.ts | 4 +- lib/routes/swpu/dxy.ts | 4 +- lib/routes/swpu/is.ts | 18 +-- lib/routes/swpu/scs.ts | 4 +- lib/routes/syosetu/ranking-isekai.ts | 5 +- lib/routes/syosetu/search.ts | 3 +- lib/routes/sysu/cse.ts | 6 +- lib/routes/sysu/ygafz.ts | 18 +-- lib/routes/szftedu/dongtai.ts | 20 ++-- lib/routes/szftedu/gonggao.ts | 20 ++-- lib/routes/szse/disclosure/listed-notice.ts | 6 +- lib/routes/szse/notice.ts | 8 +- lib/routes/szse/projectdynamic.tsx | 2 +- lib/routes/szse/rule.ts | 4 +- lib/routes/szu/yz/index.ts | 2 +- lib/routes/szu/yz/utils.ts | 4 +- lib/routes/t66y/index.ts | 6 +- lib/routes/t66y/post.ts | 2 +- lib/routes/taiwannews/hot.ts | 18 +-- lib/routes/tangshufang/index.ts | 12 +- lib/routes/taobao/mysql.ts | 27 +++-- lib/routes/taoguba/blog.ts | 4 +- lib/routes/taoguba/index.ts | 6 +- lib/routes/taoguba/util.ts | 2 +- lib/routes/taptap/types.ts | 5 + lib/routes/tass/news.ts | 8 +- lib/routes/tctmd/conference-news.ts | 10 +- lib/routes/techpowerup/index.ts | 6 +- lib/routes/techpowerup/review.ts | 6 +- lib/routes/techsir/index.ts | 6 +- lib/routes/telecompaper/news.ts | 12 +- lib/routes/telecompaper/search.ts | 12 +- lib/routes/telegram/blog.ts | 2 +- lib/routes/telegram/channel-media.ts | 2 +- lib/routes/telegram/channel.ts | 106 +++++++++--------- lib/routes/telegram/templates/video.tsx | 2 +- lib/routes/telegram/tglib/channel.ts | 5 +- lib/routes/tencent/news/author.tsx | 5 +- lib/routes/tencent/news/coronavirus/data.tsx | 4 +- lib/routes/tencent/news/coronavirus/total.tsx | 4 +- lib/routes/tencent/news/coronavirus/utils.ts | 2 +- lib/routes/tencent/pvp/newsindex.ts | 6 +- lib/routes/tencent/qq/sdk/changelog.ts | 4 +- lib/routes/tesla/cx.ts | 6 +- lib/routes/tesla/templates/description.tsx | 1 + lib/routes/test/index.ts | 34 +++--- lib/routes/theatlantic/news.ts | 4 +- lib/routes/theatlantic/utils.tsx | 2 +- lib/routes/thebrain/blog.tsx | 14 +-- lib/routes/thecover/channel.ts | 17 +-- lib/routes/thehindu/topic.ts | 22 ++-- lib/routes/theinitium/app.ts | 4 +- lib/routes/theinitium/utils.ts | 5 +- lib/routes/thenewslens/index.ts | 24 ++-- lib/routes/thepaper/839studio/category.ts | 8 +- lib/routes/thepaper/839studio/studio.ts | 8 +- lib/routes/thepaper/user.ts | 6 +- lib/routes/thepaper/utils.tsx | 5 +- lib/routes/theverge/index.ts | 10 +- lib/routes/thoughtco/index.ts | 24 ++-- lib/routes/tidb/blog.ts | 10 +- lib/routes/tiddlywiki/releases.ts | 10 +- lib/routes/timednews/news.ts | 10 +- lib/routes/tingshuitz/changsha.ts | 8 +- lib/routes/tingshuitz/dalian.ts | 10 +- lib/routes/tingshuitz/dongguan.ts | 10 +- lib/routes/tingshuitz/hangzhou.ts | 10 +- lib/routes/tingshuitz/xiaoshan.ts | 10 +- lib/routes/tingshuitz/yangjiang.ts | 2 +- lib/routes/tisi/index.ts | 18 +-- lib/routes/tju/cic/index.ts | 8 +- lib/routes/tju/news/index.ts | 4 +- lib/routes/tju/oaa/index.ts | 8 +- lib/routes/tju/yzb/index.ts | 8 +- lib/routes/tmtpost/nictation.ts | 8 +- lib/routes/tmtpost/util.ts | 8 +- lib/routes/tokeninsight/blog.ts | 2 +- lib/routes/tokeninsight/bulletin.ts | 2 +- lib/routes/tokeninsight/report.ts | 2 +- lib/routes/tongji/bks.ts | 12 +- lib/routes/tongji/gs.ts | 4 +- lib/routes/tongji/sem/_utils.ts | 4 +- lib/routes/tongji/sse/_article.ts | 2 +- lib/routes/tongji/sse/notice.ts | 8 +- lib/routes/tongji/yjs.ts | 4 +- lib/routes/tongli/news.ts | 20 ++-- lib/routes/toodaylab/index.ts | 32 +++--- lib/routes/toutiao/a-bogus.ts | 2 +- lib/routes/toutiao/types.ts | 4 +- lib/routes/toutiao/user.tsx | 20 ++-- lib/routes/towardsdatascience/latest.ts | 4 +- lib/routes/tqyb/sncsyjxh.tsx | 2 +- lib/routes/tradingview/blog.ts | 30 ++--- lib/routes/tradingview/desktop.ts | 18 +-- lib/routes/tradingview/pine.ts | 20 ++-- lib/routes/transcriptforest/index.ts | 6 +- lib/routes/trendforce/new.ts | 6 +- lib/routes/trendforce/news-cn.ts | 6 +- lib/routes/tribalfootball/latest.tsx | 15 +-- lib/routes/trow/portal.ts | 12 +- lib/routes/tsdm39/bd.ts | 2 +- lib/routes/tsinghua/lib/tzgg.ts | 14 +-- lib/routes/tsinghua/lib/zydt.ts | 22 ++-- lib/routes/tsinghua/news.ts | 8 +- lib/routes/ttv/index.ts | 17 +-- lib/routes/tver/series.ts | 7 +- lib/routes/tvtropes/featured.tsx | 14 +-- lib/routes/tw-nongmu/market.ts | 4 +- lib/routes/twitter/api/developer-api/api.ts | 13 ++- lib/routes/twitter/api/mobile-api/api.ts | 13 ++- lib/routes/twitter/api/mobile-api/login.ts | 18 ++- lib/routes/twitter/api/mobile-api/token.ts | 64 +++++------ lib/routes/twitter/api/web-api/api.ts | 2 +- lib/routes/twitter/api/web-api/utils.ts | 78 ++++++------- lib/routes/twitter/home-latest.ts | 2 +- lib/routes/twitter/home.ts | 6 +- lib/routes/twitter/keyword.ts | 2 +- lib/routes/twitter/likes.ts | 2 +- lib/routes/twitter/list.ts | 2 +- lib/routes/twitter/tweet.ts | 14 +-- lib/routes/twitter/utils.ts | 12 +- lib/routes/twreporter/fetch-article.ts | 4 +- lib/routes/txrjy/fornumtopic.tsx | 6 +- lib/routes/tynu/tynu.ts | 12 +- lib/routes/typeless/changelog.ts | 13 ++- lib/routes/typora/changelog-dev.ts | 8 +- lib/routes/typora/changelog.ts | 6 +- lib/routes/u3c3/index.ts | 6 +- lib/routes/u9a9/index.ts | 20 ++-- lib/routes/ucas/ai.ts | 6 +- lib/routes/ucas/index.ts | 4 +- lib/routes/uchicago/current.ts | 11 +- lib/routes/udn/breaking-news.tsx | 8 +- lib/routes/udn/global/index.ts | 6 +- lib/routes/uestc/bbs.ts | 2 +- lib/routes/uestc/cqe.ts | 10 +- lib/routes/uestc/news.ts | 10 +- lib/routes/uestc/scse.ts | 14 +-- lib/routes/uestc/sice.ts | 12 +- lib/routes/uestc/sise.ts | 12 +- lib/routes/uibe/hr.ts | 10 +- lib/routes/ulapia/index.ts | 2 +- lib/routes/ulapia/research.ts | 2 +- lib/routes/unipd/ilbolive/news.ts | 4 +- lib/routes/unusualwhales/news.ts | 4 +- lib/routes/upc/jsj.ts | 16 +-- lib/routes/upc/jwc.ts | 24 ++-- lib/routes/upc/main.ts | 16 +-- lib/routes/upc/yjs.ts | 8 +- lib/routes/uptimerobot/rss.tsx | 9 +- lib/routes/uraaka-joshi/uraaka-joshi-user.ts | 44 ++++---- lib/routes/uraaka-joshi/uraaka-joshi.ts | 36 +++--- lib/routes/usenix/loginonline.ts | 16 +-- lib/routes/usenix/usenix.ts | 20 ++-- lib/routes/ustb/tj/news.ts | 5 +- lib/routes/ustb/yjsy/news.ts | 12 +- lib/routes/ustb/yzxc/tzgg.ts | 10 +- lib/routes/ustc/eeis.ts | 18 +-- lib/routes/ustc/gs.ts | 16 +-- lib/routes/ustc/index.ts | 10 +- lib/routes/ustc/jwc.ts | 6 +- lib/routes/ustc/math.ts | 12 +- lib/routes/ustc/scms.ts | 12 +- lib/routes/ustc/sist.ts | 20 ++-- lib/routes/usts/jwch.ts | 22 ++-- lib/routes/uw/gix/news.ts | 13 ++- lib/routes/v1tx/index.ts | 12 +- lib/routes/v2ex/tab.ts | 2 +- lib/routes/vertikal/latest.ts | 10 +- lib/routes/vimeo/category.ts | 4 +- lib/routes/vimeo/channel.ts | 18 +-- lib/routes/vimeo/usr-videos.ts | 4 +- lib/routes/visionias/utils.ts | 6 +- lib/routes/vocus/utils.ts | 4 +- lib/routes/vom/featured.ts | 13 ++- lib/routes/wabei/index.ts | 6 +- lib/routes/wainao/topics.tsx | 6 +- lib/routes/wallhaven/index.ts | 26 +++-- lib/routes/warthunder/news.tsx | 22 ++-- lib/routes/washingtonpost/app.tsx | 16 +-- lib/routes/wchscu/recruit.ts | 12 +- lib/routes/wdc/download.ts | 2 +- lib/routes/wdfxw/bookfree.tsx | 12 +- lib/routes/web/utils.ts | 12 +- lib/routes/web3caff/index.ts | 12 +- lib/routes/webcatalog/changelog.ts | 4 +- lib/routes/wechat/announce.ts | 2 +- lib/routes/wechat/ce.ts | 6 +- lib/routes/wechat/data258.ts | 10 +- lib/routes/wechat/ershcimi.ts | 2 +- lib/routes/wechat/feeddd.ts | 2 +- lib/routes/wechat/msgalbum.ts | 4 +- lib/routes/wechat/tgchannel.ts | 28 ++--- lib/routes/wechat/wechat2rss.ts | 8 +- lib/routes/weekendhk/posts.ts | 4 +- lib/routes/weibo/search/hot.tsx | 4 +- lib/routes/weibo/utils.ts | 24 ++-- lib/routes/wenku8/chapter.ts | 4 +- lib/routes/wenku8/index.ts | 2 +- lib/routes/wenku8/volume.ts | 5 +- lib/routes/wfu/news.ts | 4 +- lib/routes/whitehouse/news.ts | 14 +-- lib/routes/who/news-room.ts | 13 ++- lib/routes/whu/cs.ts | 32 +++--- lib/routes/whu/gs/index.ts | 28 ++--- lib/routes/whu/hyxt.ts | 14 +-- lib/routes/whu/news.ts | 26 ++--- lib/routes/whu/rsgis.ts | 2 +- lib/routes/whu/swrh.ts | 24 ++-- lib/routes/whu/util.ts | 8 +- lib/routes/wiensued/index.ts | 2 +- lib/routes/wikinews/index.ts | 14 +-- lib/routes/wikipedia/current-events.ts | 2 +- lib/routes/windsurf/blog.tsx | 6 +- lib/routes/windsurf/changelog.ts | 8 +- lib/routes/winstall/update.tsx | 4 +- lib/routes/wired/tag.ts | 4 +- lib/routes/wise/pair.tsx | 6 +- lib/routes/wizfile/index.ts | 2 +- lib/routes/wmc-bj/publish.tsx | 6 +- lib/routes/wnacg/category.ts | 2 +- lib/routes/wnacg/common.tsx | 15 +-- lib/routes/wnacg/tag.ts | 2 +- lib/routes/wordpress/index.ts | 34 +++--- lib/routes/worldjournal/index.ts | 22 ++-- lib/routes/worldofwarships/devblog.ts | 21 ++-- lib/routes/woshipm/user-article.ts | 8 +- lib/routes/woshipm/wen.ts | 12 +- lib/routes/wsj/news.ts | 4 +- lib/routes/wsj/utils.tsx | 8 +- lib/routes/wsyu/news.ts | 2 +- lib/routes/wtu/index.ts | 6 +- lib/routes/wtu/job.ts | 16 +-- lib/routes/wufazhuce/one.ts | 2 +- lib/routes/wyzxwk/article.ts | 14 +-- lib/routes/wzu/news.ts | 36 +++--- lib/routes/x-mol/news.tsx | 16 +-- lib/routes/x-mol/paper.ts | 18 +-- lib/routes/x410/news.ts | 16 +-- lib/routes/x6d/index.ts | 14 +-- lib/routes/xaufe/jiaowu.ts | 20 ++-- lib/routes/xaut/index.ts | 16 +-- lib/routes/xaut/jwc.ts | 18 +-- lib/routes/xaut/rsc.ts | 16 +-- lib/routes/xbmu/academic.ts | 4 +- lib/routes/xbmu/announcement.ts | 4 +- lib/routes/xbookcn/blog.ts | 8 +- lib/routes/xboxfan/news.ts | 4 +- lib/routes/xhamster/index.ts | 2 +- lib/routes/xianbao/index.ts | 2 +- lib/routes/xiaohongshu/util.ts | 2 +- lib/routes/xiaomiyoupin/templates/goods.tsx | 2 +- lib/routes/xiaoyuzhou/pickup.ts | 2 +- lib/routes/xiaozhuanlan/column.ts | 20 ++-- lib/routes/xidian/cs.ts | 14 +-- lib/routes/xidian/gr.ts | 14 +-- lib/routes/xidian/jwc.ts | 14 +-- lib/routes/ximalaya/album.ts | 10 +- lib/routes/ximalaya/types.ts | 1 + lib/routes/xinpianchang/util.tsx | 3 +- lib/routes/xjtlu/news.ts | 3 +- lib/routes/xjtu/2yuan/news.ts | 14 +-- lib/routes/xjtu/dean.ts | 10 +- lib/routes/xjtu/dyyy/index.ts | 16 +-- lib/routes/xjtu/ee.ts | 14 +-- lib/routes/xjtu/gs/tzgg.ts | 18 +-- lib/routes/xjtu/international.ts | 18 +-- lib/routes/xjtu/std.tsx | 14 +-- lib/routes/xjtu/zs.ts | 14 +-- lib/routes/xmanhua/index.ts | 8 +- lib/routes/xmnn/epaper.ts | 14 +-- lib/routes/xmnn/news.ts | 22 ++-- lib/routes/xmu/kydt.ts | 18 +-- lib/routes/xmut/jwc/bkjw.ts | 12 +- lib/routes/xmut/jwc/yjs.ts | 14 +-- lib/routes/xsijishe/forum.ts | 28 ++--- lib/routes/xsijishe/rank.ts | 8 +- lib/routes/xueqiu/snb.ts | 2 +- lib/routes/xueqiu/user.ts | 11 +- lib/routes/xwenming/index.ts | 6 +- lib/routes/xys/new.tsx | 22 ++-- lib/routes/xyu/notices.ts | 4 +- lib/routes/yahoo/news/utils.tsx | 9 +- lib/routes/yamibo/bbs/forum.ts | 2 +- lib/routes/yamibo/bbs/thread.ts | 2 +- lib/routes/yamibo/utils.ts | 3 +- lib/routes/yangtzeu/dongke.ts | 18 +-- lib/routes/ycwb/index.tsx | 2 +- lib/routes/yicai/carousel.ts | 2 +- lib/routes/yicai/dt.ts | 18 +-- lib/routes/yicai/utils.ts | 2 +- lib/routes/ymgal/article.ts | 4 +- lib/routes/ymgal/game.tsx | 10 +- lib/routes/yna/index.ts | 10 +- lib/routes/ynet/list.ts | 12 +- lib/routes/yoasobi-music/jsonp-helper.ts | 2 +- lib/routes/yoasobi-music/media.tsx | 4 +- lib/routes/yomiuri/news.ts | 20 ++-- lib/routes/yomujp/level.ts | 11 +- lib/routes/youku/channel.tsx | 14 +-- lib/routes/youzhiyouxing/materials.ts | 16 +-- lib/routes/yuanliao/index.ts | 8 +- lib/routes/yuque/book.ts | 14 +-- lib/routes/yxdown/news.ts | 14 +-- lib/routes/yxdown/recommend.ts | 14 +-- lib/routes/yxdzqb/index.tsx | 10 +- lib/routes/yxrb/home.ts | 14 +-- lib/routes/yyets/article.ts | 16 +-- lib/routes/yyets/today.ts | 8 +- lib/routes/zagg/new-arrivals.tsx | 6 +- lib/routes/zaimanhua/comic.ts | 2 +- lib/routes/zaimanhua/update.ts | 2 +- lib/routes/zaobao/util.tsx | 2 +- lib/routes/zcmu/jwc/index.ts | 12 +- lib/routes/zcmu/yxy/index.ts | 12 +- lib/routes/zcool/discover.ts | 2 +- lib/routes/zhibo8/forum.ts | 8 +- lib/routes/zhibo8/luxiang.ts | 11 +- lib/routes/zhibo8/more.ts | 8 +- lib/routes/zhibo8/post.ts | 12 +- lib/routes/zhihu/all-collections.ts | 11 +- lib/routes/zhihu/daily.ts | 8 +- lib/routes/zhihu/execlib/x-zse-96-v3.ts | 12 +- lib/routes/zhihu/utils.ts | 2 +- lib/routes/zhihu/weekly.ts | 2 +- lib/routes/zhihu/xhu/topic.ts | 8 +- lib/routes/zhihu/xhu/zhuanlan.ts | 2 +- lib/routes/zhonglun/index.ts | 20 ++-- lib/routes/zhubai/top20.tsx | 4 +- lib/routes/zhujiceping/rss.ts | 2 +- lib/routes/zimuxia/index.ts | 12 +- lib/routes/zimuxia/portfolio.ts | 12 +- lib/routes/zjol/paper.ts | 2 +- lib/routes/zju/career/index.ts | 14 +-- lib/routes/zju/cst/custom.ts | 10 +- lib/routes/zju/cst/index.ts | 16 +-- lib/routes/zju/grs/index.ts | 14 +-- lib/routes/zju/list.ts | 6 +- lib/routes/zju/math/index.ts | 3 +- lib/routes/zju/physics/index.ts | 12 +- lib/routes/zju/sis/index.ts | 2 +- lib/routes/zjut/cs/index.ts | 2 +- lib/routes/zjut/da/index.ts | 22 ++-- lib/routes/zjut/jwc/index.ts | 2 +- lib/routes/zjut/news.ts | 12 +- lib/routes/zjut/www/index.ts | 2 +- lib/routes/zjuvag/blog.ts | 10 +- lib/routes/zotero/versions.ts | 12 +- lib/routes/zrblog/rss.ts | 2 +- lib/routes/zsxq/types.ts | 2 +- lib/routes/zuel/notice.ts | 14 +-- lib/routes/zuvio/boards.ts | 4 +- lib/routes/zuvio/student5.ts | 4 +- lib/routes/zyshow/index.tsx | 12 +- lib/routes/zyw/hot.ts | 2 +- lib/routes/zzu/dzb.ts | 2 +- lib/routes/zzu/gs.ts | 2 +- lib/routes/zzu/jwc.ts | 2 +- lib/routes/zzu/kjc.ts | 2 +- lib/routes/zzu/math.ts | 2 +- lib/routes/zzu/news.ts | 2 +- lib/routes/zzu/rsc.ts | 2 +- lib/routes/zzu/ss.ts | 4 +- lib/routes/zzu/student.ts | 4 +- lib/routes/zzu/tzhb.ts | 2 +- lib/routes/zzu/xbx.ts | 2 +- lib/routes/zzu/xuan.ts | 2 +- lib/routes/zzu/zcycwb.ts | 2 +- lib/shims/xxhash-wasm.ts | 2 +- lib/types.ts | 16 ++- lib/utils/cache/index.worker.test.ts | 1 + lib/utils/cache/redis.test.ts | 2 +- lib/utils/common-config.ts | 5 +- lib/utils/playwright.ts | 4 +- lib/utils/proxy/index.ts | 2 +- lib/utils/proxy/multi-proxy.test.ts | 2 +- lib/utils/proxy/pac-proxy.test.ts | 5 +- lib/utils/proxy/unify-proxy.test.ts | 3 +- lib/utils/proxy/unify-proxy.ts | 2 +- lib/utils/request-rewriter/fetch.test.ts | 6 +- lib/utils/request-rewriter/fetch.ts | 4 +- .../request-rewriter/fetch.worker.test.ts | 2 +- lib/utils/request-rewriter/get.test.ts | 2 +- lib/utils/request-rewriter/get.ts | 9 +- lib/utils/request-rewriter/index.test.ts | 19 ++-- lib/utils/rss-parser.ts | 2 +- lib/utils/twitter-cache-key.test.ts | 77 ------------- lib/utils/twitter-cache-key.ts | 1 - lib/utils/wechat-mp.ts | 2 +- lib/views/rss.test.tsx | 2 +- package.json | 2 +- scripts/workflow/format-description.ts | 6 +- 1958 files changed, 10003 insertions(+), 9770 deletions(-) delete mode 100644 lib/routes/linkedin/models.ts delete mode 100644 lib/utils/twitter-cache-key.test.ts delete mode 100644 lib/utils/twitter-cache-key.ts diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ce07aa9cbc..90518bb33c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -29,6 +29,8 @@ jobs: - run: pnpm i - name: Install oxlint to SARIF converter run: pnpm i -g oxlint-json-to-sarif + - name: Typecheck + run: pnpm typecheck - name: Lint run: pnpm exec oxlint --type-aware --config=.oxlintrc.ci.json --format=json | oxlint-json-to-sarif > oxlint-results.sarif diff --git a/.husky/pre-commit b/.husky/pre-commit index c27d8893a9..4fe5222fef 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,2 @@ lint-staged +pnpm typecheck diff --git a/.oxlintrc.json b/.oxlintrc.json index 5936fe34c6..43cd83ec49 100644 --- a/.oxlintrc.json +++ b/.oxlintrc.json @@ -641,7 +641,17 @@ // #region --- TypeScript --- "@typescript-eslint/array-type": ["error", { "default": "array-simple" }], - "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/ban-ts-comment": [ + "warn", + { + "ts-check": false, + "ts-expect-error": "allow-with-description", + "ts-ignore": "allow-with-description", + "ts-nocheck": "allow-with-description", + "minimumDescriptionLength": 3 + } + ], + "@typescript-eslint/consistent-indexed-object-style": "off", // stylistic "@typescript-eslint/consistent-type-definitions": "off", // stylistic "@typescript-eslint/dot-notation": "error", // type-aware diff --git a/lib/api/follow/config.test.ts b/lib/api/follow/config.test.ts index c8da4ffb18..e9279a3fa8 100644 --- a/lib/api/follow/config.test.ts +++ b/lib/api/follow/config.test.ts @@ -14,7 +14,7 @@ describe('api/follow/config', () => { json: (data: unknown) => data, }; - const result = handler(ctx as any) as Record; + const result = (handler as (c: typeof ctx) => unknown)(ctx) as Record; expect(result).toMatchObject({ ownerUserId: 'owner', diff --git a/lib/api/radar/rules/one.test.ts b/lib/api/radar/rules/one.test.ts index e5afe4abb1..37e008b8d5 100644 --- a/lib/api/radar/rules/one.test.ts +++ b/lib/api/radar/rules/one.test.ts @@ -1,4 +1,4 @@ -import type { Next } from 'hono'; +import type { Context, Next } from 'hono'; import { describe, expect, it, vi } from 'vitest'; import { handler } from '@/api/radar/rules/one'; @@ -14,7 +14,7 @@ describe('api/radar/rules/one', () => { json: vi.fn((value) => value), }; - const result = await handler(ctx as any, noopNext); + const result = await handler(ctx as unknown as Context, noopNext); expect(ctx.req.valid).toHaveBeenCalledWith('param'); expect(ctx.json).toHaveBeenCalledWith(undefined); diff --git a/lib/app-bootstrap.test.tsx b/lib/app-bootstrap.test.tsx index 980c9355ec..099c780d52 100644 --- a/lib/app-bootstrap.test.tsx +++ b/lib/app-bootstrap.test.tsx @@ -21,7 +21,7 @@ describe('app-bootstrap', () => { const before = new Set(process.listeners('uncaughtException')); await import('@/app-bootstrap'); const after = process.listeners('uncaughtException'); - const listener = after.find((fn) => !before.has(fn)); + const listener = after.find((fn) => !before.has(fn)) as ((error: Error) => void) | undefined; expect(listener).toBeDefined(); listener?.(new Error('boom')); diff --git a/lib/app.test.ts b/lib/app.test.ts index 935412324d..03ca942bc9 100644 --- a/lib/app.test.ts +++ b/lib/app.test.ts @@ -23,7 +23,7 @@ describe('request-rewriter', () => { await app.request('/test/httperror'); // headers - const headers: Headers = fetchSpy.mock.lastCall?.[0].headers; + const headers: Headers = (fetchSpy.mock.lastCall as unknown as [Request])?.[0].headers; expect(headers.get('user-agent')).toMatch(/Chrome/); }); }); diff --git a/lib/container.ts b/lib/container.ts index f19cd3a997..6d3ddd5ea8 100644 --- a/lib/container.ts +++ b/lib/container.ts @@ -2,7 +2,7 @@ // This Worker manages the RSSHub container lifecycle and proxies requests import { Container } from '@cloudflare/containers'; -import type { KVNamespace } from '@cloudflare/workers-types'; +import type { DurableObjectNamespace, KVNamespace } from '@cloudflare/workers-types'; const INSTANCE_COUNT = 20; @@ -13,7 +13,7 @@ export class RSSHubContainer extends Container { } interface Env { - RSSHUB_CONTAINER: DurableObjectNamespace; + RSSHUB_CONTAINER: DurableObjectNamespace; CONFIG: KVNamespace; } @@ -36,7 +36,7 @@ export default { // Randomly select an instance for load balancing const instanceIndex = Math.floor(Math.random() * INSTANCE_COUNT); - const container = env.RSSHUB_CONTAINER.getByName(`rsshub-${instanceIndex}`); + const container = env.RSSHUB_CONTAINER.getByName(`rsshub-${instanceIndex}`) as unknown as RSSHubContainer; // Start container with env vars and wait for port to be ready await container.startAndWaitForPorts({ diff --git a/lib/errors/index.test.ts b/lib/errors/index.test.ts index 9e148abec4..73c5dbb821 100644 --- a/lib/errors/index.test.ts +++ b/lib/errors/index.test.ts @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import type { Context } from 'hono'; import { afterEach, describe, expect, it, vi } from 'vitest'; import app from '@/app'; @@ -147,9 +148,9 @@ describe('error handler honeybadger', () => { header: vi.fn(), json: (payload: unknown) => payload, html: (payload: unknown) => payload, - }; + } as unknown as Context; - errorHandler(new Error('boom'), ctx as any); + errorHandler(new Error('boom'), ctx); expect(notify).toHaveBeenCalledWith(expect.any(Error), { context: { name: 'test' }, @@ -205,9 +206,9 @@ describe('error handler sentry', () => { header: vi.fn(), json: (payload: unknown) => payload, html: (payload: unknown) => payload, - }; + } as unknown as Context; - errorHandler(new Error('boom'), ctx as any); + errorHandler(new Error('boom'), ctx); expect(setTag).toHaveBeenCalledWith('name', 'test'); expect(captureException).toHaveBeenCalled(); diff --git a/lib/index.test.ts b/lib/index.test.ts index 5f610af975..930df7feee 100644 --- a/lib/index.test.ts +++ b/lib/index.test.ts @@ -1,6 +1,6 @@ import { afterEach, describe, expect, it, vi } from 'vitest'; -const serve = vi.fn(() => ({ close: vi.fn() })); +const serve = vi.fn<(...args: any[]) => any>(() => ({ close: vi.fn() })); const logger = { info: vi.fn(), warn: vi.fn(), diff --git a/lib/middleware/anti-hotlink.test.ts b/lib/middleware/anti-hotlink.test.ts index 2470361bc2..cbed73a098 100644 --- a/lib/middleware/anti-hotlink.test.ts +++ b/lib/middleware/anti-hotlink.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import Parser from 'rss-parser'; import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; @@ -451,7 +452,7 @@ describe('anti-hotlink edge cases', () => { }, get: (key: string) => store.get(key), set: (key: string, value: unknown) => store.set(key, value), - }; + } as unknown as Context; }; beforeAll(() => { @@ -479,7 +480,7 @@ describe('anti-hotlink edge cases', () => { }; const ctx = createCtx({ image_hotlink_template: 'https://img.test/${href}' }, data); - await antiHotlink(ctx as any, async () => {}); + await antiHotlink(ctx, async () => {}); expect(data.image).toBe('http://invalid url'); expect(errorSpy).toHaveBeenCalled(); @@ -495,7 +496,7 @@ describe('anti-hotlink edge cases', () => { }; const ctx = createCtx({ multimedia_hotlink_template: 'https://media.test/${href}' }, data); - await antiHotlink(ctx as any, async () => {}); + await antiHotlink(ctx, async () => {}); expect(data.image).toBe('https://example.com/img.jpg'); }); diff --git a/lib/middleware/cache.test.ts b/lib/middleware/cache.test.ts index 0c8e7042f4..b83ad45870 100644 --- a/lib/middleware/cache.test.ts +++ b/lib/middleware/cache.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import Parser from 'rss-parser'; import { afterAll, afterEach, describe, expect, it, vi } from 'vitest'; @@ -190,7 +191,7 @@ describe('cache', () => { }); describe('cache middleware error handling', () => { - const setSpy = vi.fn(() => null); + const setSpy = vi.fn<(...args: any[]) => null>(() => null); const getSpy = vi.fn(() => null); afterAll(() => { @@ -231,10 +232,10 @@ describe('cache middleware error handling', () => { header: vi.fn(), set: vi.fn(), get: vi.fn(), - }; + } as unknown as Context; await expect( - cacheMiddleware(ctx as any, () => { + cacheMiddleware(ctx, () => { throw new Error('boom'); }) ).rejects.toThrow('boom'); diff --git a/lib/middleware/parameter.test.ts b/lib/middleware/parameter.test.ts index ac038cb3dc..3d639fc6eb 100644 --- a/lib/middleware/parameter.test.ts +++ b/lib/middleware/parameter.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import Parser from 'rss-parser'; import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest'; @@ -19,8 +20,8 @@ const runMiddleware = async (data: any, query: Record store.get(key), set: (key: string, value: unknown) => store.set(key, value), - }; - await middleware(ctx as any, async () => {}); + } as unknown as Context; + await middleware(ctx, async () => {}); return store.get('data') as any; }; diff --git a/lib/middleware/parameter.ts b/lib/middleware/parameter.ts index 5dbad3d65e..2058ad5b5a 100644 --- a/lib/middleware/parameter.ts +++ b/lib/middleware/parameter.ts @@ -201,7 +201,7 @@ const middleware: MiddlewareHandler = async (ctx, next) => { const title = item.title || ''; const description = item.description || title; const author = getAuthorString(item); - const category = item.category || []; + const category = (item.category as string[] | undefined) || []; const isFilter = regex instanceof RE2JS ? regex.matcher(title).find() || regex.matcher(description).find() || regex.matcher(author).find() || category.some((c) => regex.matcher(c).find()) @@ -217,7 +217,7 @@ const middleware: MiddlewareHandler = async (ctx, next) => { const title = item.title || ''; const description = item.description || title; const author = getAuthorString(item); - const category = item.category || []; + const category = (item.category as string[] | undefined) || []; let isFilter = true; if (ctx.req.query('filter_title')) { @@ -246,7 +246,7 @@ const middleware: MiddlewareHandler = async (ctx, next) => { const title = item.title; const description = item.description || title; const author = getAuthorString(item); - const category = item.category || []; + const category = (item.category as string[] | undefined) || []; let isFilter = true; if (ctx.req.query('filterout') || ctx.req.query('filterout_title')) { diff --git a/lib/middleware/template.test.ts b/lib/middleware/template.test.ts index 088cb91d84..0712ee7d75 100644 --- a/lib/middleware/template.test.ts +++ b/lib/middleware/template.test.ts @@ -1,3 +1,4 @@ +import type { Context } from 'hono'; import { describe, expect, it, vi } from 'vitest'; import { config } from '@/config'; @@ -19,16 +20,16 @@ const createCtx = (query: Record, data: any, extra: redirect: vi.fn((url: string, status: number) => ({ url, status })), header: vi.fn(), res: { headers: new Headers() }, - }; + } as unknown as Context & { json: ReturnType; html: ReturnType; render: ReturnType; body: ReturnType; redirect: ReturnType; header: ReturnType }; }; describe('template middleware', () => { it('returns debug json when requested', async () => { const originalDebug = config.debugInfo; - config.debugInfo = true; + config.debugInfo = 'true'; const ctx = createCtx({ format: 'debug.json' }, { item: [] }, { json: { ok: true } }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toEqual({ ok: true }); expect(ctx.json).toHaveBeenCalled(); @@ -38,7 +39,7 @@ describe('template middleware', () => { it('returns api data without rendering', async () => { const ctx = createCtx({}, null, { apiData: { ok: true } }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toEqual({ ok: true }); expect(ctx.json).toHaveBeenCalledWith({ ok: true }); @@ -46,10 +47,10 @@ describe('template middleware', () => { it('renders debug html snippet when requested', async () => { const originalDebug = config.debugInfo; - config.debugInfo = true; + config.debugInfo = 'true'; const ctx = createCtx({ format: '0.debug.html' }, { item: [{ description: 'Hello' }] }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toBe('Hello'); expect(ctx.html).toHaveBeenCalled(); @@ -72,7 +73,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'rss' }, data); - await template(ctx as any, async () => {}); + await template(ctx, async () => {}); expect(data.item[0].title).toBe('ABC...'); expect(data.item[0].author).toBe('Alice, Bob'); @@ -93,7 +94,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'json' }, data); - await template(ctx as any, async () => {}); + await template(ctx, async () => {}); expect(data.item[0].pubDate).toBe(''); expect(data.item[0].updated).toBe(''); @@ -101,7 +102,7 @@ describe('template middleware', () => { it('returns redirect response when redirect is set', async () => { const ctx = createCtx({}, { item: [] }, { redirect: 'https://example.com' }); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(result).toEqual({ url: 'https://example.com', status: 301 }); expect(ctx.redirect).toHaveBeenCalledWith('https://example.com', 301); @@ -118,7 +119,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'rss3' }, data); - const result = await template(ctx as any, async () => {}); + const result = await template(ctx, async () => {}); expect(ctx.json).toHaveBeenCalled(); expect(result).toHaveProperty('data'); @@ -135,7 +136,7 @@ describe('template middleware', () => { ], }; const ctx = createCtx({ format: 'atom' }, data); - await template(ctx as any, async () => {}); + await template(ctx, async () => {}); expect(ctx.render).toHaveBeenCalled(); }); diff --git a/lib/middleware/trace.test.ts b/lib/middleware/trace.test.ts index 5113af92ea..9689da02dd 100644 --- a/lib/middleware/trace.test.ts +++ b/lib/middleware/trace.test.ts @@ -1,3 +1,4 @@ +import type { Context, Next } from 'hono'; import { describe, expect, it } from 'vitest'; import { config } from '@/config'; @@ -6,7 +7,7 @@ import trace from '@/middleware/trace'; describe('trace middleware', () => { it('skips tracing when debugInfo is disabled', async () => { const originalDebug = config.debugInfo; - config.debugInfo = false; + config.debugInfo = false as unknown as string; let called = false; const ctx = { @@ -14,12 +15,13 @@ describe('trace middleware', () => { method: 'GET', raw: new Request('http://localhost/test'), }, - }; - const next = () => { + } as unknown as Context; + const next: Next = () => { called = true; + return Promise.resolve(); }; - await trace(ctx as any, next); + await trace(ctx, next); expect(called).toBe(true); config.debugInfo = originalDebug; diff --git a/lib/pkg.test.ts b/lib/pkg.test.ts index f0e1c78851..5a1a48016b 100644 --- a/lib/pkg.test.ts +++ b/lib/pkg.test.ts @@ -1,5 +1,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import type { Route } from '@/types'; + describe('pkg', () => { beforeEach(() => { vi.resetModules(); @@ -104,7 +106,7 @@ describe('pkg', () => { ], allowEmpty: true, }), - }, + } as unknown as Route, { name: 'Custom Namespace', url: 'https://example.com', @@ -128,7 +130,7 @@ describe('pkg', () => { path: '/hello', name: 'Custom Response', handler: () => new Response('ok'), - }); + } as unknown as Route); const app = (await import('@/app')).default; const response = await app.request('/custom-response/hello'); diff --git a/lib/registry-dev.test.ts b/lib/registry-dev.test.ts index ec589f284a..e41c3514b4 100644 --- a/lib/registry-dev.test.ts +++ b/lib/registry-dev.test.ts @@ -88,7 +88,7 @@ afterAll(() => { const buildApp = () => { const namespaces: NamespacesType = {}; const dev = createDevRegistry({ routesDirectory, namespaces }); - const app = new Hono(); + const app = new Hono<{ Variables: { fromOuter: string; data: Record; apiData: Record } }>(); app.use(async (ctx, next) => { ctx.set('fromOuter', 'bridged'); await next(); diff --git a/lib/registry.test.ts b/lib/registry.test.ts index da75e19337..0e8b2535e3 100644 --- a/lib/registry.test.ts +++ b/lib/registry.test.ts @@ -64,6 +64,7 @@ describe('registry', () => { vi.stubEnv('DISABLE_NSFW', 'true'); const { namespaces } = await import('./registry'); + // @ts-ignore build artifact of pnpm build:routes const routesModule = await import('../assets/build/routes.json'); const rawNamespaces = (routesModule.default ?? routesModule) as Record }>; const nsfwNamespaces = Object.entries(rawNamespaces).filter(([, namespace]) => Object.values(namespace.routes ?? {}).some((route) => route.features?.nsfw)); @@ -165,7 +166,7 @@ const perDirectoryMock = (fakeDirectories: Record { - const app = new Hono(); + const app = new Hono<{ Variables: { data: Record; apiData: Record } }>(); app.use(async (ctx, next) => { const response = await next(); const apiData = ctx.get('apiData'); diff --git a/lib/registry.ts b/lib/registry.ts index d559b57ecd..7c5c01d93c 100644 --- a/lib/registry.ts +++ b/lib/registry.ts @@ -38,17 +38,19 @@ let namespaces: NamespacesType = {}; let devRegistry: DevRegistry | undefined; if (config.isPackage) { + // @ts-ignore build artifact of pnpm build:routes namespaces = (await import('../assets/build/routes.js')).default; } else { switch (process.env.NODE_ENV || process.env.VERCEL_ENV) { case 'production': + // @ts-ignore build artifact of pnpm build:routes namespaces = (await import('../assets/build/routes.js')).default; break; case 'test': - // @ts-expect-error + // @ts-expect-error TS2322 the JSON module's inferred literal type is narrower than NamespacesType namespaces = await import('../assets/build/routes.json'); if (namespaces.default) { - // @ts-ignore + // @ts-expect-error TS2322 the JSON module's default export does not satisfy NamespacesType namespaces = namespaces.default; } break; diff --git a/lib/routes/005/index.tsx b/lib/routes/005/index.tsx index 734edf37ca..4a3f743026 100644 --- a/lib/routes/005/index.tsx +++ b/lib/routes/005/index.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -23,11 +23,11 @@ export const handler = async (ctx) => { let items = $('div.article-list ul li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); - const title = item.find('h3').text(); - const image = item.find('img').prop('src'); + const title = $item.find('h3').text(); + const image = $item.find('img').prop('src'); const description = renderToString( <> @@ -36,22 +36,22 @@ export const handler = async (ctx) => { {title} ) : null} - {item.find('div.p-row').text() ?
{item.find('div.p-row').text()}
: null} + {$item.find('div.p-row').text() ?
{$item.find('div.p-row').text()}
: null} ); return { title, description, - pubDate: parseDate(item.find('span.time').text()), - link: new URL(item.find('h3 a').prop('href'), rootUrl).href, + pubDate: parseDate($item.find('span.time').text()), + link: new URL($item.find('h3 a').prop('href')!, rootUrl).href, content: { html: description, - text: item.find('div.p-row').text(), + text: $item.find('div.p-row').text(), }, image, banner: image, - language, + language: language as Language, }; }); @@ -66,14 +66,14 @@ export const handler = async (ctx) => { const description = $$('div.articleContent').html(); item.title = title; - item.description = description; + item.description = description ?? ''; item.pubDate = timezone(parseDate($$('.time').text()), 8); item.category = $$('meta[name="keywords"]').prop('content').split(/,/); item.content = { - html: description, + html: description ?? '', text: $$('div.articleContent').text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -91,7 +91,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/,/).pop(), - language, + language: language as Language, }; }; diff --git a/lib/routes/0818tuan/index.ts b/lib/routes/0818tuan/index.ts index 6605b42ef1..347f81aee0 100644 --- a/lib/routes/0818tuan/index.ts +++ b/lib/routes/0818tuan/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,18 +37,18 @@ async function handler(ctx) { const list = $(listId === '3' ? '.col-xs-12 .thumbnail > a' : '.col-md-8 .list-group > a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.attr('title'), - link: item.attr('href').startsWith('http') ? item.attr('href') : `${baseUrl}${item.attr('href')}`, + title: $item.attr('title')!, + link: $item.attr('href')!.startsWith('http') ? $item.attr('href') : `${baseUrl}${$item.attr('href')}`, }; }) - .filter((i) => !i.link.includes('m.0818tuan.com/tb1111.php') && !i.link.includes('www.0818tuan.com/pdd/zudui.php')); + .filter((i) => !i.link!.includes('m.0818tuan.com/tb1111.php') && !i.link!.includes('www.0818tuan.com/pdd/zudui.php')); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: response } = await got(item.link); const $ = load(response); diff --git a/lib/routes/0x80/index.ts b/lib/routes/0x80/index.ts index 13463db233..f4069561d3 100644 --- a/lib/routes/0x80/index.ts +++ b/lib/routes/0x80/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,11 +37,11 @@ async function handler() { const list = alist .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); - const link = item.attr('href') || ''; - const title = item.text(); + const link = $item.attr('href') || ''; + const title = $item.text(); const pubDate = extractDateFromURL(link); return { diff --git a/lib/routes/0xxx/index.ts b/lib/routes/0xxx/index.ts index bfe02481d7..cf469492f7 100644 --- a/lib/routes/0xxx/index.ts +++ b/lib/routes/0xxx/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('table#home-table tr:not(.gore)') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $categoryEl: Cheerio = $el.find('td.category'); @@ -44,11 +44,11 @@ export const handler = async (ctx: Context): Promise => { }, ] : undefined, - category: $categoryEl.html(), - catalogue: $catalogueEl.html(), + category: $categoryEl.html() ?? undefined, + catalogue: $catalogueEl.html() ?? undefined, title, size: $el.find('td.size').text(), - date: $dateEl.html(), + date: $dateEl.html() ?? undefined, }); const pubDateStr: string | undefined = $dateEl.text(); const linkUrl: string | undefined = $el.find('td.title a').attr('href'); @@ -68,7 +68,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'DD.MM.YYYY') : undefined, - language, + language: language as Language, }; return processedItem; @@ -81,7 +81,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const description: string | undefined = @@ -117,7 +117,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('div.logo img').attr('src') ? new URL($('div.logo img').attr('src') as string, baseUrl).href : undefined, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; @@ -146,7 +146,7 @@ To subscribe to [Movie HD 1080p](https://0xxx.ws?category=Movie-HD-1080p), where supportBT: false, supportPodcast: false, supportScihub: false, - nfsw: true, + nsfw: true, }, radar: [ { diff --git a/lib/routes/10000link/info.ts b/lib/routes/10000link/info.ts index cbf4e69b72..9297c039e5 100644 --- a/lib/routes/10000link/info.ts +++ b/lib/routes/10000link/info.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('ul.l_newshot li dl.lhotnew2') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('dd h1 a'); @@ -55,7 +55,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseRelativeDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -69,14 +69,14 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.entity_title h1 a').text(); const image: string | undefined = $$('div.entity_thumb img.img-responsive').attr('src'); const description: string | undefined = renderDescription({ - description: $$('div.entity_content').html(), + description: $$('div.entity_content').html() ?? undefined, }); const pubDateStr: string | undefined = detailResponse.match(/var\stime\s=\s"(.*?)";/)?.[1]; const categoryEls: Element[] = $$('div.entity_tag span a').toArray(); @@ -95,7 +95,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; return { @@ -118,7 +118,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('a.navbar-brand img').attr('src') ? new URL($('a.navbar-brand img').attr('src') as string, baseUrl).href : undefined, author, - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/10jqka/realtimenews.ts b/lib/routes/10jqka/realtimenews.ts index 6b8742133a..f230a71f0a 100644 --- a/lib/routes/10jqka/realtimenews.ts +++ b/lib/routes/10jqka/realtimenews.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -51,7 +51,7 @@ export const handler = async (ctx) => { image, banner: item.picUrl, updated: parseDate(item.rtime, 'X'), - language, + language: language as Language, }; }) ?? []; @@ -66,7 +66,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/121/weather-live.tsx b/lib/routes/121/weather-live.tsx index bc7b70de85..8c464607db 100644 --- a/lib/routes/121/weather-live.tsx +++ b/lib/routes/121/weather-live.tsx @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Context } from 'hono'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -70,7 +70,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: updated ? parseDate(updated) : undefined, - language, + language: language as Language, }; return processedItem; @@ -86,7 +86,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img').first().attr('src') ? new URL($('img').first().attr('src') as string, baseUrl).href : undefined, author: $('div#webnameDiv').text(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/12306/zxdt.ts b/lib/routes/12306/zxdt.ts index eebd0af520..5f66d442f5 100644 --- a/lib/routes/12306/zxdt.ts +++ b/lib/routes/12306/zxdt.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -42,9 +42,9 @@ async function handler(ctx) { const list = $('#newList > ul > li') .toArray() - .map((item) => ({ + .map((item): DataItem & { link: string } => ({ title: $(item).find('a').text(), - link: new URL($(item).find('a').attr('href'), link).href, + link: new URL($(item).find('a').attr('href')!, link).href, pubDate: parseDate($(item).find('span').text().slice(1, -1)), })); diff --git a/lib/routes/141jav/index.tsx b/lib/routes/141jav/index.tsx index 87517a609f..10f7beff55 100644 --- a/lib/routes/141jav/index.tsx +++ b/lib/routes/141jav/index.tsx @@ -68,29 +68,29 @@ async function handler(ctx) { const items = $('.columns') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const id = item.find('.title a').text(); - const size = item.find('.title span').text(); - const pubDate = item.find('.subtitle a').attr('href').split('/date/').pop(); - const description = item.find('.has-text-grey-dark').text(); - const actresses = item + const id = $item.find('.title a').text(); + const size = $item.find('.title span').text(); + const pubDate = $item.find('.subtitle a').attr('href')!.split('/date/').pop(); + const description = $item.find('.has-text-grey-dark').text(); + const actresses = $item .find('.panel-block') .toArray() .map((a) => $(a).text().trim()); - const tags = item + const tags = $item .find('.tag') .toArray() .map((t) => $(t).text().trim()); - const magnet = item.find('a[title="Magnet torrent"]').attr('href'); - const link = item.find('a[title="Download .torrent"]').attr('href'); - const image = item.find('.image').attr('src'); + const magnet = $item.find('a[title="Magnet torrent"]').attr('href'); + const link = $item.find('a[title="Download .torrent"]').attr('href'); + const image = $item.find('.image').attr('src'); return { title: `${id} ${size}`, - pubDate: parseDate(pubDate, 'YYYY/MM/DD'), - link: new URL(item.find('a').first().attr('href'), rootUrl).href, - description: renderToString(), + pubDate: parseDate(pubDate!, 'YYYY/MM/DD'), + link: new URL($item.find('a').first().attr('href')!, rootUrl).href, + description: renderToString(), author: actresses.join(', '), category: [...tags, ...actresses], enclosure_type: 'application/x-bittorrent', diff --git a/lib/routes/141ppv/index.tsx b/lib/routes/141ppv/index.tsx index 05172e45a8..4a9e427300 100644 --- a/lib/routes/141ppv/index.tsx +++ b/lib/routes/141ppv/index.tsx @@ -68,31 +68,31 @@ async function handler(ctx) { const items = $('.columns') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const id = item.find('.title a').text(); - const size = item.find('.title span').text(); - const pubDate = item.find('.subtitle a').attr('href').split('/date/').pop(); - const description = item.find('.has-text-grey-dark').text(); - const actresses = item + const id = $item.find('.title a').text(); + const size = $item.find('.title span').text(); + const pubDate = $item.find('.subtitle a').attr('href')!.split('/date/').pop(); + const description = $item.find('.has-text-grey-dark').text(); + const actresses = $item .find('.panel-block') .toArray() .map((a) => $(a).text().trim()); - const tags = item + const tags = $item .find('.tag') .toArray() .map((t) => $(t).text().trim()); - const magnet = item.find('a[title="Magnet torrent"]').attr('href'); - const link = item.find('a[title="Download .torrent"]').attr('href'); - const onErrorAttr = item.find('.image').attr('onerror'); + const magnet = $item.find('a[title="Magnet torrent"]').attr('href'); + const link = $item.find('a[title="Download .torrent"]').attr('href'); + const onErrorAttr = $item.find('.image').attr('onerror'); const backupImageRegex = /this\.src='(.*?)'/; - const match = backupImageRegex.exec(onErrorAttr); - const image = match ? match[1] : item.find('.image').attr('src'); + const match = backupImageRegex.exec(onErrorAttr!); + const image = match ? match[1] : $item.find('.image').attr('src'); return { title: `${id} ${size}`, - pubDate: parseDate(pubDate, 'YYYY/MM/DD'), - link: new URL(item.find('a').first().attr('href'), rootUrl).href, + pubDate: parseDate(pubDate!, 'YYYY/MM/DD'), + link: new URL($item.find('a').first().attr('href')!, rootUrl).href, description: renderToString( <> {image ? : null} diff --git a/lib/routes/163/dy2.ts b/lib/routes/163/dy2.ts index 06ff453d91..cfd448129d 100644 --- a/lib/routes/163/dy2.ts +++ b/lib/routes/163/dy2.ts @@ -38,12 +38,12 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); - const itemImg = item.find('a.img img'); + const $item = $(item); + const itemImg = $item.find('a.img img'); return { - title: item.find('h4 a').text(), - link: item.find('a').first().attr('href'), - pubDate: timezone(parseDate(item.find('.time').text()), 8), + title: $item.find('h4 a').text(), + link: $item.find('a').first().attr('href'), + pubDate: timezone(parseDate($item.find('.time').text()), 8), imgsrc: itemImg.attr('src') ?? itemImg.attr('_src'), }; }); diff --git a/lib/routes/163/music/djradio.tsx b/lib/routes/163/music/djradio.tsx index 18d117a524..e97e96a120 100644 --- a/lib/routes/163/music/djradio.tsx +++ b/lib/routes/163/music/djradio.tsx @@ -42,7 +42,7 @@ const renderDescription = (pg, description, itunes_duration, info) => {info ? (
- +

时长: {itunes_duration}

查看节目 diff --git a/lib/routes/163/news/rank.ts b/lib/routes/163/news/rank.ts index 8cd03a5bf5..040dfc900a 100644 --- a/lib/routes/163/news/rank.ts +++ b/lib/routes/163/news/rank.ts @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -140,24 +140,25 @@ async function handler(ctx) { .eq(timeRange[time].index + (category === 'whole' ? (type === 'click' ? -1 : 2) : type === 'click' ? 0 : 2)) .find('table tbody tr td a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - link: item.attr('href'), + link: $item.attr('href'), + title: '', }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { let link; if (['auto', 'house', 'travel'].includes(category)) { - const category = item.link.split('.163.com', 1)[0].split('//').pop().split('.').pop(); - link = `https://3g.163.com/${category}/article/${item.link.split('/').pop()}`; + const category = item.link!.split('.163.com', 1)[0].split('//').pop()!.split('.').pop(); + link = `https://3g.163.com/${category}/article/${item.link!.split('/').pop()}`; } else { - const pathname = new URL(item.link).pathname; + const pathname = new URL(item.link!).pathname; link = `https://3g.163.com${pathname}`; } @@ -175,8 +176,8 @@ async function handler(ctx) { elem.attribs.src = elem.attribs['data-src'] ?? elem.attribs.src; }); - item.title = content('meta[property="og:title"]').attr('content').replace('_手机网易网', ''); - item.pubDate = parseDate(content('meta[property="og:release_date"]').attr('content')); + item.title = content('meta[property="og:title"]').attr('content')!.replace('_手机网易网', ''); + item.pubDate = parseDate(content('meta[property="og:release_date"]').attr('content')!); item.description = content('.article-body').html(); } catch { return ''; @@ -190,6 +191,6 @@ async function handler(ctx) { return { title: `网易新闻${timeRange[time].title}${type === 'click' ? '点击' : '跟帖'}榜 - ${cfg.title}`, link: currentUrl, - item: items.filter(Boolean), + item: items.filter(Boolean) as DataItem[], }; } diff --git a/lib/routes/163/open/vip.tsx b/lib/routes/163/open/vip.tsx index 82784e98fb..c361976a0f 100644 --- a/lib/routes/163/open/vip.tsx +++ b/lib/routes/163/open/vip.tsx @@ -65,10 +65,10 @@ async function handler() { const initialState = JSON.parse( $('script') .text() - .match(/window\.__INITIAL_STATE__=(.*);\(function\(\)\{var/)[1] + .match(/window\.__INITIAL_STATE__=(.*);\(function\(\)\{var/)![1] ); - const list = Object.values(initialState.courseindex.myModules).flatMap((mod) => + const list = Object.values>(initialState.courseindex.myModules).flatMap((mod) => mod.contents.map((item) => ({ title: `${item.title} - ${item.subtitle}`, author: item.authorName, diff --git a/lib/routes/163/renjian.ts b/lib/routes/163/renjian.ts index d3d066ac67..c0a214b5b5 100644 --- a/lib/routes/163/renjian.ts +++ b/lib/routes/163/renjian.ts @@ -61,8 +61,8 @@ async function handler(ctx) { if (urls) { items = urls.slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50).map((item) => ({ - link: item.match(/url:"(.*)",/)[1], - })); + link: item.match(/url:"(.*)",/)![1], + })) as DataItem[]; } else { const $ = load(data); @@ -70,16 +70,16 @@ async function handler(ctx) { .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50) .toArray() .map((_, item) => { - item = $(item); + const $item = $(item as any); return { - link: item.attr('href'), + link: $item.attr('href'), }; - }); + }) as DataItem[]; } items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -89,7 +89,7 @@ async function handler(ctx) { item.title = content('h1').text(); item.author = content('script') .text() - .match(/renjian_author = '(.*)'/)[1]; + .match(/renjian_author = '(.*)'/)![1]; item.description = content('#endText').html() ?? content('#content').html(); item.pubDate = timezone(parseDate(content('.pub_time').text() ?? content('.post_info').text().split('来源:', 1)[0].trim()), 8); diff --git a/lib/routes/163/utils.tsx b/lib/routes/163/utils.tsx index 2c2f109a8f..aa995215ff 100644 --- a/lib/routes/163/utils.tsx +++ b/lib/routes/163/utils.tsx @@ -32,7 +32,7 @@ const parseDyArticle = (item) => } const url = new URL(i.attribs.src); if (url.host === 'nimg.ws.126.net') { - i.attribs.src = url.searchParams.get('url'); + i.attribs.src = url.searchParams.get('url') ?? ''; } }); diff --git a/lib/routes/18comic/album.ts b/lib/routes/18comic/album.ts index c7a5f9a0da..4f50298873 100644 --- a/lib/routes/18comic/album.ts +++ b/lib/routes/18comic/album.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import { renderDescription } from './templates/description'; @@ -70,7 +70,7 @@ async function handler(ctx) { cache.tryGet(`18comic:album:${item.id}`, async () => { const chapterApiUrl = `${getApiUrl()}/chapter?id=${item.id}`; const chapterResult = await processApiItems(chapterApiUrl); - const result = {}; + const result: DataItem = { title: '' }; const chapterNum = index + 1; result.title = `第${chapterNum}話 ${item.name === '' ? chapterNum : item.name}`; result.link = `${rootUrl}/photo/${item.id}`; diff --git a/lib/routes/18comic/blogs.ts b/lib/routes/18comic/blogs.ts index 65399a95c3..d3aafe958e 100644 --- a/lib/routes/18comic/blogs.ts +++ b/lib/routes/18comic/blogs.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -53,13 +53,13 @@ async function handler(ctx) { let items = $('.title') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { guid: string } => { + const $item = $(item); return { - title: item.text(), - link: `${rootUrl}${item.parent().attr('href')}`, - guid: `https://18comic.org${item.parent().attr('href')}`, + title: $item.text(), + link: `${rootUrl}${$item.parent().attr('href')}`, + guid: `https://18comic.org${$item.parent().attr('href')}`, }; }); diff --git a/lib/routes/18comic/search.ts b/lib/routes/18comic/search.ts index 3b9a81c78b..2ed8b8bd12 100644 --- a/lib/routes/18comic/search.ts +++ b/lib/routes/18comic/search.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import { parseDate } from '@/utils/parse-date'; @@ -67,11 +67,17 @@ async function handler(ctx) { const results = await Promise.all( filteredItemsByCategory.map((item) => cache.tryGet(`18comic:search:${item.id}`, async () => { - const result = { title: item.name, link: `${rootUrl}/album/${item.id}`, guid: `18comic:/album/${item.id}`, updated: parseDate(item.update_at) }; + const result: DataItem = { + title: item.name, + link: `${rootUrl}/album/${item.id}`, + guid: `18comic:/album/${item.id}`, + updated: parseDate(item.update_at), + }; const apiUrl = `${getApiUrl()}/album?id=${item.id}`; const apiResult = await processApiItems(apiUrl); result.pubDate = new Date(apiResult.addtime * 1000); - result.category = apiResult.tags.map((tag) => tag); + const tags = apiResult.tags.map((tag) => tag); + result.category = tags; result.author = apiResult.author.map((a) => a).join(', '); result.description = renderDescription({ introduction: apiResult.description, @@ -83,7 +89,7 @@ async function handler(ctx) { // `https://cdn-msp3.${domain}/media/photos/${item.id}/00003.webp`, ], cover: `https://cdn-msp3.${domain}/media/albums/${item.id}_3x4.jpg`, - category: result.category, + category: tags, }); return result; }) diff --git a/lib/routes/18comic/utils.ts b/lib/routes/18comic/utils.ts index a210ab843d..ae62a2b26e 100644 --- a/lib/routes/18comic/utils.ts +++ b/lib/routes/18comic/utils.ts @@ -3,6 +3,7 @@ import CryptoJS from 'crypto-js'; import { config } from '@/config'; import ConfigNotFoundError from '@/errors/types/config-not-found'; +import type { DataItem } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import md5 from '@/utils/md5'; @@ -99,13 +100,13 @@ const ProcessItems = async (ctx, currentUrl, rootUrl) => { let items = $('.video-title') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { guid: string } => { + const $item = $(item); return { - title: item.text().trim(), - link: `${rootUrl}${item.prev().find('a').attr('href')}`, - guid: `18comic:${item.prev().find('a').attr('href')}`, + title: $item.text().trim(), + link: `${rootUrl}${$item.prev().find('a').attr('href')}`, + guid: `18comic:${$item.prev().find('a').attr('href')}`, }; }); @@ -116,8 +117,8 @@ const ProcessItems = async (ctx, currentUrl, rootUrl) => { const content = load(detailResponse.data); - item.pubDate = parseDate(content('div[itemprop="datePublished"]').first().attr('content')); - item.updated = parseDate(content('div[itemprop="datePublished"]').last().attr('content')); + item.pubDate = parseDate(content('div[itemprop="datePublished"]').first().attr('content')!); + item.updated = parseDate(content('div[itemprop="datePublished"]').last().attr('content')!); item.category = content('span[data-type="tags"]') .first() .find('a') @@ -133,7 +134,7 @@ const ProcessItems = async (ctx, currentUrl, rootUrl) => { introduction: content('#intro-block .p-t-5').text(), images: content('.img_zoom_img img') .toArray() - .map((image) => content(image).attr('data-original')), + .map((image) => content(image).attr('data-original')!), cover: content('.thumb-overlay img').first().attr('src'), category: item.category, }); diff --git a/lib/routes/199it/index.tsx b/lib/routes/199it/index.tsx index b1d7ac29be..777a918657 100644 --- a/lib/routes/199it/index.tsx +++ b/lib/routes/199it/index.tsx @@ -4,7 +4,7 @@ import type { Element } from 'domhandler'; import type { Context } from 'hono'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -24,7 +24,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('article.newsplus') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('h2.entry-title').text(); @@ -43,7 +43,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -57,7 +57,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); $$('div.entry-content img.alignnone').each((_, el) => { @@ -85,7 +85,7 @@ export const handler = async (ctx: Context): Promise => { pubDate: pubDateStr ? parseDate(pubDateStr) : item.pubDate, category: categories, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const extraLinkEls: Element[] = $$('ul.related_post li a').toArray(); @@ -112,7 +112,7 @@ export const handler = async (ctx: Context): Promise => { $$('ul.related_post').parent().remove(); - const description: string | undefined = $$('div.entry-content').html(); + const description: string | undefined = $$('div.entry-content').html() ?? undefined; processedItem = { ...processedItem, @@ -142,7 +142,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('h3.site-title img').attr('src'), author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/19lou/index.ts b/lib/routes/19lou/index.ts index 8cf8cba12d..6cd4d44069 100644 --- a/lib/routes/19lou/index.ts +++ b/lib/routes/19lou/index.ts @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -10,12 +10,12 @@ import timezone from '@/utils/timezone'; import { isValidHost } from '@/utils/valid-host'; const setCookie = function (cookieName, cookieValue, seconds, path, domain, secure?) { - let expires = null; + let expires: Date | null = null; if (seconds !== -1) { expires = new Date(); expires.setTime(expires.getTime() + seconds); } - return [encodeURI(cookieName), '=', encodeURI(cookieValue), expires ? '; expires=' + expires.toGMTString() : '', path ? '; path=' + path : '/', domain ? '; domain=' + domain : '', secure ? '; secure' : ''].join(''); + return [encodeURI(cookieName), '=', encodeURI(cookieValue), expires ? '; expires=' + expires.toUTCString() : '', path ? '; path=' + path : '/', domain ? '; domain=' + domain : '', secure ? '; secure' : ''].join(''); }; export const route: Route = { @@ -72,12 +72,12 @@ async function handler(ctx) { let items = $('.center-center-jiazi') .find('a[title]') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); return { - title: item.attr('title'), - link: `https:${item.attr('href')}`, + title: $item.attr('title')!, + link: `https:${$item.attr('href')}`, }; }); @@ -100,7 +100,7 @@ async function handler(ctx) { item.author = content('.uname, .user-name').first().text(); item.description = content('.post-cont').first().html() || content('.thread-cont').html(); - item.pubDate = timezone(parseDate(content('.cont-top-left meta').attr('content')), 8); + item.pubDate = timezone(parseDate(content('.cont-top-left meta').attr('content')!), 8); return item; }) diff --git a/lib/routes/1lou/index.ts b/lib/routes/1lou/index.ts index 166c57a10c..26624596d2 100644 --- a/lib/routes/1lou/index.ts +++ b/lib/routes/1lou/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -13,7 +13,7 @@ export const handler = async (ctx) => { const limit = ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 50; const queryString = Object.entries(ctx.req.query()) - .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`) + .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value as string)}`) .join('&'); const currentUrl = new URL(`${params && params.endsWith('.htm') ? params : `${params}.htm`}${queryString ? `?${queryString}` : ''}`, rootUrl).href; @@ -27,24 +27,24 @@ export const handler = async (ctx) => { let items = $('li.media.thread.tap:not(li.hidden-sm)') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); - const subjectEl = item.find('div.subject').children('a').first(); + const subjectEl = $item.find('div.subject').children('a').first(); return { title: subjectEl.text(), - pubDate: timezone(parseDate(item.find('span.date').text()), 8), - link: new URL(subjectEl.prop('href'), rootUrl).href, + pubDate: timezone(parseDate($item.find('span.date').text()), 8), + link: new URL(subjectEl.prop('href')!, rootUrl).href, category: [ - item.find('a.text-secondary').text().replaceAll('[]', ''), - ...item + $item.find('a.text-secondary').text().replaceAll('[]', ''), + ...$item .find('a.badge') .toArray() .map((c) => $(c).text()), ].filter(Boolean), - author: item.find('a.username').text(), - language, + author: $item.find('a.username').text(), + language: language as Language, }; }); @@ -59,7 +59,7 @@ export const handler = async (ctx) => { if (title) { const description = $$('div.message.break-all').html(); - const image = new URL($$('img').first().prop('src'), rootUrl).href; + const image = new URL($$('img').first().prop('src')!, rootUrl).href; item.title = title; item.description = description; @@ -73,14 +73,14 @@ export const handler = async (ctx) => { }; item.image = image; item.banner = image; - item.language = language; + item.language = language as Language; const torrents = $$('ul.attachlist li a'); if (torrents.length > 0) { const torrent = torrents.first(); - item.enclosure_url = new URL(torrent.prop('href'), rootUrl).href; + item.enclosure_url = new URL(torrent.prop('href')!, rootUrl).href; item.enclosure_type = 'application/x-bittorrent'; item.enclosure_title = torrent.text(); } @@ -92,7 +92,7 @@ export const handler = async (ctx) => { ); const author = 'BT 之家 1LOU 站'; - const image = new URL($('img.logo-2').prop('src'), rootUrl).href; + const image = new URL($('img.logo-2').prop('src')!, rootUrl).href; return { title: `${$('title').text().split(/-/, 1)[0]} - ${author}`, @@ -102,7 +102,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author, - language, + language: language as Language, }; }; @@ -138,9 +138,9 @@ export const route: Route = { { source: ['1lou.me/:params'], target: (_, url) => { - url = new URL(url); + const parsedUrl = new URL(url); - return `/1lou${url.href.replace(rootUrl, '')}`; + return `/1lou${parsedUrl.href.replace(rootUrl, '')}`; }, }, ], diff --git a/lib/routes/1x/index.tsx b/lib/routes/1x/index.tsx index b89d21b679..5472dc0396 100644 --- a/lib/routes/1x/index.tsx +++ b/lib/routes/1x/index.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; export const handler = async (ctx) => { @@ -27,11 +27,11 @@ export const handler = async (ctx) => { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const title = item.find('span.photos-feed-data-title').first().text() || 'Untitled'; - const image = item.find('img').prop('src'); - const author = item.find('span.photos-feed-data-name').first().text(); + const title = $item.find('span.photos-feed-data-title').first().text() || 'Untitled'; + const image = $item.find('img').prop('src'); + const author = $item.find('span.photos-feed-data-name').first().text(); const text = `${title} by ${author}`; @@ -46,7 +46,7 @@ export const handler = async (ctx) => { ); - const id = item.find('img[id]').prop('id').split(/-/).pop(); + const id = $item.find('img[id]').prop('id').split(/-/).pop(); const guid = `1x-${id}`; return { @@ -62,14 +62,14 @@ export const handler = async (ctx) => { }, image, banner: image, - language, + language: language as Language, enclosure_url: image, enclosure_type: image ? `image/${image.split(/\./).pop()}` : undefined, enclosure_title: title, }; }); - const image = new URL($('img.themedlogo').prop('src'), rootUrl).href; + const image = new URL($('img.themedlogo').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -79,7 +79,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/2048/index.tsx b/lib/routes/2048/index.tsx index 6feaef9741..b032a471a7 100644 --- a/lib/routes/2048/index.tsx +++ b/lib/routes/2048/index.tsx @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -71,7 +71,7 @@ async function handler(ctx) { const onclickValue = $('.button').first().attr('onclick'); const targetUrl = onclickValue?.match(/window\.open\('([^']+)'/)?.[1]; - return { url: new URL(targetUrl, 'https://2048.info').href }; + return { url: new URL(targetUrl!, 'https://2048.info').href }; }); // 获取重定向后的url const redirectResponse = await ofetch.raw(domainInfo.url); @@ -109,13 +109,13 @@ async function handler(ctx) { .last() .nextAll('.tr3') .toArray() - .map((item) => { - item = $(item).find('a.subject'); + .map((item): DataItem & { link: string; guid: string } => { + const $item = $(item).find('a.subject'); return { - title: item.text(), - link: `${currentHost}/${item.attr('href')}`, - guid: `${rootUrl}/2048/${item.attr('href')}`, + title: $item.text(), + link: `${currentHost}/${$item.attr('href')}`, + guid: `${rootUrl}/2048/${$item.attr('href')}`, }; }) .filter((item) => !item.link.includes('undefined')); @@ -143,7 +143,7 @@ async function handler(ctx) { }); item.author = content('.fl.black').first().text(); - item.pubDate = timezone(parseDate(content('span.fl.gray').first().attr('title')), 8); + item.pubDate = timezone(parseDate(content('span.fl.gray').first().attr('title')!), 8); const readTpc = content('#read_tpc').first(); const copyLink = content('#copytext')?.first()?.text(); diff --git a/lib/routes/21caijing/channel.ts b/lib/routes/21caijing/channel.ts index f0e235293a..947b5d8d55 100644 --- a/lib/routes/21caijing/channel.ts +++ b/lib/routes/21caijing/channel.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Context } from 'hono'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -110,7 +110,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: updated ? parseDate(updated, 'X') : undefined, - language, + language: language as Language, }; return processedItem; @@ -124,7 +124,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); $$('div.rela-box').remove(); @@ -135,7 +135,7 @@ export const handler = async (ctx: Context): Promise => { const pubDateStr: string | undefined = $$('div.author-infos span') .text() .match(/(\d{4}-\d{2}-\d{2}\s\d{2}:\d{2})/)?.[1]; - const categories: string[] = $$('meta[name="keywords"]').attr('content')?.split(/,/) ?? item.category ?? []; + const categories: DataItem['category'] = $$('meta[name="keywords"]').attr('content')?.split(/,/) ?? item.category ?? []; const upDatedStr: string | undefined = pubDateStr; const processedItem: DataItem = { @@ -148,7 +148,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -169,7 +169,7 @@ export const handler = async (ctx: Context): Promise => { item: items, allowEmpty: true, author, - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/2cycd/index.ts b/lib/routes/2cycd/index.ts index 453587ef9f..48a61e5ea3 100644 --- a/lib/routes/2cycd/index.ts +++ b/lib/routes/2cycd/index.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -45,10 +45,10 @@ async function handler(ctx) { const list = $('tbody[id^="normalthread_"]') .toArray() - .map((item) => { - item = $(item); - const xst = item.find('a.s.xst'); - const author = item.find('td.by cite a').eq(0).text(); + .map((item): DataItem => { + const $item = $(item); + const xst = $item.find('a.s.xst'); + const author = $item.find('td.by cite a').eq(0).text(); return { title: xst.text(), link: xst.attr('href'), @@ -58,7 +58,7 @@ async function handler(ctx) { // console.log(list); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link, { responseType: 'buffer', }); @@ -67,7 +67,7 @@ async function handler(ctx) { const first_post = content('td[id^="postmessage_"]').first(); const dateobj = content('em[id^="authorposton"]').first(); item.description = first_post.html(); - item.pubDate = timezone(parseDate(dateobj.find('span').attr('title'), 'YYYY-M-D HH:mm:ss'), 8); + item.pubDate = timezone(parseDate(dateobj.find('span').attr('title')!, 'YYYY-M-D HH:mm:ss'), 8); return item; }) diff --git a/lib/routes/36kr/utils.ts b/lib/routes/36kr/utils.ts index 918ee0971b..81eba1dac2 100644 --- a/lib/routes/36kr/utils.ts +++ b/lib/routes/36kr/utils.ts @@ -42,7 +42,7 @@ export const getWafTokenId = () => const payload = $('script') .text() .match(/atob\('(.*?)'\)\),/)?.[1]; - const response = solveWafChallenge(payload); + const response = solveWafChallenge(payload!); const tokenIdResponse = await ofetch.raw(rootUrl, { headers: { diff --git a/lib/routes/3dmgame/game.ts b/lib/routes/3dmgame/game.ts index f8996f4aaa..6a643cee49 100644 --- a/lib/routes/3dmgame/game.ts +++ b/lib/routes/3dmgame/game.ts @@ -33,12 +33,12 @@ async function handler(ctx) { const listSelector = type === 'resource' ? $('.ZQ_Left .Llis_4 .lis li, .zq_left .rigtbox7 li').toArray() : $('.ZQ_Left .lis, .zq_left .newsleft li').toArray(); const list = listSelector.map((i) => { - i = $(i); - const a = i.find('a[href]').last(); - const time = i.find('.time'); + const $i = $(i); + const a = $i.find('a[href]').last(); + const time = $i.find('.time'); return { title: a.text(), - description: i.find('.miaoshu').text(), + description: $i.find('.miaoshu').text(), link: a.attr('href'), pubDate: time.length ? parseDate(time.text().trim()) : null, // 2020-12-31 }; diff --git a/lib/routes/3dmgame/news-center.ts b/lib/routes/3dmgame/news-center.ts index 2ca342d3e3..c40f588775 100644 --- a/lib/routes/3dmgame/news-center.ts +++ b/lib/routes/3dmgame/news-center.ts @@ -42,21 +42,21 @@ async function handler(ctx) { const list = $(isArcPost ? '.selectarcpost' : '.selectpost') .toArray() .map((item) => { - item = $(item); + const $item = $(item); if (isArcPost) { return { - title: item.find('.bt').text(), - link: item.attr('href'), - description: item.find('p').text(), - pubDate: timezone(parseDate(item.find('.time').text()), 8), + title: $item.find('.bt').text(), + link: $item.attr('href'), + description: $item.find('p').text(), + pubDate: timezone(parseDate($item.find('.time').text()), 8), }; } - const a = item.find('.text a'); + const a = $item.find('.text a'); return { title: a.first().text(), link: a.attr('href'), - description: item.find('.miaoshu').text(), - pubDate: timezone(parseDate(item.find('.time').text()), 8), + description: $item.find('.miaoshu').text(), + pubDate: timezone(parseDate($item.find('.time').text()), 8), }; }); diff --git a/lib/routes/3dmgame/utils.ts b/lib/routes/3dmgame/utils.ts index fff6bccaf3..51130925cb 100644 --- a/lib/routes/3dmgame/utils.ts +++ b/lib/routes/3dmgame/utils.ts @@ -12,9 +12,9 @@ const parseArticle = (item) => if (item.link.startsWith('https://dl.3dmgame.com/')) { const lis = $('.patchtop .lis'); - const [, category, pubDate, author] = lis.text().match(/补丁类型:([^\n]*)\n.*整理时间:([^\n]*)\n.*补丁制作:([^\n]*)\n/s); + const [, category, pubDate, author] = lis.text().match(/补丁类型:([^\n]*)\n.*整理时间:([^\n]*)\n.*补丁制作:([^\n]*)\n/s)!; - item.description = lis.html() + $('.L_title').html() + $('.GmL_1').html(); + item.description = lis.html()! + $('.L_title').html()! + $('.GmL_1').html(); item.category = category; item.pubDate = timezone(parseDate(pubDate), 8); item.author = author; diff --git a/lib/routes/423down/index.ts b/lib/routes/423down/index.ts index 84ad2ab49d..c2b6c15a07 100644 --- a/lib/routes/423down/index.ts +++ b/lib/routes/423down/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,19 +24,19 @@ export const handler = async (ctx) => { let items = $('ul.excerpt li') .toArray() .filter((item) => { - item = $(item); + const $item = $(item); - const link = item.find('h2 a').prop('href'); - const isAdItem = item.find('span.cat').text().includes('423Down'); + const link = $item.find('h2 a').prop('href'); + const isAdItem = $item.find('span.cat').text().includes('423Down'); - return new RegExp(domain).test(link) && !isAdItem; + return new RegExp(domain).test(link!) && !isAdItem; }) .slice(0, limit) .map((item) => { - item = $(item); + const $item = $(item); - const title = item.find('h2').text(); - const image = item.find('a.pic img').prop('src'); + const title = $item.find('h2').text(); + const image = $item.find('a.pic img').prop('src'); const description = renderDescription({ images: image ? [ @@ -46,25 +46,25 @@ export const handler = async (ctx) => { }, ] : undefined, - intro: item.find('div.note').text(), + intro: $item.find('div.note').text(), }); return { title, description, - pubDate: parseDate(item.find('span.time').text(), 'MM-DD'), - link: item.find('h2 a').prop('href'), - category: item + pubDate: parseDate($item.find('span.time').text(), 'MM-DD'), + link: $item.find('h2 a').prop('href'), + category: $item .find('span.cat a') .toArray() .map((c) => $(c).text()), content: { html: description, - text: item.find('div.note').text(), + text: $item.find('div.note').text(), }, image, banner: image, - language, + language: language as Language, enclosure_url: image, enclosure_type: image ? `image/${image.split(/\./).pop()}` : undefined, enclosure_title: title, @@ -73,13 +73,13 @@ export const handler = async (ctx) => { items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); const title = $$('h1.meta-tit a').text(); - const description = item.description + renderDescription({ description: $$('div.entry').html() }); + const description = item.description + renderDescription({ description: $$('div.entry').html() ?? undefined }); item.title = title; item.description = description; @@ -91,7 +91,7 @@ export const handler = async (ctx) => { html: description, text: $$('div.entry').text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -109,7 +109,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, }; }; diff --git a/lib/routes/4ksj/forum.tsx b/lib/routes/4ksj/forum.tsx index f4f811c68f..9448e56210 100644 --- a/lib/routes/4ksj/forum.tsx +++ b/lib/routes/4ksj/forum.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import md5 from '@/utils/md5'; import ofetch from '@/utils/ofetch'; @@ -98,11 +98,12 @@ async function handler(ctx) { let items = $('div.nex_cmo_piv a') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { link: string } => { + const $item = $(item); return { - link: new URL(item.prop('href'), rootUrl).href, + link: new URL($item.prop('href')!, rootUrl).href, + title: '', }; }); @@ -145,28 +146,28 @@ async function handler(ctx) { $$('div.nex_drama_intros em').first().remove(); $$('strong font').each((_, el) => { - el = $$(el); + const $el = $$(el); - el.parent().remove(); + $el.parent().remove(); }); const title = $$('div.nex_drama_Top h5').text(); const description = $$('div.nex_drama_intros').html(); const picture = $$('div.nex_drama_pic') - .html() + .html()! .match(/background:url\((.*?)\)/)?.[1] ?? ''; const details = $$('li.nex_drama_Detail_li, li.nex_drama_Detail_lis dd') .toArray() .map((li) => { - li = $$(li); + const $li = $$(li); - const key = li + const key = $li .find('em') .text() .replaceAll(/:|\s/g, ''); - const value = li.find('span').length === 0 ? li.contents().last().text().trim() : li.find('span').text().trim(); + const value = $li.find('span').length === 0 ? $li.contents().last().text().trim() : $li.find('span').text().trim(); return { [key]: value }; }); @@ -177,10 +178,10 @@ async function handler(ctx) { ? $$('td.t_f strong') .toArray() .map((l) => { - l = $$(l); + const $l = $$(l); - const title = l.contents().first().text(); - const link = l.next().prop('href') ?? l.nextUntil('a').next().prop('href'); + const title = $l.contents().first().text(); + const link = $l.next().prop('href') ?? $l.nextUntil('a').next().prop('href'); item.enclosure_url ??= link; item.enclosure_type ??= 'application/x-bittorrent'; @@ -188,7 +189,7 @@ async function handler(ctx) { return { title, - tags: l + tags: $l .contents() .last() .text() @@ -199,15 +200,15 @@ async function handler(ctx) { : $$('div.newfujian') .toArray() .map((l) => { - l = $$(l); + const $l = $$(l); return { - title: l.find('p.filename').prop('title') || l.find('p.filename').text(), - tags: l + title: $l.find('p.filename').prop('title') || $l.find('p.filename').text(), + tags: $l .find('div.fileaq') .text() .match(/【(.*?)】/g), - link: l.find('div.down_2 a').prop('href'), + link: $l.find('div.down_2 a').prop('href'), }; }); @@ -238,7 +239,7 @@ async function handler(ctx) { links, }); item.pubDate = timezone(parseDate(pubDate, 'YYYY-M-D HH:mm:ss'), 8); - item.category = Object.values(mergedDetails) + item.category = Object.values(mergedDetails) .flatMap((c) => c.split(/\s/)) .filter(Boolean); item.author = mergedDetails['导演']; @@ -268,6 +269,6 @@ async function handler(ctx) { allowEmpty: true, image, author: $('meta[name="application-name"]').prop('content'), - language, + language: language as Language, }; } diff --git a/lib/routes/50forum/zhuanjia.ts b/lib/routes/50forum/zhuanjia.ts index 5cdf4c6dfd..cd23639926 100644 --- a/lib/routes/50forum/zhuanjia.ts +++ b/lib/routes/50forum/zhuanjia.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -34,21 +34,21 @@ async function handler() { }); const data = response.data; if (!data) { - return; + return null; } const $ = load(data); let out = $('div.container div.list_list.mtop10 ul li') .find('a') .toArray() - .map((item) => { - item = $(item); - const link = rootUrl + item.attr('href'); + .map((item): DataItem & { link: string } => { + const $item = $(item); + const link = rootUrl + $item.attr('href'); const reg = /^(.+) - (.*) - (.+)$/; - const keyword = reg.exec(item.text().trim()); + const keyword = reg.exec($item.text().trim()); return { - title: keyword[1], - author: keyword[2], - pubDate: timezone(parseDate(keyword[3], 'YYYY-MM-DD'), 8), + title: keyword![1], + author: keyword![2], + pubDate: timezone(parseDate(keyword![3], 'YYYY-MM-DD'), 8), link, }; }); diff --git a/lib/routes/51cto/recommend.ts b/lib/routes/51cto/recommend.ts index ee8b1b85bf..cf92eeaac4 100644 --- a/lib/routes/51cto/recommend.ts +++ b/lib/routes/51cto/recommend.ts @@ -6,6 +6,7 @@ import got from '@/utils/got'; import logger from '@/utils/logger'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; import { getToken, sign } from './utils'; @@ -53,7 +54,7 @@ async function getFullcontent(item, cookie = '') { return { title: item.title, link: item.url, - pubDate: parseDate(item.pubdate, 8), + pubDate: timezone(parseDate(item.pubdate), 8), description: fullContent || item.abstract, // Return item.abstract if fullContent is null }; } diff --git a/lib/routes/51read/article.ts b/lib/routes/51read/article.ts index b8556f6db9..68591d898c 100644 --- a/lib/routes/51read/article.ts +++ b/lib/routes/51read/article.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { DataItem, Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -57,7 +57,7 @@ async function handler(ctx) { item, image: $book('.bi-img img').attr('src'), author: $book('.bi-wt a').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, }; } diff --git a/lib/routes/56kog/util.tsx b/lib/routes/56kog/util.tsx index 985c311179..ea01d1a68a 100644 --- a/lib/routes/56kog/util.tsx +++ b/lib/routes/56kog/util.tsx @@ -2,6 +2,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; import iconv from 'iconv-lite'; +import type { DataItem, Language } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -18,21 +19,21 @@ const fetchItems = async (limit, currentUrl) => { let items = $('p.line') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, - author: item.find('span').last().text(), + link: new URL(a.prop('href')!, rootUrl).href, + author: $item.find('span').last().text(), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { const { data: detailResponse } = await got(item.link, { responseType: 'buffer', @@ -42,16 +43,16 @@ const fetchItems = async (limit, currentUrl) => { const details = content('div.mohe-content p') .toArray() - .map((detail) => { - detail = content(detail); - const as = detail.find('a'); + .map((detail): { label: string; value: any } => { + const $detail = content(detail); + const as = $detail.find('a'); return { - label: detail.find('span.c-l-depths').text().split(/:/, 1)[0], + label: $detail.find('span.c-l-depths').text().split(/:/, 1)[0], value: as.length === 0 ? content( - detail + $detail .contents() .toArray() .find((c) => c.nodeType === 3) @@ -59,27 +60,27 @@ const fetchItems = async (limit, currentUrl) => { .text() .trim() : { - href: new URL(as.first().prop('href'), rootUrl).href, + href: new URL(as.first().prop('href')!, rootUrl).href, text: as.first().text().trim(), }, }; }); - const pubDate = details.find((detail) => detail.label === '更新').value; + const pubDate = details.find((detail) => detail.label === '更新')!.value; item.title = content('h1').contents().first().text(); item.description = renderDescription({ images: [ { - src: new URL(content('a.mohe-imgs img').prop('src'), rootUrl).href, + src: new URL(content('a.mohe-imgs img').prop('src')!, rootUrl).href, alt: item.title, }, ], details, }); - item.author = details.find((detail) => detail.label === '作者').value; - item.category = [details.find((detail) => detail.label === '状态').value, details.find((detail) => detail.label === '类型').value.text].filter(Boolean); - item.guid = `56kog-${item.link.match(/\/(\d+)\.html$/)[1]}#${pubDate}`; + item.author = details.find((detail) => detail.label === '作者')!.value; + item.category = [details.find((detail) => detail.label === '状态')!.value, details.find((detail) => detail.label === '类型')!.value.text].filter(Boolean); + item.guid = `56kog-${item.link!.match(/\/(\d+)\.html$/)![1]}#${pubDate}`; item.pubDate = timezone(parseDate(pubDate), 8); } catch { // no-empty @@ -97,7 +98,7 @@ const fetchItems = async (limit, currentUrl) => { title: $('title').text(), link: currentUrl, description: $('meta[name="description"]').prop('content'), - language: $('html').prop('lang'), + language: $('html').prop('lang') as Language, icon, logo: icon, subtitle: $('meta[name="keywords"]').prop('content'), diff --git a/lib/routes/591/list.tsx b/lib/routes/591/list.tsx index 76bbe7c99a..06e36175bb 100644 --- a/lib/routes/591/list.tsx +++ b/lib/routes/591/list.tsx @@ -24,7 +24,7 @@ function appendRentalAPIParams(urlString) { } async function getToken() { - const html = await client('https://rent.591.com.tw').text(); + const html = await (client('https://rent.591.com.tw') as any).text(); const $ = load(html); const csrfToken = $('meta[name="csrf-token"]').attr('content'); @@ -39,12 +39,14 @@ async function getToken() { async function getHouseList(houseListURL) { const csrfToken = await getToken(); - const data = await client({ - url: houseListURL, - headers: { - 'X-CSRF-TOKEN': csrfToken, - }, - }).json(); + const data = await ( + client({ + url: houseListURL, + headers: { + 'X-CSRF-TOKEN': csrfToken, + }, + }) as any + ).json(); const { data: { data: houseList }, diff --git a/lib/routes/5music/index.ts b/lib/routes/5music/index.ts index bcfd1c3af7..dd8946c948 100644 --- a/lib/routes/5music/index.ts +++ b/lib/routes/5music/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -84,6 +84,6 @@ async function handler(ctx) { title: '五大唱片 - 新货上架', link: url, item: items, - language: 'zh-tw', + language: 'zh-TW' as Language, }; } diff --git a/lib/routes/69shu/article.ts b/lib/routes/69shu/article.ts index b01f213223..37ec9106c8 100644 --- a/lib/routes/69shu/article.ts +++ b/lib/routes/69shu/article.ts @@ -45,7 +45,7 @@ export const route: Route = { item, image: $('.bookimg2>img').attr('src'), author: $('.booknav2>p:first-of-type>a').text(), - language: 'zh-cn', + language: 'zh-CN', }; }, }; diff --git a/lib/routes/6park/index.ts b/lib/routes/6park/index.ts index fd6123acce..0d10a8feb2 100644 --- a/lib/routes/6park/index.ts +++ b/lib/routes/6park/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -45,19 +45,20 @@ async function handler(ctx) { let items = $('#d_list ul li, #thread_list li, .t_l .t_subject') .toArray() .slice(0, limit) - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a').first(); + const a = $item.find('a').first(); return { link: `${rootUrl}/${id}/${a.attr('href')}`, + title: '', }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -69,7 +70,7 @@ async function handler(ctx) { item.author = detailResponse.data.match(/送交者:[^>]*>([^<]*)<\/a>/)[1].trim(); item.pubDate = timezone(parseDate(detailResponse.data.match(/于 (.*) 已读/)[1], 'YYYY-MM-DD h:m'), 8); item.description = content('pre') - .html() + .html()! .replaceAll('

', '') .replaceAll(/6park.com<\/font>/g, ''); diff --git a/lib/routes/6park/news.ts b/lib/routes/6park/news.ts index 2e6ffab358..075c49904d 100644 --- a/lib/routes/6park/news.ts +++ b/lib/routes/6park/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -58,23 +58,23 @@ async function handler(ctx) { let items = $('#d_list ul li, #thread_list li, .t_l .t_subject') .toArray() .slice(0, limit) - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a').first(); + const a = $item.find('a').first(); const link = a.attr('href'); return { title: a.text(), - link: link.startsWith('http') ? link : `${rootUrl}/${link.startsWith('view') ? `newspark/${link}` : link}`, + link: link!.startsWith('http') ? link : `${rootUrl}/${link!.startsWith('view') ? `newspark/${link}` : link}`, }; }); items = await Promise.all( items - .filter((item) => /6parknews\.com/.test(item.link)) + .filter((item) => /6parknews\.com/.test(item.link!)) .map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { const detailResponse = await got({ method: 'get', @@ -88,7 +88,7 @@ async function handler(ctx) { item.title = content('h2').text(); item.author = matches[1].trim(); item.pubDate = timezone(parseDate(matches[2], 'YYYY-MM-DD h:m'), 8); - item.description = content('#shownewsc').html().replaceAll('

', ''); + item.description = content('#shownewsc').html()!.replaceAll('

', ''); } catch { // no-empty } diff --git a/lib/routes/6v123/index.ts b/lib/routes/6v123/index.ts index 54e55a5e65..95ee35940c 100644 --- a/lib/routes/6v123/index.ts +++ b/lib/routes/6v123/index.ts @@ -4,7 +4,7 @@ import type { Element } from 'domhandler'; import type { Context } from 'hono'; import iconv from 'iconv-lite'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -28,7 +28,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('ul.list li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('a').text(); @@ -47,7 +47,7 @@ export const handler = async (ctx: Context): Promise => { guid, id: guid, updated: upDatedStr ? parseDate(upDatedStr, ['MM-DD', 'YYYY-MM-DD']) : undefined, - language, + language: language as Language, }; return processedItem; @@ -60,7 +60,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link, { + const detailResponse = await ofetch(item.link!, { responseType: 'arrayBuffer', }); const $$: CheerioAPI = load(iconv.decode(Buffer.from(detailResponse), encoding)); @@ -92,7 +92,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const $enclosureEl: Cheerio = $$('td a[href^="magnet"]').last(); @@ -125,7 +125,7 @@ export const handler = async (ctx: Context): Promise => { item: items, allowEmpty: true, image: new URL('images/logo.gif', baseUrl).href, - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/78dm/index.ts b/lib/routes/78dm/index.ts index fdebe88264..1cafb0a137 100644 --- a/lib/routes/78dm/index.ts +++ b/lib/routes/78dm/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,12 +24,12 @@ export const handler = async (ctx) => { let items = $('section.box-content div.card a.card-title') .slice(0, limit) .toArray() - .map((item) => { - item = $(item).parent(); + .map((item): DataItem => { + const $item = $(item).parent(); - const title = item.find('a.card-title').text(); + const title = $item.find('a.card-title').text(); - const src = item.find('a.card-image img').prop('data-src'); + const src = $item.find('a.card-image img').prop('data-src'); const image = src?.startsWith('//') ? `https:${src}` : src; const description = renderDescription({ @@ -42,9 +42,9 @@ export const handler = async (ctx) => { ] : undefined, }); - const pubDate = item.find('div.card-info span.item').last().text(); + const pubDate = $item.find('div.card-info span.item').last().text(); - const href = item.find('a.card-title').prop('href'); + const href = $item.find('a.card-title').prop('href'); return { title, @@ -53,22 +53,22 @@ export const handler = async (ctx) => { link: href?.startsWith('//') ? `https:${href}` : href, category: [ ...new Set([ - ...item + ...$item .find('span.tag-title') .toArray() .map((c) => $(c).text()), - item.find('div.card-info span.item').first().text(), + $item.find('div.card-info span.item').first().text(), ]), ].filter(Boolean), image, banner: image, - language, + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); @@ -76,18 +76,18 @@ export const handler = async (ctx) => { $$('i.p-status').remove(); $$('div.image-text-content p img.lazy').each((_, el) => { - el = $$(el); + const $el = $$(el); - const src = el.prop('data-src'); + const src = $el.prop('data-src'); const image = src?.startsWith('//') ? `https:${src}` : src; - el.parent().replaceWith( + $el.parent().replaceWith( renderDescription({ images: image ? [ { src: image, - alt: el.prop('title') ?? '', + alt: $el.prop('title') ?? '', }, ] : undefined, @@ -104,13 +104,13 @@ export const handler = async (ctx) => { item.title = title; item.description = description; - item.pubDate = timezone(parseDate($$('p.push-time').text().split(/:/).pop()), 8); + item.pubDate = timezone(parseDate($$('p.push-time').text().split(/:/).pop()!), 8); item.author = $$('a.push-username').contents().first().text(); item.content = { html: description, text: $$('div.image-text-content').first().text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -118,7 +118,7 @@ export const handler = async (ctx) => { ); const title = $('title').text(); - const image = new URL($('a.logo img').prop('src'), rootUrl).href; + const image = new URL($('a.logo img').prop('src')!, rootUrl).href; return { title: `${title} | ${$('div.actived').text()}`, @@ -128,7 +128,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/7mmtv/index.tsx b/lib/routes/7mmtv/index.tsx index 4104cf7092..4ebd5fa372 100644 --- a/lib/routes/7mmtv/index.tsx +++ b/lib/routes/7mmtv/index.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -64,23 +64,23 @@ async function handler(ctx) { let items = $('.video') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { poster?: string; video?: string } => { + const $item = $(item); - const title = item.find('.video-title a'); + const title = $item.find('.video-title a'); return { title: title.text(), - author: item.find('.video-channel').text(), - pubDate: parseDate(item.find('.small').text()), + author: $item.find('.video-channel').text(), + pubDate: parseDate($item.find('.small').text()), link: title.attr('href'), - poster: item.find('img').attr('data-src'), - video: item.find('video').attr('data-src'), + poster: $item.find('img').attr('data-src'), + video: $item.find('video').attr('data-src'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/81/81rc/index.ts b/lib/routes/81/81rc/index.ts index 18bdf4f9aa..f5aa5e8b17 100644 --- a/lib/routes/81/81rc/index.ts +++ b/lib/routes/81/81rc/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -22,20 +22,20 @@ export const handler = async (ctx) => { let items = $('div.left-news ul li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('a').text(), - pubDate: timezone(parseDate(item.find('span').text()), 8), - link: item.find('a').prop('href'), - language, + title: $item.find('a').text(), + pubDate: timezone(parseDate($item.find('span').text()), 8), + link: $item.find('a').prop('href'), + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); @@ -50,7 +50,7 @@ export const handler = async (ctx) => { html: description, text: $$('div.txt').text(), }; - item.language = language; + item.language = language as Language; return item; }) @@ -68,7 +68,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, }; }; diff --git a/lib/routes/8264/list.tsx b/lib/routes/8264/list.tsx index 3a752f13ee..7e47d64d27 100644 --- a/lib/routes/8264/list.tsx +++ b/lib/routes/8264/list.tsx @@ -2,7 +2,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -103,20 +103,20 @@ async function handler(ctx) { .find('a') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const link = item.prop('href'); + const link = $item.prop('href'); return { - title: item.text(), - link: link.startsWith('http') ? link : new URL(link, rootUrl).href, + title: $item.text(), + link: link!.startsWith('http') ? link : new URL(link!, rootUrl).href, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link, { responseType: 'buffer', }); @@ -127,7 +127,7 @@ async function handler(ctx) { content('i.pstatus').remove(); content('div.crly').remove(); - const pubDate = content('span.pub-time').text() || content('span.fby span').first().prop('title') || content('span.fby').first().text().split('发表于').pop().trim(); + const pubDate = content('span.pub-time').text() || content('span.fby span').first().prop('title') || content('span.fby').first().text().split('发表于').pop()!.trim(); content('img').each((_, el) => { content(el).replaceWith( @@ -160,7 +160,7 @@ async function handler(ctx) { title: `${$('span.country, h2').text()} - ${description.split(',').pop()}`, link: currentUrl, description, - language: 'zh-cn', + language: 'zh-CN' as Language, icon, logo: icon, subtitle: $('meta[name="keywords"]').prop('content').trim(), diff --git a/lib/routes/8world/index.ts b/lib/routes/8world/index.ts index 285d8d1bd8..7e19b23152 100644 --- a/lib/routes/8world/index.ts +++ b/lib/routes/8world/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import { getSubPath } from '@/utils/common-utils'; import got from '@/utils/got'; @@ -41,18 +41,18 @@ export async function handler(ctx) { let items = $('div[data-column="Two-Third"] .article-title .article-link') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text(), - link: `${rootUrl}${item.attr('href')}`, + title: $item.text(), + link: `${rootUrl}${$item.attr('href')}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -61,12 +61,12 @@ export async function handler(ctx) { const content = load(detailResponse.data); item.description = content('.text-long').html(); - item.title = content('meta[name="cXenseParse:mdc-title"]').attr('content'); + item.title = content('meta[name="cXenseParse:mdc-title"]').attr('content')!; item.author = content('meta[name="cXenseParse:author"]').attr('content'); - item.pubDate = parseDate(content('meta[name="cXenseParse:recs:publishtime"]').attr('content')); + item.pubDate = parseDate(content('meta[name="cXenseParse:recs:publishtime"]').attr('content')!); item.category = content('meta[name="cXenseParse:mdc-keywords"]') .toArray() - .map((keyword) => content(keyword).attr('content')); + .map((keyword) => content(keyword).attr('content')!); return item; }) diff --git a/lib/routes/91porn/author.ts b/lib/routes/91porn/author.ts index 6ab2df39f0..44f41fb526 100644 --- a/lib/routes/91porn/author.ts +++ b/lib/routes/91porn/author.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -53,25 +53,25 @@ async function handler(ctx) { let items = $('.row .well') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { poster?: string } => { + const $item = $(item); return { - title: item.find('.video-title').text(), - link: item.find('a').attr('href'), - poster: item.find('.img-responsive').attr('src'), + title: $item.find('.video-title').text(), + link: $item.find('a').attr('href'), + poster: $item.find('.img-responsive').attr('src'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(`91porn:${lang}:${new URL(item.link).searchParams.get('viewkey')}`, async () => { + cache.tryGet(`91porn:${lang}:${new URL(item.link!).searchParams.get('viewkey')}`, async () => { const { data } = await got(item.link); const $ = load(data); item.pubDate = parseDate($('.title-yakov').eq(0).text(), 'YYYY-MM-DD'); item.description = renderIndexDescription({ - link: item.link, - poster: item.poster, + link: item.link!, + poster: item.poster!, }); item.author = $('.title-yakov a span').text(); delete item.poster; diff --git a/lib/routes/91porn/index.ts b/lib/routes/91porn/index.ts index d5998e5d12..57912775da 100644 --- a/lib/routes/91porn/index.ts +++ b/lib/routes/91porn/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -56,25 +56,25 @@ async function handler(ctx) { let items = $('.row .well') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem & { poster?: string } => { + const $item = $(item); return { - title: item.find('.video-title').text(), - link: item.find('a').attr('href'), - poster: item.find('.img-responsive').attr('src'), + title: $item.find('.video-title').text(), + link: $item.find('a').attr('href'), + poster: $item.find('.img-responsive').attr('src'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(`91porn:${lang}:${new URL(item.link).searchParams.get('viewkey')}`, async () => { + cache.tryGet(`91porn:${lang}:${new URL(item.link!).searchParams.get('viewkey')}`, async () => { const { data } = await got(item.link); const $ = load(data); item.pubDate = parseDate($('.title-yakov').eq(0).text(), 'YYYY-MM-DD'); item.description = renderIndexDescription({ - link: item.link, - poster: item.poster, + link: item.link!, + poster: item.poster!, }); item.author = $('.title-yakov a span').text(); delete item.poster; diff --git a/lib/routes/95mm/utils.tsx b/lib/routes/95mm/utils.tsx index be22b86a9c..f9ae6d191b 100644 --- a/lib/routes/95mm/utils.tsx +++ b/lib/routes/95mm/utils.tsx @@ -1,6 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; +import type { DataItem } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -19,21 +20,21 @@ const ProcessItems = async (ctx, title, currentUrl) => { let items = $('div.list-body') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); return { title: a.text(), link: a.attr('href'), - guid: a.attr('href').replace('95mm.vip', '95mm.org'), + guid: a.attr('href')!.replace('95mm.vip', '95mm.org'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/9to5/subsite.ts b/lib/routes/9to5/subsite.ts index 5b8d492ab5..9898f67e07 100644 --- a/lib/routes/9to5/subsite.ts +++ b/lib/routes/9to5/subsite.ts @@ -64,7 +64,7 @@ async function handler(ctx) { const items = await Promise.all( feed.items.splice(0, limit).map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got({ method: 'get', url: item.link, @@ -72,7 +72,7 @@ async function handler(ctx) { const description = utils.ProcessFeed(response.data); const single = { - title: item.title, + title: item.title!, description, pubDate: item.pubDate, link: item.link, diff --git a/lib/routes/9to5/utils.ts b/lib/routes/9to5/utils.ts index 3a3542b1ea..6a1da82a34 100644 --- a/lib/routes/9to5/utils.ts +++ b/lib/routes/9to5/utils.ts @@ -6,7 +6,7 @@ const ProcessFeed = (data) => { const cover = $('meta[property="og:image"]'); if (cover.length > 0) { - $(``).insertBefore(content[0].firstChild); + $(``).insertBefore(content[0].firstChild!); } // remove useless DOMs diff --git a/lib/routes/a9vg/index.ts b/lib/routes/a9vg/index.ts index dc911e6cd1..0d1bf5e454 100644 --- a/lib/routes/a9vg/index.ts +++ b/lib/routes/a9vg/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,15 +24,15 @@ export const handler = async (ctx) => { let items = $('a.a9-rich-card-list_item') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const image = item.find('img.a9-rich-card-list_image'); - const title = item.find('div.a9-rich-card-list_label').text(); + const image = $item.find('img.a9-rich-card-list_image'); + const title = $item.find('div.a9-rich-card-list_label').text(); return { title, - link: new URL(item.prop('href'), rootUrl).href, + link: new URL($item.prop('href')!, rootUrl).href, description: renderDescription({ images: image ? [ @@ -43,28 +43,28 @@ export const handler = async (ctx) => { ] : undefined, }), - pubDate: timezone(parseDate(item.find('div.a9-rich-card-list_infos').text()), 8), - language, + pubDate: timezone(parseDate($item.find('div.a9-rich-card-list_infos').text()), 8), + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); $$('ignore_js_op img, p img').each((_, el) => { - el = $$(el); + const $el = $$(el); - el.parent().replaceWith( + $el.parent().replaceWith( renderDescription({ - images: el.prop('file') + images: $el.prop('file') ? [ { - src: el.prop('file'), - alt: el.next().find('div.xs0 p').first().text(), + src: $el.prop('file'), + alt: $el.next().find('div.xs0 p').first().text(), }, ] : undefined, @@ -74,7 +74,7 @@ export const handler = async (ctx) => { item.title = $$('h1.ts, div.c-article-main_content-title').text(); item.description = renderDescription({ - description: $$('td.t_f, div.c-article-main_contentraw').first().html(), + description: $$('td.t_f, div.c-article-main_contentraw').first().html() ?? undefined, }); item.author = $$('b a.blue').first().text() || @@ -96,7 +96,7 @@ export const handler = async (ctx) => { ), 8 ); - item.language = language; + item.language = language as Language; return item; }) @@ -114,7 +114,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: title.split(/-/).pop(), - language, + language: language as Language, }; }; diff --git a/lib/routes/aa1/60s.ts b/lib/routes/aa1/60s.ts index b125d7e71a..971bc4e3ce 100644 --- a/lib/routes/aa1/60s.ts +++ b/lib/routes/aa1/60s.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -76,7 +76,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: updated ? parseDate(updated) : undefined, - language, + language: language as Language, }; return processedItem; @@ -92,7 +92,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('header#header-div img').attr('src'), author: title.split(/-/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/aamacau/index.ts b/lib/routes/aamacau/index.ts index 5e039dcc6f..daec725567 100644 --- a/lib/routes/aamacau/index.ts +++ b/lib/routes/aamacau/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -56,18 +56,18 @@ async function handler(ctx) { const list = $('post-title a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text(), - link: item.attr('href'), + title: $item.text(), + link: $item.attr('href'), }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -79,7 +79,7 @@ async function handler(ctx) { item.description = content('#contentleft').html(); item.author = content('meta[itemprop="author"]').attr('content'); - item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')); + item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')!); return item; }) diff --git a/lib/routes/abc/index.ts b/lib/routes/abc/index.ts index dbcd8dfc38..03ce451a64 100644 --- a/lib/routes/abc/index.ts +++ b/lib/routes/abc/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -67,7 +67,7 @@ async function handler(ctx) { }); let items = response.collection.slice(0, limit).map((i) => { - const item = { + const item: DataItem = { title: i.title.children ?? i.title, link: i.link.startsWith('https://') ? i.link : new URL(i.link, rootUrl).href, description: renderDescription({ @@ -107,11 +107,11 @@ async function handler(ctx) { .children() .each((_, el) => { const element = content(el); - if (element.prop('tagName').toLowerCase() === 'figure') { + if (element.prop('tagName')!.toLowerCase() === 'figure') { element.replaceWith( renderDescription({ image: { - src: element.find('img').prop('src').split(/\?/, 1)[0], + src: element.find('img').prop('src')!.split(/\?/, 1)[0], alt: element.find('figcaption').text().trim(), }, }) @@ -178,7 +178,7 @@ async function handler(ctx) { title: $('title').first().text(), link: currentUrl, description: $('meta[property="og:description"]').prop('content'), - language: $('html').prop('lang'), + language: $('html').prop('lang') as Language, image: $('meta[property="og:image"]').prop('content').split('?', 1)[0], icon, logo: icon, diff --git a/lib/routes/abc/templates/description.tsx b/lib/routes/abc/templates/description.tsx index bd407bfaa1..5018714921 100644 --- a/lib/routes/abc/templates/description.tsx +++ b/lib/routes/abc/templates/description.tsx @@ -1,6 +1,6 @@ import { raw } from 'hono/html'; +import type { FC } from 'hono/jsx'; import { renderToString } from 'hono/jsx/dom/server'; -import type { JSX } from 'hono/jsx/jsx-runtime'; type DescriptionData = { image?: { @@ -15,7 +15,7 @@ type DescriptionData = { }; const AbcDescription = ({ image, enclosure, description }: DescriptionData) => { - const enclosureTag = enclosure?.type?.split('/', 1)[0] as keyof JSX.IntrinsicElements | undefined; + const enclosureTag = enclosure?.type?.split('/', 1)[0] as unknown as FC | undefined; return ( <> diff --git a/lib/routes/accessbriefing/index.ts b/lib/routes/accessbriefing/index.ts index 05bd4a039f..e5f98a566b 100644 --- a/lib/routes/accessbriefing/index.ts +++ b/lib/routes/accessbriefing/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -64,7 +64,7 @@ export const handler = async (ctx) => { }, image, banner: image, - language, + language: language as Language, }; }); @@ -79,7 +79,7 @@ export const handler = async (ctx) => { const description = item.description + renderDescription({ - description: $$('div.khl-article-page-storybody').html(), + description: $$('div.khl-article-page-storybody').html() ?? undefined, }); item.title = title; @@ -99,7 +99,7 @@ export const handler = async (ctx) => { ) ); - const image = new URL($('a.navbar-brand img').prop('src'), rootUrl).href; + const image = new URL($('a.navbar-brand img').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -109,7 +109,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/accessbriefing/templates/description.tsx b/lib/routes/accessbriefing/templates/description.tsx index 7e005bb11f..ee0ee0d010 100644 --- a/lib/routes/accessbriefing/templates/description.tsx +++ b/lib/routes/accessbriefing/templates/description.tsx @@ -20,7 +20,7 @@ const AccessBriefingDescription = ({ images, intro, description }: DescriptionDa ? images.map((image) => image?.src ? (
- {image.height + {(image.height
) : null ) diff --git a/lib/routes/acfun/article.ts b/lib/routes/acfun/article.ts index ef3f183f6d..1cc2de0d34 100644 --- a/lib/routes/acfun/article.ts +++ b/lib/routes/acfun/article.ts @@ -133,7 +133,7 @@ async function handler(ctx) { const $ = load(response.data); const articleInfo = $('.main script') .text() - .match(/window.articleInfo = (.*);\n\s*window.likeDomain/)[1]; + .match(/window.articleInfo = (.*);\n\s*window.likeDomain/)![1]; const data = JSON.parse(articleInfo); item.description = data.parts[0].content; diff --git a/lib/routes/acpaa/index.ts b/lib/routes/acpaa/index.ts index 77976aa563..6fee068225 100644 --- a/lib/routes/acpaa/index.ts +++ b/lib/routes/acpaa/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,19 +38,19 @@ async function handler(ctx) { let items = $('div.text01 ul li a[title]') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.prop('title'), - link: new URL(item.prop('href'), rootUrl).href, - pubDate: timezone(parseDate(item.find('span[title]').prop('title')), 8), + title: $item.prop('title')!, + link: new URL($item.prop('href')!, rootUrl).href, + pubDate: timezone(parseDate($item.find('span[title]').prop('title')), 8), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const content = load(detailResponse); @@ -71,7 +71,7 @@ async function handler(ctx) { title: `${author} - ${subtitle}`, link: currentUrl, description: $('meta[property="og:description"]').prop('content'), - language: 'zh', + language: 'zh' as Language, subtitle, author, }; diff --git a/lib/routes/acs/journal.tsx b/lib/routes/acs/journal.tsx index 68b4b0a704..6160439ac3 100644 --- a/lib/routes/acs/journal.tsx +++ b/lib/routes/acs/journal.tsx @@ -56,28 +56,28 @@ async function handler(ctx) { const $ = load(html); - title = $('meta[property="og:title"]').attr('content'); + title = $('meta[property="og:title"]').attr('content')!; return $('.issue-item') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('.issue-item_title a'); - const doi = item.find('input[name="doi"]').attr('value'); + const a = $item.find('.issue-item_title a'); + const doi = $item.find('input[name="doi"]').attr('value'); return { doi, guid: doi, title: a.text(), link: `${rootUrl}${a.attr('href')}`, - pubDate: parseDate(item.find('.pub-date-value').text(), 'MMMM D, YYYY'), - author: item + pubDate: parseDate($item.find('.pub-date-value').text(), 'MMMM D, YYYY'), + author: $item .find('.issue-item_loa li') .toArray() .map((a) => $(a).text()) .join(', '), - description: renderDescription(item.find('.issue-item_img').html(), item.find('.hlFld-Abstract').html()), + description: renderDescription($item.find('.issue-item_img').html(), $item.find('.hlFld-Abstract').html()), }; }); }, diff --git a/lib/routes/adquan/case-library.ts b/lib/routes/adquan/case-library.ts index 096685cee8..6ccafb56a2 100644 --- a/lib/routes/adquan/case-library.ts +++ b/lib/routes/adquan/case-library.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.article_1') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('p.article_2_p').text(); @@ -51,7 +51,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -65,7 +65,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('p.infoTitle_left').text(); @@ -89,7 +89,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -109,7 +109,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.navi_logo').attr('src'), author: $('meta[name="author"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/adquan/index.ts b/lib/routes/adquan/index.ts index a739a7cf41..ecdfd99c4d 100644 --- a/lib/routes/adquan/index.ts +++ b/lib/routes/adquan/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.article_1') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('p.article_2_p').text(); @@ -51,7 +51,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -65,7 +65,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('p.infoTitle_left').text(); @@ -89,7 +89,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -109,7 +109,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.navi_logo').attr('src'), author: $('meta[name="author"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/aeaweb/index.tsx b/lib/routes/aeaweb/index.tsx index d3ae3a53af..80ae98c612 100644 --- a/lib/routes/aeaweb/index.tsx +++ b/lib/routes/aeaweb/index.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -64,17 +64,18 @@ async function handler(ctx) { let items = $('h4.title a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - link: `${rootUrl}${item.attr('href').split('&', 1)[0]}`, + title: '', + link: `${rootUrl}${$item.attr('href')!.split('&', 1)[0]}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -85,16 +86,16 @@ async function handler(ctx) { item.doi = content('meta[name="citation_doi"]').attr('content'); item.guid = item.doi; - item.title = content('meta[name="citation_title"]').attr('content'); + item.title = content('meta[name="citation_title"]').attr('content')!; item.author = content('.author') .toArray() .map((a) => content(a).text().trim()) .join(', '); - item.pubDate = parseDate(content('meta[name="citation_publication_date"]').attr('content'), 'YYYY/MM'); + item.pubDate = parseDate(content('meta[name="citation_publication_date"]').attr('content')!, 'YYYY/MM'); item.description = renderToString( ); @@ -109,7 +110,7 @@ async function handler(ctx) { description, link: currentUrl, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/afdian/explore.ts b/lib/routes/afdian/explore.ts index 9e03ca7431..a54dc618f1 100644 --- a/lib/routes/afdian/explore.ts +++ b/lib/routes/afdian/explore.ts @@ -1,3 +1,4 @@ +import type { Route } from '@/types'; import got from '@/utils/got'; const categoryMap = { diff --git a/lib/routes/aflcio/blog.ts b/lib/routes/aflcio/blog.ts index e9570b925d..41c6562367 100644 --- a/lib/routes/aflcio/blog.ts +++ b/lib/routes/aflcio/blog.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -22,7 +22,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('article.article') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('header.container h1 a').first(); @@ -56,7 +56,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -70,7 +70,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('header.article-header h1').text(); @@ -101,7 +101,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; return { @@ -123,7 +123,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.main-logo').attr('src') ? new URL($('img.main-logo').attr('src') as string, baseUrl).href : undefined, author: title.split(/\|/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/agefans/detail.ts b/lib/routes/agefans/detail.ts index 1cd53e2c2b..d46b13e02c 100644 --- a/lib/routes/agefans/detail.ts +++ b/lib/routes/agefans/detail.ts @@ -39,11 +39,11 @@ async function handler(ctx) { .find('li') .toArray() .map((item) => { - item = $(item); - const a = item.find('a'); + const $item = $(item); + const a = $item.find('a'); return { title: a.text(), - link: a.attr('href').replace('http://', 'https://'), + link: a.attr('href')!.replace('http://', 'https://'), }; }) .toReversed(); diff --git a/lib/routes/agefans/update.ts b/lib/routes/agefans/update.ts index 6121640147..10ed4ff662 100644 --- a/lib/routes/agefans/update.ts +++ b/lib/routes/agefans/update.ts @@ -39,20 +39,20 @@ async function handler() { const list = $('.video_item') .toArray() - .map((item) => { - item = $(item); - const link = item.find('a').attr('href').replace('http://', 'https://'); + .map((item): DataItem => { + const $item = $(item); + const link = $item.find('a').attr('href')!.replace('http://', 'https://'); return { - title: item.text(), + title: $item.text(), link, - guid: `${link}#${item.find('.video_item--info').text()}`, + guid: `${link}#${$item.find('.video_item--info').text()}`, }; }); const items: DataItem[] = await pMap( list, (item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const content = load(detailResponse.data); diff --git a/lib/routes/agirls/topic-list.ts b/lib/routes/agirls/topic-list.ts index feeaac7988..57add56b75 100644 --- a/lib/routes/agirls/topic-list.ts +++ b/lib/routes/agirls/topic-list.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import ofetch from '@/utils/ofetch'; import { baseUrl } from './utils'; @@ -40,11 +40,11 @@ async function handler() { const items = $('.ag-topic') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.ag-topic__link').text(), - description: item.find('.ag-topic__summery').text(), - link: `${baseUrl}${item.find('.ag-topic__link').attr('href')}`, + title: $item.find('.ag-topic__link').text(), + description: $item.find('.ag-topic__summery').text(), + link: `${baseUrl}${$item.find('.ag-topic__link').attr('href')}`, }; }); @@ -53,6 +53,6 @@ async function handler() { link, description: $('head meta[name=description]').attr('content'), item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/agirls/topic.ts b/lib/routes/agirls/topic.ts index d8c9ae56cf..42bf65b9d7 100644 --- a/lib/routes/agirls/topic.ts +++ b/lib/routes/agirls/topic.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -39,10 +39,10 @@ async function handler(ctx) { const list = $('.ag-post-item__link') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.text(), - link: `${baseUrl}${item.attr('href')}`, + title: $item.text(), + link: `${baseUrl}${$item.attr('href')}`, }; }); @@ -53,6 +53,6 @@ async function handler(ctx) { link, description: ldJson['@graph'][0].description, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/agirls/z-index.ts b/lib/routes/agirls/z-index.ts index c1efd1a381..e31e4852a4 100644 --- a/lib/routes/agirls/z-index.ts +++ b/lib/routes/agirls/z-index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -43,10 +43,10 @@ async function handler(ctx) { const list = $('.ag-post-list .ag-post-item__link') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.text(), - link: `${baseUrl}${item.attr('href')}`, + title: $item.text(), + link: `${baseUrl}${$item.attr('href')}`, }; }); @@ -57,6 +57,6 @@ async function handler(ctx) { link, description: $('head meta[name=description]').attr('content'), item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/agora0/index.ts b/lib/routes/agora0/index.ts index 8863a29862..df13b039e3 100644 --- a/lib/routes/agora0/index.ts +++ b/lib/routes/agora0/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -48,18 +48,18 @@ async function handler(ctx) { let items = $('.card span:not(.comments) a') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 50) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text(), - link: item.attr('href'), + title: $item.text(), + link: $item.attr('href'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -68,7 +68,7 @@ async function handler(ctx) { const content = load(detailResponse.data); item.author = content('meta[name="author"]').attr('content'); - item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')); + item.pubDate = parseDate(content('meta[property="article:published_time"]').attr('content')!); item.description = content('.post-content').html(); return item; diff --git a/lib/routes/agora0/pen0.ts b/lib/routes/agora0/pen0.ts index 8f65d5ee8a..a225ca8b16 100644 --- a/lib/routes/agora0/pen0.ts +++ b/lib/routes/agora0/pen0.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,12 +37,12 @@ async function handler() { const list = $('div article') .toArray() .slice(0, -1) // last one is a dummy - .map((item) => { - item = $(item); - const meta = item.find('h5').first().text(); + .map((item): DataItem => { + const $item = $(item); + const meta = $item.find('h5').first().text(); return { - title: item.find('h3').text(), - link: item.find('h3 a').attr('href'), + title: $item.find('h3').text(), + link: $item.find('h3 a').attr('href'), author: meta.split('|', 1)[0].trim(), pubDate: parseDate(meta.split('|', 2)[1].trim()), }; @@ -50,7 +50,7 @@ async function handler() { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got(item.link); const $ = load(response.data); $('h1').remove(); diff --git a/lib/routes/agri/index.ts b/lib/routes/agri/index.ts index de2d4248ad..ed4c3317b2 100644 --- a/lib/routes/agri/index.ts +++ b/lib/routes/agri/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -24,15 +24,15 @@ export const handler = async (ctx) => { let items = $('div.list_li_con, div.nxw_video_com') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a').first(); + const a = $item.find('a').first(); const title = a.text(); - const image = item.find('img').first().prop('src') ? new URL(item.find('img').first().prop('src'), rootUrl).href : undefined; + const image = $item.find('img').first().prop('src') ? new URL($item.find('img').first().prop('src')!, rootUrl).href : undefined; const description = renderDescription({ - intro: item.find('p.con_text').text() || undefined, + intro: $item.find('p.con_text').text() || undefined, images: image ? [ { @@ -46,21 +46,21 @@ export const handler = async (ctx) => { return { title, description, - pubDate: parseDate(item.find('span.con_date_span').text() || `${item.find('div.com_time_p2').text().trim()}${item.find('div.com_time_p1').text()}`, ['YYYY-MM-DD', 'YYYY.MM.DD']), - link: new URL(a.prop('href'), currentUrl).href, + pubDate: parseDate($item.find('span.con_date_span').text() || `${$item.find('div.com_time_p2').text().trim()}${$item.find('div.com_time_p1').text()}`, ['YYYY-MM-DD', 'YYYY.MM.DD']), + link: new URL(a.prop('href')!, currentUrl).href, content: { html: description, - text: item.find('p.con_text').text() || undefined, + text: $item.find('p.con_text').text() || undefined, }, image, banner: image, - language, + language: language as Language, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const $$ = load(detailResponse); @@ -78,7 +78,7 @@ export const handler = async (ctx) => { html: description, text: $$('div.content_body_box').text(), }; - item.language = language; + item.language = language as Language; item.enclosure_url = $$('div.content_body_box video').prop('src') ?? undefined; item.enclosure_type = item.enclosure_url ? 'video/mp4' : undefined; @@ -89,7 +89,7 @@ export const handler = async (ctx) => { ) ); - const image = new URL($('div.logo img').prop('src'), rootUrl).href; + const image = new URL($('div.logo img').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -97,7 +97,7 @@ export const handler = async (ctx) => { item: items, allowEmpty: true, image, - language, + language: language as Language, }; }; diff --git a/lib/routes/ahjzu/news.ts b/lib/routes/ahjzu/news.ts index 4ee5ad425f..d8749c42bc 100644 --- a/lib/routes/ahjzu/news.ts +++ b/lib/routes/ahjzu/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -44,15 +44,15 @@ async function handler() { const list = $('#wp_news_w9') .find('li') .toArray() - .map((item) => { - item = $(item); - const date = item.find('.column-news-date').text(); + .map((item): DataItem => { + const $item = $(item); + const date = $item.find('.column-news-date').text(); // 置顶链接自带http前缀,其他不带,需要手动判断 - const a = item.find('a').attr('href'); - const link = a.slice(0, 4) === 'http' ? a : rootUrl + a; + const a = $item.find('a').attr('href'); + const link = a!.startsWith('http') ? a : rootUrl + a; return { - title: item.find('a').attr('title'), + title: $item.find('a').attr('title')!, link, pubDate: timezone(parseDate(date), 8), }; @@ -60,7 +60,7 @@ async function handler() { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/aibase/daily.ts b/lib/routes/aibase/daily.ts index e3c7efcdf1..9959ef62db 100644 --- a/lib/routes/aibase/daily.ts +++ b/lib/routes/aibase/daily.ts @@ -61,7 +61,7 @@ export const route: Route = { return { title: 'AI日报', description: '每天三分钟关注AI行业趋势', - language: 'zh-cn', + language: 'zh-CN', link: 'https://www.aibase.com/zh/daily', item: items, allowEmpty: true, diff --git a/lib/routes/aibase/discover.ts b/lib/routes/aibase/discover.ts index fa413dbcc1..74e805dde5 100644 --- a/lib/routes/aibase/discover.ts +++ b/lib/routes/aibase/discover.ts @@ -63,7 +63,7 @@ export const handler = async (ctx) => { const items = processItems(apiProcs?.slice(0, limit) ?? []); - const image = new URL($('img.logo').prop('src'), rootUrl).href; + const image = new URL($('img.logo').prop('src')!, rootUrl).href; const author = $('title').text().split(/_/).pop(); diff --git a/lib/routes/aibase/news.ts b/lib/routes/aibase/news.ts index 60e8cf4446..977ae896d7 100644 --- a/lib/routes/aibase/news.ts +++ b/lib/routes/aibase/news.ts @@ -50,7 +50,7 @@ export const route: Route = { return { title: 'AI新闻资讯', description: 'AI新闻资讯 - 不错过全球AI革新的每一个时刻', - language: 'zh-cn', + language: 'zh-CN', link: 'https://www.aibase.com/zh/news', item: items, allowEmpty: true, diff --git a/lib/routes/aibase/topic.ts b/lib/routes/aibase/topic.ts index e9a445caa4..214e261d5e 100644 --- a/lib/routes/aibase/topic.ts +++ b/lib/routes/aibase/topic.ts @@ -33,7 +33,7 @@ export const handler = async (ctx) => { const items = processItems(apiTagProcs?.slice(0, limit) ?? []); - const image = new URL($('img.logo').prop('src'), rootUrl).href; + const image = new URL($('img.logo').prop('src')!, rootUrl).href; const author = $('title').text().split(/_/).pop(); diff --git a/lib/routes/aijishu/utils.ts b/lib/routes/aijishu/utils.ts index 6d4e2346d1..33fc382b91 100644 --- a/lib/routes/aijishu/utils.ts +++ b/lib/routes/aijishu/utils.ts @@ -16,7 +16,7 @@ const parseArticle = (item) => { const $ = load(resp.data); desc = $('article.fmt').html(); } catch (error) { - if (error.response.status === 403) { + if ((error as { response: { status: number } }).response.status === 403) { // skip it } else { throw error; diff --git a/lib/routes/ainvest/article.ts b/lib/routes/ainvest/article.ts index a638d3a357..e4bc563f27 100644 --- a/lib/routes/ainvest/article.ts +++ b/lib/routes/ainvest/article.ts @@ -1,5 +1,5 @@ import { fetchContentItems } from '@/routes/ainvest/utils'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; export const route: Route = { path: '/article', @@ -32,7 +32,7 @@ async function handler(ctx) { return { title: 'AInvest - Latest Articles', link: 'https://www.ainvest.com/news/articles-latest/', - language: 'en', + language: 'en' as Language, item: items, }; } diff --git a/lib/routes/ainvest/news.ts b/lib/routes/ainvest/news.ts index 8aeb08e178..4ea4f55cd9 100644 --- a/lib/routes/ainvest/news.ts +++ b/lib/routes/ainvest/news.ts @@ -1,5 +1,5 @@ import { fetchContentItems } from '@/routes/ainvest/utils'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { ViewType } from '@/types'; export const route: Route = { @@ -35,7 +35,7 @@ async function handler(ctx) { return { title: 'AInvest - Latest News', link: 'https://www.ainvest.com/news/', - language: 'en', + language: 'en' as Language, item: items, }; } diff --git a/lib/routes/ainvest/utils.ts b/lib/routes/ainvest/utils.ts index 9c196820a0..cb7e8b5421 100644 --- a/lib/routes/ainvest/utils.ts +++ b/lib/routes/ainvest/utils.ts @@ -1,4 +1,5 @@ import { config } from '@/config'; +import type { DataItem } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -6,7 +7,7 @@ import { parseDate } from '@/utils/parse-date'; const contentStreamUrl = 'https://news.ainvest.com/news-w-ds-hxcmp-content-stream/content_stream/api/stream_item/v1/query_content_stream'; const contentPageUrl = 'https://news.ainvest.com/content-page/v1/page'; -const normalizeItem = (item) => ({ +const normalizeItem = (item): DataItem & { seoKey?: string } => ({ title: item.title, link: item.h5_url, pubDate: parseDate(item.ctime, 'X'), @@ -40,7 +41,7 @@ export const fetchContentItems = async (streamIds, limit) => { return Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await ofetch(`${contentPageUrl}/${item.seoKey}`); const { data } = response; diff --git a/lib/routes/aip/journal-pupp.ts b/lib/routes/aip/journal-pupp.ts index 5372bfb3d7..7a4adcd694 100644 --- a/lib/routes/aip/journal-pupp.ts +++ b/lib/routes/aip/journal-pupp.ts @@ -34,7 +34,7 @@ const handler = async (ctx) => { const authors = $(item).find('.entryAuthor.all').text(); const img = $(item).find('img').attr('src'); const link = $(item).find('.ref.nowrap').attr('href'); - const doi = link.replace('/doi/full/', ''); + const doi = link!.replace('/doi/full/', ''); const description = renderDesc(title, authors, doi, img); return { title, diff --git a/lib/routes/aip/journal.ts b/lib/routes/aip/journal.ts index f5c718e57e..8ecf94cb61 100644 --- a/lib/routes/aip/journal.ts +++ b/lib/routes/aip/journal.ts @@ -42,16 +42,16 @@ async function handler(ctx) { const { data: response } = await got.get(jrnlUrl); const $ = load(response); const jrnlName = $('meta[property="og:title"]') - .attr('content') - .match(/(?:[^=]*=)?\s*([^>]+)/)[1]; + .attr('content')! + .match(/(?:[^=]*=)?\s*([^>]+)/)![1]; const publication = $('.al-article-item-wrap.al-normal'); const list = publication.toArray().map((item) => { const title = $(item).find('.item-title a:first').text(); const link = $(item).find('.item-title a:first').attr('href'); const doilink = $(item).find('.citation-label a').attr('href'); - const doi = doilink && doilink.match(/10\.\d+\/\S+/)[0]; - const id = $(item).find('h5[data-resource-id-access]').data('resource-id-access'); + const doi = doilink && doilink.match(/10\.\d+\/\S+/)![0]; + const id = $(item).find('h5[data-resource-id-access]').data('resource-id-access') as string; const authors = $(item) .find('.al-authors-list') .find('a') diff --git a/lib/routes/airchina/index.ts b/lib/routes/airchina/index.ts index 8f92d8b5fd..f6bbf25da6 100644 --- a/lib/routes/airchina/index.ts +++ b/lib/routes/airchina/index.ts @@ -57,7 +57,7 @@ async function handler() { item.description = await cache.tryGet(detailLink, async () => { const result = await got(detailLink); const $ = load(result.data); - return $('.serviceMsg').html(); + return $('.serviceMsg').html() ?? ''; }); }) ); diff --git a/lib/routes/aisixiang/column.ts b/lib/routes/aisixiang/column.ts index a3d9607f5b..55d03bc89b 100644 --- a/lib/routes/aisixiang/column.ts +++ b/lib/routes/aisixiang/column.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; import timezone from '@/utils/timezone'; @@ -41,15 +41,15 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('a[title]'); + const a = $item.find('a[title]'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, + link: new URL(a.prop('href')!, rootUrl).href, author: a.text().split(':', 1)[0], - pubDate: timezone(parseDate(item.find('span').text()), 8), + pubDate: timezone(parseDate($item.find('span').text()), 8), }; }); @@ -58,7 +58,7 @@ async function handler(ctx) { title: `爱思想 - ${title}`, link: currentUrl, description: $('div.tips').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/aisixiang/thinktank.ts b/lib/routes/aisixiang/thinktank.ts index 5e27bf2350..2452385386 100644 --- a/lib/routes/aisixiang/thinktank.ts +++ b/lib/routes/aisixiang/thinktank.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { ossUrl, ProcessFeed, rootUrl } from './utils'; @@ -38,7 +38,7 @@ async function handler(ctx) { const title = `${$('h2').first().text()}${type}`; - let items = []; + let items: any[] = []; const targetList = $('h3') .toArray() @@ -52,11 +52,11 @@ async function handler(ctx) { } items = items.slice(0, limit).map((item) => { - item = $(item); + const $item = $(item); return { - title: item.text().split(':').pop(), - link: new URL(item.prop('href'), rootUrl).href, + title: $item.text().split(':').pop(), + link: new URL($item.prop('href')!, rootUrl).href, }; }); @@ -65,7 +65,7 @@ async function handler(ctx) { title: `爱思想 - ${title}`, link: currentUrl, description: $('div.thinktank-author-description-box p').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo_thinktank.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/aisixiang/toplist.ts b/lib/routes/aisixiang/toplist.ts index a4908ea578..990a70474a 100644 --- a/lib/routes/aisixiang/toplist.ts +++ b/lib/routes/aisixiang/toplist.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -35,15 +35,15 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('div.tips a'); + const a = $item.find('div.tips a'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, - author: item.find('div.name').text(), - pubDate: parseDate(item.find('div.times').text()), + link: new URL(a.prop('href')!, rootUrl).href, + author: $item.find('div.name').text(), + pubDate: parseDate($item.find('div.times').text()), }; }); @@ -51,7 +51,7 @@ async function handler(ctx) { item: await ProcessFeed(limit, items), title: `爱思想 - ${title}`, link: currentUrl, - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo_toplist.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/aisixiang/utils.ts b/lib/routes/aisixiang/utils.ts index befc488ba6..d63f8fae13 100644 --- a/lib/routes/aisixiang/utils.ts +++ b/lib/routes/aisixiang/utils.ts @@ -29,7 +29,7 @@ const ProcessFeed = (limit, items) => .find('u') .toArray() .map((c) => content(c).text()); - item.pubDate = timezone(parseDate(content('div.info').text().split('时间:').pop()), 8); + item.pubDate = timezone(parseDate(content('div.info').text().split('时间:').pop()!), 8); item.upvotes = content('span.like-num').text() ? Number(content('span.like-num').text()) : 0; item.comments = commentMatches ? Number(commentMatches[1]) : 0; diff --git a/lib/routes/aisixiang/zhuanti.ts b/lib/routes/aisixiang/zhuanti.ts index 845c0773a7..249c0fd0e8 100644 --- a/lib/routes/aisixiang/zhuanti.ts +++ b/lib/routes/aisixiang/zhuanti.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; import timezone from '@/utils/timezone'; @@ -44,15 +44,15 @@ async function handler(ctx) { .slice(0, limit) .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.prop('href'), rootUrl).href, + link: new URL(a.prop('href')!, rootUrl).href, author: a.text().split(':', 1)[0], - pubDate: timezone(parseDate(item.find('span').text()), 8), + pubDate: timezone(parseDate($item.find('span').text()), 8), }; }); @@ -61,7 +61,7 @@ async function handler(ctx) { title: `爱思想 - ${title}`, link: currentUrl, description: $('div.tips p').text(), - language: 'zh-cn', + language: 'zh-CN' as Language, image: new URL('images/logo_zhuanti.jpg', ossUrl).href, subtitle: title, }; diff --git a/lib/routes/ali213/news.ts b/lib/routes/ali213/news.ts index bdb7b64428..985d5dac53 100644 --- a/lib/routes/ali213/news.ts +++ b/lib/routes/ali213/news.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -66,7 +66,7 @@ export const handler = async (ctx: Context): Promise => { }, image: imageSrc, banner: imageSrc, - language, + language: language as Language, }; }); @@ -79,7 +79,7 @@ export const handler = async (ctx: Context): Promise => { return cache.tryGet(item.link, async (): Promise => { try { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('h1.newstit').text(); @@ -92,7 +92,7 @@ export const handler = async (ctx: Context): Promise => { mediaContent.each((_, el) => { const $$el: Cheerio = $$(el); - const pEl: Cheerio = $$el.closest('p'); + const pEl: Cheerio = $$el.closest('p') as Cheerio; const mediaUrl: string | undefined = $$el.prop('src'); const mediaType: string | undefined = mediaUrl?.split(/\./).pop(); @@ -141,7 +141,7 @@ export const handler = async (ctx: Context): Promise => { }, image, banner: image, - language, + language: language as Language, media: Object.keys(media).length > 0 ? media : undefined, _extra: { links: extraLinks.length > 0 ? extraLinks : undefined, @@ -167,7 +167,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: feedImage, author, - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/ali213/zl.ts b/lib/routes/ali213/zl.ts index c93d750f98..7ea0074f7c 100644 --- a/lib/routes/ali213/zl.ts +++ b/lib/routes/ali213/zl.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -56,7 +56,7 @@ export const handler = async (ctx: Context): Promise => { }, image, banner: image, - language, + language: language as Language, }; }); @@ -68,7 +68,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('h1.newstit').text(); @@ -131,7 +131,7 @@ export const handler = async (ctx: Context): Promise => { }, image: item.image, banner: item.image, - language, + language: language as Language, _extra: { links: extraLinks.length > 0 ? extraLinks : undefined, }, @@ -152,7 +152,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: feedImage, author: title.split(/_/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/alicesoft/infomation.ts b/lib/routes/alicesoft/infomation.ts index d91c0572a2..487efc7b17 100644 --- a/lib/routes/alicesoft/infomation.ts +++ b/lib/routes/alicesoft/infomation.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -52,21 +52,21 @@ async function handler(ctx) { let items = $('div.cont-main li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('p.txt').text(), - link: item.find('a').attr('href'), - pubDate: new Date(item.find('time').attr('datetime')), + title: $item.find('p.txt').text(), + link: $item.find('a').attr('href'), + pubDate: new Date($item.find('time').attr('datetime')!), }; }); items = await Promise.all( items.map((item) => { - if (!item.link.startsWith(`${baseUrl}/information/`)) { + if (!item.link!.startsWith(`${baseUrl}/information/`)) { return item; } - return cache.tryGet(item.link, async () => { + return cache.tryGet(item.link!, async () => { const contentResponse = await got(item.link); const content = load(contentResponse.data); @@ -89,6 +89,6 @@ async function handler(ctx) { .text(), link: url, item: items, - language: 'ja', + language: 'ja' as Language, }; } diff --git a/lib/routes/alistapart/index.ts b/lib/routes/alistapart/index.ts index ded80ed7db..87901e94d6 100644 --- a/lib/routes/alistapart/index.ts +++ b/lib/routes/alistapart/index.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { getData, getList } from './utils'; @@ -32,6 +32,6 @@ async function handler() { description: 'Articles on aListApart.com', logo: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=192,192&ssl=1', icon: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=32,32&ssl=1', - language: 'en-us', + language: 'en-us' as Language, }; } diff --git a/lib/routes/alistapart/topic.ts b/lib/routes/alistapart/topic.ts index 350a682532..863403a387 100644 --- a/lib/routes/alistapart/topic.ts +++ b/lib/routes/alistapart/topic.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { getData, getList } from './utils'; @@ -90,6 +90,6 @@ async function handler(ctx) { description: `${topic[0].toUpperCase() + topic.slice(1)} Articles on aListApart.com`, logo: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=192,192&ssl=1', icon: 'https://i0.wp.com/alistapart.com/wp-content/uploads/2019/03/cropped-icon_navigation-laurel-512.jpg?fit=32,32&ssl=1', - language: 'en-us', + language: 'en-us' as Language, }; } diff --git a/lib/routes/aliyun/database-month.ts b/lib/routes/aliyun/database-month.ts index be75ade658..e8f1633019 100644 --- a/lib/routes/aliyun/database-month.ts +++ b/lib/routes/aliyun/database-month.ts @@ -53,7 +53,7 @@ async function handler() { return cache.tryGet(link, async () => { const itemReponse = await got(link); const itemElement = load(itemReponse.data); - item.description = itemElement('.content').html(); + item.description = itemElement('.content').html() ?? ''; return item; }); }) diff --git a/lib/routes/aliyun/developer/group.ts b/lib/routes/aliyun/developer/group.ts index 60a01fbc9b..830e49f8ea 100644 --- a/lib/routes/aliyun/developer/group.ts +++ b/lib/routes/aliyun/developer/group.ts @@ -43,7 +43,7 @@ async function handler(ctx) { const $ = load(data); const title = $('div[class="header-information-title"]') .contents() - .filter((element) => element.nodeType === 3) + .filter((element: any) => element.nodeType === 3) .text() .trim(); const desc = $('div[class="header-information"]').find('span').last().text().trim(); @@ -54,13 +54,13 @@ async function handler(ctx) { link, description: desc, item: list.toArray().map((item) => { - item = $(item); - const desc = item.find('.question-desc'); - const description = item.find('.browse').text() + ' ' + desc.find('.answer').text(); + const $item = $(item); + const desc = $item.find('.question-desc'); + const description = $item.find('.browse').text() + ' ' + desc.find('.answer').text(); return { - title: item.find('.question-title').text().trim() || item.find('a p').text().trim(), - link: item.find('a').attr('href'), - pubDate: parseDate(item.find('.time').text()), + title: $item.find('.question-title').text().trim() || $item.find('a p').text().trim(), + link: $item.find('a').attr('href'), + pubDate: parseDate($item.find('.time').text()), description, }; }), diff --git a/lib/routes/aliyun/notice.ts b/lib/routes/aliyun/notice.ts index 027bf7452c..fe8753365b 100644 --- a/lib/routes/aliyun/notice.ts +++ b/lib/routes/aliyun/notice.ts @@ -53,7 +53,7 @@ async function handler(ctx) { .map((e) => { const element = $(e); const title = element.find('a').text().trim(); - const link = 'https://help.aliyun.com' + element.find('a').attr('href').trim(); + const link = 'https://help.aliyun.com' + element.find('a').attr('href')!.trim(); const date = element.find('.y-right').text(); const pubDate = timezone(parseDate(date), 8); return { @@ -69,7 +69,7 @@ async function handler(ctx) { cache.tryGet(item.link, async () => { const itemReponse = await got(item.link); const itemElement = load(itemReponse.data); - item.description = itemElement('#se-knowledge').html(); + item.description = itemElement('#se-knowledge').html() ?? ''; return item; }) diff --git a/lib/routes/aljazeera/index.tsx b/lib/routes/aljazeera/index.tsx index 5905d5fcaa..a5db835806 100644 --- a/lib/routes/aljazeera/index.tsx +++ b/lib/routes/aljazeera/index.tsx @@ -95,10 +95,10 @@ export async function handler(ctx) { : $('.u-clickable-card__link') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - link: `${rootUrl}${item.attr('href')}`, + link: `${rootUrl}${$item.attr('href')}`, }; }); diff --git a/lib/routes/ally/rail.ts b/lib/routes/ally/rail.ts index 2d18beac54..d3b8699623 100644 --- a/lib/routes/ally/rail.ts +++ b/lib/routes/ally/rail.ts @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import type { Element } from 'domhandler'; import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; @@ -65,33 +66,33 @@ async function handler(ctx) { links = $('.left a, .container_left a').toArray(); } - let items = links + let items: DataItem[] = links .map((link) => { - link = $(link); - const url = link.attr('href'); + const $link = $(link); + const url = $link.attr('href'); const urlMatch = url && url.match(/\/html\/(\d{4})\/\w+_(\d{4})\/\d+\.html/); if (!urlMatch) { return null; } - const title = link.text(); + const title = $link.text(); return { title, link: url.startsWith('/') ? `${rootUrl}${url}` : url, pubDate: timezone(parseDate(`${urlMatch[1]}${urlMatch[2]}`), 8), }; }) - .filter(Boolean); + .filter(Boolean) as DataItem[]; const uniqueItems: DataItem[] = []; for (const item of items) { if (uniqueItems.every((uniqueItem) => uniqueItem.link !== item?.link)) { uniqueItems.push(item!); } } - items = uniqueItems.toSorted((a, b) => b.pubDate - a.pubDate).slice(0, ctx.req.query('limit') || 20); + items = uniqueItems.toSorted((a, b) => Number(b.pubDate) - Number(a.pubDate)).slice(0, ctx.req.query('limit') || 20); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got(item.link); const $ = load(response.data); // fix weird format @@ -104,7 +105,7 @@ async function handler(ctx) { .each((_, child) => { const $child = $(child); let innerHtml; - if (child.name === 'div') { + if ((child as Element).name === 'div') { innerHtml = $child.html(); innerHtml &&= innerHtml.trim(); description += !innerHtml || innerHtml === ' ' ? (description ? '
' : '') : innerHtml; @@ -115,7 +116,7 @@ async function handler(ctx) { }); } else { // http://rail.ally.net.cn/html/2022/InviteTen_0407/4686.html - description = $('div.content div').first().html(); + description = $('div.content div').first().html() ?? ''; } description = description.replace(/\s*
\s*$/, ''); // trim
at the end diff --git a/lib/routes/alwayscontrol/news.ts b/lib/routes/alwayscontrol/news.ts index 3e900aa1ed..47a1c4962c 100644 --- a/lib/routes/alwayscontrol/news.ts +++ b/lib/routes/alwayscontrol/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -43,7 +43,7 @@ async function handler() { // 解析新闻列表 const list = $('div.grid > a') .toArray() - .map((item) => { + .map((item): DataItem => { const $item = $(item); const image = $item.find('img').attr('src'); @@ -58,11 +58,11 @@ async function handler() { // 获取每篇新闻的详细内容 const items = await Promise.all( list.map((item) => { - if (new URL(item.link).host === 'mp.weixin.qq.com') { + if (new URL(item.link!).host === 'mp.weixin.qq.com') { return finishArticleItem({ ...item, guid: item.link }); } - return cache.tryGet(item.link, async () => { + return cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const $detail = load(detailResponse.data); @@ -92,7 +92,7 @@ async function handler() { title: 'Always Control - 最新动态', link: listUrl, description: 'Always Control(旭衡电子)- 智能能源管理系统解决方案专家最新动态', - language: 'zh-CN', + language: 'zh-CN' as Language, item: items, image: `${baseUrl}/logo.png`, }; diff --git a/lib/routes/amazfitwatchfaces/index.ts b/lib/routes/amazfitwatchfaces/index.ts index a4a54df796..70258ed896 100644 --- a/lib/routes/amazfitwatchfaces/index.ts +++ b/lib/routes/amazfitwatchfaces/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.wf-panel') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.prop('title'); @@ -66,7 +66,7 @@ export const handler = async (ctx: Context): Promise => { }, image, banner: image, - language, + language: language as Language, }; return processedItem; @@ -80,7 +80,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.page-title h1').text(); @@ -126,7 +126,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'DD.MM.YYYY HH:mm') : item.updated, - language, + language: language as Language, }; return { @@ -146,7 +146,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.mainlogolg').attr('src') ? new URL($('img.mainlogolg').attr('src') as string, baseUrl).href : undefined, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/amazon/kindle-software-updates.tsx b/lib/routes/amazon/kindle-software-updates.tsx index a26c078831..193d7a1980 100644 --- a/lib/routes/amazon/kindle-software-updates.tsx +++ b/lib/routes/amazon/kindle-software-updates.tsx @@ -46,7 +46,7 @@ async function handler() { website: `${url}?nodeId=${nodeIdValue}`, description: $(item) .find('.a-column.a-span8') - .html() + .html()! .replaceAll(/[\t\n]/g, ''), }; return data; diff --git a/lib/routes/android/platform-tools-releases.ts b/lib/routes/android/platform-tools-releases.ts index 974d49c3f9..168ca992a5 100644 --- a/lib/routes/android/platform-tools-releases.ts +++ b/lib/routes/android/platform-tools-releases.ts @@ -48,20 +48,20 @@ async function handler() { const items = $('h4') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const title = item.attr('data-text'); + const title = $item.attr('data-text'); let description = ''; - item.nextUntil('h4').each((_, el) => { + $item.nextUntil('h4').each((_, el) => { description += $(el).html(); }); return { - title, + title: title!, description, - link: `${currentUrl}#${item.attr('id')}`, - pubDate: parseDate(title.match(/\((.*)\)/)[1], 'MMMM YYYY'), + link: `${currentUrl}#${$item.attr('id')}`, + pubDate: parseDate(title!.match(/\((.*)\)/)![1], 'MMMM YYYY'), }; }); diff --git a/lib/routes/annualreviews/index.ts b/lib/routes/annualreviews/index.ts index b4a223bf6b..e499a5b705 100644 --- a/lib/routes/annualreviews/index.ts +++ b/lib/routes/annualreviews/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -51,18 +51,18 @@ async function handler(ctx) { let items = $('entry') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const doi = item.find('id').text().split('doi=').pop(); + const doi = $item.find('id').text().split('doi=').pop(); return { doi, guid: doi, - title: item.find('title').text(), - link: item.find('link').attr('href').split('?', 1)[0], - description: item.find('content').text(), - pubDate: parseDate(item.find('published').text()), - author: item + title: $item.find('title').text(), + link: $item.find('link').attr('href')!.split('?', 1)[0], + description: $item.find('content').text(), + pubDate: parseDate($item.find('published').text()), + author: $item .find('author name') .toArray() .map((a) => $(a).text()) @@ -72,7 +72,7 @@ async function handler(ctx) { items = await Promise.all( items.map((item) => - cache.tryGet(item.guid, async () => { + cache.tryGet(item.guid!, async () => { const apiUrl = `${apiRootUrl}/works/${item.doi}`; const detailResponse = await got({ @@ -95,6 +95,6 @@ async function handler(ctx) { description: $('subtitle').first().text(), link: currentUrl, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/anquanke/category.ts b/lib/routes/anquanke/category.ts index 90911962e9..107a0c09a7 100644 --- a/lib/routes/anquanke/category.ts +++ b/lib/routes/anquanke/category.ts @@ -45,7 +45,7 @@ async function handler(ctx) { ? await cache.tryGet(art_url, async () => { const { data: res } = await got(art_url); const content = load(res); - return content('#js-article').html(); + return content('#js-article').html() ?? ''; }) : item.desc, pubDate: timezone(parseDate(item.date), 8), diff --git a/lib/routes/anthropic/red.ts b/lib/routes/anthropic/red.ts index e39335e502..b48ea07ae4 100644 --- a/lib/routes/anthropic/red.ts +++ b/lib/routes/anthropic/red.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -29,7 +29,7 @@ async function handler() { const list = $('a[class^="note"]') .toArray() - .map((element) => { + .map((element): DataItem => { const $e = $(element); return { title: $e.find('h2, h3').text().trim(), @@ -40,8 +40,8 @@ async function handler() { const items = await pMap( list, (item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const response = await ofetch(item.link!); const $ = load(response); item.pubDate = parseDate($('d-article p').first().text().trim()); diff --git a/lib/routes/anthropic/research.ts b/lib/routes/anthropic/research.ts index 9a7baa33b6..d2b630087e 100644 --- a/lib/routes/anthropic/research.ts +++ b/lib/routes/anthropic/research.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -70,17 +70,19 @@ async function handler() { const publicationSections = sections.filter((section) => section?.title === 'Publications'); const posts = publicationSections .flatMap((section) => section?.posts ?? []) - .map((post) => ({ - title: post.title, - link: `https://www.anthropic.com/research/${post.slug.current}`, - pubDate: parseDate(post.publishedOn), - })); + .map( + (post): DataItem => ({ + title: post.title, + link: `https://www.anthropic.com/research/${post.slug.current}`, + pubDate: parseDate(post.publishedOn), + }) + ); const items = await pMap( posts, (item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const response = await ofetch(item.link!); const $ = load(response); const content = $('#main-content > article'); diff --git a/lib/routes/anytxt/release-notes.ts b/lib/routes/anytxt/release-notes.ts index e28d2a4a18..e4dafa1812 100644 --- a/lib/routes/anytxt/release-notes.ts +++ b/lib/routes/anytxt/release-notes.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -23,7 +23,7 @@ export const handler = async (ctx: Context): Promise => { const items: DataItem[] = $('p.has-medium-font-size') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.text(); @@ -44,7 +44,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -59,7 +59,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/apache/apisix/blog.ts b/lib/routes/apache/apisix/blog.ts index 8bf1d32742..43eed0377f 100644 --- a/lib/routes/apache/apisix/blog.ts +++ b/lib/routes/apache/apisix/blog.ts @@ -15,7 +15,7 @@ async function getArticles() { title: a.find('h2').text(), description: a.find('p').text(), link: a.attr('href'), - pubDate: parseDate($(elem).find('footer').find('time').attr('datetime')), + pubDate: parseDate($(elem).find('footer').find('time').attr('datetime')!), category: $(elem) .find('header div a') .toArray() diff --git a/lib/routes/apkpure/versions.ts b/lib/routes/apkpure/versions.ts index 93f2e5b6db..e03afa5f18 100644 --- a/lib/routes/apkpure/versions.ts +++ b/lib/routes/apkpure/versions.ts @@ -43,19 +43,19 @@ async function handler(ctx) { await context.close(); const $ = load(r); - const img = new URL($('.ver-top img').attr('src')); + const img = new URL($('.ver-top img').attr('src')!); img.searchParams.delete('w'); // get full resolution icon const items = $('.ver li') .toArray() .map((ver) => { - ver = $(ver); + const $ver = $(ver); return { - title: ver.find('.ver-item-n').text(), - description: ver.html(), - link: `${baseUrl}${ver.find('a').attr('href')}`, + title: $ver.find('.ver-item-n').text(), + description: $ver.html(), + link: `${baseUrl}${$ver.find('a').attr('href')}`, pubDate: parseDate( - ver + $ver .find('.update-on') .text() .replaceAll(/年|月/g, '-') diff --git a/lib/routes/apnews/mobile-api.ts b/lib/routes/apnews/mobile-api.ts index 7263daa9dc..64260ffdf0 100644 --- a/lib/routes/apnews/mobile-api.ts +++ b/lib/routes/apnews/mobile-api.ts @@ -84,7 +84,7 @@ async function handler(ctx) { return; }) .filter(Boolean) - .toSorted((a, b) => b.pubDate - a.pubDate) + .toSorted((a, b) => Number(b!.pubDate) - Number(a!.pubDate)) .slice(0, ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 20); const items = ctx.req.query('fulltext') === 'true' ? await pMap(list, (item) => fetchArticle(item), { concurrency: 10 }) : list; diff --git a/lib/routes/apnews/rss.ts b/lib/routes/apnews/rss.ts index 8a2889422a..8c10b14280 100644 --- a/lib/routes/apnews/rss.ts +++ b/lib/routes/apnews/rss.ts @@ -1,4 +1,4 @@ -import type { Route } from '@/types'; +import type { Data, Route } from '@/types'; import { ViewType } from '@/types'; import parser from '@/utils/rss-parser'; @@ -46,5 +46,5 @@ async function handler(ctx) { return { ...res, item: items, - }; + } as unknown as Data; } diff --git a/lib/routes/apnews/sitemap.ts b/lib/routes/apnews/sitemap.ts index 3d61a0c0af..9e443a2bdc 100644 --- a/lib/routes/apnews/sitemap.ts +++ b/lib/routes/apnews/sitemap.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -67,7 +67,7 @@ async function handler(ctx) { .find(String.raw`news\:language`) .text() ); - let res = { link: $(e).find('loc').text() }; + let res: DataItem & { link: string; lastmod?: Date } = { link: $(e).find('loc').text(), title: '' }; if (title) { res = Object.assign(res, { title }); } @@ -83,7 +83,7 @@ async function handler(ctx) { return res; }) .filter((e) => Boolean(e.link) && !new URL(e.link).pathname.split('/').includes('hub')) - .toSorted((a, b) => (a.pubDate && b.pubDate ? b.pubDate - a.pubDate : b.lastmod - a.lastmod)) + .toSorted((a, b) => (a.pubDate && b.pubDate ? Number(b.pubDate) - Number(a.pubDate) : Number(b.lastmod) - Number(a.lastmod))) .slice(0, ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 20); const items = ctx.req.query('fulltext') === 'true' ? await pMap(list, (item) => fetchArticle(item), { concurrency: 20 }) : list; diff --git a/lib/routes/apnews/topics.ts b/lib/routes/apnews/topics.ts index cdb8eeb919..4e35540e21 100644 --- a/lib/routes/apnews/topics.ts +++ b/lib/routes/apnews/topics.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import got from '@/utils/got'; @@ -61,7 +61,7 @@ async function handler(ctx) { title: $('title').text(), description: $("meta[property='og:description']").text(), link: url, - item: removeDuplicateByKey(items, 'link'), - language: $('html').attr('lang'), + item: removeDuplicateByKey(items, 'link') as DataItem[], + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/apnic/index.ts b/lib/routes/apnic/index.ts index fcf98adb86..8f0b6db312 100644 --- a/lib/routes/apnic/index.ts +++ b/lib/routes/apnic/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -25,7 +25,7 @@ async function handler() { // 从 RSS XML 中直接提取文章信息 const list = $('item') .toArray() - .map((item) => { + .map((item): DataItem => { const $item = $(item); return { title: $item.find('title').text(), @@ -42,7 +42,7 @@ async function handler() { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: articleData } = await got(item.link); const $article = load(articleData); diff --git a/lib/routes/app-sales/index.ts b/lib/routes/app-sales/index.ts index ffbc99d8f2..d8ffb40968 100644 --- a/lib/routes/app-sales/index.ts +++ b/lib/routes/app-sales/index.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; @@ -35,7 +35,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('a.brand-logo img').attr('src') ? new URL($('a.brand-logo img').attr('src') as string, baseUrl).href : undefined, author: title.split(/\|/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/app-sales/mostwanted.ts b/lib/routes/app-sales/mostwanted.ts index 90ea983392..4f0932d309 100644 --- a/lib/routes/app-sales/mostwanted.ts +++ b/lib/routes/app-sales/mostwanted.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; @@ -36,7 +36,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('a.brand-logo img').attr('src') ? new URL($('a.brand-logo img').attr('src') as string, baseUrl).href : undefined, author: title.split(/\|/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/app-sales/util.tsx b/lib/routes/app-sales/util.tsx index 4f5c2e08ce..a508a5dbb8 100644 --- a/lib/routes/app-sales/util.tsx +++ b/lib/routes/app-sales/util.tsx @@ -135,7 +135,7 @@ const processItems = ($: CheerioAPI, selector: string): DataItem[] => $(selector) .toArray() .map((el) => { - const $el: Cheerio = $(el); + const $el = $(el) as Cheerio; const appName: string = $el.find('p.app-name').text()?.trim(); const appDev: string = $el.find('p.app-dev').text()?.trim(); diff --git a/lib/routes/apple/apps.ts b/lib/routes/apple/apps.ts index cf854838fb..d0f4b20146 100644 --- a/lib/routes/apple/apps.ts +++ b/lib/routes/apple/apps.ts @@ -1,4 +1,4 @@ -import type { DataItem, Route } from '@/types'; +import type { Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -113,7 +113,7 @@ async function handler(ctx) { const artistName = attributes.artistName; const platformAttributes = attributes.platformAttributes; - let items: DataItem[] = []; + let items: any[] = []; let title: string; let description = ''; let image = ''; @@ -129,7 +129,7 @@ async function handler(ctx) { image = platformAttribute.iconArtwork?.url?.replace('{w}x{h}{c}.{f}', '3000x3000bb.webp'); } else { title = appName; - for (const [pid, platformAttribute] of Object.entries(platformAttributes)) { + for (const [pid, platformAttribute] of Object.entries(platformAttributes)) { items = [ ...items, ...platformAttribute.versionHistory.map((v) => ({ diff --git a/lib/routes/apple/exchange-repair.ts b/lib/routes/apple/exchange-repair.ts index 1f879c470e..64d595a11b 100644 --- a/lib/routes/apple/exchange-repair.ts +++ b/lib/routes/apple/exchange-repair.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -39,19 +39,19 @@ async function handler(ctx) { const $ = load(response.data); const list = $('section.as-container-column') .toArray() - .map((item) => { - item = $(item); - const a = item.find('.icon-chevronright').parent(); + .map((item): DataItem => { + const $item = $(item); + const a = $item.find('.icon-chevronright').parent(); return { title: a.text(), - link: new URL(a.attr('href'), host).href, - pubDate: parseDate(item.find('.note').text(), ['MMMM D, YYYY', 'D MMMM YYYY', 'YYYY 年 M 月 D 日']), + link: new URL(a.attr('href')!, host).href, + pubDate: parseDate($item.find('.note').text(), ['MMMM D, YYYY', 'D MMMM YYYY', 'YYYY 年 M 月 D 日']), }; }); const out = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got(item.link); const $$ = load(response.data); diff --git a/lib/routes/apple/newsroom.ts b/lib/routes/apple/newsroom.ts index 949b2dce19..958314dc12 100644 --- a/lib/routes/apple/newsroom.ts +++ b/lib/routes/apple/newsroom.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Item } from 'rss-parser'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -31,7 +31,7 @@ const extractArticleDescription = ($: CheerioAPI) => { return article.html() ?? undefined; }; -const fetchArticle = (item: Item & { link: string }) => +const fetchArticle = (item: Item & { link: string; author?: string }) => cache.tryGet(item.link, async () => { const response = await ofetch(item.link); const $ = load(response); @@ -72,7 +72,7 @@ async function handler(ctx) { feedLink: feedUrl, description: 'Apple 新闻中心是 Apple 新闻的来源。阅读新闻稿、获取最新消息、观看视频和下载图片。', item: items, - language: 'zh-CN', + language: 'zh-CN' as Language, }; } diff --git a/lib/routes/apple/podcast.ts b/lib/routes/apple/podcast.ts index ffaaaeec0e..2e5adc9d36 100644 --- a/lib/routes/apple/podcast.ts +++ b/lib/routes/apple/podcast.ts @@ -50,7 +50,7 @@ async function handler(ctx) { const bearerToken = await cache.tryGet( 'apple:podcast:bearer', async () => { - const moduleAddress = new URL($('head script[type="module"]').attr('src'), baseUrl).href; + const moduleAddress = new URL($('head script[type="module"]').attr('src')!, baseUrl).href; const modulesResponse = await ofetch(moduleAddress, { parseResponse: (txt) => txt, }); diff --git a/lib/routes/apple/security-releases.ts b/lib/routes/apple/security-releases.ts index 54f5330653..1ebf493fea 100644 --- a/lib/routes/apple/security-releases.ts +++ b/lib/routes/apple/security-releases.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -30,7 +30,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $trEls .slice(1, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const titleEl: Cheerio = $el.find('td').first(); @@ -58,7 +58,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr, ['DD MMM YYYY', 'YYYY 年 MM 月 DD 日']) : undefined, - language, + language: language as Language, }; return processedItem; @@ -71,7 +71,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = item.title ?? $$('h1.gb-header').text(); @@ -81,7 +81,7 @@ export const handler = async (ctx: Context): Promise => { const description: string | undefined = item.description + renderDescription({ - description: $$('div#sections').html(), + description: $$('div#sections').html() ?? undefined, }); const pubDateStr: string | undefined = detailResponse.match(/publish_date:\s"(\d{8})",/, '')?.[1]; const authors: DataItem['author'] = $$('meta[property="og:site_name"]').attr('content'); @@ -97,7 +97,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr, 'MMDDYYYY') : item.updated, - language, + language: language as Language, }; return { @@ -115,7 +115,7 @@ export const handler = async (ctx: Context): Promise => { item: items, allowEmpty: true, author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/appleinsider/index.ts b/lib/routes/appleinsider/index.ts index 227b4c299d..518bb0bc6e 100644 --- a/lib/routes/appleinsider/index.ts +++ b/lib/routes/appleinsider/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -48,18 +48,18 @@ async function handler(ctx) { let items = $(`${category === '' ? '#news-river ' : ''}.river`) .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 30) .toArray() - .map((item) => { - item = $(item).find('a').first(); + .map((item): DataItem => { + const $item = $(item).find('a').first(); return { - title: item.text(), - link: item.attr('href'), + title: $item.text(), + link: $item.attr('href'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -73,7 +73,7 @@ async function handler(ctx) { item.title = content('.h1-adjust').text(); item.author = content('.avatar-link a').attr('title'); - item.pubDate = parseDate(content('time').first().attr('datetime')); + item.pubDate = parseDate(content('time').first().attr('datetime')!); item.description = content('header').next('.row').html(); return item; diff --git a/lib/routes/appstore/price.ts b/lib/routes/appstore/price.ts index 829df08ea3..aba710ac68 100644 --- a/lib/routes/appstore/price.ts +++ b/lib/routes/appstore/price.ts @@ -59,7 +59,7 @@ async function handler(ctx) { result = res.data.results.macapps; } - const item = []; + const item: any[] = []; const title = `${country === 'cn' ? '限免提醒' : 'Price watcher'}: ${result.title} for ${type === 'macapps' ? 'macOS' : 'iOS'}`; diff --git a/lib/routes/appstorrent/programs.tsx b/lib/routes/appstorrent/programs.tsx index 009ca2d296..2a9b1cda04 100644 --- a/lib/routes/appstorrent/programs.tsx +++ b/lib/routes/appstorrent/programs.tsx @@ -5,7 +5,6 @@ import { renderToString } from 'hono/jsx/dom/server'; import type { Data, DataItem, Route } from '@/types'; import cache from '@/utils/cache'; -import type { Options } from '@/utils/got'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -23,7 +22,7 @@ async function handler(ctx?: Context): Promise { const limit = ctx?.req.query('limit') ? Number.parseInt(ctx?.req.query('limit') ?? '20') : 20; const baseUrl = 'https://appstorrent.ru'; const currentUrl = `${baseUrl}/programs/`; - const gotOptions: Options = { + const gotOptions: Parameters[1] = { http2: true, }; diff --git a/lib/routes/aqara/news.ts b/lib/routes/aqara/news.ts index e28bfe468d..4a5ea99f47 100644 --- a/lib/routes/aqara/news.ts +++ b/lib/routes/aqara/news.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -49,14 +49,14 @@ async function handler(ctx) { ) ); - const icon = $('link[rel="shortcut icon"]').prop('href').split('?', 1)[0]; + const icon = $('link[rel="shortcut icon"]').prop('href')!.split('?', 1)[0]; return { item: items, title: $('title').text(), link: currentUrl, description: $('meta[name="description"]').prop('content'), - language: 'zh-cn', + language: 'zh-CN' as Language, image: $('meta[property="og:image"]').prop('content'), icon, logo: icon, diff --git a/lib/routes/aqara/post.tsx b/lib/routes/aqara/post.tsx index bcdc2aeab7..b69c7ebc0f 100644 --- a/lib/routes/aqara/post.tsx +++ b/lib/routes/aqara/post.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -99,7 +99,7 @@ async function handler(ctx) { title: `${title}${filterName ? ` - ${filterName}` : ''}`, link: currentUrl, description: $('meta[property="og:title"]').prop('content'), - language: $('meta[property="og:locale"]').prop('content'), + language: $('meta[property="og:locale"]').prop('content') as Language, image: $('meta[name="msapplication-TileImage"]').prop('content'), icon, logo: icon, diff --git a/lib/routes/aqara/region.ts b/lib/routes/aqara/region.ts index d8954d3c94..d130d9e3b8 100644 --- a/lib/routes/aqara/region.ts +++ b/lib/routes/aqara/region.ts @@ -28,5 +28,5 @@ function handler(ctx) { const { region = 'en', type = 'news' } = ctx.req.param(); const redirectTo = `/aqara/${region}/category/${types[type]}`; - ctx.set('redirect', redirectTo); + return ctx.set('redirect', redirectTo); } diff --git a/lib/routes/aqicn/aqi.ts b/lib/routes/aqicn/aqi.ts index 6f07c3e636..e6e8217b1d 100644 --- a/lib/routes/aqicn/aqi.ts +++ b/lib/routes/aqicn/aqi.ts @@ -19,22 +19,20 @@ export const route: Route = { maintainers: ['ladeng07'], handler, url: 'aqicn.org', - descriptions: ` -| 参数 | 污染成分 | -| -------- | -------- | -| pm25 | PM2.5 | -| pm10 | PM10 | -| o3 | O3 | -| no2 | NO2 | -| so2 | SO2 | -| co | CO | + description: `| 参数 | 污染成分 | +| ---- | -------- | +| pm25 | PM2.5 | +| pm10 | PM10 | +| o3 | O3 | +| no2 | NO2 | +| so2 | SO2 | +| co | CO | -举例: [https://rsshub.app/aqicn/beijing/pm25,pm10](https://rsshub.app/aqicn/beijing/pm25,pm10) +举例: -1. 显示单个污染成分,例如「pm25」, [https://rsshub.app/aqicn/beijing/pm25](https://rsshub.app/aqicn/beijing/pm25) -2. 逗号分隔显示多个污染成分,例如「pm25,pm10」,[https://rsshub.app/aqicn/beijing/pm25,pm10](https://rsshub.app/aqicn/beijing/pm25,pm10) -3. 城市子站 ID 获取方法:右键显示网页源代码,搜索 "idx" (带双冒号),后面的 ID 就是子站的 ID,如你给的链接 ID 是 4258,RSS 地址就是 [https://rsshub.app/aqicn/4258](https://rsshub.app/aqicn/4258) -`, +1. 显示单个污染成分,例如「pm25」, +2. 逗号分隔显示多个污染成分,例如「pm25,pm10」, +3. 城市子站 ID 获取方法:右键显示网页源代码,搜索 "idx" (带双冒号),后面的 ID 就是子站的 ID,如你给的链接 ID 是 4258,RSS 地址就是 `, }; async function handler(ctx) { diff --git a/lib/routes/arcteryx/regear-new-arrivals.tsx b/lib/routes/arcteryx/regear-new-arrivals.tsx index bd6b4773ea..06e7c3e3e1 100644 --- a/lib/routes/arcteryx/regear-new-arrivals.tsx +++ b/lib/routes/arcteryx/regear-new-arrivals.tsx @@ -43,7 +43,7 @@ async function handler() { const $ = load(data); const contents = $('script:contains("window.__PRELOADED_STATE__")').text(); const regex = /\{.*\}/; - let items = JSON.parse(contents.match(regex)[0]).shop.items; + let items = JSON.parse(contents.match(regex)![0]).shop.items; items = items.filter((item) => item.availableSizes.length !== 0); const list = items.map((item) => { diff --git a/lib/routes/arcteryx/utils.ts b/lib/routes/arcteryx/utils.ts index 13cbda2296..2342802265 100644 --- a/lib/routes/arcteryx/utils.ts +++ b/lib/routes/arcteryx/utils.ts @@ -1,7 +1,7 @@ function generateRssData(item, index, arr, country) { const attributeSet = new Set(['name', 'image', 'short_description', 'slug', `price_${country}`, `discount_price_${country}`]); const attributes = item.attribute; - const data = {}; + const data = {} as Record; for (const attribute of attributes) { const key = attribute.name; diff --git a/lib/routes/aschmelyun/blog.ts b/lib/routes/aschmelyun/blog.ts index 0a2b43cbbe..6b78722256 100644 --- a/lib/routes/aschmelyun/blog.ts +++ b/lib/routes/aschmelyun/blog.ts @@ -26,17 +26,17 @@ async function handler() { const items = $('div.rounded-lg') .toArray() .map((item) => { - item = $(item); - const a = item.find('a.text-xl').first(); + const $item = $(item); + const a = $item.find('a.text-xl').first(); return { title: a.text(), - link: new URL(a.attr('href'), 'https://aschmelyun.com/blog/').href, - pubDate: parseDate(item.find('span.text-sm').text()), - category: item + link: new URL(a.attr('href')!, 'https://aschmelyun.com/blog/').href, + pubDate: parseDate($item.find('span.text-sm').text()), + category: $item .find('a.rounded-full') .toArray() .map((cat) => $(cat).text().trim()), - description: item.find('p').first().text(), + description: $item.find('p').first().text(), }; }); diff --git a/lib/routes/asiafruitchina/categories.ts b/lib/routes/asiafruitchina/categories.ts index 15367ada38..f16283e6ce 100644 --- a/lib/routes/asiafruitchina/categories.ts +++ b/lib/routes/asiafruitchina/categories.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.listBlocks ul li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('div.storyDetails h3 a'); @@ -63,7 +63,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -77,7 +77,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.story_title h1').text(); @@ -104,7 +104,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const extraLinkEls: Element[] = $$('div.extrasStory ul li').toArray(); @@ -148,7 +148,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.logo').attr('src'), author: title.split(/-/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/asiafruitchina/news.ts b/lib/routes/asiafruitchina/news.ts index 94a2477ac8..ff2fa1c66d 100644 --- a/lib/routes/asiafruitchina/news.ts +++ b/lib/routes/asiafruitchina/news.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -24,7 +24,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.listBlocks ul li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('div.storyDetails h3 a'); @@ -62,7 +62,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -76,7 +76,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.story_title h1').text(); @@ -103,7 +103,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; const extraLinkEls: Element[] = $$('div.extrasStory ul li').toArray(); @@ -147,7 +147,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img.logo').attr('src'), author: title.split(/-/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/asiantolick/index.ts b/lib/routes/asiantolick/index.ts index d9996974d2..9df0f2b37e 100644 --- a/lib/routes/asiantolick/index.ts +++ b/lib/routes/asiantolick/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import { getSubPath } from '@/utils/common-utils'; import got from '@/utils/got'; @@ -35,7 +35,7 @@ export async function handler(ctx) { const apiUrl = new URL('ajax/buscar_posts.php', rootUrl).href; const currentUrl = new URL(category.replace(/^(tag|category)?\/(\d+)/, '$1-$2'), rootUrl).href; - const searchParams = {}; + const searchParams: Record = {}; const matches = category.match(/^(tag|category|search|page)?[/-]?(\w+)/); if (matches) { @@ -53,14 +53,14 @@ export async function handler(ctx) { let items = $('a.miniatura') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const image = item.find('div.background_miniatura img'); + const image = $item.find('div.background_miniatura img'); return { - title: item.find('div.base_tt').text(), - link: item.prop('href'), + title: $item.find('div.base_tt').text(), + link: $item.prop('href'), description: renderDescription({ images: image ? [ @@ -71,25 +71,25 @@ export async function handler(ctx) { ] : undefined, }), - author: item.find('.author').text(), - category: item + author: $item.find('.author').text(), + category: $item .find('.category') .toArray() .map((c) => $(c).text()), - guid: image ? image.prop('post-id') : item.link.match(/\/(\d+)/)[1], + guid: image ? image.prop('post-id') : ($item as any).link.match(/\/(\d+)/)[1], }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link); const content = load(detailResponse); item.title = content('h1').text(); item.description = renderDescription({ - description: content('#metadata_qrcode').html(), + description: content('#metadata_qrcode').html() ?? undefined, images: content('div.miniatura') .toArray() .map((i) => ({ @@ -124,7 +124,7 @@ export async function handler(ctx) { title: title === 'Asian To Lick' ? title : `Asian To Lick - ${title}`, link: currentUrl, description: $('meta[property="og:description"]').prop('content'), - language: $('html').prop('lang'), + language: $('html').prop('lang') as Language, image: $('meta[name="msapplication-TileImage"]').prop('content'), icon, logo: icon, diff --git a/lib/routes/asus/gpu-tweak.ts b/lib/routes/asus/gpu-tweak.ts index 75e87aad69..188143de8f 100644 --- a/lib/routes/asus/gpu-tweak.ts +++ b/lib/routes/asus/gpu-tweak.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -37,22 +37,22 @@ async function handler() { const items = $('section div.inner div.item') .toArray() .map((item) => { - item = $(item); - item.find('.last').remove(); + const $item = $(item); + $item.find('.last').remove(); return { - title: item.find('.ver h6').text().trim(), - description: item.find('.btnbox a.open_patch_lightbox').attr('data-info'), - pubDate: parseDate(item.find('.ti').text()), - link: item.find('.btnbox a[download=]').attr('href'), + title: $item.find('.ver h6').text().trim(), + description: $item.find('.btnbox a.open_patch_lightbox').attr('data-info'), + pubDate: parseDate($item.find('.ti').text()), + link: $item.find('.btnbox a[download=]').attr('href'), }; }); return { title: $('head title').text(), description: $('meta[name=description]').attr('content'), - image: new URL($('head link[rel="shortcut icon"]').attr('href'), pageUrl).href, + image: new URL($('head link[rel="shortcut icon"]').attr('href')!, pageUrl).href, link: pageUrl, item: items, - language: $('html').attr('lang'), + language: $('html').attr('lang') as Language, }; } diff --git a/lib/routes/atcoder/contest.ts b/lib/routes/atcoder/contest.ts index bba128343b..1201752bca 100644 --- a/lib/routes/atcoder/contest.ts +++ b/lib/routes/atcoder/contest.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -68,18 +68,18 @@ async function handler(ctx) { .find('tr') .slice(1, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20) .toArray() - .map((item) => { - item = $(item).find('td a').eq(1); + .map((item): DataItem => { + const $item = $(item).find('td a').eq(1); return { - title: item.text(), - link: `${rootUrl}${item.attr('href')}?lang=${language}`, + title: $item.text(), + link: `${rootUrl}${$item.attr('href')}?lang=${language}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/atcoder/post.ts b/lib/routes/atcoder/post.ts index 18e2ff9379..b8d545eaa5 100644 --- a/lib/routes/atcoder/post.ts +++ b/lib/routes/atcoder/post.ts @@ -40,13 +40,13 @@ async function handler(ctx) { const items = $('.panel') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.panel-title').text(), - description: item.find('.panel-body').html(), - link: `${rootUrl}${item.find('.panel-title a').attr('href')}`, - pubDate: timezone(parseDate(item.find('.timeago').attr('datetime')), 9), + title: $item.find('.panel-title').text(), + description: $item.find('.panel-body').html(), + link: `${rootUrl}${$item.find('.panel-title a').attr('href')}`, + pubDate: timezone(parseDate($item.find('.timeago').attr('datetime')!), 9), }; }); diff --git a/lib/routes/augmentcode/blog.tsx b/lib/routes/augmentcode/blog.tsx index a0cfba8c5c..1dcf7c76f3 100644 --- a/lib/routes/augmentcode/blog.tsx +++ b/lib/routes/augmentcode/blog.tsx @@ -5,7 +5,7 @@ import type { Context } from 'hono'; import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -43,7 +43,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div[data-slot="card"]') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const title: string = $el.find('div[data-slot="card-content"]').text(); @@ -70,7 +70,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -83,7 +83,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('article h1').text(); @@ -105,7 +105,7 @@ export const handler = async (ctx: Context): Promise => { const $$authorEl: Cheerio = $$(authorEl); return { - name: $$authorEl.attr('content'), + name: $$authorEl.attr('content')!, url: undefined, avatar: undefined, }; @@ -124,7 +124,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : item.updated, - language, + language: language as Language, }; return { @@ -145,7 +145,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('meta[property="og:image"]').attr('content'), author: title.split(/-/).pop()?.trim(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/auto-stats/index.ts b/lib/routes/auto-stats/index.ts index dd9b81d8e8..2ae24337af 100644 --- a/lib/routes/auto-stats/index.ts +++ b/lib/routes/auto-stats/index.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import iconv from 'iconv-lite'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -44,22 +44,22 @@ async function handler(ctx) { let items = $('a.dnews font') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const title = item.text(); + const title = $item.text(); const pubDate = title.match(/(\d{4}(?:\/\d{1,2}){2}\s\d{1,2}(?::\d{2}){2})/)?.[1] ?? undefined; return { title: title.replace(/●/, '').split(/(\d+/, 1)[0], - link: new URL(item.parent().prop('href'), rootUrl).href, - pubDate: timezone(parseDate(pubDate, 'YYYY/M/D H:mm:ss'), 8), + link: new URL($item.parent().prop('href')!, rootUrl).href, + pubDate: timezone(parseDate(pubDate!, 'YYYY/M/D H:mm:ss'), 8), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: detailResponse } = await got(item.link, { responseType: 'buffer', }); @@ -84,7 +84,7 @@ async function handler(ctx) { title: $('title').text(), link: currentUrl, description: subtitle, - language: 'zh', + language: 'zh' as Language, image, subtitle, allowEmpty: true, diff --git a/lib/routes/azul/packages.ts b/lib/routes/azul/packages.ts index 8a29eb08a8..55a204c411 100644 --- a/lib/routes/azul/packages.ts +++ b/lib/routes/azul/packages.ts @@ -2,7 +2,7 @@ import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; @@ -44,7 +44,7 @@ export const handler = async (ctx: Context): Promise => { category: categories, guid, id: guid, - language, + language: language as Language, }; const enclosureUrl: string | undefined = item.download_url; @@ -72,7 +72,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('meta[property="og:image"]').attr('content'), author: $('meta[property="og:site_name"]').attr('content'), - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/azurlane/news.ts b/lib/routes/azurlane/news.ts index a0b38daab7..6b824a1772 100644 --- a/lib/routes/azurlane/news.ts +++ b/lib/routes/azurlane/news.ts @@ -59,7 +59,7 @@ const ja: Route['handler'] = async (ctx) => { return { title: `アズールレーン - ${JP[type]}`, link: 'https://www.azurlane.jp/news', - language: 'ja-JP', + language: 'ja', image: 'https://play-lh.googleusercontent.com/9QTLYD2_Jd6OIKHwRHkEBnFAgPmVKJwf2xmHjzPk-5w0SRLZumsCoQZGlO8d_kB3Gdld=w480-h960-rw', icon: 'https://play-lh.googleusercontent.com/9QTLYD2_Jd6OIKHwRHkEBnFAgPmVKJwf2xmHjzPk-5w0SRLZumsCoQZGlO8d_kB3Gdld=w480-h960-rw', logo: 'https://play-lh.googleusercontent.com/9QTLYD2_Jd6OIKHwRHkEBnFAgPmVKJwf2xmHjzPk-5w0SRLZumsCoQZGlO8d_kB3Gdld=w480-h960-rw', diff --git a/lib/routes/backlinko/blog.ts b/lib/routes/backlinko/blog.ts index a90fe1bde0..e9699991a8 100644 --- a/lib/routes/backlinko/blog.ts +++ b/lib/routes/backlinko/blog.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -40,7 +40,7 @@ async function handler() { props: { pageProps }, } = nextData; - const posts = [...pageProps.posts.nodes, ...pageProps.backlinkoLockedPosts.nodes].map((post) => ({ + const posts = [...pageProps.posts.nodes, ...pageProps.backlinkoLockedPosts.nodes].map((post): DataItem & { apiUrl: string } => ({ title: post.title, link: `${baseUrl}/${post.slug}`, pubDate: parseDate(post.modified), @@ -50,7 +50,7 @@ async function handler() { const items = await Promise.all( posts.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data } = await got(item.apiUrl); const post = data.pageProps.post || data.pageProps.lockedPost; @@ -65,7 +65,7 @@ async function handler() { title: pageProps.page.seo.title, description: pageProps.page.seo.metaDesc, link, - language: 'en', + language: 'en' as Language, item: items, }; } diff --git a/lib/routes/bad/index.ts b/lib/routes/bad/index.ts index ac4654c4d1..169a966433 100644 --- a/lib/routes/bad/index.ts +++ b/lib/routes/bad/index.ts @@ -35,18 +35,18 @@ async function handler(ctx) { const items = $('.entry') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const a = item.find('a.title'); + const a = $item.find('a.title'); - item.find('img').each((_, el) => { + $item.find('img').each((_, el) => { $(el).attr('src', $(el).attr('data-echo')); $(el).removeClass('lazy'); $(el).removeAttr('data-echo'); $(el).removeAttr('id'); }); - item.find('video').each((_, el) => { + $item.find('video').each((_, el) => { $(el).attr('poster', $(el).attr('data-echo')); $(el).removeAttr('data-echo'); $(el).removeAttr('onerror'); @@ -56,10 +56,10 @@ async function handler(ctx) { return { title: a.text(), link: a.attr('href'), - description: item.find('.coverdiv').html(), - author: item.find('.author').text().trim(), - pubDate: timezone(parseDate(item.find('time').attr('datetime')), 8), - category: item + description: $item.find('.coverdiv').html(), + author: $item.find('.author').text().trim(), + pubDate: timezone(parseDate($item.find('time').attr('datetime')!), 8), + category: $item .find('.label') .toArray() .map((l) => $(l).text().trim()), diff --git a/lib/routes/baidu/search.tsx b/lib/routes/baidu/search.tsx index 72beec7aa1..9238e56560 100644 --- a/lib/routes/baidu/search.tsx +++ b/lib/routes/baidu/search.tsx @@ -3,7 +3,7 @@ import { raw } from 'hono/html'; import { renderToString } from 'hono/jsx/dom/server'; import { config } from '@/config'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -79,6 +79,6 @@ async function handler(ctx) { title: `${keyword} - 百度搜索`, description: `${keyword} - 百度搜索`, link: url, - item: items, + item: items as DataItem[], }; } diff --git a/lib/routes/baidu/tieba/post.tsx b/lib/routes/baidu/tieba/post.tsx index e3b1b89cb8..975dd947e6 100644 --- a/lib/routes/baidu/tieba/post.tsx +++ b/lib/routes/baidu/tieba/post.tsx @@ -67,7 +67,7 @@ async function handler(ctx) { const html = await getPost(id, lz); const $ = load(html); - const title = $('.pb-title-wrap .pb-title').text().trim() || ''; + const title = $('.pb-title-wrap .pb-title').text().trim(); // 使用新的 Vue 渲染页面选择器 - 只选择 virtual-list-item 避免重复 const list = $('.virtual-list-item'); diff --git a/lib/routes/baidu/top.tsx b/lib/routes/baidu/top.tsx index f62471298d..9c0c915982 100644 --- a/lib/routes/baidu/top.tsx +++ b/lib/routes/baidu/top.tsx @@ -1,4 +1,5 @@ import { load } from 'cheerio'; +import type { Comment } from 'domhandler'; import { renderToString } from 'hono/jsx/dom/server'; import type { Route } from '@/types'; @@ -53,12 +54,15 @@ async function handler(ctx) { const $ = load(response); - const { data } = JSON.parse( - $('#sanRoot') - .contents() - .filter((e) => e.nodeType === 8) - .prevObject[0].data.match(/s-data:(.*)/)[1] - ); + const sDataMatch = $('#sanRoot') + .contents() + .toArray() + .find((e): e is Comment => e.nodeType === 8) + ?.data.match(/s-data:(.*)/); + if (!sDataMatch) { + throw new Error('Unable to find s-data in page'); + } + const { data } = JSON.parse(sDataMatch[1]); const items = data.cards[0].content.map((item) => ({ title: item.word, diff --git a/lib/routes/bakamh/manga.ts b/lib/routes/bakamh/manga.ts index 3bad01f2f8..17abe20cd5 100644 --- a/lib/routes/bakamh/manga.ts +++ b/lib/routes/bakamh/manga.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -18,7 +18,7 @@ const handler = async (ctx) => { const list = $('li.wp-manga-chapter') .toArray() .slice(0, limit) - .map((item) => { + .map((item): DataItem => { const $item = $(item); const itemDate = $item.find('i').text().replaceAll(' ', ''); @@ -36,14 +36,14 @@ const handler = async (ctx) => { const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { - const response = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const response = await ofetch(item.link!); const $ = load(response); const comicpage = $('div.reading-content img'); const containerDiv = $('
'); comicpage.appendTo(containerDiv); item.description = containerDiv.html(); - item.pubDate = parseDate(item.pubDate, 'YYYY年M月D日'); + item.pubDate = parseDate(item.pubDate!, 'YYYY年M月D日'); return item; }) ) diff --git a/lib/routes/bandcamp/live.ts b/lib/routes/bandcamp/live.ts index 03024db9f3..876f8cc57e 100644 --- a/lib/routes/bandcamp/live.ts +++ b/lib/routes/bandcamp/live.ts @@ -43,18 +43,18 @@ async function handler() { const items = $('.live-listing') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - link: item.find('.title-link').attr('href'), - title: item.find('.show-title').text(), - author: item.find('.show-artist').text(), - pubDate: parseDate(item.find('.show-time-container').text().trim().split(' UTC', 1)[0]), + link: $item.find('.title-link').attr('href'), + title: $item.find('.show-title').text(), + author: $item.find('.show-artist').text(), + pubDate: parseDate($item.find('.show-time-container').text().trim().split(' UTC', 1)[0]), description: ``, }; }); diff --git a/lib/routes/bandcamp/tag.ts b/lib/routes/bandcamp/tag.ts index 1cd069a3d3..8f142a4037 100644 --- a/lib/routes/bandcamp/tag.ts +++ b/lib/routes/bandcamp/tag.ts @@ -58,7 +58,7 @@ async function handler(ctx) { item.title = content('.trackTitle').eq(0).text(); item.author = content('h3 span a').text(); - item.description = content('#tralbumArt').html() + content('#trackInfo').html(); + item.description = content('#tralbumArt').html()! + content('#trackInfo').html()!; return item; }) diff --git a/lib/routes/bandisoft/history.ts b/lib/routes/bandisoft/history.ts index e931d079c6..a2d81fd9a0 100644 --- a/lib/routes/bandisoft/history.ts +++ b/lib/routes/bandisoft/history.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -153,7 +153,7 @@ export const handler = async (ctx: Context): Promise => { const items: DataItem[] = $('div.row') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const version: string | undefined = $el.find('div.cell1').text(); @@ -179,7 +179,7 @@ export const handler = async (ctx: Context): Promise => { text: description, }, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language: lang, + language: lang as Language, }; return processedItem; @@ -193,7 +193,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: $('img#logo_light').attr('src'), author, - language: lang, + language: lang as Language, id: targetUrl, }; }; diff --git a/lib/routes/bangumi.tv/calendar/today.tsx b/lib/routes/bangumi.tv/calendar/today.tsx index f329bf89e2..21382de7e1 100644 --- a/lib/routes/bangumi.tv/calendar/today.tsx +++ b/lib/routes/bangumi.tv/calendar/today.tsx @@ -88,7 +88,7 @@ async function handler() { guid: id, title: [ bgm.title, - Object.values(bgm.titleTranslate) + Object.values(bgm.titleTranslate) .map((t) => t.join('|')) .join('|'), ] diff --git a/lib/routes/bangumi.tv/group/reply.ts b/lib/routes/bangumi.tv/group/reply.ts index b235bfbb56..445946a1a9 100644 --- a/lib/routes/bangumi.tv/group/reply.ts +++ b/lib/routes/bangumi.tv/group/reply.ts @@ -57,7 +57,7 @@ async function handler(ctx) { date: $el.children().first().find('small').children().remove().end().text().slice(3), }; }); - const finalLatestReplies = [...latestReplies, ...latestSubReplies].toSorted((a, b) => b.id.localeCompare(a.id)); + const finalLatestReplies = [...latestReplies, ...latestSubReplies].toSorted((a, b) => b.id!.localeCompare(a.id!)); const postTopic = { title, diff --git a/lib/routes/bangumi.tv/group/topic.ts b/lib/routes/bangumi.tv/group/topic.ts index 3b135a7987..27b3bee632 100644 --- a/lib/routes/bangumi.tv/group/topic.ts +++ b/lib/routes/bangumi.tv/group/topic.ts @@ -41,7 +41,7 @@ async function handler(ctx) { $('.topic_list .topic') .toArray() .map((elem) => { - const link = new URL($('.subject a', elem).attr('href'), baseUrl).href; + const link = new URL($('.subject a', elem).attr('href')!, baseUrl).href; return cache.tryGet(link, async () => { const html = await ofetch(link); const $ = load(html); @@ -49,7 +49,7 @@ async function handler(ctx) { const summary = 'Reply: ' + $('.posts', elem).text(); return { link, - title: $('.subject a', elem).attr('title'), + title: $('.subject a', elem).attr('title')!, pubDate: parseDate($('.lastpost .time', elem).text()), description: fullText ? summary + '

' + fullText : summary, author: $('.author a', elem).text(), diff --git a/lib/routes/bangumi.tv/subject/comments.ts b/lib/routes/bangumi.tv/subject/comments.ts index aa325f0062..7a8454b060 100644 --- a/lib/routes/bangumi.tv/subject/comments.ts +++ b/lib/routes/bangumi.tv/subject/comments.ts @@ -14,9 +14,9 @@ export const getComments = async (subjectID, minLength) => { .map((el) => { const $el = $(el); const $rateEl = $el.find('.starlight'); - let rate = null; + let rate: string | null = null; if ($rateEl.length > 0) { - rate = $rateEl.attr('class').match(/stars(\d)/)[1]; + rate = $rateEl.attr('class')!.match(/stars(\d)/)![1]; } const dateString = $el.find('small.grey').text().slice(2); diff --git a/lib/routes/bangumi.tv/user/blog.ts b/lib/routes/bangumi.tv/user/blog.ts index c96c32a56b..299c7bcd35 100644 --- a/lib/routes/bangumi.tv/user/blog.ts +++ b/lib/routes/bangumi.tv/user/blog.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -39,20 +39,20 @@ async function handler(ctx) { const list = $('#entry_list div.item') .find('h2.title') .toArray() - .map((item) => { - item = $(item); - const a = item.find('a'); + .map((item): DataItem => { + const $item = $(item); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.attr('href'), 'https://bgm.tv').href, - pubDate: timezone(parseDate(item.parent().find('small.time').text()), 0), + link: new URL(a.attr('href')!, 'https://bgm.tv').href, + pubDate: timezone(parseDate($item.parent().find('small.time').text()), 0), }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { - const res = await ofetch(item.link); + cache.tryGet(item.link!, async () => { + const res = await ofetch(item.link!); const content = load(res); item.description = content('#entry_content').html(); diff --git a/lib/routes/banshujiang/index.ts b/lib/routes/banshujiang/index.ts index 8da9a402f5..4b27553337 100644 --- a/lib/routes/banshujiang/index.ts +++ b/lib/routes/banshujiang/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -25,7 +25,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('ul.small-list li.row') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('span.book-property__title').first().next('a'); @@ -40,7 +40,7 @@ export const handler = async (ctx: Context): Promise => { }, ] : undefined, - description: $el.find('div.small-list__item-desc').html(), + description: $el.find('div.small-list__item-desc').html() ?? undefined, }); const pubDateStr: string | undefined = image?.split(/\?timestamp=/).pop(); const linkUrl: string | undefined = $aEl.attr('href'); @@ -63,7 +63,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'x') : undefined, - language, + language: language as Language, }; return processedItem; @@ -76,7 +76,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.ebook-title').text().trim(); @@ -122,7 +122,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr, 'x') : item.updated, - language, + language: language as Language, }; return { @@ -145,7 +145,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: new URL('logo.png?imageView2/2/w/128/h/128/q/100', baseUrl).href, author: $('a.brand').text(), - language, + language: language as Language, id: $('meta[property="og:url"]').attr('content'), }; }; diff --git a/lib/routes/banyuetan/index.ts b/lib/routes/banyuetan/index.ts index b8055ebb80..b864cf574c 100644 --- a/lib/routes/banyuetan/index.ts +++ b/lib/routes/banyuetan/index.ts @@ -3,7 +3,7 @@ import { load } from 'cheerio'; import type { Element } from 'domhandler'; import type { Context } from 'hono'; -import type { Data, DataItem, Route } from '@/types'; +import type { Data, DataItem, Language, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; @@ -26,7 +26,7 @@ export const handler = async (ctx: Context): Promise => { let items: DataItem[] = $('div.bty_tbtj_list ul.clearFix li') .slice(0, limit) .toArray() - .map((el): Element => { + .map((el) => { const $el: Cheerio = $(el); const $aEl: Cheerio = $el.find('h3 a'); @@ -59,7 +59,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? parseDate(upDatedStr) : undefined, - language, + language: language as Language, }; return processedItem; @@ -72,7 +72,7 @@ export const handler = async (ctx: Context): Promise => { } return cache.tryGet(item.link, async (): Promise => { - const detailResponse = await ofetch(item.link); + const detailResponse = await ofetch(item.link!); const $$: CheerioAPI = load(detailResponse); const title: string = $$('div.detail_tit h1').text(); @@ -88,7 +88,7 @@ export const handler = async (ctx: Context): Promise => { const $$authorEl: Cheerio = $$(authorEl); return { - name: $$authorEl.attr('content'), + name: $$authorEl.attr('content')!, url: undefined, avatar: undefined, }; @@ -109,7 +109,7 @@ export const handler = async (ctx: Context): Promise => { image, banner: image, updated: upDatedStr ? timezone(parseDate(upDatedStr), 8) : item.updated, - language, + language: language as Language, }; return { @@ -130,7 +130,7 @@ export const handler = async (ctx: Context): Promise => { allowEmpty: true, image: new URL('static/v1/image/logo.png', baseUrl).href, author: title.split(/—/).pop(), - language, + language: language as Language, id: targetUrl, }; }; diff --git a/lib/routes/baobua/category.ts b/lib/routes/baobua/category.ts index a764c987db..c59fc8ea24 100644 --- a/lib/routes/baobua/category.ts +++ b/lib/routes/baobua/category.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -43,7 +43,7 @@ async function handler(ctx) { return { title: `${SUB_NAME_PREFIX} - Category: ${category}`, link: url, - item: await Promise.all( + item: (await Promise.all( itemRaw .map((e) => { const item = $(e); @@ -57,6 +57,6 @@ async function handler(ctx) { return cache.tryGet(link, () => loadArticle(link)); }) .filter(Boolean) - ), + )) as DataItem[], }; } diff --git a/lib/routes/baobua/latest.ts b/lib/routes/baobua/latest.ts index 23fed0300e..259d52d347 100644 --- a/lib/routes/baobua/latest.ts +++ b/lib/routes/baobua/latest.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -40,7 +40,7 @@ async function handler() { return { title: `${SUB_NAME_PREFIX} - Latest`, link: SUB_URL, - item: await Promise.all( + item: (await Promise.all( itemRaw .map((e) => { const item = $(e); @@ -54,6 +54,6 @@ async function handler() { return cache.tryGet(link, () => loadArticle(link)); }) .filter(Boolean) - ), + )) as DataItem[], }; } diff --git a/lib/routes/baobua/search.ts b/lib/routes/baobua/search.ts index 29dd7ac0a3..cf3669e18c 100644 --- a/lib/routes/baobua/search.ts +++ b/lib/routes/baobua/search.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -56,7 +56,7 @@ async function handler(ctx) { } return cache.tryGet(link, () => loadArticle(link)); }) - .filter(Boolean) + .filter(Boolean) as Array> ), }; } diff --git a/lib/routes/baozimh/index.tsx b/lib/routes/baozimh/index.tsx index 7e1b2aa28f..fb59dc7d23 100644 --- a/lib/routes/baozimh/index.tsx +++ b/lib/routes/baozimh/index.tsx @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import { renderToString } from 'hono/jsx/dom/server'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -41,7 +41,7 @@ async function handler(ctx) { .first() .children() .toArray() - .map((item) => { + .map((item): DataItem => { const title = $(item).find('span').text(); const link = rootUrl + $(item).find('a').attr('href'); @@ -56,7 +56,7 @@ async function handler(ctx) { .first() .children() .toArray() - .map((item) => { + .map((item): DataItem => { const title = $(item).find('span').text(); const link = rootUrl + $(item).find('a').attr('href'); @@ -71,7 +71,7 @@ async function handler(ctx) { const items = await Promise.all( combinedList.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const $ = load(detailResponse.data); item.description = renderToString( diff --git a/lib/routes/barronschina/index.ts b/lib/routes/barronschina/index.ts index 8005332270..b477b94a13 100644 --- a/lib/routes/barronschina/index.ts +++ b/lib/routes/barronschina/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -51,15 +51,15 @@ async function handler(ctx) { ? await Promise.all( $('.title') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('.title').text(), - link: `${rootUrl}${item.parent().attr('href')}`, + title: $item.find('.title').text(), + link: `${rootUrl}${$item.parent().attr('href')}`, }; }) .map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -77,19 +77,19 @@ async function handler(ctx) { : $('dd') .toArray() .map((item) => { - item = $(item); + const $item = $(item); - const title = item.find('strong').text(); - item.find('strong').remove(); + const title = $item.find('strong').text(); + $item.find('strong').remove(); - const description = item.find('.short').html(); - item.find('.short').remove(); + const description = $item.find('.short').html(); + $item.find('.short').remove(); return { title, description, link: currentUrl, - pubDate: timezone(parseDate(`${item.parent().find('dt').text()} ${item.text()}`), 8), + pubDate: timezone(parseDate(`${$item.parent().find('dt').text()} ${$item.text()}`), 8), }; }); diff --git a/lib/routes/bast/index.ts b/lib/routes/bast/index.ts index 462a956730..f84608ff38 100644 --- a/lib/routes/bast/index.ts +++ b/lib/routes/bast/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -56,19 +56,19 @@ async function handler(ctx) { let items = selection .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.text().trim(), - link: item.attr('href'), + title: $item.text().trim(), + link: $item.attr('href'), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { - if (/bast\.net\.cn/.test(item.link)) { + cache.tryGet(item.link!, async () => { + if (/bast\.net\.cn/.test(item.link!)) { const detailResponse = await got({ method: 'get', url: item.link, @@ -76,10 +76,10 @@ async function handler(ctx) { const content = load(detailResponse.data); - item.title = content('meta[name="ArticleTitle"]').attr('content'); + item.title = content('meta[name="ArticleTitle"]').attr('content')!; item.author = content('meta[name="contentSource"]').attr('content'); - item.pubDate = timezone(parseDate(content('meta[name="pubdate"]').attr('content')), 8); - item.category = [content('meta[name="ColumnName"]').attr('content')]; + item.pubDate = timezone(parseDate(content('meta[name="pubdate"]').attr('content')!), 8); + item.category = [content('meta[name="ColumnName"]').attr('content')!]; item.description = content('.arccont').html(); } diff --git a/lib/routes/bbc/sport.ts b/lib/routes/bbc/sport.ts index 92ecda00eb..42e35156ec 100644 --- a/lib/routes/bbc/sport.ts +++ b/lib/routes/bbc/sport.ts @@ -34,7 +34,7 @@ async function handler(ctx) { const initialData = extractInitialData($); const { page } = initialData.stores.metadata; - const list: DataItem[] = Object.values(initialData.data) + const list: DataItem[] = Object.values(initialData.data) .filter((d) => d.name === 'hierarchical-promo-collection' && d.props.title !== 'Elsewhere on the BBC') .flatMap((d) => d.data.promos) .map((item) => ({ diff --git a/lib/routes/bbc/utils.tsx b/lib/routes/bbc/utils.tsx index a298262cfb..065e103f59 100644 --- a/lib/routes/bbc/utils.tsx +++ b/lib/routes/bbc/utils.tsx @@ -376,7 +376,7 @@ const extractArticleWithInitialData = ($: CheerioAPI, item) => { }; } - const article = Object.values(initialData.data).find((d) => d.name === 'article')?.data; + const article = Object.values(initialData.data).find((d) => d.name === 'article')?.data; const topics = Array.isArray(article?.topics) ? article.topics : []; const blocks = article?.content?.model?.blocks; diff --git a/lib/routes/bbcnewslabs/news.ts b/lib/routes/bbcnewslabs/news.ts index 267d5efdf9..c6a511036b 100644 --- a/lib/routes/bbcnewslabs/news.ts +++ b/lib/routes/bbcnewslabs/news.ts @@ -40,12 +40,12 @@ async function handler() { const items = $('a[href^="/news/20"]') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('h3[class^="thumbnail-module--thumbnailTitle--"]').text(), - description: item.find('span[class^="thumbnail-module--thumbnailDescription--"]').text(), - pubDate: parseDate(item.find('span[class^="thumbnail-module--thumbnailType--"]').text()), - link: rootUrl + item.attr('href'), + title: $item.find('h3[class^="thumbnail-module--thumbnailTitle--"]').text(), + description: $item.find('span[class^="thumbnail-module--thumbnailDescription--"]').text(), + pubDate: parseDate($item.find('span[class^="thumbnail-module--thumbnailType--"]').text()), + link: rootUrl + $item.attr('href'), }; }); diff --git a/lib/routes/bc3ts/list.tsx b/lib/routes/bc3ts/list.tsx index 586b83e0d4..5125b41937 100644 --- a/lib/routes/bc3ts/list.tsx +++ b/lib/routes/bc3ts/list.tsx @@ -1,7 +1,7 @@ import { renderToString } from 'hono/jsx/dom/server'; import { config } from '@/config'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import ofetch from '@/utils/ofetch'; import { parseDate } from '@/utils/parse-date'; @@ -76,7 +76,7 @@ async function handler(ctx) { return { title: `爆料公社${sort === '1' ? '最新' : '熱門'}動態`, link: baseUrl, - language: 'zh-TW', + language: 'zh-TW' as Language, image: 'https://img.bc3ts.net/image/web/main/logo-white-new-2023.png', icon: 'https://img.bc3ts.net/image/web/main/logo/logo_icon_6th_2024_192x192.png', item: items, diff --git a/lib/routes/bdys/index.tsx b/lib/routes/bdys/index.tsx index 2e910f432c..6ab829381f 100644 --- a/lib/routes/bdys/index.tsx +++ b/lib/routes/bdys/index.tsx @@ -5,7 +5,7 @@ import pMap from 'p-map'; import { config } from '@/config'; import ConfigNotFoundError from '@/errors/types/config-not-found'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -123,11 +123,11 @@ async function handler(ctx) { const list = $('.card-body .card a') .slice(0, 15) .toArray() - .map((item) => { - item = $(item); - const link = item.attr('href').split(';jsessionid='); + .map((item): DataItem => { + const $item = $(item); + const link = $item.attr('href')!.split(';jsessionid='); jsessionid = link[1]; - const next = item.next(); + const next = $item.next(); return { title: next.find('h3').text(), link: `${rootUrl}${link[0]}`, @@ -142,7 +142,7 @@ async function handler(ctx) { const items = await pMap( list, (item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, @@ -150,7 +150,7 @@ async function handler(ctx) { }); const downloadResponse = await got({ method: 'get', - url: `${rootUrl}/downloadInfo/list?mid=${item.link.split('/', 5)[4].split('.', 1)[0]}`, + url: `${rootUrl}/downloadInfo/list?mid=${item.link!.split('/', 5)[4].split('.', 1)[0]}`, headers, }); const content = load(detailResponse.data); diff --git a/lib/routes/beijingprice/index.ts b/lib/routes/beijingprice/index.ts index 0422acc019..b4a24e5697 100644 --- a/lib/routes/beijingprice/index.ts +++ b/lib/routes/beijingprice/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Language, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -21,10 +21,10 @@ export const handler = async (ctx) => { let items = $('div.jgzx.rightcontent ul li') .slice(0, limit) .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); - const a = item.find('a'); + const a = $item.find('a'); const link = a.prop('href'); const msg = a.prop('msg'); @@ -41,9 +41,9 @@ export const handler = async (ctx) => { return { title, - pubDate: parseDate(item.contents().last().text()), - link: enclosureUrl ?? (link.startsWith('http') ? link : new URL(link, rootUrl).href), - language, + pubDate: parseDate($item.contents().last().text()), + link: enclosureUrl ?? (link!.startsWith('http') ? link : new URL(link!, rootUrl).href), + language: language as Language, enclosure_url: enclosureUrl, enclosure_type: enclosureType, enclosure_title: enclosureUrl ? title : undefined, @@ -52,8 +52,8 @@ export const handler = async (ctx) => { items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { - if (!item.link.includes('www.beijingprice.cn') || item.link.endsWith('.pdf')) { + cache.tryGet(item.link!, async () => { + if (!item.link!.includes('www.beijingprice.cn') || item.link!.endsWith('.pdf')) { return item; } @@ -79,14 +79,14 @@ export const handler = async (ctx) => { html: description, text: $$('div.news-content').text(), }; - item.language = language; + item.language = language as Language; return item; }) ) ); - const image = new URL($('a.header-logo img').prop('src'), rootUrl).href; + const image = new URL($('a.header-logo img').prop('src')!, rootUrl).href; return { title: $('title').text(), @@ -96,7 +96,7 @@ export const handler = async (ctx) => { allowEmpty: true, image, author: $('meta[name="keywords"]').prop('content'), - language, + language: language as Language, }; }; diff --git a/lib/routes/bendibao/news.ts b/lib/routes/bendibao/news.ts index aa0f41606f..ad035d2d56 100644 --- a/lib/routes/bendibao/news.ts +++ b/lib/routes/bendibao/news.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import InvalidParameterError from '@/errors/types/invalid-parameter'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -63,14 +63,14 @@ async function handler(ctx) { let items = $('ul.focus-news li') .toArray() - .map((item) => { - item = $(item).find('a'); + .map((item): DataItem => { + const $item = $(item).find('a'); - const link = item.attr('href'); + const link = $item.attr('href'); return { - title: item.text(), - link: link.indexOf('http') === 0 ? link : `${rootUrl}${link}`, + title: $item.text(), + link: link!.startsWith('http') ? link : `${rootUrl}${link}`, }; }); @@ -91,21 +91,21 @@ async function handler(ctx) { items = $('#listNewsTimeLy div.info') .toArray() - .map((item) => { - item = $(item).find('a'); + .map((item): DataItem => { + const $item = $(item).find('a'); - const link = item.attr('href'); + const link = $item.attr('href'); return { - title: item.text(), - link: link.indexOf('http') === 0 ? link : `${rootUrl}${link}`, + title: $item.text(), + link: link!.startsWith('http') ? link : `${rootUrl}${link}`, }; }); } - items = await Promise.all( + items = (await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { try { const detailResponse = await got({ method: 'get', @@ -137,7 +137,7 @@ async function handler(ctx) { } }) ) - ); + )) as typeof items; return { title, diff --git a/lib/routes/bilibili/bangumi.ts b/lib/routes/bilibili/bangumi.ts index 49369c150b..5ec26b7b45 100644 --- a/lib/routes/bilibili/bangumi.ts +++ b/lib/routes/bilibili/bangumi.ts @@ -44,7 +44,7 @@ async function handler(ctx) { description: utils.renderOGVDescription(embed, item.cover, item.long_title, seasonId, String(item.id)), link: item.share_url, image: item.cover.replace('http://', 'https://'), - language: 'zh-cn', + language: 'zh-CN', }) as DataItem; for (const item of seasonData.main_section.episodes) { @@ -65,6 +65,6 @@ async function handler(ctx) { link: mediaData.share_url, item: episodes, image: mediaData.cover.replace('http://', 'https://'), - language: 'zh-cn', + language: 'zh-CN', } as Data; } diff --git a/lib/routes/bilibili/cache.ts b/lib/routes/bilibili/cache.ts index 0aeaa6e92b..e0aaf0cb7c 100644 --- a/lib/routes/bilibili/cache.ts +++ b/lib/routes/bilibili/cache.ts @@ -121,7 +121,7 @@ const getWbiVerifyString = () => { // 62, 11, 36, 20, 34, 44, 52, // ]; const array = JSON.parse(jsResponse.match(/\[(?:\d+,){63}\d+\]/)); - const o = []; + const o: any[] = []; for (const t of array) { if (r.charAt(t)) { o.push(r.charAt(t)); @@ -328,7 +328,7 @@ const getAidFromBvid = async (bvid) => { if (response.data && response.data.data && response.data.data.aid) { aid = response.data.data.aid; } - cache.set(key, aid); + cache.set(key, aid ?? ''); } return aid; }; @@ -355,7 +355,7 @@ const getArticleDataFromCvid = async (cvid, uid) => { const newFormatData = JSON.parse( $('script:contains("window.__INITIAL_STATE__")') .text() - .match(/window\.__INITIAL_STATE__\s*=\s*(\S.*?)?;\(/)[1] + .match(/window\.__INITIAL_STATE__\s*=\s*(\S.*?)?;\(/)![1] ); if (newFormatData?.readInfo?.opus?.content?.paragraphs) { diff --git a/lib/routes/bilibili/danmaku.ts b/lib/routes/bilibili/danmaku.ts index 0f429e6177..8618cb452b 100644 --- a/lib/routes/bilibili/danmaku.ts +++ b/lib/routes/bilibili/danmaku.ts @@ -59,7 +59,7 @@ async function handler(ctx) { danmakuText = await ((danmakuText[0] & 0x0f) === 0x08 ? zlib.inflateSync(danmakuText) : zlib.inflateRawSync(danmakuText)); - let danmakuList = []; + let danmakuList: any[] = []; const $ = load(danmakuText, { xmlMode: true }); $('d').each((index, item) => { danmakuList.push({ p: $(item).attr('p'), text: $(item).text() }); diff --git a/lib/routes/bilibili/mall-new.ts b/lib/routes/bilibili/mall-new.ts index 212da7d91f..488d20cfff 100644 --- a/lib/routes/bilibili/mall-new.ts +++ b/lib/routes/bilibili/mall-new.ts @@ -36,7 +36,7 @@ async function handler(ctx) { }); const days = response.data.data.vo.days; - const items = []; + const items: any[] = []; for (const day of days) { items.push(...day.presaleItems); } diff --git a/lib/routes/bilibili/user-channel.ts b/lib/routes/bilibili/user-channel.ts index b4e17b8b0e..e1b998c3f8 100644 --- a/lib/routes/bilibili/user-channel.ts +++ b/lib/routes/bilibili/user-channel.ts @@ -69,9 +69,9 @@ async function handler(ctx) { title: `${username} 的 bilibili 频道 ${channelInfo.meta.name}`, link, description: `${username} 的 bilibili 频道`, - image: face, - logo: face, - icon: face, + image: face ?? undefined, + logo: face ?? undefined, + icon: face ?? undefined, item: data.archives.map((item) => ({ title: item.title, description: utils.renderUGCDescription(embed, item.pic, '', item.aid, undefined, item.bvid), diff --git a/lib/routes/bilibili/user-collection.ts b/lib/routes/bilibili/user-collection.ts index 29b3110189..f8916923dd 100644 --- a/lib/routes/bilibili/user-collection.ts +++ b/lib/routes/bilibili/user-collection.ts @@ -61,9 +61,9 @@ async function handler(ctx) { title: `${username} 的 bilibili 合集 ${data.meta.name}`, link, description: `${username} 的 bilibili 合集`, - image: face, - logo: face, - icon: face, + image: face ?? undefined, + logo: face ?? undefined, + icon: face ?? undefined, item: data.archives.map((item) => ({ title: item.title, description: utils.renderUGCDescription(embed, item.pic, '', item.aid, undefined, item.bvid), diff --git a/lib/routes/bilibili/video-all.ts b/lib/routes/bilibili/video-all.ts index 574b17e1fa..3114f721ce 100644 --- a/lib/routes/bilibili/video-all.ts +++ b/lib/routes/bilibili/video-all.ts @@ -24,7 +24,7 @@ async function handler(ctx) { const cookie = await cache.getCookie(); const wbiVerifyString = await cache.getWbiVerifyString(); const dmImgList = utils.getDmImgList(); - const [name, face] = await cache.getUsernameAndFaceFromUID(uid); + const [name, face] = (await cache.getUsernameAndFaceFromUID(uid)) as [string, string]; await got(`https://space.bilibili.com/${uid}/video?tid=0&page=1&keyword=&order=pubdate`, { headers: { @@ -60,7 +60,7 @@ async function handler(ctx) { }); }; - const promises = []; + const promises: Array> = []; if (pageTotal > 1) { for (let i = 2; i <= pageTotal; i++) { diff --git a/lib/routes/bilibili/video.ts b/lib/routes/bilibili/video.ts index c34a821c3b..552711bb8e 100644 --- a/lib/routes/bilibili/video.ts +++ b/lib/routes/bilibili/video.ts @@ -224,7 +224,7 @@ async function handler(ctx: Context) { const uid = ctx.req.param('uid'); const embed = !ctx.req.param('embed'); - const data = await getVideoList(uid); + const data = await getVideoList(uid!); const videos = data.list?.vlist ?? []; let name = videos[0]?.author || uid; @@ -233,7 +233,7 @@ async function handler(ctx: Context) { try { const usernameAndFace = await cache.getUsernameAndFaceFromUID(uid); name = usernameAndFace[0] || name; - face = usernameAndFace[1]; + face = usernameAndFace[1] ?? undefined; } catch (error) { logger.warn(`[bilibili/video] failed to fetch user profile: ${error}`); } @@ -250,7 +250,7 @@ async function handler(ctx: Context) { const subtitles = isJsonFeed && !config.bilibili.excludeSubtitles && item.bvid ? await cache.getVideoSubtitleAttachment(item.bvid) : []; return { title: item.title, - description: utils.renderUGCDescription(embed, item.pic, item.description, item.aid, undefined, item.bvid), + description: utils.renderUGCDescription(embed, item.pic, item.description, String(item.aid), undefined, item.bvid), pubDate: new Date(item.created * 1000).toUTCString(), link: item.created > utils.bvidTime && item.bvid ? `https://www.bilibili.com/video/${item.bvid}` : `https://www.bilibili.com/video/av${item.aid}`, author: name, diff --git a/lib/routes/bilibili/wasm-exec.ts b/lib/routes/bilibili/wasm-exec.ts index 6159de0ac5..9a142d8cfb 100644 --- a/lib/routes/bilibili/wasm-exec.ts +++ b/lib/routes/bilibili/wasm-exec.ts @@ -1,3 +1,4 @@ +// @ts-nocheck https://github.com/golang/go/blob/master/lib/wasm/wasm_exec.js // oxlint-disable unicorn/prefer-math-trunc // oxlint-disable unicorn-js/no-this-outside-of-class // oxlint-disable unicorn-js/no-array-from-fill @@ -598,7 +599,7 @@ const argc = this.argv.length; - const argvPtrs = []; + const argvPtrs: number[] = []; for (const arg of this.argv) { argvPtrs.push(strPtr(arg)); } diff --git a/lib/routes/bing/search.ts b/lib/routes/bing/search.ts index 5faef975aa..4fc24ff233 100644 --- a/lib/routes/bing/search.ts +++ b/lib/routes/bing/search.ts @@ -3,7 +3,7 @@ import 'dayjs/locale/zh-cn.js'; import dayjs from 'dayjs'; import localizedFormat from 'dayjs/plugin/localizedFormat.js'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import { parseDate } from '@/utils/parse-date'; import parser from '@/utils/rss-parser'; @@ -44,14 +44,14 @@ async function handler(ctx) { url.search = searchParams.toString(); const data = await parser.parseURL(url.href); return { - title: data.title, + title: data.title!, link: data.link, description: data.description + ' - ' + data.copyright, - image: data.image.url, + image: data.image!.url, item: data.items.map((e) => ({ ...e, description: e.content, - pubDate: parseDate(e.pubDate, 'dddd, DD MMM YYYY HH:mm:ss [GMT]', 'zh-cn'), - })), + pubDate: parseDate(e.pubDate!, 'dddd, DD MMM YYYY HH:mm:ss [GMT]', 'zh-cn'), + })) as DataItem[], }; } diff --git a/lib/routes/bioone/featured.ts b/lib/routes/bioone/featured.ts index 8afafa0b09..81acced41f 100644 --- a/lib/routes/bioone/featured.ts +++ b/lib/routes/bioone/featured.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,25 +38,25 @@ async function handler(ctx) { let items = $('.items h4 a') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 10) .toArray() - .map((item) => { - item = $(item); - const link = item.attr('href').split('?', 1)[0]; + .map((item): DataItem => { + const $item = $(item); + const link = $item.attr('href')!.split('?', 1)[0]; return { - title: item.text(), + title: $item.text(), link: link.includes('http') ? link : `${rootUrl}${link}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const content = load(detailResponse.data); item.description = content('#divARTICLECONTENTTop').html(); item.doi = content('meta[name="dc.Identifier"]').attr('content'); - item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')); + item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')!); return item; }) diff --git a/lib/routes/bioone/journal.ts b/lib/routes/bioone/journal.ts index 87ab9f11e0..569b4943f9 100644 --- a/lib/routes/bioone/journal.ts +++ b/lib/routes/bioone/journal.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -41,17 +41,18 @@ async function handler(ctx) { let items = $('.TOCLineItemBoldText') .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20) .toArray() - .map((item) => { - item = $(item).parent(); + .map((item): DataItem => { + const $item = $(item).parent(); return { - link: `${rootUrl}${item.attr('href')}`, + title: '', + link: `${rootUrl}${$item.attr('href')}`, }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link); const content = load(detailResponse.data); @@ -60,10 +61,10 @@ async function handler(ctx) { content('#divNotSignedSection, #rightRail').remove(); item.description = content('.panel-body').html(); - item.title = content('meta[name="dc.Title"]').attr('content'); + item.title = content('meta[name="dc.Title"]').attr('content')!; item.author = content('meta[name="dc.Creator"]').attr('content'); item.doi = content('meta[name="dc.Identifier"]').attr('content'); - item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')); + item.pubDate = parseDate(content('meta[name="dc.Date"]').attr('content')!); return item; }) diff --git a/lib/routes/biquge/index.ts b/lib/routes/biquge/index.ts index 29286c71c6..a283d9e98c 100644 --- a/lib/routes/biquge/index.ts +++ b/lib/routes/biquge/index.ts @@ -3,7 +3,7 @@ import iconv from 'iconv-lite'; import { config } from '@/config'; import ConfigNotFoundError from '@/errors/types/config-not-found'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -76,27 +76,27 @@ async function handler(ctx) { const $ = load(iconv.decode(response.data, encoding)); const author = $('meta[property="og:novel:author"]').attr('content'); - const pubDate = timezone(parseDate($('meta[property="og:novel:update_time"]').attr('content')), 8); + const pubDate = timezone(parseDate($('meta[property="og:novel:update_time"]').attr('content')!), 8); let items = $('dl dd a') .toArray() .toReversed() .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 1) - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); let link: string; - const url = item.attr('href'); - if (url.startsWith('http')) { - link = url; - } else if (url.startsWith('/')) { + const url = $item.attr('href'); + if (url!.startsWith('http')) { + link = url!; + } else if (url!.startsWith('/')) { link = `${rootUrl}${url}`; } else { link = `${currentUrl}/${url}`; } return { - title: item.text(), + title: $item.text(), link, author, pubDate, @@ -105,7 +105,7 @@ async function handler(ctx) { items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got(item.link, { responseType: 'buffer', }); diff --git a/lib/routes/bit/cs/utils.ts b/lib/routes/bit/cs/utils.ts index ad67790a43..468bb7daa3 100644 --- a/lib/routes/bit/cs/utils.ts +++ b/lib/routes/bit/cs/utils.ts @@ -32,7 +32,7 @@ const ProcessFeed = (list, caches) => { const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), host).href; + const itemUrl = new URL($title.attr('href')!, host).href; // 列表上提取到的信息 const single = { diff --git a/lib/routes/bit/jwc/utils.ts b/lib/routes/bit/jwc/utils.ts index 1bcc9b522b..f4cf2c0bb2 100644 --- a/lib/routes/bit/jwc/utils.ts +++ b/lib/routes/bit/jwc/utils.ts @@ -28,7 +28,7 @@ const ProcessFeed = (list, caches) => { const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), host).href; + const itemUrl = new URL($title.attr('href')!, host).href; // 列表上提取到的信息 const single = { diff --git a/lib/routes/bit/yjs.ts b/lib/routes/bit/yjs.ts index c20f2aa017..8c71e63df0 100644 --- a/lib/routes/bit/yjs.ts +++ b/lib/routes/bit/yjs.ts @@ -41,12 +41,12 @@ async function handler() { item: list && list.toArray().map((item) => { - item = $(item); - const a = item.find('a'); + const $item = $(item); + const a = $item.find('a'); return { title: a.text(), - link: new URL(a.attr('href'), link).href, - pubDate: parseDate(item.find('span').text(), 'YYYY-MM-DD'), + link: new URL(a.attr('href')!, link).href, + pubDate: parseDate($item.find('span').text(), 'YYYY-MM-DD'), }; }), }; diff --git a/lib/routes/bjfu/grs.ts b/lib/routes/bjfu/grs.ts index 17cb96940f..7d1a8dbcc1 100644 --- a/lib/routes/bjfu/grs.ts +++ b/lib/routes/bjfu/grs.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,7 +38,7 @@ async function handler() { const list = $('.itemList li') .slice(0, 11) .toArray() - .map((e) => { + .map((e): DataItem => { const element = $(e); const title = element.find('li a').attr('title'); const link = element.find('li a').attr('href'); @@ -46,10 +46,10 @@ async function handler() { .find('li a') .text() .match(/\d{4}-\d{2}-\d{2}/); - const pubDate = timezone(parseDate(date), 8); + const pubDate = timezone(parseDate(date?.[0] ?? ''), 8); return { - title, + title: title!, link: 'http://graduate.bjfu.edu.cn/pygl/pydt/' + link, author: '北京林业大学研究生院培养动态', pubDate, @@ -58,7 +58,7 @@ async function handler() { const result = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const itemReponse = await got.get(item.link); const data = itemReponse.data; const itemElement = load(data); diff --git a/lib/routes/bjfu/it/utils.ts b/lib/routes/bjfu/it/utils.ts index 2998f726e3..d390d8dc67 100644 --- a/lib/routes/bjfu/it/utils.ts +++ b/lib/routes/bjfu/it/utils.ts @@ -26,7 +26,7 @@ async function loadContent(link) { } // 提取内容 - const description = ($('.template-body').length ? $('.template-body').html() : '') + ($('.template-tail').length ? $('.template-tail').html() : ''); + const description = ($('.template-body').length ? $('.template-body').html() : '')! + ($('.template-tail').length ? $('.template-tail').html() : '')!; // 返回解析的结果 return { description }; @@ -41,14 +41,14 @@ const ProcessFeed = (base, list, caches) => const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), base).href; // 感谢@hoilc指导 + const itemUrl = new URL($title.attr('href')!, base).href; // 感谢@hoilc指导 // 解析日期 const pubDate = timezone( parseDate( $('span') .text() - .match(/\d{4}-\d{2}-\d{2}/) + .match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? '' ), 8 ); diff --git a/lib/routes/bjfu/jwc/utils.ts b/lib/routes/bjfu/jwc/utils.ts index 526bbda34d..2f4177b345 100644 --- a/lib/routes/bjfu/jwc/utils.ts +++ b/lib/routes/bjfu/jwc/utils.ts @@ -14,7 +14,7 @@ async function loadContent(link) { const $ = load(data); // 提取内容 - const description = ($('#con_c').length ? $('#con_c').html() : '') + ($('#con_fujian').length ? $('#con_fujian').html() : ''); + const description = ($('#con_c').length ? $('#con_c').html() : '')! + ($('#con_fujian').length ? $('#con_fujian').html() : '')!; // 返回解析的结果 return { description }; @@ -28,14 +28,14 @@ const ProcessFeed = (base, list, caches) => const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), base).href; // 感谢@hoilc指导 + const itemUrl = new URL($title.attr('href')!, base).href; // 感谢@hoilc指导 // 解析日期 const pubDate = timezone( parseDate( $('.datetime') .text() - .match(/\d{4}-\d{2}-\d{2}/) + .match(/\d{4}-\d{2}-\d{2}/)?.[0] ?? '' ), 8 ); diff --git a/lib/routes/bjfu/kjc.ts b/lib/routes/bjfu/kjc.ts index dee0e77ed3..4327203c22 100644 --- a/lib/routes/bjfu/kjc.ts +++ b/lib/routes/bjfu/kjc.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,7 +38,7 @@ async function handler() { const list = $('.ll_con_r_b li') .slice(0, 15) .toArray() - .map((e) => { + .map((e): DataItem => { const element = $(e); const title = element.find('.ll_con_r_b_title a').text(); const link = element.find('a').attr('href'); @@ -46,7 +46,7 @@ async function handler() { .find('.ll_con_r_b_time') .text() .match(/\d{4}-\d{2}-\d{2}/); - const pubDate = timezone(parseDate(date), 8); + const pubDate = timezone(parseDate(date?.[0] ?? ''), 8); return { title, @@ -58,7 +58,7 @@ async function handler() { const result = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const itemReponse = await got.get(item.link); const data = itemReponse.data; const itemElement = load(data); diff --git a/lib/routes/bjfu/news/index.ts b/lib/routes/bjfu/news/index.ts index 843c7858ec..c218ceed2a 100644 --- a/lib/routes/bjfu/news/index.ts +++ b/lib/routes/bjfu/news/index.ts @@ -69,7 +69,7 @@ async function handler(ctx) { const data = response.data; let $ = load(iconv.decode(data, 'utf-8')); const charset = $('meta[http-equiv="Content-Type"]') - .attr('content') + .attr('content')! .match(/charset=(.*)/)?.[1]; if (charset?.toLowerCase() !== 'utf-8') { $ = load(iconv.decode(data, charset ?? 'utf-8')); diff --git a/lib/routes/bjfu/news/utils.ts b/lib/routes/bjfu/news/utils.ts index b13dcc30b3..8bb8563026 100644 --- a/lib/routes/bjfu/news/utils.ts +++ b/lib/routes/bjfu/news/utils.ts @@ -18,7 +18,7 @@ async function loadContent(link) { parseDate( $('.article') .text() - .match(/\d{4}(?:\/\d{2}){2}/) + .match(/\d{4}(?:\/\d{2}){2}/)?.[0] ?? '' ), 8 ); @@ -39,7 +39,7 @@ const ProcessFeed = (base, list, caches) => const $title = $('a'); // 还原相对链接为绝对链接 - const itemUrl = new URL($title.attr('href'), base).href; // 感谢@hoilc指导 + const itemUrl = new URL($title.attr('href')!, base).href; // 感谢@hoilc指导 // 使用tryGet方法从缓存获取内容。 // 当缓存中无法获取到链接内容的时候,则使用load方法加载文章内容。 diff --git a/lib/routes/bjp/apod.ts b/lib/routes/bjp/apod.ts index 8fcc8bed6f..084585920e 100644 --- a/lib/routes/bjp/apod.ts +++ b/lib/routes/bjp/apod.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import { ViewType } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; @@ -42,20 +42,20 @@ async function handler(ctx) { const list = $('td[align=left] b') .toArray() - .map((e) => { - e = $(e); + .map((e): DataItem => { + const $e = $(e); return { - title: e.find('a').attr('title'), - link: `${baseUrl}${e.find('a').attr('href')}`, - pubDate: timezone(parseDate(e.find('span').text().replace(':', ''), 'YYYY-MM-DD'), 8), + title: $e.find('a').attr('title')!, + link: `${baseUrl}${$e.find('a').attr('href')}`, + pubDate: timezone(parseDate($e.find('span').text().replace(':', ''), 'YYYY-MM-DD'), 8), }; }) - .toSorted((a, b) => b.pubDate - a.pubDate) + .toSorted((a, b) => Number(b.pubDate) - Number(a.pubDate)) .slice(0, ctx.req.query('limit') ? Number(ctx.req.query('limit')) : 10); const items = await Promise.all( list.map((e) => - cache.tryGet(e.link, async () => { + cache.tryGet(e.link!, async () => { const { data } = await got.get(e.link); const $ = load(data); diff --git a/lib/routes/bjsk/index.ts b/lib/routes/bjsk/index.ts index e5deceeea0..4ae39a1793 100644 --- a/lib/routes/bjsk/index.ts +++ b/lib/routes/bjsk/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -38,24 +38,24 @@ async function handler(ctx) { const list = $('.article-list a') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.attr('title'), - link: `${baseUrl}${item.attr('href')}`, - pubDate: parseDate(item.find('.time').text(), 'YYYY.MM.DD'), + title: $item.attr('title')!, + link: `${baseUrl}${$item.attr('href')}`, + pubDate: parseDate($item.find('.time').text(), 'YYYY.MM.DD'), }; }); const items = await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const { data: response } = await got(item.link); const $ = load(response); item.description = $('.article-main').html(); item.author = $('.info') .text() - .match(/作者:(.*?)来源/)[1] + .match(/作者:(.*?)来源/)![1] .trim(); return item; }) diff --git a/lib/routes/bjsk/keti.ts b/lib/routes/bjsk/keti.ts index ea706b6f66..f11a475a0e 100644 --- a/lib/routes/bjsk/keti.ts +++ b/lib/routes/bjsk/keti.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -49,19 +49,19 @@ async function handler(ctx) { let items = $('a.news') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('.zizizi').text(), - link: `${rootUrl}${item.attr('href')}`, - pubDate: parseDate(item.find('.date').text()), + title: $item.find('.zizizi').text(), + link: `${rootUrl}${$item.attr('href')}`, + pubDate: parseDate($item.find('.date').text()), }; }); items = await Promise.all( items.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const detailResponse = await got({ method: 'get', url: item.link, diff --git a/lib/routes/bjwxdxh/index.ts b/lib/routes/bjwxdxh/index.ts index 5b7a58cfe1..eafa3f7ffa 100644 --- a/lib/routes/bjwxdxh/index.ts +++ b/lib/routes/bjwxdxh/index.ts @@ -1,6 +1,6 @@ import { load } from 'cheerio'; -import type { Route } from '@/types'; +import type { DataItem, Route } from '@/types'; import cache from '@/utils/cache'; import got from '@/utils/got'; import { parseDate } from '@/utils/parse-date'; @@ -40,18 +40,18 @@ async function handler(ctx) { const $ = load(response.data); const list = $('div#newsquery > ul > li') .toArray() - .map((item) => { - item = $(item); + .map((item): DataItem => { + const $item = $(item); return { - title: item.find('div.title > a').text(), - link: new URL(item.find('div.title > a').attr('href'), baseUrl).href, + title: $item.find('div.title > a').text(), + link: new URL($item.find('div.title > a').attr('href')!, baseUrl).href, // pubDate: parseDate(item.find('div.time').text(), 'YYYY-MM-DD'), }; }); await Promise.all( list.map((item) => - cache.tryGet(item.link, async () => { + cache.tryGet(item.link!, async () => { const response = await got({ method: 'get', url: item.link, @@ -60,9 +60,9 @@ async function handler(ctx) { const info = content('div.info') .text() .match(/作者:(\S*)\s+发布于:(\S*\s+.*?)\s/); - item.author = info[1]; - item.pubDate = timezone(parseDate(info[2], 'YYYY-MM-DD HH:mm:ss'), 8); - item.description = content('div#con').html().replaceAll('\n', ''); + item.author = info![1]; + item.pubDate = timezone(parseDate(info![2], 'YYYY-MM-DD HH:mm:ss'), 8); + item.description = content('div#con').html()!.replaceAll('\n', ''); return item; }) ) diff --git a/lib/routes/bjx/huanbao.ts b/lib/routes/bjx/huanbao.ts index 33ff748fcf..eaf3f6b82c 100644 --- a/lib/routes/bjx/huanbao.ts +++ b/lib/routes/bjx/huanbao.ts @@ -1,3 +1,4 @@ +import type { CheerioAPI } from 'cheerio'; import { load } from 'cheerio'; import pMap from 'p-map'; @@ -39,11 +40,11 @@ async function handler() { let items = $('.cc-layout-3 .cc-list-content li') .toArray() .map((e) => { - e = $(e); + const $e = $(e); return { - title: e.find('a').attr('title'), - link: e.find('a').attr('href'), - pubDate: parseDate(e.find('span').text()), + title: $e.find('a').attr('title')!, + link: $e.find('a').attr('href'), + pubDate: parseDate($e.find('span').text()), }; }); @@ -64,7 +65,7 @@ async function handler() { const fetchPage = (link) => cache.tryGet(link, async () => { // 可能一篇文章过长会分成多页 - const pages = []; + const pages: CheerioAPI[] = []; const result = await got(link); const $page = load(result.data); @@ -79,7 +80,7 @@ const fetchPage = (link) => if (!/^\d+$/.test($a.text().trim())) { continue; } - const sublink = new URL($a.attr('href'), link).href; + const sublink = new URL($a.attr('href')!, link).href; /* eslint-disable no-await-in-loop */ const result = await got(sublink); pages.push(load(result.data)); diff --git a/lib/routes/bjx/types.ts b/lib/routes/bjx/types.ts index 3dd8f58c99..597bfcfedc 100644 --- a/lib/routes/bjx/types.ts +++ b/lib/routes/bjx/types.ts @@ -42,12 +42,12 @@ async function handler(ctx) { description: $('meta[name="Description"]').attr('content'), link: `https://guangfu.bjx.com.cn/${type}/`, item: list.toArray().map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('a').attr('title'), - description: item.html(), - link: item.find('a').attr('href'), - pubDate: parseDate(item.find('span').text()), + title: $item.find('a').attr('title')!, + description: $item.html(), + link: $item.find('a').attr('href'), + pubDate: parseDate($item.find('span').text()), }; }), }; diff --git a/lib/routes/blizzard/news-cn.ts b/lib/routes/blizzard/news-cn.ts index e0d38c71c3..bb2e468467 100644 --- a/lib/routes/blizzard/news-cn.ts +++ b/lib/routes/blizzard/news-cn.ts @@ -52,39 +52,39 @@ const parsers = { $('.list-data-container .list-item-container') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.content-title').text(), - link: item.find('.fill-link').attr('href'), - description: item.find('.content-intro').text(), - pubDate: parseDate(item.find('.content-date').text()), - image: item.find('.item-pic').attr('src'), + title: $item.find('.content-title').text(), + link: $item.find('.fill-link').attr('href'), + description: $item.find('.content-intro').text(), + pubDate: parseDate($item.find('.content-date').text()), + image: $item.find('.item-pic').attr('src'), }; }), hs: ($) => $('.article-container>a') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.title').text(), - link: item.attr('href'), - description: item.find('.desc').text(), - pubDate: parseDate(item.find('.date').attr('data-time')), - image: item.find('.article-img img').attr('src'), + title: $item.find('.title').text(), + link: $item.attr('href'), + description: $item.find('.desc').text(), + pubDate: parseDate($item.find('.date').attr('data-time')), + image: $item.find('.article-img img').attr('src'), }; }), wow: ($) => $('.Pane-list>a') .toArray() .map((item) => { - item = $(item); + const $item = $(item); return { - title: item.find('.list-title').text(), - link: item.attr('href'), - description: item.find('.list-desc').text(), - pubDate: parseDate(item.find('.list-time').attr('data-time')), - image: item.find('.img-box img').attr('src'), + title: $item.find('.list-title').text(), + link: $item.attr('href'), + description: $item.find('.list-desc').text(), + pubDate: parseDate($item.find('.list-time').attr('data-time')), + image: $item.find('.img-box img').attr('src'), }; }), }; diff --git a/lib/routes/blockworks/index.ts b/lib/routes/blockworks/index.ts index e09cac3115..341fa59166 100644 --- a/lib/routes/blockworks/index.ts +++ b/lib/routes/blockworks/index.ts @@ -44,10 +44,7 @@ async function handler(ctx): Promise { const items = await Promise.all( limitedItems - .map((item) => ({ - ...item, - link: item.link?.split('?', 1)[0], - })) + .map((item) => ({ ...item, link: item.link?.split('?', 1)[0] }) as typeof item & { author?: DataItem['author'] }) .map((item) => cache.tryGet(item.link!, async () => { // Get cached content or fetch new content diff --git a/lib/routes/blogread/index.ts b/lib/routes/blogread/index.ts index 8ccfff9c0a..c6bd77640d 100644 --- a/lib/routes/blogread/index.ts +++ b/lib/routes/blogread/index.ts @@ -27,14 +27,14 @@ async function handler() { const resultItem = $('.media') .toArray() .map((elem) => { - elem = $(elem); - const $link = elem.find('dt a'); + const $elem = $(elem); + const $link = $elem.find('dt a'); return { title: $link.text(), - description: elem.find('dd').eq(0).text(), + description: $elem.find('dd').eq(0).text(), link: $link.attr('href'), - author: elem.find('.small a').eq(0).text(), - pubDate: elem.find('dd').eq(1).text().split('\n', 3)[2], + author: $elem.find('.small a').eq(0).text(), + pubDate: $elem.find('dd').eq(1).text().split('\n', 3)[2], }; }); return { diff --git a/lib/routes/bloomberg/authors.ts b/lib/routes/bloomberg/authors.ts index bcee63b7f8..a3ae76bcc8 100644 --- a/lib/routes/bloomberg/authors.ts +++ b/lib/routes/bloomberg/authors.ts @@ -1,7 +1,7 @@ import { load } from 'cheerio'; import pMap from 'p-map'; -import type { Route } from '@/types'; +import type { Language, Route } from '@/types'; import { ViewType } from '@/types'; import ofetch from '@/utils/ofetch'; import rssParser from '@/utils/rss-parser'; @@ -19,13 +19,13 @@ const parseAuthorNewsList = async (slug) => { const $ = load(resp.html); const articles = $('article.story-list-story'); return articles.toArray().map((item) => { - item = $(item); - const headline = item.find('a.story-list-story__info__headline-link'); + const $item = $(item); + const headline = $item.find('a.story-list-story__info__headline-link'); return { title: headline.text(), - pubDate: item.attr('data-updated-at'), - guid: `bloomberg:${item.attr('data-id')}`, - link: new URL(headline.attr('href'), baseURL).href, + pubDate: $item.attr('data-updated-at'), + guid: `bloomberg:${$item.attr('data-id')}`, + link: new URL(headline.attr('href')!, baseURL).href, }; }); }; @@ -59,7 +59,7 @@ async function handler(ctx) { const { id, slug, source } = ctx.req.param(); const link = `https://www.bloomberg.com/authors/${id}/${slug}`; - let list = []; + let list: any[] = []; if (!source || source === 'api') { list = await parseAuthorNewsList(`${id}/${slug}`); } @@ -74,7 +74,7 @@ async function handler(ctx) { return { title: `Bloomberg - ${authorName}`, link, - language: 'en-us', + language: 'en-us' as Language, item, }; } diff --git a/lib/routes/bloomberg/templates/lede-media.tsx b/lib/routes/bloomberg/templates/lede-media.tsx index fe8238bc24..296a938aa9 100644 --- a/lib/routes/bloomberg/templates/lede-media.tsx +++ b/lib/routes/bloomberg/templates/lede-media.tsx @@ -3,7 +3,7 @@ import { renderToString } from 'hono/jsx/dom/server'; import { renderVideoMedia } from './video-media'; -type LedeMedia = { +export type LedeMedia = { kind?: string; src?: string; description?: string; diff --git a/lib/routes/bloomberg/templates/video-media.tsx b/lib/routes/bloomberg/templates/video-media.tsx index 8b8b7a1471..8475b4f199 100644 --- a/lib/routes/bloomberg/templates/video-media.tsx +++ b/lib/routes/bloomberg/templates/video-media.tsx @@ -13,7 +13,7 @@ export const renderVideoMedia = ({ stream, mp4, coverUrl, caption }: VideoMediaD