From a4e0dfe6624f0b08ac6a1f2322a34917fd17195b Mon Sep 17 00:00:00 2001 From: quiniapiezoelectricity <73748843+quiniapiezoelectricity@users.noreply.github.com> Date: Wed, 18 Sep 2024 16:29:52 +0100 Subject: [PATCH] =?UTF-8?q?feat(route):=20add=20/app=20route=20for=20?= =?UTF-8?q?=E7=AB=AF=E4=BC=A0=E5=AA=92=20(#16775)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add /theinitium/app route * Update app.ts * change to spread operator * fix duplicate categories * api change * fix * Update app.ts * Apply suggestions from code review * description update * Update app.ts --- lib/routes/theinitium/app.ts | 137 ++++++++++++++++++ .../theinitium/templates/description.art | 17 +++ 2 files changed, 154 insertions(+) create mode 100644 lib/routes/theinitium/app.ts create mode 100644 lib/routes/theinitium/templates/description.art diff --git a/lib/routes/theinitium/app.ts b/lib/routes/theinitium/app.ts new file mode 100644 index 00000000000000..fbf38a24dc1d4e --- /dev/null +++ b/lib/routes/theinitium/app.ts @@ -0,0 +1,137 @@ +import { Route } from '@/types'; +import cache from '@/utils/cache'; +import got from '@/utils/got'; +import { load } from 'cheerio'; +import { art } from '@/utils/render'; +import path from 'node:path'; +import { config } from '@/config'; +import { getCurrentPath } from '@/utils/helpers'; + +export const route: Route = { + path: '/app/:category?', + categories: ['new-media'], + example: '/theinitium/app', + parameters: { + category: 'Category, see below, latest_sc by default', + }, + features: { + requirePuppeteer: false, + antiCrawler: false, + supportBT: false, + supportPodcast: false, + supportScihub: false, + }, + name: 'App', + maintainers: ['quiniapiezoelectricity'], + radar: [ + { + source: ['app.theinitium.com/t/latest/:category'], + target: '/app/:category', + }, + ], + handler, + description: `抓取[The Initium App](https://app.theinitium.com/)的文章列表 + +:::warning +此路由暂不支持登陆认证 +::: + +Category 栏目: + +| ----- | 简体中文 | 繁體中文 | +| ----- | ----------------- | ---------------- | +| 最新 | latest_sc | latest_tc | +| 日报 | daily_brief_sc | daily_brief_tc | +| 速递 | whats_new_sc | whats_new_tc | +| 专题 | report_sc | report_tc | +| 评论 | opinion_sc | opinion_tc | +| 国际 | international_sc | international_tc | +| 大陆 | mainland_sc | mainland_tc | +| 香港 | hongkong_sc | hongkong_tc | +| 台湾 | taiwan_sc | taiwan_tc | +| 播客 | article_audio_sc | article_audio_tc |`, +}; + +async function handler(ctx) { + const category = ctx.req.param('category') ?? 'latest_sc'; + const __dirname = getCurrentPath(import.meta.url); + + const feedListLink = 'https://app.theinitium.com/timelines.json'; + + const feedList = await cache.tryGet( + feedListLink, + async () => + await got({ + method: 'get', + url: feedListLink, + }), + config.cache.routeExpire, + false + ); + + const feedInfo = feedList.data.timelines.find((timeline) => timeline.id === category); + + const link = `https://app.theinitium.com${feedInfo.feed.slice(1)}`; + + const feedResponse = await got({ + method: 'get', + url: link, + }); + + const feed = feedResponse.data.stories.filter((item) => item.type === 'article'); + + const items = await Promise.all( + feed.map((item) => + cache.tryGet('https://app.theinitium.com/' + item.url.replaceAll('../', ''), async () => { + item.link = 'https://app.theinitium.com/' + item.url.replaceAll('../', ''); + item.description = item.summary; + item.pubDate = item.published; + item.category = []; + if (item.section) { + item.category = [...item.category, item.section]; + } + if (item.taxonomy) { + if (item.taxonomy.collection_tag) { + item.category = [...item.category, ...item.taxonomy.collection_tag]; + } + if (item.taxonomy.sections) { + item.category = [...item.category, ...item.taxonomy.sections]; + } + } + item.category = [...new Set(item.category)]; + const response = await got(item.link); + const $ = load(response.data); + const article = $('.pp-article__body'); + article.find('.block-related-articles').remove(); + item.description = art(path.join(__dirname, 'templates/description.art'), { + header: $('.pp-header-group__standfirst').html(), + coverImage: $('.pp-media__image').attr('src'), + coverCaption: $('.pp-media__caption').html(), + article: article.html(), + copyright: $('.copyright').html(), + }); + return item; + }) + ) + ); + + let lang; + let titleLoc; + if (feedInfo.timeline_sets[0] === 'chinese-simplified') { + lang = 'zh-hans'; + titleLoc = '端传媒'; + } else if (feedInfo.timeline_sets[0] === 'chinese-traditional') { + lang = 'zh-hant'; + titleLoc = '端傳媒'; + } else { + lang = 'zh-hans'; + titleLoc = '端传媒'; + } + + return { + title: `${titleLoc} - ${feedInfo.title}`, + link: `https://app.theinitium.com/t/latest/${category}/`, + language: lang, + item: items, + }; +} diff --git a/lib/routes/theinitium/templates/description.art b/lib/routes/theinitium/templates/description.art new file mode 100644 index 00000000000000..c0e09d15d56bfc --- /dev/null +++ b/lib/routes/theinitium/templates/description.art @@ -0,0 +1,17 @@ +{{ if header }} +

{{ header }}

+{{ /if }} +{{ if coverImage}} +
+ + {{ if coverCaption }} +
{{ coverCaption }}
+ {{ /if }} +
+{{ /if }} +{{ if article }} + {{@ article }} +{{ /if }} +{{ if copyright }} +
{{@ copyright }}
+{{ /if }} \ No newline at end of file