RSSHub/lib/routes/dgtle/util.ts

201 lines
6.5 KiB
TypeScript

import type { CheerioAPI } from 'cheerio';
import { load } from 'cheerio';
import MarkdownIt from 'markdown-it';
import type { DataItem } from '@/types';
import cache from '@/utils/cache';
import ofetch from '@/utils/ofetch';
import { parseDate } from '@/utils/parse-date';
import { renderDescription } from './templates/description';
const md = MarkdownIt({
html: true,
linkify: true,
});
const baseUrl = 'https://www.dgtle.com';
const ProcessItems = async (limit: number, dataList: any): Promise<DataItem[]> => {
let items: DataItem[] = dataList.slice(0, limit).map((item): DataItem => {
const title: string = item.title || item.content;
const image: string | undefined = item.cover;
const description: string | undefined = renderDescription({
images: image
? [
{
src: image,
alt: title,
},
]
: undefined,
intro: item.content,
});
const pubDate: number | string = item.created_at;
const linkUrl: string | undefined = `${item.live_status === undefined ? (item.category_name ? 'article' : 'news') : 'live'}-${item.id}-1.html`;
const categories: string[] = [...new Set([item.column, item.category_name].filter(Boolean))];
const authors: DataItem['author'] = [
{
name: item.user?.username ?? item.user_name,
url: new URL(`user?uid=${item.user_id}`, baseUrl).href,
avatar: item.user?.avatar_path ?? item.avatar_path,
},
];
const guid = `dgtle-${item.id}`;
const updated: number | string = pubDate;
const processedItem: DataItem = {
title,
description,
pubDate: pubDate ? parseDate(pubDate, 'X') : undefined,
link: new URL(linkUrl, baseUrl).href,
category: categories,
author: authors,
guid,
id: guid,
content: {
html: description,
text: description,
},
image,
banner: image,
updated: updated ? parseDate(updated, 'X') : undefined,
live_status: item.live_status,
};
return processedItem;
});
items = await Promise.all(
items.map((item) => {
if (item.live_status !== undefined || !item.link) {
delete item.live_status;
return item;
}
delete item.live_status;
return cache.tryGet(item.link, async (): Promise<DataItem> => {
const detailResponse = await ofetch(item.link);
const $$: CheerioAPI = load(detailResponse);
$$('div.logo').remove();
$$('p.tip').remove();
$$('p.dgtle').remove();
$$('figure').each((_, el) => {
const $$el = $$(el);
$$el.replaceWith(
renderDescription({
images: [
{
src: $$el
.find('img')
.attr('data-original')
?.replace(/_\d+_\d+_w/, ''),
},
],
})
);
});
const description: string | undefined = renderDescription({
description: $$('div.whale_news_detail-daily-content, div#articleContent, div.forum-viewthread-article-box').html(),
});
const processedItem: DataItem = {
description,
};
return {
...item,
...processedItem,
};
});
})
);
return items;
};
const ProcessFeedItems = (limit: number, dataList: any, $: CheerioAPI): DataItem[] =>
dataList.slice(0, limit).map((item): DataItem => {
const content: string = item.content ? md.render(item.content) : '';
const title: string = $(content).text();
const description: string | undefined = renderDescription({
images: item.imgs_url.map((src) => ({
src,
})),
description: content,
});
const pubDate: number | string = item.created_at;
const linkUrl: string | undefined = item.url;
const categories: string[] = [...new Set((item.tags_info?.map((t) => t.title) ?? []).filter(Boolean) as string[])];
const authors: DataItem['author'] = [
{
name: item.user_name,
url: new URL(`user?uid=${item.encode_uid}`, baseUrl).href,
avatar: item.avatar_path,
},
];
const guid = `dgtle-${item.id}`;
const image: string | undefined = item.imgs_url?.[0];
const updated: number | string = item.updated_at ?? pubDate;
let processedItem: DataItem = {
title,
description,
pubDate: pubDate ? parseDate(pubDate, 'X') : undefined,
link: linkUrl ? new URL(linkUrl, baseUrl).href : undefined,
category: categories,
author: authors,
guid,
id: guid,
content: {
html: description,
text: description,
},
image,
banner: image,
updated: updated ? parseDate(updated, 'X') : undefined,
};
const medias: Record<string, Record<string, string>> = (() => {
const acc: Record<string, Record<string, string>> = {};
for (const media of item.imgs_url) {
const url: string | undefined = media;
if (!url) {
continue;
}
const medium = 'image';
const count: number = Object.values(acc).filter((m) => m.medium === medium).length + 1;
const key = `${medium}${count}`;
acc[key] = {
url,
medium,
title: '',
description: '',
thumbnail: url,
};
}
return acc;
})();
processedItem = {
...processedItem,
media: medias,
};
return processedItem;
});
export { baseUrl, ProcessFeedItems, ProcessItems };