From 457a47fc43d2ff66057e205ac9d7db13b8d2e705 Mon Sep 17 00:00:00 2001 From: Tony Date: Wed, 1 May 2024 07:19:07 +0800 Subject: [PATCH] feat(route): yenpress (#15419) * feat(route): yenpress * fix: duplicate category --- lib/routes/yenpress/namespace.ts | 7 ++ lib/routes/yenpress/series.ts | 115 +++++++++++++++++++++++ lib/routes/yenpress/templates/series.art | 25 +++++ 3 files changed, 147 insertions(+) create mode 100644 lib/routes/yenpress/namespace.ts create mode 100644 lib/routes/yenpress/series.ts create mode 100644 lib/routes/yenpress/templates/series.art diff --git a/lib/routes/yenpress/namespace.ts b/lib/routes/yenpress/namespace.ts new file mode 100644 index 00000000000000..2749ef6d48edf1 --- /dev/null +++ b/lib/routes/yenpress/namespace.ts @@ -0,0 +1,7 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: 'Yen Press', + url: 'yenpress.com', + categories: ['reading'], +}; diff --git a/lib/routes/yenpress/series.ts b/lib/routes/yenpress/series.ts new file mode 100644 index 00000000000000..e953ac205aea7c --- /dev/null +++ b/lib/routes/yenpress/series.ts @@ -0,0 +1,115 @@ +import { DataItem, Route } from '@/types'; +import type { Context } from 'hono'; + +import ofetch from '@/utils/ofetch'; +import cache from '@/utils/cache'; +import * as cheerio from 'cheerio'; +import timezone from '@/utils/timezone'; +import { parseDate } from '@/utils/parse-date'; +import { art } from '@/utils/render'; +import path from 'node:path'; +import { getCurrentPath } from '@/utils/helpers'; + +const __dirname = getCurrentPath(import.meta.url); + +const render = (data) => art(path.join(__dirname, 'templates', 'series.art'), data); + +export const route: Route = { + path: '/series/:name', + example: '/yenpress/series/alya-sometimes-hides-her-feelings-in-russian', + parameters: { name: 'Series name' }, + name: 'Series', + maintainers: ['TonyRL'], + handler, + radar: [ + { + source: ['yenpress.com/series/:name'], + target: '/series/:name', + }, + ], +}; + +async function handler(ctx: Context) { + const { name: series } = ctx.req.param(); + const baseUrl = 'https://yenpress.com'; + const link = `https://yenpress.com/series/${series}`; + + const response = await ofetch(link); + const $ = cheerio.load(response); + + const list = $('.show-more-container .inline_block') + .toArray() + .map((item) => { + const $item = $(item); + return { + title: $item.find('span').text().trim(), + link: new URL($item.find('a').attr('href')!, baseUrl).href, + }; + }) as DataItem[]; + + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link!, async () => { + const response = await ofetch(item.link!); + const $ = cheerio.load(response); + + item.category = $('.detail-labels.mobile-only') + .eq(0) + .find('a') + .toArray() + .map((a) => $(a).text().trim()); + + $('svg, .social-share, .desktop-only, .detail-labels').remove(); + + const cover = $('.book-info').find('.book-cover-img').html(); + + const bookInfo = $('.buy-info .deliver') + .toArray() + .map((item, i) => ({ + deliver: $(item).text().trim(), + price: $('.book-price').eq(i).text().trim(), + from: $('.services') + .eq(i) + .find('.service') + .toArray() + .map((service) => { + const a = $(service).find('a'); + return { + name: a.text().trim(), + link: a.attr('href'), + }; + }), + detail: $('.detail-info') + .eq(i) + .find('div span') + .toArray() + .map((span) => { + const $span = $(span); + return { + key: $span.text().trim(), + value: $span.next().text().trim(), + }; + }), + })); + + const info = $('.book-info'); + info.find('.buy-info, .series-cover').remove(); + + item.description = render({ + cover: cover! + info.html(), + bookInfo, + }); + item.pubDate = timezone(parseDate(bookInfo[0].detail.find((d) => d.key === 'Release Date')!.value), 0); + + return item; + }) + ) + ); + + return { + title: $('head title').text().trim(), + description: $('.social-share p').text().trim(), + link, + item: items, + }; +} diff --git a/lib/routes/yenpress/templates/series.art b/lib/routes/yenpress/templates/series.art new file mode 100644 index 00000000000000..5e108752caddad --- /dev/null +++ b/lib/routes/yenpress/templates/series.art @@ -0,0 +1,25 @@ +{{ if cover }} + {{@ cover }}
+{{ /if }} + +{{ if bookInfo }} + {{ each bookInfo info }} +

{{ info.deliver }}: {{ info.price }}

+ Buy from: + + FULL DETAILS + + {{ each info.detail d }} + + + + + {{ /each }} +
{{ d.key }}{{ d.value }}
+
+ {{ /each }} +{{ /if }}