From 2c04940a6fe39094b523a5b4bbc839b17bb44ad9 Mon Sep 17 00:00:00 2001 From: Andvari <31068367+dzx-dzx@users.noreply.github.com> Date: Sun, 14 Jul 2024 23:12:03 +0800 Subject: [PATCH] feat(route/mirrormedia): Add route for category. (#16138) * feat(route/mirrormedia): Add route for category. * Fix pubDate. * . * Update filter.ts * . * . * . --- lib/routes/mirrormedia/category.ts | 100 +++++++++++++++++++++++++++++ lib/routes/mirrormedia/index.ts | 19 +----- lib/routes/mirrormedia/utils.ts | 20 ++++++ 3 files changed, 123 insertions(+), 16 deletions(-) create mode 100644 lib/routes/mirrormedia/category.ts create mode 100644 lib/routes/mirrormedia/utils.ts diff --git a/lib/routes/mirrormedia/category.ts b/lib/routes/mirrormedia/category.ts new file mode 100644 index 00000000000000..b8156caa231c54 --- /dev/null +++ b/lib/routes/mirrormedia/category.ts @@ -0,0 +1,100 @@ +import { Route } from '@/types'; + +import { parseDate } from '@/utils/parse-date'; +import ofetch from '@/utils/ofetch'; +import { getArticle } from './utils'; + +export const route: Route = { + path: ['/category/:category', '/section/:section'], + categories: ['traditional-media'], + example: '/mirrormedia/category/political', + parameters: { category: '分类名', section: '子板名' }, + name: '分类', + maintainers: ['dzx-dzx'], + radar: [ + { + source: ['mirrormedia.mg/category/:category', 'mirrormedia.mg/section/:section'], + }, + ], + handler, +}; + +async function handler(ctx) { + const { category, section } = ctx.req.param(); + const categoryFilter = category ? { categories: { some: { slug: { equals: category } } } } : {}; + const sectionFilter = section ? { sections: { some: { slug: { equals: section } } } } : {}; + const rootUrl = 'https://www.mirrormedia.mg'; + + const response = await ofetch('https://adam-weekly-api-server-prod-ufaummkd5q-de.a.run.app/content/graphql', { + method: 'POST', + body: { + variables: { + take: ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 24, + skip: 0, + orderBy: { publishedDate: 'desc' }, + filter: { + state: { equals: 'published' }, + ...categoryFilter, ...sectionFilter, + }, + }, + query: ` +fragment section on Section { + id + name + slug + state + __typename +} + +fragment category on Category { + id + name + slug + state + __typename +} + +fragment listingPost on Post { + id + slug + title + brief + publishedDate + state + sections(where: {state: {equals: "active"}}) { + ...section + __typename + } + categories(where: {state: {equals: "active"}}) { + ...category + __typename + } + isFeatured + __typename +} + +query ($take: Int, $skip: Int, $orderBy: [PostOrderByInput!]!, $filter: PostWhereInput!) { + postsCount(where: $filter) + posts(take: $take, skip: $skip, orderBy: $orderBy, where: $filter) { + ...listingPost + __typename + } +}`, + }, + }); + + const items = response.data.posts.map((e) => ({ + title: e.title, + pubDate: parseDate(e.publishedDate), + category: [...(e.sections ?? []).map((_) => `section:${_.name}`), ...(e.categories ?? []).map((_) => `category:${_.name}`)], + link: `${rootUrl}/${'story'}/${e.slug}`, + })); + + const list = await Promise.all(items.map((item) => getArticle(item))); + + return { + title: `鏡週刊 Mirror Media - ${category}`, + link: rootUrl, + item: list, + }; +} diff --git a/lib/routes/mirrormedia/index.ts b/lib/routes/mirrormedia/index.ts index 87d5df88f5025b..75d14b6d2f9ee8 100644 --- a/lib/routes/mirrormedia/index.ts +++ b/lib/routes/mirrormedia/index.ts @@ -1,9 +1,8 @@ import { Route } from '@/types'; -import { load } from 'cheerio'; import { parseDate } from '@/utils/parse-date'; -import cache from '@/utils/cache'; import ofetch from '@/utils/ofetch'; +import { getArticle } from './utils'; export const route: Route = { path: '/', @@ -28,25 +27,13 @@ async function handler(ctx) { const items = [...response.choices.map((e) => ({ __from: 'choices', ...e })), ...response.latest.map((e) => ({ __from: 'latest', ...e }))] .map((e) => ({ title: e.title, - pubDate: parseDate(e.publishDate), + pubDate: parseDate(e.publishedDate), category: [...(e.sections ?? []).map((_) => _.name), e.__from], link: `${rootUrl}/${e.style === '' ? 'external' : 'story'}/${e.slug}`, })) .slice(0, ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit'), 10) : 20); - const list = await Promise.all( - items.map((item) => - cache.tryGet(item.link, async () => { - const detailResponse = await ofetch(item.link); - - const content = load(detailResponse); - - item.description = content("div[data-contents='true']").html(); - - return item; - }) - ) - ); + const list = await Promise.all(items.map((item) => getArticle(item))); return { title: '鏡週刊 Mirror Media', diff --git a/lib/routes/mirrormedia/utils.ts b/lib/routes/mirrormedia/utils.ts new file mode 100644 index 00000000000000..7d991863aec0b9 --- /dev/null +++ b/lib/routes/mirrormedia/utils.ts @@ -0,0 +1,20 @@ +import { load } from 'cheerio'; +import cache from '@/utils/cache'; +import ofetch from '@/utils/ofetch'; + +export function getArticle(item) { + return cache.tryGet(item.link, async () => { + const detailResponse = await ofetch(item.link); + + const content = load(detailResponse); + + item.description = item.link.includes('external') + ? content(':is([class^=external-article-brief],[class^=external-article-content])').html() + : content(':is([class^=brief__BriefContainer],[class^=article-content__Wrapper])').html(); + + item.category = [...item.category, ...(content("meta[name='keywords']").attr("content") ?? "").split(",")]; + + + return item; + }); +}