diff --git a/lib/routes/ebc/namespace.ts b/lib/routes/ebc/namespace.ts new file mode 100644 index 00000000000000..83d203397aaef1 --- /dev/null +++ b/lib/routes/ebc/namespace.ts @@ -0,0 +1,6 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: '東森新聞', + url: 'ebc.net.tw', +}; diff --git a/lib/routes/ebc/realtime.ts b/lib/routes/ebc/realtime.ts new file mode 100644 index 00000000000000..b81aa09a89f9c8 --- /dev/null +++ b/lib/routes/ebc/realtime.ts @@ -0,0 +1,94 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { load } from 'cheerio'; +import { parseDate } from '@/utils/parse-date'; + +export const route: Route = { + path: '/realtime/:category?', + categories: ['traditional-media'], + example: '/ebc/realtime/politics', + parameters: { + category: 'Category from the last segment of the URL of the corresponding site', + }, + features: { + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + requireConfig: false, + }, + name: '即時新聞', + maintainers: ['quiniapiezoelectricity'], + handler, + description: '', + radar: [ + { + source: ['news.ebc.net.tw/realtime/:category'], + target: '/:category', + }, + ], +}; + +async function handler(ctx) { + const category = ctx.req.param('category') ?? ''; + const response = await got('https://news.ebc.net.tw/list/load', { + method: 'POST', + headers: { + Accept: '*/*', + 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', + 'X-Requested-With': 'XMLHttpRequest', + }, + body: new URLSearchParams({ + list_type: 'realtime', + cate_code: category, + page: '1', + }).toString(), + }); + const $ = load(response.data); + const feed = $('div.list > a') + .toArray() + .map((item) => new URL($(item).attr('href') ?? '', 'https://news.ebc.net.tw').href); + const items = await Promise.all( + feed.map((url) => + cache.tryGet(url, async () => { + const response = await got(url); + const $ = load(response.data); + const metadata = $('[type="application/ld+json"]') + .toArray() + .flatMap((item) => JSON.parse($(item).text())) + .find((item) => item['@type'] === 'NewsArticle'); + // handle image box + $('.img_box').each((_, elem) => { + $(elem) + .children('div.img_caption') + .replaceWith($(`
${$(elem).children('div.img_caption').text()}
`)); + $(elem).children('div.img').children().unwrap(); + $(elem).wrapInner($('
')); + }); + // handle small text + $('[style="font-size:16px;"]').each((_, elem) => { + $(elem).replaceWith(`${$(elem).text()}`); + }); + const cover = $('div.article_cover'); + const content = $('div.article_content'); + content.find('.inline_text, .inline_box, .rss_box').remove(); + return { + title: metadata.headline, + link: url, + pubDate: parseDate(metadata.datePublished), + author: metadata.author.name, + description: cover.html() + content.html(), + category: metadata.keywords ? [metadata.articleSection, ...metadata.keywords.split(',')] : [metadata.articleSection], + }; + }) + ) + ); + return { + title: '東森新聞|即時', + link: category ? `https://news.ebc.net.tw/realtime/${category}` : 'https://news.ebc.net.tw/realtime', + language: 'zh-TW', + item: items, + }; +}