mirror of
https://github.com/DIYgod/RSSHub.git
synced 2026-09-01 14:57:14 +08:00
feat(route): kakuyomu (#16679)
* feat(route): kakuyomu * remove any types
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
import type { Namespace } from '@/types';
|
||||
|
||||
export const namespace: Namespace = {
|
||||
name: 'カクヨム',
|
||||
url: 'kakuyomu.jp',
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
export interface NextDataEpisode {
|
||||
__typename: 'Episode';
|
||||
id: string;
|
||||
title: string;
|
||||
publishedAt: string;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { Data, DataItem, Route } from '@/types';
|
||||
import { load } from 'cheerio';
|
||||
import type { Context } from 'hono';
|
||||
import ofetch from '@/utils/ofetch';
|
||||
import cache from '@/utils/cache';
|
||||
import type { NextDataEpisode } from './types';
|
||||
import { parseDate } from '@/utils/parse-date';
|
||||
|
||||
export const route: Route = {
|
||||
name: '投稿',
|
||||
categories: ['reading'],
|
||||
path: '/works/:id',
|
||||
example: '/kakuyomu/works/1177354054894027232',
|
||||
parameters: {
|
||||
id: '投稿 ID',
|
||||
},
|
||||
maintainers: ['KarasuShin'],
|
||||
handler,
|
||||
features: {
|
||||
supportRadar: true,
|
||||
},
|
||||
radar: [
|
||||
{
|
||||
source: ['kakuyomu.jp/works/:id'],
|
||||
target: '/works/:id',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
async function handler(ctx: Context): Promise<Data> {
|
||||
const id = ctx.req.param('id');
|
||||
const url = `https://kakuyomu.jp/works/${id}`;
|
||||
const limit = Number.parseInt(ctx.req.query('limit') || '10');
|
||||
const $ = load(await ofetch(url));
|
||||
|
||||
const nextData = JSON.parse($('#__NEXT_DATA__').text());
|
||||
|
||||
const {
|
||||
props: {
|
||||
pageProps: { __APOLLO_STATE__ },
|
||||
},
|
||||
} = nextData;
|
||||
|
||||
const {
|
||||
[`Work:${id}`]: { title, catchphrase },
|
||||
} = __APOLLO_STATE__;
|
||||
|
||||
const values = Object.values(__APOLLO_STATE__);
|
||||
const episodes = values.filter((value) => value.__typename === 'Episode') as NextDataEpisode[];
|
||||
const items = (await Promise.all(
|
||||
episodes
|
||||
.sort((a, b) => b.publishedAt.localeCompare(a.publishedAt))
|
||||
.slice(0, limit)
|
||||
.map((item) => {
|
||||
const episodeUrl = `https://kakuyomu.jp/works/${id}/episodes/${item.id}`;
|
||||
return cache.tryGet(episodeUrl, async () => {
|
||||
const $ = load(await ofetch(episodeUrl));
|
||||
const description = $('.widget-episodeBody').html();
|
||||
return {
|
||||
title: item.title,
|
||||
description,
|
||||
pubDate: parseDate(item.publishedAt),
|
||||
};
|
||||
});
|
||||
})
|
||||
)) as DataItem[];
|
||||
|
||||
return {
|
||||
title,
|
||||
description: catchphrase,
|
||||
item: items,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user