diff --git a/lib/config.ts b/lib/config.ts index 87d28699df773..de1d1e9233400 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -270,6 +270,9 @@ export type Config = { skeb: { bearerToken?: string; }; + sorrycc: { + cookie?: string; + }; spotify: { clientId?: string; clientSecret?: string; @@ -663,6 +666,9 @@ const calculateValue = () => { skeb: { bearerToken: envs.SKEB_BEARER_TOKEN, }, + sorrycc: { + cookie: envs.SORRYCC_COOKIES, + }, spotify: { clientId: envs.SPOTIFY_CLIENT_ID, clientSecret: envs.SPOTIFY_CLIENT_SECRET, diff --git a/lib/routes/sorrycc/index.ts b/lib/routes/sorrycc/index.ts new file mode 100644 index 0000000000000..f9f3d6cc50352 --- /dev/null +++ b/lib/routes/sorrycc/index.ts @@ -0,0 +1,85 @@ +import { type DataItem, ViewType, type Data, type Route } from '@/types'; +import type { Context } from 'hono'; +import ofetch from '@/utils/ofetch'; +import { load } from 'cheerio'; +import cache from '@/utils/cache'; +import type { Post } from './types'; +import { config } from '@/config'; +import { parseDate } from '@/utils/parse-date'; + +const WORDPRESS_HASH = 'f05fca638390aed897fbe3c2fff03000'; + +export const route: Route = { + name: '文章', + categories: ['blog'], + path: '/', + example: '/sorrycc', + radar: [ + { + source: ['sorrycc.com'], + }, + ], + handler, + maintainers: ['KarasuShin'], + view: ViewType.Articles, + features: { + supportRadar: true, + requireConfig: [ + { + name: 'SORRYCC_COOKIES', + description: `登录用户的Cookie,获取方式:\n1. 登录sorrycc.com\n2. 打开浏览器开发者工具,切换到 Application 面板\n3. 点击侧边栏中的Storage -> Cookies -> https://sorrycc.com\n4. 复制 Cookie 中的 wordpress_logged_in_${WORDPRESS_HASH} 值`, + optional: true, + }, + ], + }, + description: '云谦的博客,部分内容存在权限校验,访问完整内容请部署RSSHub私有实例并配置授权信息', +}; + +async function handler(ctx: Context): Promise { + const host = 'https://sorrycc.com'; + const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')!, 10) : 100; + const cookie = config.sorrycc.cookie; + + const data = await ofetch(`${host}/wp-json/wp/v2/posts?per_page=${limit}`); + + const items: DataItem[] = await Promise.all( + data.map(async (item) => { + const title = item.title.rendered; + const link = item.link; + const published = parseDate(item.date_gmt); + const updated = parseDate(item.modified_gmt); + if (item.categories.includes(7) && cookie) { + return (await cache.tryGet(link, async () => { + const article = await ofetch(link, { + headers: { + Cookie: `wordpress_logged_in_${WORDPRESS_HASH}=${cookie}`, + }, + }); + const $article = load(article); + const description = $article('.content').html(); + return { + title, + description, + link, + published, + updated, + }; + })) as unknown as DataItem; + } + return { + title, + description: item.content.rendered, + link, + published, + updated, + } as DataItem; + }) + ); + + return { + title: '文章', + item: items, + link: host, + image: `${host}/wp-content/uploads/2024/01/cropped-CC-1-32x32.png`, + }; +} diff --git a/lib/routes/sorrycc/namespace.ts b/lib/routes/sorrycc/namespace.ts new file mode 100644 index 0000000000000..6c1c27d4ef323 --- /dev/null +++ b/lib/routes/sorrycc/namespace.ts @@ -0,0 +1,6 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: '云谦的博客', + url: 'sorrycc.com', +}; diff --git a/lib/routes/sorrycc/types.ts b/lib/routes/sorrycc/types.ts new file mode 100644 index 0000000000000..ff84da8ae6168 --- /dev/null +++ b/lib/routes/sorrycc/types.ts @@ -0,0 +1,13 @@ +export interface Post { + id: number; + content: { + rendered: string; + }; + date_gmt: string; + modified_gmt: string; + link: string; + categories: number[]; + title: { + rendered: string; + }; +}