mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-10-17 05:11:57 +08:00
fix(modb): cache article bodies with bounded detail requests
This commit is contained in:
+33
-12
@@ -1,5 +1,6 @@
|
||||
import { load } from 'cheerio';
|
||||
import { escapeUTF8 } from 'entities/escape';
|
||||
import pMap from 'p-map';
|
||||
|
||||
import type { DataItem, Route } from '@/types';
|
||||
import cache from '@/utils/cache';
|
||||
@@ -34,6 +35,20 @@ interface TopicDoc {
|
||||
tags?: string[];
|
||||
}
|
||||
|
||||
class ArticleBodyUnavailableError extends Error {}
|
||||
|
||||
const getArticleDescription = (link: string) =>
|
||||
cache.tryGet(`modb:topic:article-body:v1:${link}`, async () => {
|
||||
const response = await ofetch(link);
|
||||
const $ = load(response);
|
||||
const article = $('div.editor-content-styl.article-style').first();
|
||||
article.find('script, style').remove();
|
||||
if (!article.text().trim() && !article.find('img, video, audio, iframe, table').length) {
|
||||
throw new ArticleBodyUnavailableError(`The MODB article does not expose a public body: ${link}`);
|
||||
}
|
||||
return { description: article.html()! };
|
||||
});
|
||||
|
||||
async function handler(ctx) {
|
||||
const baseUrl = 'https://www.modb.pro';
|
||||
const topicId = ctx.req.param('id');
|
||||
@@ -44,7 +59,7 @@ async function handler(ctx) {
|
||||
columnId: topicId,
|
||||
},
|
||||
});
|
||||
const list = response.list.flatMap((item): Array<DataItem & { link: string }> => {
|
||||
const list: Array<DataItem & { link: string }> = response.list.flatMap((item): Array<DataItem & { link: string }> => {
|
||||
const doc: TopicDoc | undefined = item.type === 0 ? item.knowledge : item.type === 1 ? item.dbDoc : undefined;
|
||||
if (!doc?.title || item.rid === undefined || item.rid === null) {
|
||||
logger.error(`Unsupported or incomplete topic entry of type ${item.type}`);
|
||||
@@ -64,17 +79,23 @@ async function handler(ctx) {
|
||||
];
|
||||
});
|
||||
|
||||
const items = await Promise.all(
|
||||
list.map((item) =>
|
||||
item.description === undefined
|
||||
? cache.tryGet(item.link, async () => {
|
||||
const response = await ofetch(item.link);
|
||||
const $ = load(response);
|
||||
item.description = $('div.editor-content-styl.article-style').first().html();
|
||||
return item;
|
||||
})
|
||||
: item
|
||||
)
|
||||
const items = await pMap(
|
||||
list,
|
||||
async (item) => {
|
||||
if (item.description !== undefined) {
|
||||
return item;
|
||||
}
|
||||
try {
|
||||
const details = await getArticleDescription(item.link);
|
||||
return { ...item, ...details };
|
||||
} catch (error) {
|
||||
if (error instanceof ArticleBodyUnavailableError) {
|
||||
return item;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
{ concurrency: 3 }
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user