diff --git a/lib/v2/readhub/index.js b/lib/v2/readhub/index.js
index 20f5281fe6..2f79c9700f 100644
--- a/lib/v2/readhub/index.js
+++ b/lib/v2/readhub/index.js
@@ -1,106 +1,115 @@
const got = require('@/utils/got');
+const cheerio = require('cheerio');
+const timezone = require('@/utils/timezone');
const { parseDate } = require('@/utils/parse-date');
-
-const titles = {
- topic: '热门话题',
- news: '科技动态',
- tech: '技术资讯',
- technews: '技术资讯',
- blockchain: '区块链快讯',
- daily: '每日早报',
-};
+const { art } = require('@/utils/render');
+const path = require('path');
+const dayjs = require('dayjs');
module.exports = async (ctx) => {
- let category = 'topic';
- let overview = false;
- if (titles[ctx.params.category]) {
- category = ctx.params.category;
- overview = !!ctx.params.overview;
- category = category === 'tech' ? 'technews' : category;
- } else if (ctx.params.category) {
- overview = true;
- }
+ const { category } = ctx.params;
+ const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 20;
- const rootUrl = 'https://readhub.cn';
- const apiRootUrl = 'https://api.readhub.cn';
- const currentUrl = `${rootUrl}/topic/${category}`;
- const apiUrl = `${apiRootUrl}/${category === 'daily' ? 'topic/daily' : category}`;
+ const domain = 'readhub.cn';
+ const rootUrl = `https://${domain}`;
+ const apiRootUrl = `https://api.${domain}`;
+ const currentUrl = new URL(category ?? '', rootUrl).href;
- const response = await got({
- method: 'get',
- url: apiUrl,
+ const isCategory = !category || category === 'daily';
+
+ const formatDate = (date, format) => dayjs(date).format(format);
+ const toTopicUrl = (id) => new URL(`topic/${id}`, rootUrl).href;
+
+ art.defaults.imports = {
+ ...art.defaults.imports,
+ ...{
+ formatDate,
+ toTopicUrl,
+ },
+ };
+
+ const { data: currentResponse } = await got(currentUrl);
+
+ const buildId = currentResponse.match(/"buildId":"(\w+)"/)[1];
+
+ const apiUrl = new URL(category ? (category === 'daily' ? `_next/data/${buildId}/daily.json` : 'news/list') : 'topic/list', category === 'daily' ? rootUrl : apiRootUrl).href;
+
+ const { data: response } = await got(apiUrl, {
+ searchParams: {
+ ...(isCategory
+ ? {}
+ : {
+ type: currentResponse.match(/"query":\{"type":"(\d+)"\}/)[1],
+ }),
+ ...{
+ page: 1,
+ size: limit,
+ },
+ },
});
- const list = response.data.data.map((item) => ({
- id: item.id,
+ let items = (response.data?.items ?? response.pageProps.daily).slice(0, limit).map((item) => ({
title: item.title,
- pubDate: parseDate(item.publishDate),
- description: item.summaryAuto || item.summary || '',
- link: item.url || item.mobileUrl || `${rootUrl}/topic/${item.id}`,
- author: item.authorName || item.siteName || '',
- hasInstantView: item.hasInstantView || false,
+ link: item.url ?? new URL(`topic/${item.uid}`, rootUrl).href,
+ description: art(path.join(__dirname, 'templates/description.art'), {
+ description: item.summary,
+ news: item.newsAggList,
+ timeline: item.timeline,
+ }),
+ author: item.siteNameDisplay,
+ category: item.tagList?.map((c) => c.name) ?? [],
+ guid: isCategory ? item.uid : `readhub-${item.guid}`,
+ pubDate: timezone(parseDate(item.publishDate), +8),
}));
- const items = await Promise.all(
- list.map((item) =>
- ctx.cache.tryGet(item.id + overview, async () => {
- if (item.hasInstantView || category === 'daily') {
- const { data } = await got({
- method: 'get',
- url: `${apiRootUrl}/topic/instantview?topicId=${item.id}`,
+ if (isCategory) {
+ items = await Promise.all(
+ items.map((item) =>
+ ctx.cache.tryGet(`readhub-${item.guid}`, async () => {
+ const { data: detailResponse } = await got(new URL(`_next/data/${buildId}/topic/${item.guid}.json`, rootUrl).href);
+
+ const data = detailResponse.pageProps.topic;
+
+ item.title = data.title;
+ item.link = data.url ?? new URL(`topic/${data.uid}`, rootUrl).href;
+ item.description = art(path.join(__dirname, 'templates/description.art'), {
+ description: data.summary,
+ news: data.newsAggList,
+ timeline: data.timeline,
});
+ item.author = data.entityList.map((a) => a.name).join('/');
+ item.category = data.tagList.map((c) => c.name);
+ item.guid = `readhub-${data.uid}`;
+ item.pubDate = timezone(parseDate(data.publishDate), +8);
- item.description = `访问原网址
${!overview ? data.content : ''}`;
- }
+ return item;
+ })
+ )
+ );
+ }
- if (isNaN(item.id)) {
- const { data } = await got({
- method: 'get',
- url: `${apiRootUrl}/topic/${item.id}`,
- });
+ const $ = cheerio.load(currentResponse);
- if (data.summary && overview) {
- item.description += `${data.summary}
{{ description }}
+{{ /if }} + +{{ if news }} +| + {{ n.title }} + | ++ {{ n.siteNameDisplay }} + | +
|---|
| + {{ t.publishDate | formatDate 'YYYY-MM-DD HH:mm:ss' }} + | ++ {{ t.title }} + | +
|---|