From 50c1bb7fd9fab323ac5bbce042773bb08006e8f8 Mon Sep 17 00:00:00 2001 From: Tony Date: Mon, 27 May 2024 04:39:20 +0800 Subject: [PATCH] feat(route): stream-capital (#15719) --- lib/routes/stream-capital/namespace.ts | 6 ++ lib/routes/stream-capital/search.ts | 79 ++++++++++++++++++++++++++ lib/routes/stream-capital/types.ts | 44 ++++++++++++++ lib/routes/stream-capital/utils.ts | 18 ++++++ 4 files changed, 147 insertions(+) create mode 100644 lib/routes/stream-capital/namespace.ts create mode 100644 lib/routes/stream-capital/search.ts create mode 100644 lib/routes/stream-capital/types.ts create mode 100644 lib/routes/stream-capital/utils.ts diff --git a/lib/routes/stream-capital/namespace.ts b/lib/routes/stream-capital/namespace.ts new file mode 100644 index 00000000000000..9310c86cc866ce --- /dev/null +++ b/lib/routes/stream-capital/namespace.ts @@ -0,0 +1,6 @@ +import type { Namespace } from '@/types'; + +export const namespace: Namespace = { + name: '远川研究所', + url: 'www.stream-capital.com', +}; diff --git a/lib/routes/stream-capital/search.ts b/lib/routes/stream-capital/search.ts new file mode 100644 index 00000000000000..c1adec94782c65 --- /dev/null +++ b/lib/routes/stream-capital/search.ts @@ -0,0 +1,79 @@ +import { Route } from '@/types'; +import ofetch from '@/utils/ofetch'; +import { parseDate } from '@/utils/parse-date'; +import timezone from '@/utils/timezone'; +import { encrypt, decrypt } from './utils'; +import { EncryptedResponse, WebBlog } from './types'; +import cache from '@/utils/cache'; + +export const route: Route = { + path: '/search', + name: '最新', + categories: ['finance'], + example: '/stream-capital/search', + maintainers: ['TonyRL'], + handler, + radar: [ + { + source: ['www.stream-capital.com/search'], + }, + ], +}; + +async function handler() { + const baseUrl = 'https://www.stream-capital.com'; + const apiBaseUrl = 'https://api.yuanchuan.cn'; + + const response = await ofetch(`${apiBaseUrl}/yc/webbloglist`, { + method: 'POST', + query: { + apptype: 9, + }, + body: encrypt( + JSON.stringify({ + type: 0, + name: null, + page: 1, + }) + ), + }); + + const list = (JSON.parse(decrypt(response.data)).list as WebBlog[]).map((item) => ({ + title: item.title, + author: item.userName, + pubDate: timezone(parseDate(item.ctime, 'YYYY-MM-DD HH:mm:ss'), 8), + link: `${baseUrl}/article/${item.id}`, + description: item.content, + category: item.tags.map((t) => t.tagName), + id: item.id, + })); + + const items = await Promise.all( + list.map((item) => + cache.tryGet(item.link, async () => { + const response = await ofetch(`${apiBaseUrl}/yc/webblogdetail`, { + method: 'POST', + query: { + apptype: 9, + }, + body: encrypt( + JSON.stringify({ + blogId: item.id, + }) + ), + }); + + item.description = (JSON.parse(decrypt(response.data)) as WebBlog).detailInfo.articleContent; + + return item; + }) + ) + ); + + return { + title: '最新 - 远川研究所', + link: `${baseUrl}/search`, + language: 'zh', + item: items, + }; +} diff --git a/lib/routes/stream-capital/types.ts b/lib/routes/stream-capital/types.ts new file mode 100644 index 00000000000000..6fe06499174cae --- /dev/null +++ b/lib/routes/stream-capital/types.ts @@ -0,0 +1,44 @@ +export interface EncryptedResponse { + code: number; + data: string; + msg: string; +} + +interface Tag { + blogId: number; + tagId: number; + length: number; + tagName: string; + beginIndex: number; +} + +interface DetailInfo { + articleContent: string; + blogId: number; + videoCoverPicUrl: string; + excerpt: string; + id: number; + videoUrl: string; +} + +export interface WebBlog { + title: string; + type: number; + intro: null; + avatarUrl: null; + userName: string; + ctime: string; + isPublish: number; + id: number; + themeTitle: string; + themeId: number; + viewCount: number; + coverUrl: string; + videoDuration: number; + originUrl: string; + userId: number; + content: string; + tags: Tag[]; + isCollect: number; + detailInfo: DetailInfo; +} diff --git a/lib/routes/stream-capital/utils.ts b/lib/routes/stream-capital/utils.ts new file mode 100644 index 00000000000000..1f0a72c97ebb07 --- /dev/null +++ b/lib/routes/stream-capital/utils.ts @@ -0,0 +1,18 @@ +import CryptoJS from 'crypto-js'; + +const secret = CryptoJS.enc.Utf8.parse('r4rt5A8L6ye6ts8y'); +const iv = CryptoJS.enc.Utf8.parse('fs0Hkjg8a23u8sE0'); + +export const encrypt = (plainText) => + CryptoJS.AES.encrypt(plainText, secret, { + iv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }).toString(); + +export const decrypt = (encrypted) => + CryptoJS.AES.decrypt(encrypted, secret, { + iv, + mode: CryptoJS.mode.CBC, + padding: CryptoJS.pad.Pkcs7, + }).toString(CryptoJS.enc.Utf8);