rsshub 1.0.0-master.f6cb490 → 1.0.0-master.f6f0273

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 (88) hide show
  1. package/lib/api/index.ts +1 -6
  2. package/lib/routes/2048/index.ts +24 -23
  3. package/lib/routes/anthropic/news.ts +27 -13
  4. package/lib/routes/asianfanfics/namespace.ts +7 -0
  5. package/lib/routes/asianfanfics/tag.ts +89 -0
  6. package/lib/routes/asianfanfics/text-search.ts +68 -0
  7. package/lib/routes/blockworks/index.ts +128 -0
  8. package/lib/routes/blockworks/namespace.ts +7 -0
  9. package/lib/routes/cmu/andypavlo/blog.ts +55 -0
  10. package/lib/routes/cmu/namespace.ts +7 -0
  11. package/lib/routes/coindesk/{index.ts → consensus-magazine.ts} +17 -21
  12. package/lib/routes/coindesk/namespace.ts +2 -1
  13. package/lib/routes/coindesk/news.ts +47 -0
  14. package/lib/routes/coindesk/utils.ts +26 -0
  15. package/lib/routes/cointelegraph/index.ts +106 -0
  16. package/lib/routes/cointelegraph/namespace.ts +7 -0
  17. package/lib/routes/collabo-cafe/category.ts +37 -0
  18. package/lib/routes/collabo-cafe/index.ts +35 -0
  19. package/lib/routes/collabo-cafe/namespace.ts +9 -0
  20. package/lib/routes/collabo-cafe/parser.ts +29 -0
  21. package/lib/routes/collabo-cafe/tag.ts +37 -0
  22. package/lib/routes/cryptoslate/index.ts +98 -0
  23. package/lib/routes/cryptoslate/namespace.ts +7 -0
  24. package/lib/routes/decrypt/index.ts +115 -0
  25. package/lib/routes/decrypt/namespace.ts +7 -0
  26. package/lib/routes/discuz/discuz.ts +7 -9
  27. package/lib/routes/fangchan/list.ts +224 -0
  28. package/lib/routes/fangchan/namespace.ts +9 -0
  29. package/lib/routes/fangchan/templates/description.art +7 -0
  30. package/lib/routes/foreignaffairs/namespace.ts +7 -0
  31. package/lib/routes/foreignaffairs/rss.ts +55 -0
  32. package/lib/routes/forklog/index.ts +72 -0
  33. package/lib/routes/forklog/namespace.ts +7 -0
  34. package/lib/routes/gcores/categories.ts +129 -0
  35. package/lib/routes/gcores/collections.ts +129 -0
  36. package/lib/routes/gcores/topics.ts +63 -0
  37. package/lib/routes/gov/moa/gjs.ts +210 -0
  38. package/lib/routes/gov/tianjin/tjftz.ts +53 -0
  39. package/lib/routes/gov/tianjin/tjrcgzw.ts +51 -0
  40. package/lib/routes/grainoil/category.ts +207 -0
  41. package/lib/routes/grainoil/namespace.ts +9 -0
  42. package/lib/routes/huxiu/util.ts +11 -9
  43. package/lib/routes/ifanr/category.ts +7 -2
  44. package/lib/routes/ifanr/digest.ts +1 -1
  45. package/lib/routes/ifanr/index.ts +1 -1
  46. package/lib/routes/instructables/projects.ts +20 -15
  47. package/lib/routes/juejin/collections.ts +1 -1
  48. package/lib/routes/komiic/comic.ts +88 -0
  49. package/lib/routes/komiic/namespace.ts +7 -0
  50. package/lib/routes/leagueoflegends/namespace.ts +8 -0
  51. package/lib/routes/leagueoflegends/patch-notes.ts +76 -0
  52. package/lib/routes/likeshop/index.ts +43 -0
  53. package/lib/routes/likeshop/namespace.ts +7 -0
  54. package/lib/routes/ltaaa/article.ts +180 -0
  55. package/lib/routes/ltaaa/namespace.ts +9 -0
  56. package/lib/routes/ltaaa/templates/description.art +7 -0
  57. package/lib/routes/mashiro/index.ts +1 -0
  58. package/lib/routes/nhentai/util.ts +4 -1
  59. package/lib/routes/pinterest/user.ts +9 -0
  60. package/lib/routes/sohu/mp.ts +3 -2
  61. package/lib/routes/spotify/show.ts +1 -1
  62. package/lib/routes/stcn/index.ts +241 -136
  63. package/lib/routes/stcn/kx.ts +144 -0
  64. package/lib/routes/swjtu/namespace.ts +1 -1
  65. package/lib/routes/swjtu/{scai/bks.ts → scai.ts} +34 -20
  66. package/lib/routes/swjtu/sports.ts +77 -0
  67. package/lib/routes/theblock/index.ts +142 -0
  68. package/lib/routes/theblock/namespace.ts +7 -0
  69. package/lib/routes/theverge/index.ts +73 -62
  70. package/lib/routes/theverge/templates/header.art +19 -0
  71. package/lib/routes/threads/index.ts +73 -54
  72. package/lib/routes/threads/utils.ts +60 -78
  73. package/lib/routes/tmtpost/column.ts +298 -0
  74. package/lib/routes/tmtpost/new.ts +4 -199
  75. package/lib/routes/tmtpost/util.ts +207 -0
  76. package/lib/routes/toranoana/namespace.ts +7 -0
  77. package/lib/routes/toranoana/news.ts +110 -0
  78. package/lib/routes/wainao/templates/description.art +9 -0
  79. package/lib/routes/wainao/topics.ts +214 -0
  80. package/lib/routes/xiaoyuzhou/podcast.ts +27 -27
  81. package/lib/routes/xjtu/yz.ts +74 -0
  82. package/lib/routes/youmemark/index.ts +6 -6
  83. package/lib/routes/zaobao/util.ts +11 -3
  84. package/lib/routes/zhihu/answers.ts +26 -54
  85. package/package.json +36 -35
  86. package/lib/routes/gcores/category.ts +0 -171
  87. package/lib/routes/gcores/collection.ts +0 -161
  88. package/lib/routes-deprecated/ltaaa/index.js +0 -69
