rsshub
Version:
Make RSS Great Again!
108 lines (93 loc) • 3.06 kB
text/typescript
import { Data, DataItem, Route } from '@/types';
import ofetch from '@/utils/ofetch';
import cache from '@/utils/cache';
import { load } from 'cheerio';
import { parseDate } from '@/utils/parse-date';
const base = 'https://www.jpmorganchase.com';
const frontPageUrl = `${base}/institute/all-topics`;
const indexUrl = `${base}/services/json/v1/dynamic-grid.service/parent=jpmorganchase/global/US/en/home/institute/all-topics&comp=root/content-parsys/dynamic_grid&page=p1.json`;
export const route: Route = {
path: '/',
example: '/jpmorganchase',
categories: ['finance'],
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: false,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['jpmorganchase.com/institute/all-topics'],
target: '/',
},
],
name: 'Research Topics',
maintainers: ['dousha'],
handler,
url: 'www.jpmorganchase.com/institute/all-topics',
};
type PartitionMeta = {
'total-items': number;
page: number;
'page-size': number;
'max-pages': number;
'partition-size': string;
};
type IndexEntry = {
title: string;
date: string;
hideDate: boolean;
description: string;
type: string;
link: string;
linkText: string;
image: string;
};
async function fetchIndexEntires(): Promise<IndexEntry[]> {
const response = await ofetch(indexUrl);
if (!('meta' in response)) {
return [];
}
const meta = response.meta as PartitionMeta;
const maxItemCount = Number(meta['partition-size']);
return (response.items as IndexEntry[]).slice(0, maxItemCount);
}
function fetchDataItem(entry: IndexEntry): Promise<DataItem> {
const url = `${base}${entry.link}`;
return cache.tryGet(url, async () => {
let authors: string[] = [];
let description: string = '';
let category: string[] = [];
let articleDate: string = entry.date;
const pageContent: string = await ofetch(url);
if (pageContent.length > 0) {
const $ = load(pageContent);
category = [$('.eyebrow').text()];
authors = $('.author-name')
.toArray()
.map((el) => $(el).text().trim());
articleDate = $('.date').text().trim() || entry.date;
description = $('.root').children('div').children('div:eq(1)').html() || '';
}
return {
category,
author: authors.join(', '),
title: entry.title,
description,
link: url,
pubDate: parseDate(articleDate),
} satisfies DataItem;
}) as Promise<DataItem>;
}
async function handler(): Promise<Data> {
const entires = await fetchIndexEntires();
const items = await Promise.all(entires.map((it) => fetchDataItem(it)));
return {
title: 'All Topics - JPMorganChase Institute',
link: frontPageUrl,
item: items,
};
}