diff --git a/lib/routes/meritalk/articles.ts b/lib/routes/meritalk/articles.ts new file mode 100644 index 000000000..a602e2b50 --- /dev/null +++ b/lib/routes/meritalk/articles.ts @@ -0,0 +1,80 @@ +import { load } from 'cheerio'; + +import type { Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { parseDate } from '@/utils/parse-date'; + +import { renderDescription } from './templates/description'; + +export const route: Route = { + path: '/articles', + categories: ['new-media'], + example: '/meritalk/articles', + features: { + requireConfig: false, + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + radar: [ + { + source: ['meritalk.com/articles/'], + target: '/articles', + }, + ], + name: 'Latest Articles', + maintainers: ['superguyDiluc'], + handler, +}; + +async function handler() { + const baseUrl = 'https://www.meritalk.com/articles'; + + const { data: response } = await got(baseUrl); + const $ = load(response); + + const list = $('div.news-block-sm') + .toArray() + .map((item) => { + const $item = $(item); + const a = $item.find('.news-block-title a'); + const link = a.attr('href'); + return { + title: a.text().trim(), + link: link as string, + pubDate: parseDate($item.find('time[datetime]').attr('datetime') as string), + category: $item + .find('.category-header-name a') + .toArray() + .map((elem) => $(elem).text()), + description: '', + }; + }); + + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link, async () => { + const { data: response } = await got(item.link); + const $ = load(response); + + const featuredImage = $('.single-featured-image').first().html() || ''; + const fullContent = $('.single-body').first().html() || ''; + item!.description = renderDescription({ + featuredImage, + fullContent, + }); + + return item; + }) + ) + ); + + return { + title: 'News – MeriTalk', + link: 'https://www.meritalk.com/articles/', + item: items, + }; +} diff --git a/lib/routes/meritalk/namespace.ts b/lib/routes/meritalk/namespace.ts new file mode 100644 index 000000000..793aef163 --- /dev/null +++ b/lib/routes/meritalk/namespace.ts @@ -0,0 +1,6 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'MeriTalk', + url: 'meritalk.com', +}; diff --git a/lib/routes/meritalk/templates/description.tsx b/lib/routes/meritalk/templates/description.tsx new file mode 100644 index 000000000..f3b6d0045 --- /dev/null +++ b/lib/routes/meritalk/templates/description.tsx @@ -0,0 +1,21 @@ +import { raw } from 'hono/html'; +import { renderToString } from 'hono/jsx/dom/server'; + +type DescriptionParams = { + featuredImage?: string; + fullContent?: string; +}; + +export const renderDescription = ({ featuredImage, fullContent }: DescriptionParams) => + renderToString( + <> + {featuredImage ? ( + <> + {raw(featuredImage)} +
+ + ) : null} + + {fullContent ? raw(fullContent) : null} + + );