@@ -0,0 +1,214 @@
1
+ import { type Data, type DataItem, type Route, ViewType } from '@/types';
2
+
3
+ import { art } from '@/utils/render';
4
+ import { getCurrentPath } from '@/utils/helpers';
5
+ import ofetch from '@/utils/ofetch';
6
+ import { parseDate } from '@/utils/parse-date';
7
+
8
+ import { type CheerioAPI, load } from 'cheerio';
9
+ import { type Context } from 'hono';
10
+ import path from 'node:path';
11
+
12
+ const __dirname = getCurrentPath(import.meta.url);
13
+
14
+ export const handler = async (ctx: Context): Promise<Data> => {
15
+ const { id = 'hotspot' } = ctx.req.param();
16
+ const limit: number = Number.parseInt(ctx.req.query('limit') ?? '30', 10);
17
+
18
+ const baseUrl: string = 'https://www.wainao.me';
19
+ const targetUrl: string = new URL(`topics/${id}`, baseUrl).href;
20
+ const apiUrl: string = new URL('pf/api/v3/content/fetch/story-feed-sections', baseUrl).href;
21
+
22
+ const response = await ofetch(apiUrl, {
23
+ query: {
24
+ query: JSON.stringify({
25
+ feedOffset: 0,
26
+ feedSize: limit,
27
+ includeSections: `/topics/${id}`,
28
+ }),
29
+ d: 81,
30
+ _website: 'wainao',
31
+ },
32
+ });
33
+
34
+ const targetResponse = await ofetch(targetUrl);
35
+ const $: CheerioAPI = load(targetResponse);
36
+ const language = $('html').attr('lang') ?? 'zh-CN';
37
+
38
+ let items: DataItem[] = [];
39
+
40
+ items = response.content_elements
41
+ .slice(0, limit)
42
+ .map((item): DataItem => {
43
+ const title: string = item.headlines.basic;
44
+ const description: string = art(path.join(__dirname, 'templates/description.art'), {
45
+ elements: item.content_elements,
46
+ });
47
+ const pubDate: number | string = item.publish_date;
48
+ const linkUrl: string | undefined = item.website_url;
49
+ const categories: string[] = [item.taxonomy?.primary_section?.name].filter(Boolean);
50
+ const authors: DataItem['author'] =
51
+ item.credits?.by?.map((author) => ({
52
+ name: author.name,
53
+ })) ?? [];
54
+ const guid: string = item.website_url;
55
+ const image: string | undefined = item.promo_items.basic.url;
56
+ const updated: number | string = item.last_updated_date;
57
+
58
+ const processedItem: DataItem = {
59
+ title,
60
+ description,
61
+ pubDate: pubDate ? parseDate(pubDate) : undefined,
62
+ link: linkUrl ? new URL(linkUrl, baseUrl).href : undefined,
63
+ category: categories,
64
+ author: authors,
65
+ guid,
66
+ id: guid,
67
+ content: {
68
+ html: description,
69
+ text: description,
70
+ },
71
+ image,
72
+ banner: image,
73
+ updated: updated ? parseDate(updated) : undefined,
74
+ language,
75
+ };
76
+
77
+ return processedItem;
78
+ })
79
+ .filter((_): _ is DataItem => true);
80
+
81
+ return {
82
+ title: $('title').text(),
83
+ description: $('meta[property="og:title"]').attr('content'),
84
+ link: targetUrl,
85
+ item: items,
86
+ allowEmpty: true,
87
+ image: $('meta[property="og:image"]').attr('content'),
88
+ author: $('meta[property="og:site_name"]').attr('content'),
89
+ language,
90
+ id: targetUrl,
91
+ };
92
+ };
93
+
94
+ export const route: Route = {
95
+ path: '/topics/:id?',
96
+ name: '主题',
97
+ url: 'wainao.me',
98
+ maintainers: ['nczitzk'],
99
+ handler,
100
+ example: '/wainao/topics/hotspot',
101
+ parameters: {
102
+ id: {
103
+ description: '主题 id,默认为 `hotspot`,即热点,可在对应主题页 URL 中找到',
104
+ options: [
105
+ {
106
+ label: '热点',
107
+ value: 'hotspot',
108
+ },
109
+ {
110
+ label: '人物',
111
+ value: 'people',
112
+ },
113
+ {
114
+ label: '身份',
115
+ value: 'identity',
116
+ },
117
+ {
118
+ label: '政治',
119
+ value: 'politics',
120
+ },
121
+ {
122
+ label: '社会',
123
+ value: 'society',
124
+ },
125
+ {
126
+ label: '文化',
127
+ value: 'culture',
128
+ },
129
+ {
130
+ label: '经济',
131
+ value: 'economics',
132
+ },
133
+ {
134
+ label: '环境',
135
+ value: 'environment',
136
+ },
137
+ {
138
+ label: 'FUN',
139
+ value: 'fun',
140
+ },
141
+ ],
142
+ },
143
+ },
144
+ description: `:::tip
145
+ 若订阅 [人物](https://www.wainao.me/topics/people),网址为 \`https://www.wainao.me/topics/people\`,请截取 \`https://www.wainao.me/topics/\` 到末尾的部分 \`people\` 作为 \`id\` 参数填入,此时目标路由为 [\`/wainao/topics/people\`](https://rsshub.app/wainao/topics/people)。
146
+ :::
147
+
148
+ | [热点](https://www.wainao.me/topics/hotspot) | [人物](https://www.wainao.me/topics/people) | [身份](https://www.wainao.me/topics/identity) | [政治](https://www.wainao.me/topics/politics) | [社会](https://www.wainao.me/topics/society) | [文化](https://www.wainao.me/topics/culture) | [经济](https://www.wainao.me/topics/economics) | [环境](https://www.wainao.me/topics/environment) | [FUN](https://www.wainao.me/topics/fun) |
149
+ | --------------------------------------------------- | ------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------- | --------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------- |
150
+ | [hotspot](https://rsshub.app/wainao/topics/hotspot) | [people](https://rsshub.app/wainao/topics/people) | [identity](https://rsshub.app/wainao/topics/identity) | [politics](https://rsshub.app/wainao/topics/politics) | [society](https://rsshub.app/wainao/topics/society) | [culture](https://rsshub.app/wainao/topics/culture) | [economics](https://rsshub.app/wainao/topics/economics) | [environment](https://rsshub.app/wainao/topics/environment) | [fun](https://rsshub.app/wainao/topics/fun) |
151
+ `,
152
+ categories: ['new-media'],
153
+ features: {
154
+ requireConfig: false,
155
+ requirePuppeteer: false,
156
+ antiCrawler: false,
157
+ supportRadar: true,
158
+ supportBT: false,
159
+ supportPodcast: false,
160
+ supportScihub: false,
161
+ },
162
+ radar: [
163
+ {
164
+ source: ['www.wainao.me/topics/:id'],
165
+ target: '/topics/:id',
166
+ },
167
+ {
168
+ title: '热点',
169
+ source: ['www.wainao.me/topics/hotspot'],
170
+ target: '/topics/hotspot',
171
+ },
172
+ {
173
+ title: '人物',
174
+ source: ['www.wainao.me/topics/people'],
175
+ target: '/topics/people',
176
+ },
177
+ {
178
+ title: '身份',
179
+ source: ['www.wainao.me/topics/identity'],
180
+ target: '/topics/identity',
181
+ },
182
+ {
183
+ title: '政治',
184
+ source: ['www.wainao.me/topics/politics'],
185
+ target: '/topics/politics',
186
+ },
187
+ {
188
+ title: '社会',
189
+ source: ['www.wainao.me/topics/society'],
190
+ target: '/topics/society',
191
+ },
192
+ {
193
+ title: '文化',
194
+ source: ['www.wainao.me/topics/culture'],
195
+ target: '/topics/culture',
196
+ },
197
+ {
198
+ title: '经济',
199
+ source: ['www.wainao.me/topics/economics'],
200
+ target: '/topics/economics',
201
+ },
202
+ {
203
+ title: '环境',
204
+ source: ['www.wainao.me/topics/environment'],
205
+ target: '/topics/environment',
206
+ },
207
+ {
208
+ title: 'FUN',
209
+ source: ['www.wainao.me/topics/fun'],
210
+ target: '/topics/fun',
211
+ },
212
+ ],
213
+ view: ViewType.Articles,
214
+ };
@@ -1,5 +1,5 @@
1
1
  import { Route, ViewType } from '@/types';
