rsshub 1.0.0-master.f9b85f5 → 1.0.0-master.f9c381a

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.
Files changed (166) hide show
  1. package/lib/config.ts +10 -0
  2. package/lib/middleware/cache.ts +4 -0
  3. package/lib/middleware/parameter.ts +1 -1
  4. package/lib/registry.ts +6 -2
  5. package/lib/routes/51cto/utils.ts +1 -1
  6. package/lib/routes/abc/index.ts +1 -1
  7. package/lib/routes/acgvinyl/namespace.ts +6 -0
  8. package/lib/routes/acgvinyl/news.ts +86 -0
  9. package/lib/routes/ally/rail.ts +1 -1
  10. package/lib/routes/anthropic/news.ts +13 -11
  11. package/lib/routes/apnews/mobile-api.ts +1 -1
  12. package/lib/routes/apnews/sitemap.ts +1 -1
  13. package/lib/routes/apple/apps.ts +2 -2
  14. package/lib/routes/apple/podcast.ts +58 -25
  15. package/lib/routes/bangumi.tv/group/reply.ts +1 -1
  16. package/lib/routes/bilibili/cache.ts +18 -2
  17. package/lib/routes/bilibili/dynamic.ts +31 -7
  18. package/lib/routes/bilibili/page.ts +1 -1
  19. package/lib/routes/bilibili/ranking.ts +23 -17
  20. package/lib/routes/bilibili/wasm-exec.ts +1 -1
  21. package/lib/routes/bilibili/weekly-recommend.ts +22 -6
  22. package/lib/routes/bjp/apod.ts +1 -1
  23. package/lib/routes/buaa/jiaowu.ts +1 -1
  24. package/lib/routes/bullionvault/gold-news.ts +3 -3
  25. package/lib/routes/cast/index.ts +1 -1
  26. package/lib/routes/coolapk/utils.ts +5 -4
  27. package/lib/routes/coolbuy/index.ts +106 -0
  28. package/lib/routes/{xinhuanet → coolbuy}/namespace.ts +3 -3
  29. package/lib/routes/coolbuy/templates/description.art +48 -0
  30. package/lib/routes/coolidge/film-guide.ts +60 -0
  31. package/lib/routes/coolidge/namespace.ts +7 -0
  32. package/lib/routes/coolidge/news.ts +65 -0
  33. package/lib/routes/coolidge/templates/description.art +4 -0
  34. package/lib/routes/copymanga/comic.ts +1 -1
  35. package/lib/routes/cpta/handler.ts +1 -1
  36. package/lib/routes/creative-comic/book.ts +1 -1
  37. package/lib/routes/daum/potplayer.ts +1 -1
  38. package/lib/routes/dockerhub/utils.ts +1 -1
  39. package/lib/routes/dora-world/article.ts +2 -2
  40. package/lib/routes/ehentai/ehapi.ts +3 -3
  41. package/lib/routes/eventbrite/events.ts +152 -0
  42. package/lib/routes/eventbrite/namespace.ts +7 -0
  43. package/lib/routes/github/activity.ts +1 -1
  44. package/lib/routes/google/jules.ts +63 -0
  45. package/lib/routes/gov/mem/namespace.ts +7 -0
  46. package/lib/routes/gov/mem/zfxxgkpt.ts +96 -0
  47. package/lib/routes/gov/mot/index.ts +158 -53
  48. package/lib/routes/hameln/chapter.ts +1 -1
  49. package/lib/routes/hpoi/banner-item.ts +28 -11
  50. package/lib/routes/hpoi/info.ts +1 -1
  51. package/lib/routes/huggingface/daily-papers.ts +1 -1
  52. package/lib/routes/hupu/index.ts +158 -74
  53. package/lib/routes/hupu/types.ts +163 -0
  54. package/lib/routes/hust/gs.ts +1 -1
  55. package/lib/routes/hust/mse.ts +1 -1
  56. package/lib/routes/huxiu/util.ts +2 -2
  57. package/lib/routes/infoq/presentations.ts +1 -1
  58. package/lib/routes/instagram/common-utils.ts +3 -3
  59. package/lib/routes/itch/devlog.ts +7 -3
  60. package/lib/routes/javbus/index.ts +1 -1
  61. package/lib/routes/javlibrary/utils.ts +1 -1
  62. package/lib/routes/jbma/namespace.ts +17 -0
  63. package/lib/routes/jbma/report.ts +473 -0
  64. package/lib/routes/jetbrains/comments.ts +1 -1
  65. package/lib/routes/jingzhengu/utils.ts +1 -1
  66. package/lib/routes/juejin/aicoding.ts +102 -0
  67. package/lib/routes/juejin/utils.ts +36 -51
  68. package/lib/routes/kakuyomu/works.ts +1 -1
  69. package/lib/routes/kemono/index.ts +2 -2
  70. package/lib/routes/komiic/comic.ts +1 -1
  71. package/lib/routes/koyso/index.ts +338 -0
  72. package/lib/routes/koyso/namespace.ts +9 -0
  73. package/lib/routes/koyso/templates/description.art +13 -0
  74. package/lib/routes/letterboxd/index.ts +65 -0
  75. package/lib/routes/letterboxd/namespace.ts +8 -0
  76. package/lib/routes/maccms/index.ts +1 -1
  77. package/lib/routes/mercari/util.ts +1 -1
  78. package/lib/routes/mingpao/index.ts +1 -1
  79. package/lib/routes/nankai/ai-notice.ts +142 -0
  80. package/lib/routes/nankai/graduate-notice.ts +162 -0
  81. package/lib/routes/natgeo/natgeo.ts +1 -0
  82. package/lib/routes/nhk/news-web-easy.ts +1 -1
  83. package/lib/routes/nicovideo/mylist.ts +39 -0
  84. package/lib/routes/nicovideo/types.ts +27 -0
  85. package/lib/routes/nicovideo/utils.ts +27 -1
  86. package/lib/routes/nikkei/cn/index.ts +1 -4
  87. package/lib/routes/now/news.ts +1 -1
  88. package/lib/routes/nytimes/index.ts +1 -1
  89. package/lib/routes/pixiv/novel-api/user-novels/sfw.ts +1 -1
  90. package/lib/routes/pixivision/utils.ts +1 -1
  91. package/lib/routes/pku/hr.ts +1 -1
  92. package/lib/routes/pku/scc/recruit.ts +1 -1
  93. package/lib/routes/producthunt/templates/description.art +2 -2
  94. package/lib/routes/producthunt/today.ts +17 -8
  95. package/lib/routes/ps/trophy.ts +1 -1
  96. package/lib/routes/pubscholar/utils.ts +14 -1
  97. package/lib/routes/qweather/3days.ts +14 -14
  98. package/lib/routes/qweather/now.ts +12 -10
  99. package/lib/routes/qweather/util.tsx +89 -0
  100. package/lib/routes/qwenlm/blog.ts +75 -0
  101. package/lib/routes/qwenlm/namespace.ts +6 -0
  102. package/lib/routes/radio-canada/latest.ts +30 -17
  103. package/lib/routes/ruc/ai.ts +1 -1
  104. package/lib/routes/ruc/hr.ts +1 -1
  105. package/lib/routes/samrdprc/index.ts +241 -0
  106. package/lib/routes/samrdprc/namespace.ts +1 -1
  107. package/lib/routes/sdo/ff14risingstones/api.ts +78 -0
  108. package/lib/routes/sdo/ff14risingstones/constant.ts +338 -0
  109. package/lib/routes/sdo/ff14risingstones/posts.ts +80 -0
  110. package/lib/routes/sdo/ff14risingstones/strats.ts +75 -0
  111. package/lib/routes/sdo/ff14risingstones/templates/duties-party.art +41 -0
  112. package/lib/routes/sdo/ff14risingstones/templates/fc-party.art +26 -0
  113. package/lib/routes/sdo/ff14risingstones/templates/novice-network-party.art +9 -0
  114. package/lib/routes/sdo/ff14risingstones/templates/rp-party.art +15 -0
  115. package/lib/routes/sdo/ff14risingstones/timeline.ts +31 -0
  116. package/lib/routes/sdo/ff14risingstones/types/dynamic.ts +50 -0
  117. package/lib/routes/sdo/ff14risingstones/types/index.ts +3 -0
  118. package/lib/routes/sdo/ff14risingstones/types/other.ts +57 -0
  119. package/lib/routes/sdo/ff14risingstones/types/party.ts +111 -0
  120. package/lib/routes/sdo/ff14risingstones/user-dynamics.ts +32 -0
  121. package/lib/routes/sdo/ff14risingstones/user-posts.ts +32 -0
  122. package/lib/routes/sdo/ff14risingstones/user-resently.ts +38 -0
  123. package/lib/routes/sdo/ff14risingstones/user-strats.ts +32 -0
  124. package/lib/routes/sdo/ff14risingstones/utils.ts +215 -0
  125. package/lib/routes/sdo/namespace.ts +7 -0
  126. package/lib/routes/showstart/utils.ts +1 -1
  127. package/lib/routes/sohu/mp.ts +1 -1
  128. package/lib/routes/sotwe/user.ts +1 -1
  129. package/lib/routes/surfshark/blog.ts +273 -77
  130. package/lib/routes/surfshark/templates/description.art +16 -4
  131. package/lib/routes/sustainabilitymag/articles.ts +1 -1
  132. package/lib/routes/syosetu/dev.ts +1 -1
  133. package/lib/routes/syosetu/ranking-isekai.ts +1 -1
  134. package/lib/routes/szse/disclosure/listed-notice.ts +44 -6
  135. package/lib/routes/telegram/channel-media.ts +249 -0
  136. package/lib/routes/telegram/channel.ts +5 -4
  137. package/lib/routes/telegram/stories.ts +130 -0
  138. package/lib/routes/telegram/tglib/channel.ts +136 -118
  139. package/lib/routes/telegram/tglib/client.ts +37 -139
  140. package/lib/routes/tesla/cx.ts +1 -1
  141. package/lib/routes/theverge/index.ts +20 -6
  142. package/lib/routes/threads/utils.ts +7 -3
  143. package/lib/routes/tidb/blog.ts +1 -1
  144. package/lib/routes/toutiao/user.ts +2 -2
  145. package/lib/routes/twitter/api/mobile-api/api.ts +1 -1
  146. package/lib/routes/txrjy/fornumtopic.ts +2 -2
  147. package/lib/routes/typst/universe.ts +1 -1
  148. package/lib/routes/uber/blog.ts +87 -46
  149. package/lib/routes/weibo/utils.ts +17 -9
  150. package/lib/routes/xiaohongshu/user.ts +1 -1
  151. package/lib/routes/xjtu/ee-jzxx.ts +1 -1
  152. package/lib/routes/yahoo/news/utils.ts +1 -1
  153. package/lib/routes/ymgal/article.ts +1 -1
  154. package/lib/routes/yoasobi-music/media.ts +1 -1
  155. package/lib/routes/youtube/api/youtubei.ts +1 -1
  156. package/lib/routes/youtube/community.ts +4 -4
  157. package/lib/routes/zaker/utils.ts +1 -1
  158. package/lib/routes/zaobao/util.tsx +1 -1
  159. package/lib/server.ts +1 -1
  160. package/lib/types.ts +1 -1
  161. package/lib/utils/puppeteer-utils.test.ts +2 -2
  162. package/lib/views/index.tsx +4 -4
  163. package/package.json +40 -40
  164. package/lib/routes/qweather/templates/3days.art +0 -22
  165. package/lib/routes/qweather/templates/now.art +0 -16
  166. package/lib/routes/xinhuanet/app.ts +0 -109
