rsshub
Version:
Make RSS Great Again!
78 lines (71 loc) • 2.59 kB
text/typescript
import { Route, ViewType } from '@/types';
import { load } from 'cheerio';
import ofetch from '@/utils/ofetch';
import rssParser from '@/utils/rss-parser';
import { parseArticle } from './utils';
import pMap from 'p-map';
const parseAuthorNewsList = async (slug) => {
const baseURL = `https://www.bloomberg.com/authors/${slug}`;
const apiUrl = `https://www.bloomberg.com/lineup/api/lazy_load_author_stories?slug=${slug}&authorType=default&page=1`;
const resp = await ofetch(apiUrl);
// Likely rate limited
if (!resp.html) {
return [];
}
const $ = load(resp.html);
const articles = $('article.story-list-story');
return articles.toArray().map((item) => {
item = $(item);
const headline = item.find('a.story-list-story__info__headline-link');
return {
title: headline.text(),
pubDate: item.attr('data-updated-at'),
guid: `bloomberg:${item.attr('data-id')}`,
link: new URL(headline.attr('href'), baseURL).href,
};
});
};
export const route: Route = {
path: '/authors/:id/:slug/:source?',
categories: ['finance'],
view: ViewType.Articles,
example: '/bloomberg/authors/ARbTQlRLRjE/matthew-s-levine',
parameters: { id: 'Author ID, can be found in URL', slug: 'Author Slug, can be found in URL', source: 'Data source, either `api` or `rss`,`api` by default' },
features: {
requireConfig: false,
requirePuppeteer: false,
antiCrawler: true,
supportBT: false,
supportPodcast: false,
supportScihub: false,
},
radar: [
{
source: ['www.bloomberg.com/*/authors/:id/:slug', 'www.bloomberg.com/authors/:id/:slug'],
target: '/authors/:id/:slug',
},
],
name: 'Authors',
maintainers: ['josh', 'pseudoyu'],
handler,
};
async function handler(ctx) {
const { id, slug, source } = ctx.req.param();
const link = `https://www.bloomberg.com/authors/${id}/${slug}`;
let list = [];
if (!source || source === 'api') {
list = await parseAuthorNewsList(`${id}/${slug}`);
}
// Fallback to rss if api failed or requested by param
if (source === 'rss' || list.length === 0) {
list = (await rssParser.parseURL(`${link}.rss`)).items;
}
const item = await pMap(list, (item) => parseArticle(item), { concurrency: 1 });
const authorName = item.find((i) => i.author)?.author ?? slug;
return {
title: `Bloomberg - ${authorName}`,
link,
language: 'en-us',
item,
};
}