2
- import got from '@/utils/got';
2
+ import ofetch from '@/utils/ofetch';
3
3
  import { load } from 'cheerio';
4
4
  import { parseDate } from '@/utils/parse-date';
5
5
 
@@ -30,43 +30,43 @@ export const route: Route = {
30
30
 
31
31
  async function handler(ctx) {
32
32
  const id = ctx.req.param('id');
33
- let link = `https://www.xiaoyuzhoufm.com/podcast/${id}`;
34
- let response = await got({
35
- method: 'get',
36
- url: link,
37
- });
33
+ let link;
34
+ let response;
35
+ let $;
36
+ let page_data;
38
37
 
39
- let $ = load(response.data);
40
- let page_data = JSON.parse($('#__NEXT_DATA__')[0].children[0].data);
38
+ // First try podcast URL, if that fails try episode URL
39
+ try {
40
+ link = `https://www.xiaoyuzhoufm.com/podcast/${id}`;
41
+ response = await ofetch(link);
41
42
 
42
- if (!page_data.props.pageProps.podcast?.episodes) {
43
- // If episodes are not found, it might be an episode page
44
- // Try to get the podcast id from the episode page
43
+ $ = load(response);
44
+ const nextDataElement = $('#__NEXT_DATA__').get(0);
45
+ page_data = JSON.parse(nextDataElement.children[0].data);
46
+
47
+ // If no episodes found, we should try episode URL
48
+ if (!page_data.props.pageProps.podcast?.episodes) {
49
+ throw new Error('No episodes found in podcast data');
50
+ }
51
+ } catch {
52
+ // Try as episode instead
45
53
  link = `https://www.xiaoyuzhoufm.com/episode/${id}`;
46
- response = await got({
47
- method: 'get',
48
- url: link,
49
- });
54
+ response = await ofetch(link);
55
+
56
+ $ = load(response);
57
+ const podcastLink = $('a[href^="/podcast/"].name').attr('href');
50
58
 
51
- $ = load(response.data);
52
- const podcastLink = $('.jsx-605929003.podcast-title .jsx-605929003.name').attr('href');
53
59
  if (podcastLink) {
54
60
  const podcastId = podcastLink.split('/').pop();
55
61
  link = `https://www.xiaoyuzhoufm.com/podcast/${podcastId}`;
56
- response = await got({
57
- method: 'get',
58
- url: link,
59
- });
62
+ response = await ofetch(link);
60
63
 
61
- $ = load(response.data);
62
- page_data = JSON.parse($('#__NEXT_DATA__')[0].children[0].data);
64
+ $ = load(response);
65
+ const nextDataElement = $('#__NEXT_DATA__').get(0);
66
+ page_data = JSON.parse(nextDataElement.children[0].data);
63
67
  }
64
68
  }
65
69
 
66
- if (!page_data.props.pageProps.podcast?.episodes) {
67
- throw new Error('Failed to fetch podcast episodes');
68
- }
69
-
70
70
  const episodes = page_data.props.pageProps.podcast.episodes.map((item) => ({
71
71
  title: item.title,
72
72
  enclosure_url: item.enclosure.url,
@@ -0,0 +1,74 @@
1
+ import type { Data, DataItem, Route } from '@/types';
2
+ import ofetch from '@/utils/ofetch';
3
+ import { load } from 'cheerio';
4
+ import { parseDate } from '@/utils/parse-date';
5
+ import cache from '@/utils/cache';
6
+ import logger from '@/utils/logger';
7
+ import timezone from '@/utils/timezone';
8
+
9
+ export const route: Route = {
10
+ path: '/yz/:category?',
11
+ categories: ['university'],
12
+ example: '/xjtu/yz/zsdt',
13
+ parameters: { category: '栏目类型,默认请求`zsdt`,详见下方表格' },
14
+ features: {
15
+ requireConfig: false,
16
+ requirePuppeteer: false,
17
+ antiCrawler: false,
18
+ supportBT: false,
19
+ supportPodcast: false,
20
+ supportScihub: false,
21
+ },
22
+ radar: [
23
+ {
24
+ source: ['yz.xjtu.edu.cn/index/:category.htm'],
25
+ target: '/yz/:category',
26
+ },
27
+ ],
28
+ name: '研究生招生信息网',
29
+ maintainers: ['YoghurtGuy'],
30
+ handler,
31
+ description: `栏目类型
32
+
33
+ | 招生动态 | 通知公告 | 政策法规 | 招生统计 | 历年复试线 | 博士招生 | 硕士招生 | 推免生 | 其他招生 |
34
+ | -------- | -------- | -------- | -------- | ---------- | -------- | -------- | ------ | -------- |
35
+ | zsdt | tzgg | zcfg | zstj | lnfsx | bszs | sszs | tms | qtzs |`,
36
+ };
37
+ async function handler(ctx) {
38
+ const { category = 'zsdt' } = ctx.req.param();
39
+ const baseUrl = 'https://yz.xjtu.edu.cn';
40
+
41
+ const response = await ofetch(`${baseUrl}/index/${category}.htm`);
42
+ const $ = load(response);
43
+ const list = $('div.list-con ul li')
44
+ .toArray()
45
+ .map((item_) => {
46
+ const item = $(item_);
47
+ const a = item.find('a');
48
+ return {
49
+ title: a.attr('title'),
50
+ link: new URL(a.attr('href')!, baseUrl).href,
51
+ pubDate: timezone(parseDate(item.find('span.date.fr').text()), +8),
52
+ } as DataItem;
53
+ });
54
+ const items = await Promise.all(
55
+ list.map((item) =>
56
+ cache.tryGet(item.link!, async () => {
57
+ try {
58
+ const res = await ofetch(item.link!);
59
+ const content = load(res);
60
+ item.description = content('#vsb_content').html()! + (content('form ul').length > 0 ? content('form ul').html() : '');
61
+ return item;
62
+ } catch (error) {
63
+ logger.error(`Fetch failed for ${item.link}:`, error);
64
+ return item;
65
+ }
66
+ })
67
+ )
68
+ );
69
+ return {
70
+ title: '西安交通大学研究生招生信息网',
71
+ link: 'https://yz.xjtu.edu.cn',
72
+ item: items,
73
+ } as Data;
74
+ }
@@ -44,13 +44,13 @@ async function handler(ctx): Promise<Data> {
44
44
  const $ = load(response);
45
45
 
46
46
  const name = $('h2.font-bold').text().trim();
47
- const avatar = $('span.relative.flex img').attr('src');
48
- const intro = $('.text-center .prose p').first().text().trim();
47
+ const avatar = $('span.relative.flex img, span.relative.flex.shrink-0 img').attr('src');
48
+ const intro = $('.text-center .prose p, .text-sm.text-gray-500.text-center .prose p').first().text().trim();
49
49
 
50
50
  const items: Data['item'] = [];
51
51
  $('h2:contains("收集箱")')
52
- .next()
53
- .find('> .rounded-lg')
52
+ .parent()
53
+ .find('.rounded-lg.space-y-2')
54
54
  .each((_, element) => {
55
55
  const $item = $(element);
56
56
 
@@ -60,10 +60,10 @@ async function handler(ctx): Promise<Data> {
60
60
  const domain = $link.find('span').last().text().trim().replaceAll(/[()]/g, '').trim();
61
61
  const link = $link.attr('href');
62
62
 
63
- const $contentDiv = $linkDiv.find('> div').first();
63
+ const $contentDiv = $linkDiv.find('> div.text-sm.text-gray-500');
64
64
  const content = $contentDiv.find('p').text().trim();
65
65
 
66
- const dateStr = $item.children('div').last().text().trim();
66
+ const dateStr = $item.find('.text-xs.text-gray-500 span').text().trim();
67
67
 
68
68
  if (link && title && dateStr) {
69
69
  items.push({
@@ -90,11 +90,19 @@ const parseList = async (
90
90
  if ($1('#seo-article-page').text() === '') {
91
91
  // HK
92
92
  title = $1('h1.article-title').text();
93
- time = new Date(JSON.parse($1("head script[type='application/ld+json']").eq(1).text())?.datePublished);
93
+ const jsonText = $1("head script[type='application/ld+json']")
94
+ .eq(1)
95
+ .text()
96
+ .replaceAll(/[\u0000-\u001F\u007F-\u009F]/g, '');
97
+ time = new Date(JSON.parse(jsonText)?.datePublished);
94
98
  } else {
95
99
  // SG
96
- title = JSON.parse($1('#seo-article-page').text())['@graph'][0]?.headline;
97
- time = new Date(JSON.parse($1('#seo-article-page').text())['@graph'][0]?.datePublished);
100
+ const jsonText = $1('#seo-article-page')
101
+ .text()
102
+ .replaceAll(/[\u0000-\u001F\u007F-\u009F]/g, '');
103
+ const json = JSON.parse(jsonText);
104
+ title = json['@graph'][0]?.headline;
105
+ time = new Date(json['@graph'][0]?.datePublished);
98
106
  }
99
107
 
100
108
  $1('.overlay-microtransaction').remove();
@@ -1,7 +1,6 @@
1
1
  import { Route } from '@/types';
2
- import cache from '@/utils/cache';
3
2
  import got from '@/utils/got';
4
- import { getCookieValueByKey, header, processImage } from './utils';
3
+ import { header, getSignedHeader } from './utils';
5
4
  import { parseDate } from '@/utils/parse-date';
6
5
 
7
6
  export const route: Route = {
@@ -30,66 +29,39 @@ export const route: Route = {
30
29
  async function handler(ctx) {
31
30
  const id = ctx.req.param('id');
32
31
 
33
- const zc0 = getCookieValueByKey('z_c0');
32
+ // second: get real data from zhihu
33
+ const apiPath = `/api/v4/members/${id}/answers?limit=7&include=data[*].is_normal,content`;
34
34
 
35
- const headers = {
36
- 'User-Agent': 'ZhihuHybrid com.zhihu.android/Futureve/6.59.0 Mozilla/5.0 (Linux; Android 10; GM1900 Build/QKQ1.190716.003; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/85.0.4183.127 Mobile Safari/537.36',
37
- Referer: `https://www.zhihu.com/people/${id}/answers`,
38
- Cookie: zc0 ? `z_c0=${zc0}` : '',
39
- };
35
+ const signedHeader = await getSignedHeader(`https://www.zhihu.com/people/${id}`, apiPath);
40
36
 
41
- const response = await got({
42
- method: 'get',
43
- url: `https://api.zhihu.com/people/${id}/answers?order_by=created&offset=0&limit=10`,
44
- headers,
37
+ const response = await got(`https://www.zhihu.com${apiPath}`, {
38
+ headers: {
39
+ ...header,
40
+ ...signedHeader,
41
+ Referer: `https://www.zhihu.com/people/${id}/activities`,
42
+ // Authorization: 'oauth c3cef7c66a1843f8b3a9e6a1e3160e20', // hard-coded in js
43
+ },
45
44
  });
46
45
 
47
46
  const data = response.data.data;
48
- let name = data[0].author.name;
49
-
50
- if (name === '知乎用户') {
51
- const userProfile = await cache.tryGet(`zhihu:profile:${id}`, async () => {
52
- const apiPath = `/api/v4/members/${id}`;
47
+ const items = data.map((item) => {
48
+ const title = item.question.title;
49
+ // let description = processImage(detail.content);
50
+ const url = `https://www.zhihu.com/question/${item.question.id}/answer/${item.id}`;
51
+ const author = item.author.name;
52
+ const description = item.content;
53
53
 
54
- const { data } = await got({
55
- method: 'get',
56
- url: `https://www.zhihu.com${apiPath}`,
57
- headers: {
58
- ...header,
59
- Referer: `https://www.zhihu.com/people/${id}`,
60
- },
61
- });
62
- return data;
63
- });
64
- name = userProfile.name;
65
- }
66
-
67
- const items = await Promise.all(
68
- data.map(async (item) => {
69
- let description;
70
- const link = `https://www.zhihu.com/question/${item.question.id}/answer/${item.id}`;
71
- const title = item.question.title;
72
- try {
73
- const detail = await got({
74
- method: 'get',
75
- url: `https://api.zhihu.com/appview/api/v4/answers/${item.id}?include=content&is_appview=true`,
76
- headers,
77
- });
78
- description = processImage(detail.data.content);
79
- } catch {
80
- description = `<a href="${link}" target="_blank">${title}</a>`;
81
- }
82
- return {
83
- title,
84
- description,
85
- pubDate: parseDate(item.created_time * 1000),
86
- link,
87
- };
88
- })
89
- );
54
+ return {
55
+ title,
56
+ author,
57
+ description,
58
+ pubDate: parseDate(item.created_time * 1000),
59
+ link: url,
60
+ };
61
+ });
90
62
 
91
63
  return {
92
- title: `${name}的知乎回答`,
64
+ title: `${data[0].author.name}的知乎回答`,
93
65
  link: `https://www.zhihu.com/people/${id}/answers`,
94
66
  item: items,
95
67
  };