RSSHub/lib/v2/latepost/index.js

117 lines
4.1 KiB
JavaScript

const got = require('@/utils/got');
const cheerio = require('cheerio');
const timezone = require('@/utils/timezone');
const { parseDate, parseRelativeDate } = require('@/utils/parse-date');
/**
* Convert an array into a dictionary object.
* The keys of the dictionary object are the `id` properties of the elements in the array,
* and the values are the remaining properties of each element.
* @param {Array} arr - The array to be converted.
* @returns {Object} - The converted dictionary object.
*/
const arrayToDictionary = (arr) =>
arr.reduce(
(dictionary, { id, ...rest }) => ({
...dictionary,
[id]: {
...rest,
},
}),
{}
);
module.exports = async (ctx) => {
const { proma } = ctx.params;
const limit = ctx.query.limit ? parseInt(ctx.query.limit, 10) : 5;
const title = '晚点';
const defaultTitle = '最新报道';
const exclusiveCategory = '晚点独家';
const rootUrl = 'https://www.latepost.com';
const currentUrl = new URL(proma ? `news/index?proma=${proma}` : '', rootUrl).href;
const apiColumnUrl = new URL('site/get-column', rootUrl).href;
const apiCommentUrl = new URL('news/get-comment', rootUrl).href;
const apiUrl = new URL(proma ? 'news/get-news-data' : 'site/index', rootUrl).href;
const { data: columnResponse } = await got(apiColumnUrl);
const columns = arrayToDictionary(columnResponse?.data ?? []);
const { data: response } = await got.post(apiUrl, {
form: {
page: 1,
limit,
programa: parseInt(proma, 10),
},
});
let items = response.data.slice(0, limit).map((item) => ({
title: item.title,
link: new URL(item.detail_url, rootUrl).href,
category: [item.is_dj ? exclusiveCategory : undefined, item.programa ? columns[item.programa].title : undefined, ...item.label.map((c) => c.label)],
guid: item.id,
pubDate: parseDate(item.release_time, ['MM月DD日', 'YYYY年MM月DD日']),
}));
items = await Promise.all(
items.map((item) =>
ctx.cache.tryGet(item.link, async () => {
const { data: detailResponse } = await got(item.link);
const { data: commentResponse } = await got.post(apiCommentUrl, {
news_id: item.guid,
page: 1,
limit: Infinity,
sort: 1,
delete_num: 0,
});
const content = cheerio.load(detailResponse);
item.title = item.title ?? content('div.article-header-title').text();
item.description = content('#select-main')
.html()
.replace(/<p><br><\/p>/g, '');
item.author = content('div.article-header-author div.author-link a.label').first().text();
item.category = item.category.filter((c) => c);
item.guid = `latepost-${item.guid}`;
const pubDate = content('div.article-header-date').text();
if (pubDate) {
if (/\d+月\d+日/.test(pubDate)) {
item.pubDate = parseDate(pubDate, ['MM月DD日 HH:mm', 'YYYY年MM月DD日 HH:mm']);
} else {
item.pubDate = parseRelativeDate(pubDate);
}
}
item.pubDate = timezone(item.pubDate, +8);
item.comments = commentResponse.data?.length() ?? 0;
return item;
})
)
);
const icon = new URL('favicon.ico', rootUrl).href;
const { data: currentResponse } = await got(currentUrl);
const $ = cheerio.load(currentResponse);
ctx.state.data = {
item: items,
title: `${title} - ${proma ? columns[proma].title : defaultTitle}`,
link: currentUrl,
description: $('div.logo-txt').first().text(),
language: 'zh-cn',
image: new URL($('div.logo-txt img').prop('src'), rootUrl).href,
icon,
logo: icon,
author: title,
};
};