@@ -0,0 +1,7 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: 'Eventbrite',
5
+ url: 'eventbrite.com',
6
+ lang: 'en',
7
+ };
@@ -45,7 +45,7 @@ export const route: Route = {
45
45
  item: feed.items.map((item) => ({
46
46
  title: item.title ?? '',
47
47
  link: item.link,
48
- description: sanitizeHtml(item.content?.replace(/href="\/(.+?)"/g, `href="https://github.com/$1"`) ?? '', { allowedTags: [...sanitizeHtml.defaults.allowedTags, 'img'] }),
48
+ description: sanitizeHtml(item.content?.replaceAll(/href="\/(.+?)"/g, `href="https://github.com/$1"`) ?? '', { allowedTags: [...sanitizeHtml.defaults.allowedTags, 'img'] }),
49
49
  pubDate: item.pubDate ? parseDate(item.pubDate) : undefined,
50
50
  author: item.author,
51
51
  guid: item.id,
@@ -0,0 +1,63 @@
1
+ import { Route } from '@/types';
2
+ import ofetch from '@/utils/ofetch';
3
+ import { load } from 'cheerio';
4
+ import { parseDate } from '@/utils/parse-date';
5
+
6
+ export const route: Route = {
7
+ path: '/jules/changelog',
8
+ categories: ['program-update'],
9
+ example: '/google/jules/changelog',
10
+ features: {
11
+ requireConfig: false,
12
+ requirePuppeteer: false,
13
+ antiCrawler: false,
14
+ supportBT: false,
15
+ supportPodcast: false,
16
+ supportScihub: false,
17
+ },
18
+ name: 'Jules Changelog',
19
+ url: 'jules.google/docs/changelog/',
20
+ maintainers: ['johan456789'],
21
+ handler,
22
+ };
23
+
24
+ async function handler() {
25
+ const url = 'https://jules.google/docs/changelog/';
26
+ const html = await ofetch(url);
27
+ const $ = load(html);
28
+
29
+ const items = $('main article')
30
+ .toArray()
31
+ .map((el) => {
32
+ const article = $(el);
33
+ const h2 = article.find('h2').first();
34
+ const id = h2.attr('id') || article.attr('id');
35
+ const title = h2.text().trim();
36
+ const anchor = id ? `${url}#${id}` : url;
37
+ // Date appears as a bold text node after h2 (no <time> tag)
38
+ const pubDateText = h2.nextAll('b').first().text().trim();
39
+
40
+ // First image if exists
41
+ const imgEl = article.find('img').first();
42
+ const imgSrc = imgEl.attr('src');
43
+ const image = imgSrc ? new URL(imgSrc, url).href : undefined;
44
+
45
+ // Full HTML for the item content
46
+ article.find('h2').first().remove(); // remove title
47
+ article.find('b').first().remove(); // remove date
48
+
49
+ return {
50
+ title,
51
+ description: article.html() || undefined,
52
+ link: anchor,
53
+ pubDate: pubDateText ? parseDate(pubDateText) : undefined,
54
+ image,
55
+ };
56
+ });
57
+
58
+ return {
59
+ title: 'Jules Changelog',
60
+ link: url,
61
+ item: items,
62
+ };
63
+ }
@@ -0,0 +1,7 @@
1
+ import type { Namespace } from '@/types';
2
+
3
+ export const namespace: Namespace = {
4
+ name: '中华人民共和国应急管理部',
5
+ url: 'www.mem.gov.cn',
6
+ lang: 'zh-CN',
7
+ };
@@ -0,0 +1,96 @@
1
+ import { Route } from '@/types';
2
+ import cache from '@/utils/cache';
3
+ import got from '@/utils/got';
4
+ import { load } from 'cheerio';
5
+ import { parseDate } from '@/utils/parse-date';
6
+
7
+ export const route: Route = {
8
+ path: '/mem/gk/zfxxgkpt/fdzdgknr',
9
+ categories: ['government'],
10
+ example: '/gov/mem/gk/zfxxgkpt/fdzdgknr',
11
+ parameters: {},
12
+ features: {
13
+ requireConfig: false,
14
+ requirePuppeteer: false,
15
+ antiCrawler: false,
16
+ supportBT: false,
17
+ supportPodcast: false,
18
+ supportScihub: false,
19
+ },
20
+ radar: [
21
+ {
22
+ source: ['www.mem.gov.cn/gk/zfxxgkpt/fdzdgknr'],
23
+ target: '/mem/gk/zfxxgkpt/fdzdgknr',
24
+ },
25
+ ],
26
+ name: '法定主动公开内容',
27
+ maintainers: ['skeaven'],
28
+ handler,
29
+ description: '应急管理部法定主动公开内容,包含通知、公告、督办、政策解读等,可供应急相关工作人员及时获取政策信息',
30
+ };
31
+
32
+ async function handler(ctx) {
33
+ const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 30;
34
+
35
+ const rootUrl = 'https://www.mem.gov.cn';
36
+ const currentUrl = new URL('gk/zfxxgkpt/fdzdgknr/', rootUrl).href;
37
+
38
+ const { data: fdzdgknrResponse } = await got(currentUrl);
39
+ const fdzdgknr$ = load(fdzdgknrResponse);
40
+
41
+ const iframeUrl = fdzdgknr$('div.scy_main_r iframe').attr('src');
42
+ const { data: response } = await got(iframeUrl);
43
+ const $ = load(response);
44
+ const icon = new URL('favicon.ico', rootUrl).href;
45
+
46
+ let items = $('div.scy_main_V2_list')
47
+ .find('tr')
48
+ .slice(1, limit)
49
+ .toArray()
50
+ .map((item) => {
51
+ const aLabel = $(item).find('a[href]');
52
+ const href = aLabel.attr('href');
53
+ if (href) {
54
+ const link = currentUrl + aLabel.attr('href').replaceAll('..', '');
55
+ return {
56
+ title: aLabel.contents().first().text(),
57
+ link,
58
+ pubDate: parseDate($(item).find('.fbsj').text()),
59
+ };
60
+ } else {
61
+ return null;
62
+ }
63
+ })
64
+ .filter(Boolean);
65
+
66
+ items = await Promise.all(
67
+ items.map((item) =>
68
+ cache.tryGet(item.link, async () => {
69
+ if (!item.link.endsWith('.html') && !item.link.endsWith('.shtml')) {
70
+ return item;
71
+ }
72
+
73
+ const { data: detailResponse } = await got(item.link);
74
+ const content = load(detailResponse);
75
+
76
+ const description = content('#content').html();
77
+ const author = content('td.td_lable:contains("所属机构")').next('td').text().trim();
78
+ const category = content('td.td_lable:contains("主题分类")').next('td').text().trim();
79
+
80
+ return {
81
+ ...item,
82
+ description,
83
+ author: author || '未知机构',
84
+ category: category || '未知分类',
85
+ };
86
+ })
87
+ )
88
+ );
89
+
90
+ return {
91
+ item: items,
92
+ title: route.name,
93
+ link: currentUrl,
94
+ icon,
95
+ };
96
+ }
@@ -1,75 +1,180 @@
1
- import { Route } from '@/types';
1
+ import { type Data, type DataItem, type Route, ViewType } from '@/types';
2
+
2
3
  import cache from '@/utils/cache';
3
- import got from '@/utils/got';
4
- import { load } from 'cheerio';
5
- import timezone from '@/utils/timezone';
4
+ import ofetch from '@/utils/ofetch';
6
5
  import { parseDate } from '@/utils/parse-date';
7
6
 
8
- export const route: Route = {
9
- path: '/mot/:category{.+}?',
10
- name: '中华人民共和国交通运输部',
11
- maintainers: ['ladeng07'],
12
- handler,
13
- };
7
+ import { type CheerioAPI, type Cheerio, load } from 'cheerio';
8
+ import type { Element } from 'domhandler';
9
+ import { type Context } from 'hono';
14
10
 
15
- async function handler(ctx) {
16
- const { category = 'tongjishuju/gonglu' } = ctx.req.param();
17
- const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 30;
11
+ export const handler = async (ctx: Context): Promise<Data> => {
12
+ const { category = 'jiaotongyaowen' } = ctx.req.param();
13
+ const limit: number = Number.parseInt(ctx.req.query('limit') ?? '30', 10);
18
14
 
19
- const rootUrl = 'https://www.mot.gov.cn';
20
- const currentUrl = new URL(`${category}/`, rootUrl).href;
15
+ const baseUrl: string = 'https://www.mot.gov.cn';
16
+ const targetUrl: string = new URL(category.endsWith('/') ? category : `${category}/`, baseUrl).href;
21
17
 
22
- const { data: response } = await got(currentUrl);
18
+ const response = await ofetch(targetUrl);
19
+ const $: CheerioAPI = load(response);
20
+ const language = $('html').attr('lang') ?? 'zh';
23
21
 
24
- const $ = load(response);
22
+ let items: DataItem[] = [];
25
23
 
26
- let items = $('div.tab-pane a[title]')
24
+ items = $('div.tab-pane a')
27
25
  .slice(0, limit)
28
26
  .toArray()
29
- .map((item) => {
30
- item = $(item);
27
+ .map((el): Element => {
28
+ const $el: Cheerio<Element> = $(el);
31
29
 
32
- const link = item.prop('href');
30
+ const title: string = $el.attr('title') ?? $el.find('span').first().text();
31
+ const pubDateStr: string | undefined = $el.find('span.badge').text();
32
+ const linkUrl: string | undefined = $el.attr('href');
33
+ const upDatedStr: string | undefined = $el.find('.time').text() || pubDateStr;
33
34
 
34
- return {
35
- title: item.prop('title'),
36
- link: link.startsWith('http') ? link : new URL(item.prop('href'), currentUrl).href,
37
- pubDate: parseDate(item.find('span.badge').text()),
35
+ const processedItem: DataItem = {
36
+ title,
37
+ pubDate: pubDateStr ? parseDate(pubDateStr) : undefined,
38
+ link: linkUrl ? (linkUrl.startsWith('http') ? linkUrl : new URL(linkUrl as string, targetUrl).href) : undefined,
39
+ updated: upDatedStr ? parseDate(upDatedStr) : undefined,
40
+ language,
38
41
  };
42
+
43
+ return processedItem;
39
44
  });
40
45
 
41
46
  items = await Promise.all(
42
- items.map((item) =>
43
- cache.tryGet(item.link, async () => {
44
- if (/\.gov\.cn/.test(item.link) && item.link.endsWith('.html')) {
45
- const { data: detailResponse } = await got(item.link);
46
-
47
- const content = load(detailResponse);
48
-
49
- item.title = content('meta[name="ArticleTitle"]').prop('content') || content('h1#ti').text();
50
- item.description = content('div.TRS_UEDITOR').html();
51
- item.author = [...new Set([content('meta[name="Author"]').prop('content'), content('meta[name="ContentSource"]').prop('content')])].find(Boolean);
52
- item.category = [
53
- ...new Set([content('meta[name="ColumnName"]').prop('content'), content('meta[name="ColumnType"]').prop('content'), ...(content('meta[name="Keywords"]').prop('content')?.split(/,|;/) ?? [])]),
54
- ].filter(Boolean);
55
- item.pubDate = timezone(parseDate(content('meta[name="PubDate"]').prop('content')), +8);
56
- }
57
-
47
+ items.map((item) => {
48
+ if (!item.link || !/mot\.gov\.cn/.test(item.link) || !item.link.endsWith('.html')) {
58
49
  return item;
59
- })
60
- )
61
- );
50
+ }
62
51
 
63
- const image = new URL($('a.navbar-brand img').prop('src'), rootUrl).href;
52
+ return cache.tryGet(item.link, async (): Promise<DataItem> => {
53
+ const detailResponse = await ofetch(item.link);
54
+ const $$: CheerioAPI = load(detailResponse);
55
+
56
+ const title: string = $$('h1').first().text();
57
+ const description: string | undefined = $$('div.TRS_UEDITOR').html() ?? undefined;
58
+ const pubDateStr: string | undefined = $$('meta[name="PubDate"]').attr('content');
59
+ const categories: string[] = [
60
+ ...new Set(
61
+ [
62
+ $$('meta[name="ColumnName"]').attr('content'),
63
+ $$('meta[name="ColumnType"]').attr('content'),
64
+ $$('meta[name="ContentSource"]').attr('content'),
65
+ ...($$('meta[name="Keywords"]').attr('content')?.split(';') ?? []),
66
+ ].filter(Boolean)
67
+ ),
68
+ ];
69
+ const authors: DataItem['author'] = [$$('meta[name="ColumnSource"]').attr('content'), $$('meta[name="Author"]').attr('content')].filter(Boolean).map((author) => ({
70
+ name: author,
71
+ url: undefined,
72
+ avatar: undefined,
73
+ }));
74
+ const image: string | undefined = $$('a.navbar-brand img').attr('src') ? new URL($$('a.navbar-brand img').attr('src') as string, baseUrl).href : undefined;
75
+ const upDatedStr: string | undefined = pubDateStr;
76
+
77
+ const processedItem: DataItem = {
78
+ title,
79
+ description,
80
+ pubDate: pubDateStr ? parseDate(pubDateStr) : item.pubDate,
81
+ category: categories,
82
+ author: authors,
83
+ content: {
84
+ html: description,
85
+ text: description,
86
+ },
87
+ image,
88
+ banner: image,
89
+ updated: upDatedStr ? parseDate(upDatedStr) : item.updated,
90
+ language,
91
+ };
92
+
93
+ return {
94
+ ...item,
95
+ ...processedItem,
96
+ };
97
+ });
98
+ })
99
+ );
64
100
 
65
101
  return {
66
- item: items,
67
102
  title: $('title').text(),
68
- link: currentUrl,
69
- description: $('meta[name="ColumnDescription"]').prop('content'),
70
- language: $('html').prop('lang'),
71
- image,
72
- subtitle: $('meta[name="ColumnName"]').prop('content'),
73
- author: $('meta[name="SiteName"]').prop('content'),
103
+ description: $('meta[name="ColumnDescription"]').attr('content'),
104
+ link: targetUrl,
105
+ item: items,
106
+ allowEmpty: true,
107
+ image: $('a.navbar-brand img').attr('src') ? new URL($('a.navbar-brand img').attr('src') as string, baseUrl).href : undefined,
108
+ author: $('meta[name="SiteName"]').attr('content'),
109
+ language,
110
+ id: targetUrl,
74
111
  };
75
- }
112
+ };
113
+
114
+ export const route: Route = {
115
+ path: '/mot/:category{.+}?',
116
+ name: '中华人民共和国交通运输部',
117
+ url: 'www.mot.gov.cn',
118
+ maintainers: ['ladeng07', 'nczitzk'],
119
+ handler,
120
+ example: '/gov/mot/jiaotongyaowen',
121
+ parameters: {
122
+ category: {
123
+ description: '分类,默认为 `jiaotongyaowen`,即交通要闻,可在对应分类页 URL 中找到',
124
+ options: [
125
+ {
126
+ label: '交通要闻',
127
+ value: 'jiaotongyaowen',
128
+ },
129
+ {
130
+ label: '时政要闻',
131
+ value: 'shizhengyaowen',
132
+ },
133
+ {
134
+ label: '重要会议',
135
+ value: 'zhongyaohuiyi',
136
+ },
137
+ ],
138
+ },
139
+ },
140
+ description: `:::tip
141
+ 若订阅 [重要会议](https://www.mot.gov.cn/zhongyaohuiyi/),网址为 \`https://www.mot.gov.cn/zhongyaohuiyi/\`,请截取 \`https://www.mot.gov.cn/\` 到末尾 \`/\` 的部分 \`zhongyaohuiyi\` 作为 \`category\` 参数填入,此时目标路由为 [\`/gov/mot/zhongyaohuiyi\`](https://rsshub.app/gov/mot/zhongyaohuiyi)。
142
+ :::
143
+ `,
144
+ categories: ['government'],
145
+ features: {
146
+ requireConfig: false,
147
+ requirePuppeteer: false,
148
+ antiCrawler: false,
149
+ supportRadar: true,
150
+ supportBT: false,
151
+ supportPodcast: false,
152
+ supportScihub: false,
153
+ },
154
+ radar: [
155
+ {
156
+ source: ['www.mot.gov.cn/:category'],
157
+ target: (params) => {
158
+ const category: string = params.category;
159
+
160
+ return `/mot${category ? `/${category}` : ''}`;
161
+ },
162
+ },
163
+ {
164
+ title: '交通要闻',
165
+ source: ['www.mot.gov.cn/jiaotongyaowen/'],
166
+ target: '/mot/jiaotongyaowen',
167
+ },
168
+ {
169
+ title: '时政要闻',
170
+ source: ['www.mot.gov.cn/shizhengyaowen/'],
171
+ target: '/mot/shizhengyaowen',
172
+ },
173
+ {
174
+ title: '重要会议',
175
+ source: ['www.mot.gov.cn/zhongyaohuiyi/'],
176
+ target: '/mot/zhongyaohuiyi',
177
+ },
178
+ ],
179
+ view: ViewType.Articles,
180
+ };
@@ -49,7 +49,7 @@ async function handler(ctx) {
49
49
  pubDate: timezone(parseDate($_chapter.find('nobr').text(), 'YYYYMMDD HH:mm'), +9),
50
50
  };
51
51
  })
52
- .sort((a, b) => (a.pubDate <= b.pubDate ? 1 : -1))
52
+ .toSorted((a, b) => (a.pubDate <= b.pubDate ? 1 : -1))
53
53
  .slice(0, limit);
54
54
 
55
55
  const item_list = await Promise.all(
@@ -1,4 +1,5 @@
1
1
  import { Route } from '@/types';
2
+ import cache from '@/utils/cache';
2
3
  import got from '@/utils/got';
3
4
  import { load } from 'cheerio';
4
5
 
@@ -33,19 +34,35 @@ async function handler() {
33
34
  url: link,
34
35
  });
35
36
  const $ = load(response.data);
37
+
38
+ const items = await Promise.all(
39
+ $('#content .item')
40
+ .toArray()
41
+ .map(async (_item) => {
42
+ const $item = $(_item);
43
+ const link = new URL($item.find('a').attr('href') ?? '', 'https://www.hpoi.net').href;
44
+ if (!link.startsWith('https://www.hpoi.net')) {
45
+ return;
46
+ }
47
+ return await cache.tryGet(link, async () => {
48
+ const detailResponse = await got(link);
49
+ const $$ = load(detailResponse.data);
50
+ $$('.hpoi-album-content .album-ibox').remove();
51
+ $$('.hpoi-album-content .row').remove();
52
+ $$('.hpoi-album-content .hpoi-hr-line').remove();
53
+ return {
54
+ title: $item.find('.title').text(),
55
+ link,
56
+ description: $$('.hpoi-album-content').html() || `<img src="${$item.find('img').attr('src')}">`,
57
+ pubDate: new Date($item.find('.time').text().replace('发布时间:', '')).toUTCString(),
58
+ };
59
+ });
60
+ })
61
+ );
62
+
36
63
  return {
37
64
  title: `Hpoi 手办维基 - 热门推荐`,
38
65
  link,
39
- item: $('#content .item')
40
- .toArray()
41
- .map((_item) => {
42
- _item = $(_item);
43
- return {
44
- title: _item.find('.title').text(),
45
- link: 'https://www.hpoi.net/' + _item.find('a').attr('href'),
46
- description: `<img src="${_item.find('img').attr('src')}">`,
47
- pubDate: new Date(_item.find('.time').text().replace('发布时间:', '')).toUTCString(),
48
- };
49
- }),
66
+ item: items.filter((item) => !!item),
50
67
  };
51
68
  }
@@ -63,7 +63,7 @@ async function handler(ctx) {
63
63
  gkdiy: 'GK/其他',
64
64
  };
65
65
 
66
- const filterArr = catType.split('|').sort();
66
+ const filterArr = catType.split('|').toSorted();
67
67
 
68
68
  const filterSet = new Set(filterArr.map((e: string) => classMap[e]));
69
69
  if (catType.includes('all')) {
@@ -77,7 +77,7 @@ async function handler(ctx) {
77
77
  author: item.paper.authors.map((author) => author.name).join(', '),
78
78
  upvotes: item.paper.upvotes,
79
79
  }))
80
- .sort((a, b) => b.upvotes - a.upvotes);
80
+ .toSorted((a, b) => b.upvotes - a.upvotes);
81
81
 
82
82
  return {
83
83
  title: 'Huggingface Daily Papers',