rsshub 1.0.0-master.f9ec483 → 1.0.0-master.fa1dcc5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/config.ts +42 -1
- package/lib/middleware/access-control.ts +3 -3
- package/lib/middleware/cache.ts +5 -3
- package/lib/middleware/template.test.ts +6 -0
- package/lib/middleware/template.tsx +3 -1
- package/lib/router.js +0 -6
- package/lib/routes/141jav/index.ts +1 -1
- package/lib/routes/141ppv/index.ts +1 -1
- package/lib/routes/36kr/hot-list.ts +1 -1
- package/lib/routes/36kr/index.ts +1 -1
- package/lib/routes/78dm/index.ts +429 -43
- package/lib/routes/78dm/namespace.ts +2 -0
- package/lib/routes/78dm/templates/description.art +17 -0
- package/lib/routes/abc/index.ts +10 -9
- package/lib/routes/aeon/category.ts +1 -1
- package/lib/routes/aeon/type.ts +1 -1
- package/lib/routes/afr/latest.ts +69 -0
- package/lib/routes/afr/namespace.ts +7 -0
- package/lib/routes/afr/navigation.ts +75 -0
- package/lib/routes/afr/query.ts +349 -0
- package/lib/routes/afr/utils.ts +80 -0
- package/lib/routes/aibase/discover.ts +1 -1
- package/lib/routes/aibase/news.ts +1 -1
- package/lib/routes/aibase/topic.ts +1 -1
- package/lib/routes/air-level/index.ts +49 -0
- package/lib/routes/air-level/levelrank.ts +65 -0
- package/lib/routes/air-level/namespace.ts +12 -0
- package/lib/routes/ajcass/namespace.ts +11 -0
- package/lib/routes/ajcass/shxyj.ts +73 -0
- package/lib/routes/alpinelinux/pkgs.ts +2 -2
- package/lib/routes/anime1/anime.ts +1 -1
- package/lib/routes/apnews/utils.ts +6 -2
- package/lib/routes/appleinsider/index.ts +1 -1
- package/lib/routes/aqara/region.ts +1 -1
- package/lib/routes/asus/bios.ts +0 -1
- package/lib/routes/baoyu/index.ts +57 -0
- package/lib/routes/baoyu/namespace.ts +8 -0
- package/lib/routes/bilibili/article.ts +37 -14
- package/lib/routes/bilibili/dynamic.ts +15 -7
- package/lib/routes/bilibili/followings-dynamic.ts +2 -2
- package/lib/routes/bilibili/manga-update.ts +3 -0
- package/lib/routes/bilibili/ranking.ts +188 -117
- package/lib/routes/bilibili/reply.ts +2 -0
- package/lib/routes/bilibili/templates/description.art +2 -0
- package/lib/routes/bing/daily-wallpaper.ts +5 -1
- package/lib/routes/bsky/posts.ts +0 -1
- package/lib/routes/bsky/templates/post.art +8 -1
- package/lib/routes/buaa/lib/space/newbook.ts +1 -1
- package/lib/routes/c114/namespace.ts +2 -0
- package/lib/routes/c114/roll.ts +71 -42
- package/lib/routes/cags/edu/index.ts +84 -0
- package/lib/routes/cags/namespace.ts +9 -0
- package/lib/routes/caixin/article.ts +1 -1
- package/lib/routes/caixin/blog.ts +2 -3
- package/lib/routes/caixin/category.ts +1 -1
- package/lib/routes/caixin/latest.ts +12 -16
- package/lib/routes/caixin/namespace.ts +1 -1
- package/lib/routes/caixin/utils-fulltext.ts +51 -0
- package/lib/routes/caixin/utils.ts +37 -37
- package/lib/routes/cara/likes.ts +1 -1
- package/lib/routes/cara/portfolio.ts +1 -1
- package/lib/routes/cara/timeline.ts +1 -1
- package/lib/routes/ccfa/index.ts +11 -11
- package/lib/routes/chub/characters.ts +1 -1
- package/lib/routes/cnbeta/namespace.ts +1 -1
- package/lib/routes/cngold/index.ts +195 -0
- package/lib/routes/cngold/namespace.ts +9 -0
- package/lib/routes/cnki/author.ts +120 -48
- package/lib/routes/cnki/utils.ts +4 -4
- package/lib/routes/coomer/artist.ts +1 -1
- package/lib/routes/coomer/namespace.ts +1 -1
- package/lib/routes/coomer/posts.ts +2 -2
- package/lib/routes/coomer/utils.ts +1 -1
- package/lib/routes/cpcaauto/index.ts +22 -22
- package/lib/routes/cs/zzkx.ts +1 -1
- package/lib/routes/csdn/blog.ts +17 -13
- package/lib/routes/cybersecurityventures/namespace.ts +7 -0
- package/lib/routes/cybersecurityventures/news.ts +121 -0
- package/lib/routes/cybersecurityventures/types.ts +17 -0
- package/lib/routes/daily/discussed.ts +22 -21
- package/lib/routes/daily/index.ts +14 -11
- package/lib/routes/daily/namespace.ts +1 -1
- package/lib/routes/daily/source.ts +186 -0
- package/lib/routes/daily/upvoted.ts +17 -17
- package/lib/routes/daily/user.ts +6 -23
- package/lib/routes/daily/utils.ts +27 -32
- package/lib/routes/dataguidance/index.ts +19 -30
- package/lib/routes/dcfever/news.ts +1 -1
- package/lib/routes/dcfever/reviews.ts +1 -1
- package/lib/routes/dcfever/trading-search.ts +1 -1
- package/lib/routes/dcfever/trading.ts +1 -1
- package/lib/routes/deeplearning/namespace.ts +3 -1
- package/lib/routes/deeplearning/templates/description.art +21 -0
- package/lib/routes/deeplearning/the-batch.ts +296 -0
- package/lib/routes/deepmind/blog.ts +1 -1
- package/lib/routes/digitalcameraworld/news.ts +1 -1
- package/lib/routes/discord/discord-api.ts +44 -2
- package/lib/routes/discord/search.ts +106 -0
- package/lib/routes/dn/news.ts +1 -1
- package/lib/routes/dockerhub/repositories.ts +42 -0
- package/lib/routes/dongqiudi/daily.ts +1 -1
- package/lib/routes/dw/namespace.ts +6 -0
- package/lib/routes/dw/news.ts +89 -0
- package/lib/routes/dw/rss.ts +62 -0
- package/lib/routes/dw/templates/description.art +23 -0
- package/lib/routes/dw/templates/liveblog.art +13 -0
- package/lib/routes/dw/templates/video.art +14 -0
- package/lib/routes/dw/utils.ts +172 -0
- package/lib/routes/ecnu/jwc.ts +5 -1
- package/lib/routes/espn/news.ts +1 -1
- package/lib/routes/fashionnetwork/namespace.ts +1 -1
- package/lib/routes/flyert/forum.ts +99 -0
- package/lib/routes/flyert/namespace.ts +1 -0
- package/lib/routes/flyert/templates/description.art +21 -0
- package/lib/routes/flyert/util.ts +188 -0
- package/lib/routes/follow/profile.ts +2 -2
- package/lib/routes/foresightnews/article.ts +1 -1
- package/lib/routes/foresightnews/column.ts +1 -1
- package/lib/routes/foresightnews/index.ts +3 -1
- package/lib/routes/foresightnews/news.ts +1 -1
- package/lib/routes/freecomputerbooks/index.ts +0 -10
- package/lib/routes/ftm/index.ts +1 -1
- package/lib/routes/furaffinity/art.ts +85 -0
- package/lib/routes/furaffinity/browse.ts +58 -0
- package/lib/routes/furaffinity/commissions.ts +55 -0
- package/lib/routes/furaffinity/home.ts +80 -0
- package/lib/routes/furaffinity/journal-comments.ts +64 -0
- package/lib/routes/furaffinity/journals.ts +56 -0
- package/lib/routes/furaffinity/namespace.ts +7 -0
- package/lib/routes/furaffinity/search.ts +72 -0
- package/lib/routes/furaffinity/shouts.ts +56 -0
- package/lib/routes/furaffinity/status.ts +58 -0
- package/lib/routes/furaffinity/submission-comments.ts +64 -0
- package/lib/{routes-deprecated/furaffinity/user.js → routes/furaffinity/user.ts} +53 -41
- package/lib/routes/furaffinity/watchers.ts +62 -0
- package/lib/routes/furaffinity/watching.ts +62 -0
- package/lib/routes/google/developers.ts +71 -0
- package/lib/routes/google/news.ts +26 -6
- package/lib/routes/gov/cbirc/index.ts +35 -35
- package/lib/routes/hamel/index.ts +81 -0
- package/lib/routes/hamel/namespace.ts +7 -0
- package/lib/routes/hellogithub/volume.ts +3 -0
- package/lib/routes/hket/index.ts +13 -1
- package/lib/routes/hostmonit/cloudflareyesv6.ts +1 -1
- package/lib/routes/hrbeu/sec/list.ts +80 -0
- package/lib/routes/hrbust/jwzx.ts +6 -0
- package/lib/routes/hunau/gfxy/index.ts +1 -1
- package/lib/routes/hunau/ied.ts +1 -1
- package/lib/routes/hunau/jwc.ts +1 -1
- package/lib/routes/hunau/xky/index.ts +1 -1
- package/lib/routes/hust/gs.ts +4 -3
- package/lib/routes/idolmaster/namespace.ts +7 -0
- package/lib/routes/idolmaster/news.ts +112 -0
- package/lib/routes/ieee/author.ts +95 -0
- package/lib/routes/ikea/cn/low-price.ts +2 -1
- package/lib/routes/imdb/chart.ts +1 -1
- package/lib/routes/inspirehep/author.ts +9 -1
- package/lib/routes/isct/namespace.ts +11 -0
- package/lib/routes/isct/news.ts +66 -0
- package/lib/routes/javtrailers/casts.ts +41 -0
- package/lib/routes/javtrailers/categories.ts +40 -0
- package/lib/routes/javtrailers/namespace.ts +7 -0
- package/lib/routes/javtrailers/studios.ts +39 -0
- package/lib/routes/javtrailers/templates/description.art +31 -0
- package/lib/routes/javtrailers/types.ts +59 -0
- package/lib/routes/javtrailers/utils.ts +48 -0
- package/lib/routes/jiemian/list.ts +1 -1
- package/lib/routes/jiuyangongshe/community.ts +1 -1
- package/lib/routes/jlu/phy/index.ts +55 -0
- package/lib/routes/joins/chinese.ts +13 -13
- package/lib/routes/kcna/news.ts +7 -5
- package/lib/routes/keep/user.ts +1 -1
- package/lib/routes/langchain/index.ts +74 -0
- package/lib/routes/langchain/namespace.ts +7 -0
- package/lib/routes/last-origin/namespace.ts +7 -0
- package/lib/routes/last-origin/news.ts +65 -0
- package/lib/routes/linkresearcher/index.ts +108 -46
- package/lib/routes/linkresearcher/namespace.ts +8 -2
- package/lib/routes/linkresearcher/templates/bilingual.art +7 -0
- package/lib/routes/linkresearcher/types.ts +103 -0
- package/lib/routes/liulinblog/itnews.ts +1 -1
- package/lib/routes/lofter/collection.ts +1 -1
- package/lib/routes/lofter/tag.ts +1 -1
- package/lib/routes/logrocket/index.ts +71 -0
- package/lib/routes/logrocket/namespace.ts +7 -0
- package/lib/routes/m-78/namespace.ts +7 -0
- package/lib/routes/m-78/news.ts +115 -0
- package/lib/routes/m-78/types.ts +13 -0
- package/lib/routes/mastodon/account-id.ts +1 -1
- package/lib/routes/mastodon/acct.ts +1 -1
- package/lib/routes/mastodon/timeline-local.ts +2 -2
- package/lib/routes/mastodon/timeline-remote.ts +2 -2
- package/lib/routes/mastodon/utils.ts +1 -1
- package/lib/routes/metacritic/index.ts +1 -1
- package/lib/routes/mi/utils.ts +1 -1
- package/lib/routes/mihoyo/bbs/official.ts +2 -1
- package/lib/routes/misskey/utils.ts +19 -1
- package/lib/routes/mittrchina/index.ts +2 -2
- package/lib/routes/natgeo/natgeo.ts +25 -24
- package/lib/routes/nbd/daily.ts +1 -1
- package/lib/routes/nielsberglund/index.ts +78 -0
- package/lib/routes/nielsberglund/namespace.ts +7 -0
- package/lib/routes/nytimes/rss.ts +57 -0
- package/lib/routes/openrice/chart.ts +68 -0
- package/lib/routes/openrice/templates/chart.art +9 -0
- package/lib/routes/openrice/voting.ts +84 -0
- package/lib/routes/oschina/news.ts +26 -7
- package/lib/routes/patreon/feed.ts +126 -0
- package/lib/routes/patreon/namespace.ts +7 -0
- package/lib/routes/patreon/templates/description.art +39 -0
- package/lib/routes/patreon/types.ts +387 -0
- package/lib/routes/pixiv/api/get-illust-detail.ts +22 -0
- package/lib/routes/pixiv/novel-api/content/nsfw.ts +73 -0
- package/lib/routes/pixiv/novel-api/content/sfw.ts +63 -0
- package/lib/routes/pixiv/novel-api/content/types.ts +254 -0
- package/lib/routes/pixiv/novel-api/content/utils.ts +133 -0
- package/lib/routes/pixiv/novel-api/series/nsfw.ts +84 -0
- package/lib/routes/pixiv/novel-api/series/sfw.ts +70 -0
- package/lib/routes/pixiv/novel-api/series/types.ts +94 -0
- package/lib/routes/pixiv/novel-api/user-novels/nsfw.ts +82 -0
- package/lib/routes/pixiv/novel-api/user-novels/sfw.ts +74 -0
- package/lib/routes/pixiv/novel-api/user-novels/types.ts +133 -0
- package/lib/routes/pixiv/novel-series.ts +52 -0
- package/lib/routes/pixiv/novels.ts +69 -44
- package/lib/routes/pixiv/utils.ts +3 -0
- package/lib/routes/plurk/anonymous.ts +1 -1
- package/lib/routes/plurk/hotlinks.ts +1 -1
- package/lib/routes/plurk/news.ts +1 -1
- package/lib/routes/plurk/search.ts +1 -1
- package/lib/routes/qstheory/index.ts +121 -0
- package/lib/routes/qstheory/magazine.ts +64 -0
- package/lib/routes/qstheory/namespace.ts +7 -0
- package/lib/routes/qstheory/utils.ts +25 -0
- package/lib/routes/ruc/ai.ts +1 -1
- package/lib/routes/scmp/coronavirus.ts +1 -1
- package/lib/routes/scu/jwc/tzgg.ts +75 -0
- package/lib/routes/scu/namespace.ts +7 -0
- package/lib/routes/scu/scupi/_utils.ts +62 -0
- package/lib/routes/scu/scupi/notice.ts +41 -0
- package/lib/routes/solidot/namespace.ts +1 -1
- package/lib/routes/stbu/jsjxy.ts +4 -1
- package/lib/routes/steam/search.ts +7 -0
- package/lib/routes/sycl/feeds.ts +1 -1
- package/lib/routes/syosetu/dev.ts +67 -0
- package/lib/routes/syosetu/index.ts +85 -0
- package/lib/routes/syosetu/namespace.ts +2 -2
- package/lib/routes/syosetu/ranking-isekai.ts +93 -0
- package/lib/routes/syosetu/ranking-r18.ts +192 -0
- package/lib/routes/syosetu/ranking.ts +285 -0
- package/lib/routes/syosetu/search.ts +161 -0
- package/lib/routes/syosetu/templates/description.art +73 -0
- package/lib/routes/syosetu/types/ranking-r18.ts +60 -0
- package/lib/routes/syosetu/types/ranking.ts +67 -0
- package/lib/routes/syosetu/types/search.ts +138 -0
- package/lib/routes/syosetu/utils.ts +50 -0
- package/lib/routes/telegram/channel.ts +31 -1
- package/lib/routes/telegram/scripts/get-telegram-session.mjs +16 -6
- package/lib/routes/telegram/stickerpack.ts +1 -1
- package/lib/routes/telegram/tglib/channel.ts +12 -9
- package/lib/routes/telegram/tglib/client.ts +13 -9
- package/lib/routes/test/index.ts +4 -0
- package/lib/routes/theblockbeats/index.ts +1 -1
- package/lib/routes/thegradient/index.ts +80 -0
- package/lib/routes/thegradient/namespace.ts +7 -0
- package/lib/routes/theinitium/app.ts +4 -0
- package/lib/routes/thepaper/channel.ts +1 -1
- package/lib/routes/thepaper/factpaper.ts +1 -1
- package/lib/routes/thepaper/featured.ts +1 -1
- package/lib/routes/thepaper/list.ts +1 -1
- package/lib/routes/thepaper/user.ts +174 -0
- package/lib/routes/tongji/sem/_utils.ts +65 -0
- package/lib/routes/tongji/sem/notice.ts +58 -0
- package/lib/routes/toutiao/a-bogus.ts +540 -0
- package/lib/routes/toutiao/namespace.ts +7 -0
- package/lib/routes/toutiao/templates/video.art +7 -0
- package/lib/routes/toutiao/types.ts +443 -0
- package/lib/routes/toutiao/user.ts +127 -0
- package/lib/routes/twitter/api/mobile-api/api.ts +8 -0
- package/lib/routes/twitter/api/web-api/utils.ts +21 -9
- package/lib/routes/twitter/namespace.ts +1 -0
- package/lib/routes/twitter/utils.ts +7 -1
- package/lib/routes/vertikal/latest.ts +73 -0
- package/lib/routes/vertikal/namespace.ts +7 -0
- package/lib/routes/vice/topic.ts +1 -1
- package/lib/routes/vocus/publication.ts +1 -1
- package/lib/routes/vocus/user.ts +1 -1
- package/lib/routes/wallstreetcn/calendar.ts +90 -0
- package/lib/routes/wallstreetcn/hot.ts +2 -2
- package/lib/routes/wallstreetcn/live.ts +1 -1
- package/lib/routes/wallstreetcn/news.ts +5 -3
- package/lib/routes/weibo/timeline.ts +3 -2
- package/lib/routes/wellcee/rent.ts +1 -1
- package/lib/routes/wufazhuce/namespace.ts +7 -0
- package/lib/routes/wufazhuce/one.ts +90 -0
- package/lib/routes/xiaoheihe/discount.ts +72 -28
- package/lib/routes/xiaohongshu/user.ts +40 -3
- package/lib/routes/xiaohongshu/util.ts +112 -105
- package/lib/routes/xsijishe/rank.ts +33 -7
- package/lib/routes/xueqiu/cookies.ts +13 -18
- package/lib/routes/yahoo/news/listid.ts +4 -1
- package/lib/routes/yahoo/news/provider-helper.ts +4 -1
- package/lib/routes/yahoo/news/provider.ts +4 -1
- package/lib/routes/yande/post.ts +13 -3
- package/lib/routes/youtube/user.ts +37 -25
- package/lib/routes/zhonglun/index.ts +5 -6
- package/lib/routes/zjut/cs/index.ts +1 -1
- package/lib/utils/got.ts +2 -1
- package/lib/utils/helpers.test.ts +13 -1
- package/lib/utils/helpers.ts +10 -0
- package/lib/utils/ofetch.ts +3 -0
- package/lib/utils/request-rewriter/fetch.test.ts +94 -0
- package/lib/utils/request-rewriter/fetch.ts +14 -1
- package/lib/views/error.tsx +1 -1
- package/package.json +40 -37
- package/lib/routes/78dm/templates/image.art +0 -1
- package/lib/routes/deeplearning/thebatch.ts +0 -74
- package/lib/routes/syosetu/chapter.ts +0 -87
- package/lib/routes/xiaohongshu/notes.ts +0 -39
- package/lib/routes-deprecated/furaffinity/browse.js +0 -44
- package/lib/routes-deprecated/furaffinity/commissions.js +0 -39
- package/lib/routes-deprecated/furaffinity/favorites.js +0 -56
- package/lib/routes-deprecated/furaffinity/gallery.js +0 -56
- package/lib/routes-deprecated/furaffinity/home.js +0 -72
- package/lib/routes-deprecated/furaffinity/journal-comments.js +0 -50
- package/lib/routes-deprecated/furaffinity/journals.js +0 -49
- package/lib/routes-deprecated/furaffinity/scraps.js +0 -56
- package/lib/routes-deprecated/furaffinity/search.js +0 -56
- package/lib/routes-deprecated/furaffinity/shouts.js +0 -40
- package/lib/routes-deprecated/furaffinity/status.js +0 -38
- package/lib/routes-deprecated/furaffinity/submission-comments.js +0 -50
- package/lib/routes-deprecated/furaffinity/watchers.js +0 -47
- package/lib/routes-deprecated/furaffinity/watching.js +0 -47
- package/lib/routes-deprecated/ieee/author.js +0 -30
- package/lib/routes-deprecated/qstheory/index.js +0 -122
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { type Data, type Route, ViewType } from '@/types';
|
|
2
|
+
import ofetch from '@/utils/ofetch';
|
|
3
|
+
import type { Context } from 'hono';
|
|
4
|
+
import type { Post } from './types';
|
|
5
|
+
import { parseDate } from '@/utils/parse-date';
|
|
6
|
+
import { load } from 'cheerio';
|
|
7
|
+
import InvalidParameterError from '@/errors/types/invalid-parameter';
|
|
8
|
+
|
|
9
|
+
export const route: Route = {
|
|
10
|
+
name: 'ニュース',
|
|
11
|
+
categories: ['anime'],
|
|
12
|
+
path: '/news/:category?',
|
|
13
|
+
example: '/m-78/news',
|
|
14
|
+
radar: [
|
|
15
|
+
{
|
|
16
|
+
source: ['m-78.jp/news'],
|
|
17
|
+
target: '/news',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
source: ['m-78.jp/news/category/:category'],
|
|
21
|
+
target: '/news/:category',
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
parameters: {
|
|
25
|
+
category: {
|
|
26
|
+
description: 'news category',
|
|
27
|
+
default: 'news',
|
|
28
|
+
options: [
|
|
29
|
+
{
|
|
30
|
+
value: 'news',
|
|
31
|
+
label: 'ニュース',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
value: 'streaming',
|
|
35
|
+
label: '動画配信',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
value: 'event',
|
|
39
|
+
label: 'イベント',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
value: 'onair',
|
|
43
|
+
label: '放送',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
value: 'broadcast',
|
|
47
|
+
label: '放送/配信',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
value: 'goods',
|
|
51
|
+
label: 'グッズ',
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
value: 'ultraman-cardgame',
|
|
55
|
+
label: 'ウルトラマン カードゲーム',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
value: 'shop',
|
|
59
|
+
label: 'ショップ',
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
value: 'blu-ray_dvd',
|
|
63
|
+
label: 'Blu-ray・DVD',
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
value: 'digital',
|
|
67
|
+
label: 'デジタル',
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
handler,
|
|
73
|
+
maintainers: ['KarasuShin'],
|
|
74
|
+
features: {
|
|
75
|
+
supportRadar: true,
|
|
76
|
+
},
|
|
77
|
+
view: ViewType.Articles,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
async function handler(ctx: Context): Promise<Data> {
|
|
81
|
+
const rootUrl = 'https://m-78.jp';
|
|
82
|
+
const cateAPIUrl = `${rootUrl}/wp-json/wp/v2/categories`;
|
|
83
|
+
const postsAPIUrl = `${rootUrl}/wp-json/wp/v2/posts`;
|
|
84
|
+
const category = ctx.req.param('category') ?? 'news';
|
|
85
|
+
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')!, 10) : 20;
|
|
86
|
+
|
|
87
|
+
const categories = await ofetch(`${cateAPIUrl}?slug=${category}`);
|
|
88
|
+
if (categories.length === 0) {
|
|
89
|
+
throw new InvalidParameterError('Category not found');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { id: categoryId, link: categoryLink, name: categoryName } = categories[0];
|
|
93
|
+
|
|
94
|
+
const posts = await ofetch<Post[]>(`${postsAPIUrl}?categories=${categoryId}&per_page=${limit}`);
|
|
95
|
+
return {
|
|
96
|
+
title: `${categoryName} | ニュース`,
|
|
97
|
+
link: categoryLink,
|
|
98
|
+
item: posts.map((post) => {
|
|
99
|
+
const $ = load(post.content.rendered, null, false);
|
|
100
|
+
$('#ez-toc-container').remove();
|
|
101
|
+
$('img').each((_, img) => {
|
|
102
|
+
if (/wp-content\/uploads/.test(img.attribs.src)) {
|
|
103
|
+
img.attribs.src = img.attribs.src.replace(/(-\d+x\d+)/, '');
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
title: post.title.rendered,
|
|
108
|
+
link: post.link,
|
|
109
|
+
description: $.html(),
|
|
110
|
+
pubDate: parseDate(post.date_gmt),
|
|
111
|
+
updated: parseDate(post.modified_gmt),
|
|
112
|
+
};
|
|
113
|
+
}),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
@@ -36,7 +36,7 @@ export const route: Route = {
|
|
|
36
36
|
async function handler(ctx) {
|
|
37
37
|
const site = ctx.req.param('site');
|
|
38
38
|
const account_id = ctx.req.param('account_id');
|
|
39
|
-
const only_media = ctx.req.param('only_media') ? 'true' : 'false';
|
|
39
|
+
const only_media = ctx.req.param('only_media') === 'true' ? 'true' : 'false';
|
|
40
40
|
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
|
|
41
41
|
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
|
42
42
|
}
|
|
@@ -35,7 +35,7 @@ However, you can still specify these route-specific configurations if you need t
|
|
|
35
35
|
|
|
36
36
|
async function handler(ctx) {
|
|
37
37
|
const acct = ctx.req.param('acct');
|
|
38
|
-
const only_media = ctx.req.param('only_media') ? 'true' : 'false';
|
|
38
|
+
const only_media = ctx.req.param('only_media') === 'true' ? 'true' : 'false';
|
|
39
39
|
|
|
40
40
|
const { site, account_id } = await utils.getAccountIdByAcct(acct);
|
|
41
41
|
|
|
@@ -36,7 +36,7 @@ export const route: Route = {
|
|
|
36
36
|
|
|
37
37
|
async function handler(ctx) {
|
|
38
38
|
const site = ctx.req.param('site');
|
|
39
|
-
const only_media = ctx.req.param('only_media') ? 'true' : 'false';
|
|
39
|
+
const only_media = ctx.req.param('only_media') === 'true' ? 'true' : 'false';
|
|
40
40
|
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
|
|
41
41
|
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
|
42
42
|
}
|
|
@@ -47,7 +47,7 @@ async function handler(ctx) {
|
|
|
47
47
|
const list = response.data;
|
|
48
48
|
|
|
49
49
|
return {
|
|
50
|
-
title: `Local Public${ctx.req.param('only_media') ? ' Media' : ''} Timeline on ${site}`,
|
|
50
|
+
title: `Local Public${ctx.req.param('only_media') === 'true' ? ' Media' : ''} Timeline on ${site}`,
|
|
51
51
|
link: `https://${site}`,
|
|
52
52
|
item: utils.parseStatuses(list),
|
|
53
53
|
};
|
|
@@ -36,7 +36,7 @@ export const route: Route = {
|
|
|
36
36
|
|
|
37
37
|
async function handler(ctx) {
|
|
38
38
|
const site = ctx.req.param('site');
|
|
39
|
-
const only_media = ctx.req.param('only_media') ? 'true' : 'false';
|
|
39
|
+
const only_media = ctx.req.param('only_media') === 'true' ? 'true' : 'false';
|
|
40
40
|
if (!config.feature.allow_user_supply_unsafe_domain && !utils.allowSiteList.includes(site)) {
|
|
41
41
|
throw new ConfigNotFoundError(`This RSS is disabled unless 'ALLOW_USER_SUPPLY_UNSAFE_DOMAIN' is set to 'true'.`);
|
|
42
42
|
}
|
|
@@ -47,7 +47,7 @@ async function handler(ctx) {
|
|
|
47
47
|
const list = response.data;
|
|
48
48
|
|
|
49
49
|
return {
|
|
50
|
-
title: `Federated Public${ctx.req.param('only_media') ? ' Media' : ''} Timeline on ${site}`,
|
|
50
|
+
title: `Federated Public${ctx.req.param('only_media') === 'true' ? ' Media' : ''} Timeline on ${site}`,
|
|
51
51
|
link: `https://${site}`,
|
|
52
52
|
item: utils.parseStatuses(list),
|
|
53
53
|
};
|
|
@@ -4,7 +4,7 @@ import { parseDate } from '@/utils/parse-date';
|
|
|
4
4
|
import { config } from '@/config';
|
|
5
5
|
import ConfigNotFoundError from '@/errors/types/config-not-found';
|
|
6
6
|
|
|
7
|
-
const allowSiteList = ['mastodon.social', 'pawoo.net', config.mastodon.apiHost].filter(Boolean);
|
|
7
|
+
const allowSiteList = ['mastodon.social', 'pawoo.net', 'fosstodon.org', config.mastodon.apiHost].filter(Boolean);
|
|
8
8
|
|
|
9
9
|
const apiHeaders = (site) => {
|
|
10
10
|
const { accessToken, apiHost } = config.mastodon;
|
|
@@ -22,7 +22,7 @@ async function handler(ctx) {
|
|
|
22
22
|
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 50;
|
|
23
23
|
|
|
24
24
|
const rootUrl = 'https://www.metacritic.com';
|
|
25
|
-
const rootApiUrl = 'https://
|
|
25
|
+
const rootApiUrl = 'https://backend.metacritic.com';
|
|
26
26
|
const apiUrl = new URL('v1/xapi/finder/metacritic/web', rootApiUrl).href;
|
|
27
27
|
|
|
28
28
|
const currentUrlObject = new URL(`/browse/${type}/all/all/all-time/${sort}/${filter ? `?${filter}` : ''}`, rootUrl);
|
package/lib/routes/mi/utils.ts
CHANGED
|
@@ -9,7 +9,7 @@ import 'dayjs/locale/zh-cn';
|
|
|
9
9
|
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
|
10
10
|
import timezone from 'dayjs/plugin/timezone';
|
|
11
11
|
import utc from 'dayjs/plugin/utc';
|
|
12
|
-
import path from 'path';
|
|
12
|
+
import path from 'node:path';
|
|
13
13
|
import { CrowdfundingData, CrowdfundingDetailData, CrowdfundingDetailInfo, CrowdfundingItem, CrowdfundingList, DataResponse } from './types';
|
|
14
14
|
|
|
15
15
|
dayjs.extend(localizedFormat);
|
|
@@ -53,12 +53,13 @@ class MiHoYoOfficialError extends Error {
|
|
|
53
53
|
|
|
54
54
|
const getNewsList = async ({ gids, type, page_size, last_id }) => {
|
|
55
55
|
const query = new URLSearchParams({
|
|
56
|
+
client_type: '4',
|
|
56
57
|
gids,
|
|
57
58
|
type,
|
|
58
59
|
page_size,
|
|
59
60
|
last_id,
|
|
60
61
|
}).toString();
|
|
61
|
-
const url = `https://bbs-api.miyoushe.com/
|
|
62
|
+
const url = `https://bbs-api-static.miyoushe.com/painter/wapi/getNewsList?${query}`;
|
|
62
63
|
const response = await got({
|
|
63
64
|
method: 'get',
|
|
64
65
|
url,
|
|
@@ -38,7 +38,25 @@ const parseNotes = (data: MisskeyNote[], site: string) =>
|
|
|
38
38
|
title = `${author}: "${noteToUse.text ?? ''}"`;
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
/**
|
|
42
|
+
* For renotes from non-Misskey instances (e.g. Mastodon, Pleroma),
|
|
43
|
+
* we can't use noteToUse.id to link to the original note since:
|
|
44
|
+
* 1. The URL format differs from Misskey's /notes/{id} pattern
|
|
45
|
+
* 2. Direct access to the original note may not be possible
|
|
46
|
+
* Therefore, we link to the renote itself in such cases
|
|
47
|
+
*/
|
|
48
|
+
let noteId = noteToUse.id;
|
|
49
|
+
|
|
50
|
+
if (isRenote) {
|
|
51
|
+
const renoteHost = item.user.host ?? site;
|
|
52
|
+
const noteHost = noteToUse.user.host ?? site;
|
|
53
|
+
|
|
54
|
+
// Use renote's ID if the note is from a different host or not in allowSiteList
|
|
55
|
+
if (renoteHost !== noteHost || !allowSiteList.includes(noteHost)) {
|
|
56
|
+
noteId = item.id;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
const link = `https://${host}/notes/${noteId}`;
|
|
42
60
|
const pubDate = parseDate(noteToUse.createdAt);
|
|
43
61
|
|
|
44
62
|
return {
|
|
@@ -52,7 +52,7 @@ async function handler(ctx) {
|
|
|
52
52
|
const { type = 'index' } = ctx.req.param();
|
|
53
53
|
const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 10;
|
|
54
54
|
|
|
55
|
-
const link = `https://apii.mittrchina.com${typeMap[type].apiPath}`;
|
|
55
|
+
const link = `https://apii.web.mittrchina.com${typeMap[type].apiPath}`;
|
|
56
56
|
const { data: response } =
|
|
57
57
|
type === 'breaking'
|
|
58
58
|
? await got.post(link, {
|
|
@@ -95,7 +95,7 @@ async function handler(ctx) {
|
|
|
95
95
|
cache.tryGet(item.link, async () => {
|
|
96
96
|
const {
|
|
97
97
|
data: { data: details },
|
|
98
|
-
} = await got(`https://apii.mittrchina.com/information/details?id=${item.id}`);
|
|
98
|
+
} = await got(`https://apii.web.mittrchina.com/information/details?id=${item.id}`);
|
|
99
99
|
|
|
100
100
|
item.description = details.content;
|
|
101
101
|
|
|
@@ -1,29 +1,36 @@
|
|
|
1
1
|
import { Route } from '@/types';
|
|
2
2
|
import cache from '@/utils/cache';
|
|
3
3
|
import { load } from 'cheerio';
|
|
4
|
-
import
|
|
4
|
+
import ofetch from '@/utils/ofetch';
|
|
5
5
|
import { parseDate } from '@/utils/parse-date';
|
|
6
6
|
|
|
7
|
-
// https://www.natgeomedia.com
|
|
7
|
+
// https://www.natgeomedia.com/article/
|
|
8
8
|
|
|
9
9
|
async function loadContent(link) {
|
|
10
|
-
const
|
|
10
|
+
const data = await ofetch(link);
|
|
11
11
|
const $ = load(data);
|
|
12
12
|
const dtStr = $('.content-title-area')
|
|
13
13
|
.find('h6')
|
|
14
14
|
.first()
|
|
15
|
-
.
|
|
15
|
+
.text()
|
|
16
16
|
.replaceAll(/ /gi, ' ')
|
|
17
17
|
.trim();
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
$('.splide__arrows, .slide-control').remove();
|
|
20
|
+
|
|
21
|
+
let description = ($('article').eq(0).html() ?? '') + ($('article').eq(1).html() ?? '');
|
|
22
|
+
if (/photo|gallery/.test(link)) {
|
|
21
23
|
description = $('#content-album').html() + description;
|
|
22
24
|
}
|
|
23
25
|
return {
|
|
24
26
|
title: $('title').text(),
|
|
25
|
-
pubDate: parseDate(dtStr
|
|
27
|
+
pubDate: parseDate(dtStr),
|
|
26
28
|
description,
|
|
29
|
+
category: $('.content-tag a')
|
|
30
|
+
.toArray()
|
|
31
|
+
.map((i) => $(i).text()),
|
|
32
|
+
link,
|
|
33
|
+
image: $('link[rel="image_src"]').attr('href'),
|
|
27
34
|
};
|
|
28
35
|
}
|
|
29
36
|
|
|
@@ -42,8 +49,8 @@ export const route: Route = {
|
|
|
42
49
|
},
|
|
43
50
|
radar: [
|
|
44
51
|
{
|
|
45
|
-
source: ['natgeomedia.com/:cat/:type', 'natgeomedia.com/'],
|
|
46
|
-
target: '/:cat/:type',
|
|
52
|
+
source: ['natgeomedia.com/:cat/:type', 'natgeomedia.com/:cat/', 'natgeomedia.com/'],
|
|
53
|
+
target: '/:cat/:type?',
|
|
47
54
|
},
|
|
48
55
|
],
|
|
49
56
|
name: '分类',
|
|
@@ -54,29 +61,23 @@ export const route: Route = {
|
|
|
54
61
|
async function handler(ctx) {
|
|
55
62
|
const type = ctx.req.param('type') ?? '';
|
|
56
63
|
const url = `https://www.natgeomedia.com/${ctx.req.param('cat')}/${type}`;
|
|
57
|
-
const res = await
|
|
58
|
-
const $ = load(res
|
|
64
|
+
const res = await ofetch(url);
|
|
65
|
+
const $ = load(res);
|
|
59
66
|
|
|
60
|
-
const urlList = $('.article-link-
|
|
61
|
-
.find('.read-btn')
|
|
67
|
+
const urlList = $('.article-link-content h4')
|
|
62
68
|
.toArray()
|
|
63
69
|
.map((i) => ({
|
|
64
70
|
link: $(i).find('a[href]').first().attr('href'),
|
|
65
|
-
}))
|
|
71
|
+
}))
|
|
72
|
+
.filter((i) => i.link);
|
|
73
|
+
|
|
74
|
+
const out = await Promise.all(urlList.map((i) => cache.tryGet(i.link!, () => loadContent(i.link))));
|
|
66
75
|
|
|
67
|
-
const out = await Promise.all(
|
|
68
|
-
urlList.map(async (i) => {
|
|
69
|
-
const link = i.link;
|
|
70
|
-
const single = {
|
|
71
|
-
link,
|
|
72
|
-
};
|
|
73
|
-
const other = await cache.tryGet(link, () => loadContent(link));
|
|
74
|
-
return { ...single, ...other };
|
|
75
|
-
})
|
|
76
|
-
);
|
|
77
76
|
return {
|
|
78
77
|
title: $('title').text(),
|
|
78
|
+
description: $('meta[name="description"]').attr('content'),
|
|
79
79
|
link: url,
|
|
80
|
+
image: 'https://www.natgeomedia.com/img/app_icon.png',
|
|
80
81
|
item: out,
|
|
81
82
|
};
|
|
82
83
|
}
|
package/lib/routes/nbd/daily.ts
CHANGED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { Route, DataItem } from '@/types';
|
|
2
|
+
import got from '@/utils/got';
|
|
3
|
+
import { load } from 'cheerio';
|
|
4
|
+
import { parseDate } from '@/utils/parse-date';
|
|
5
|
+
import cache from '@/utils/cache';
|
|
6
|
+
|
|
7
|
+
export const route: Route = {
|
|
8
|
+
path: '/blog',
|
|
9
|
+
categories: ['blog'],
|
|
10
|
+
example: '/nielsberglund/blog',
|
|
11
|
+
radar: [
|
|
12
|
+
{
|
|
13
|
+
source: ['nielsberglund.com/'],
|
|
14
|
+
},
|
|
15
|
+
],
|
|
16
|
+
url: 'nielsberglund.com/',
|
|
17
|
+
name: 'Blog',
|
|
18
|
+
maintainers: ['liyaozhong'],
|
|
19
|
+
handler,
|
|
20
|
+
description: 'Niels Berglund Blog Posts',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
async function handler() {
|
|
24
|
+
const rootUrl = 'https://nielsberglund.com';
|
|
25
|
+
const currentUrl = rootUrl;
|
|
26
|
+
|
|
27
|
+
const response = await got(currentUrl);
|
|
28
|
+
const $ = load(response.data);
|
|
29
|
+
|
|
30
|
+
let items = $('.post-preview')
|
|
31
|
+
.toArray()
|
|
32
|
+
.map((item) => {
|
|
33
|
+
const $item = $(item);
|
|
34
|
+
const $link = $item.find('a').first();
|
|
35
|
+
const href = $link.attr('href');
|
|
36
|
+
const title = $item.find('.post-title').first().text().trim();
|
|
37
|
+
const dateStr = $item.find('.post-meta').text().trim();
|
|
38
|
+
|
|
39
|
+
if (!href || !title) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const link = new URL(href, rootUrl).href;
|
|
44
|
+
const pubDate = parseDate(dateStr);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
title,
|
|
48
|
+
link,
|
|
49
|
+
pubDate,
|
|
50
|
+
} as DataItem;
|
|
51
|
+
})
|
|
52
|
+
.filter((item): item is DataItem => item !== null);
|
|
53
|
+
|
|
54
|
+
items = (
|
|
55
|
+
await Promise.all(
|
|
56
|
+
items.map((item) =>
|
|
57
|
+
cache.tryGet(item.link as string, async () => {
|
|
58
|
+
try {
|
|
59
|
+
const detailResponse = await got(item.link);
|
|
60
|
+
const $detail = load(detailResponse.data);
|
|
61
|
+
|
|
62
|
+
item.description = $detail('.post-container').html() || '';
|
|
63
|
+
|
|
64
|
+
return item;
|
|
65
|
+
} catch {
|
|
66
|
+
return item;
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
)
|
|
70
|
+
)
|
|
71
|
+
).filter((item): item is DataItem => item !== null);
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
title: 'Niels Berglund Blog',
|
|
75
|
+
link: rootUrl,
|
|
76
|
+
item: items,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Route, ViewType } from '@/types';
|
|
2
|
+
import cache from '@/utils/cache';
|
|
3
|
+
import parser from '@/utils/rss-parser';
|
|
4
|
+
import { load } from 'cheerio';
|
|
5
|
+
import ofetch from '@/utils/ofetch';
|
|
6
|
+
|
|
7
|
+
export const route: Route = {
|
|
8
|
+
path: '/rss/:cat?',
|
|
9
|
+
categories: ['traditional-media', 'popular'],
|
|
10
|
+
view: ViewType.Articles,
|
|
11
|
+
example: '/nytimes/rss/HomePage',
|
|
12
|
+
parameters: {
|
|
13
|
+
cat: {
|
|
14
|
+
description: "Category name, corresponding to the last segment of [official feed's](https://www.nytimes.com/rss) url.",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
features: {
|
|
18
|
+
requireConfig: false,
|
|
19
|
+
requirePuppeteer: false,
|
|
20
|
+
antiCrawler: false,
|
|
21
|
+
supportBT: false,
|
|
22
|
+
supportPodcast: false,
|
|
23
|
+
supportScihub: false,
|
|
24
|
+
},
|
|
25
|
+
radar: [
|
|
26
|
+
{
|
|
27
|
+
source: ['nytimes.com/'],
|
|
28
|
+
target: '',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
name: 'News',
|
|
32
|
+
maintainers: ['HenryQW', 'pseudoyu', 'dzx-dzx'],
|
|
33
|
+
handler,
|
|
34
|
+
url: 'nytimes.com/',
|
|
35
|
+
description: `Enhance the official EN RSS feed`,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
async function handler(ctx) {
|
|
39
|
+
const url = `https://rss.nytimes.com/services/xml/rss/nyt/${ctx.req.param('cat')}.xml`;
|
|
40
|
+
|
|
41
|
+
const rss = await parser.parseURL(url);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
...rss,
|
|
45
|
+
item: await Promise.all(
|
|
46
|
+
rss.items.map((e) =>
|
|
47
|
+
cache.tryGet(e.link, async () => {
|
|
48
|
+
const res = await ofetch(e.link, { headers: { 'User-Agent': 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' }, referrer: 'https://www.google.com/' });
|
|
49
|
+
|
|
50
|
+
const $ = load(res);
|
|
51
|
+
|
|
52
|
+
return { ...e, description: $("[name='articleBody']").html() };
|
|
53
|
+
})
|
|
54
|
+
)
|
|
55
|
+
),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Route } from '@/types';
|
|
2
|
+
import ofetch from '@/utils/ofetch';
|
|
3
|
+
import { load } from 'cheerio';
|
|
4
|
+
import { art } from '@/utils/render';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { getCurrentPath } from '@/utils/helpers';
|
|
7
|
+
const __dirname = getCurrentPath(import.meta.url);
|
|
8
|
+
const baseUrl = 'https://www.openrice.com';
|
|
9
|
+
|
|
10
|
+
export const route: Route = {
|
|
11
|
+
path: '/:lang/hongkong/explore/chart/:category',
|
|
12
|
+
maintainers: ['after9'],
|
|
13
|
+
handler,
|
|
14
|
+
categories: ['shopping'],
|
|
15
|
+
example: '/openrice/zh/hongkong/explore/chart/most-bookmarked',
|
|
16
|
+
parameters: { lang: '语言,缺省为 zh', category: '类别,缺省为 most-bookmarked' },
|
|
17
|
+
name: '香港餐廳排行榜',
|
|
18
|
+
description: `
|
|
19
|
+
| 简体 | 繁體 | EN |
|
|
20
|
+
| ----- | ------ | ----- |
|
|
21
|
+
| zh-cn | zh | en |
|
|
22
|
+
|
|
23
|
+
| 最多收藏 | 每周最高评分 | 最高浏览 | 最佳甜品餐厅 |
|
|
24
|
+
| ----- | ------ | ----- | ----- |
|
|
25
|
+
| most-bookmarked | best-rating | most-popular | best-dessert |
|
|
26
|
+
`,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
async function handler(ctx) {
|
|
30
|
+
const lang = ctx.req.param('lang') ?? 'zh';
|
|
31
|
+
const category = ctx.req.param('category') ?? 'most-bookmarked';
|
|
32
|
+
|
|
33
|
+
const urlPath: string = `/${lang}/hongkong/explore/chart/${category}`;
|
|
34
|
+
const response = await ofetch(baseUrl + urlPath);
|
|
35
|
+
const $ = load(response);
|
|
36
|
+
|
|
37
|
+
const title = $('title').text() ?? 'Hong Kong Restaurant Chart';
|
|
38
|
+
const description = $('title').text() ?? 'Hong Kong Restaurant Chart';
|
|
39
|
+
|
|
40
|
+
const data = $('.poi-chart-main-grid-item-desktop-wrapper');
|
|
41
|
+
const resultList = data.toArray().map((item) => {
|
|
42
|
+
const $item = $(item);
|
|
43
|
+
const rankClass = $item.find('.rank-icon').attr('class');
|
|
44
|
+
const rankNumber = rankClass?.match(/rank-(\d+)/)?.[1] ?? '';
|
|
45
|
+
const desTags = $item.find('.pcmgidtr-left-section-poi-info-details .pcmgidtrls-poi-info-details-text');
|
|
46
|
+
const desTagsArray: string[] = desTags.toArray().map((tag) => $(tag).text());
|
|
47
|
+
const title = $item.find('.pcmgidtr-left-section-poi-info-name .link').text() ?? '';
|
|
48
|
+
const link = $item.find('.pcmgidtr-left-section-poi-info-name .link').attr('href') ?? '';
|
|
49
|
+
const coverImg = $item.find('.pcmgidtr-left-section-door-photo img').attr('src') ?? null;
|
|
50
|
+
const description = art(path.join(__dirname, 'templates/chart.art'), {
|
|
51
|
+
description: desTagsArray ?? [],
|
|
52
|
+
rankNumber,
|
|
53
|
+
image: coverImg,
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
title,
|
|
57
|
+
description,
|
|
58
|
+
link,
|
|
59
|
+
};
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
title,
|
|
64
|
+
link: baseUrl + urlPath,
|
|
65
|
+
description,
|
|
66
|
+
item: resultList,
|
|
67
|
+
};
|
|
68
|
+
}
|