diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..5ad5657 --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,13 @@ +export default { + // see https://prettier.io/docs/en/options.html + // 优先使用单引号 + singleQuote: false, + // 尾随逗号 + trailingComma: "all", + // 缩进空格数 + tabWidth: 2, + // 使用分号 + semi: true, + // 换行符 + printWidth: 100, +}; diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index 0e02eb0..0000000 --- a/.prettierrc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/prettierrc", - "singleQuote": false, - "trailingComma": "all", - "tabWidth": 2, - "semi": true, - "printWidth": 100 -} diff --git a/src/router.types.d.ts b/src/router.types.d.ts index 755832e..d4278d8 100644 --- a/src/router.types.d.ts +++ b/src/router.types.d.ts @@ -315,13 +315,6 @@ export type RouterType = { message: string; replynum: number; }; - xueqiu: { - pic: string; - tag: string; - id: number; - hot: number; - content: string; - }; guokr: { id: number; title: string; @@ -337,9 +330,37 @@ export type RouterType = { name: string; hotValue: string; iconUrl: string; - poster:string; + poster: string; photoIds: { json: string[]; }; }; + smzdm: { + content: string; + title: string; + article_id: string; + nickname: string; + jump_link: string; + pic_url: string; + collection_count: string; + time_sort: string; + }; + yystv: { + id: string; + cover: string; + title: string; + preface: string; + author: string; + createtime: string; + }; + dgtle: { + id: number; + content: string; + cover: string; + from: string; + title: string; + membernum: number; + created_at: number; + type: number; + }; }; diff --git a/src/routes/52pojie.ts b/src/routes/52pojie.ts index e2fa2d2..0d46da2 100644 --- a/src/routes/52pojie.ts +++ b/src/routes/52pojie.ts @@ -43,7 +43,7 @@ const getList = async (options: Options, noCache: boolean): Promise { + const listData = await getList(noCache); + const routeData: RouterData = { + name: "dgtle", + title: "数字尾巴", + type: "热门文章", + description: + "致力于分享美好数字生活体验,囊括你闻所未闻的最丰富数码资讯,触所未触最抢鲜产品评测,随时随地感受尾巴们各式数字生活精彩图文、摄影感悟、旅行游记、爱物分享。", + link: "https://www.dgtle.com/", + total: listData.data?.length || 0, + ...listData, + }; + return routeData; +}; + +const getList = async (noCache: boolean) => { + const url = `https://opser.api.dgtle.com/v2/news/index`; + const result = await get({ url, noCache }); + const list = result.data?.items; + return { + ...result, + data: list.map((v: RouterType["dgtle"]) => ({ + id: v.id, + title: v.title || v.content, + desc: v.content, + cover: v.cover, + author: v.from, + hot: v.membernum, + timestamp: getTime(v.created_at), + url: `https://www.dgtle.com/news-${v.id}-${v.type}.html`, + mobileUrl: `https://m.dgtle.com/news-details/${v.id}`, + })), + }; +}; diff --git a/src/routes/nytimes.ts b/src/routes/nytimes.ts new file mode 100644 index 0000000..7b3c6e3 --- /dev/null +++ b/src/routes/nytimes.ts @@ -0,0 +1,59 @@ +import type { RouterData, ListContext, Options, RouterResType } from "../types.js"; +import { get } from "../utils/getData.js"; +import { getTime } from "../utils/getTime.js"; +import { parseRSS } from "../utils/parseRSS.js"; + +const areaMap: Record = { + china: "中文网", + global: "全球版", +}; + +export const handleRoute = async (c: ListContext, noCache: boolean) => { + const area = c.req.query("type") || "china"; + const listData = await getList({ area }, noCache); + const routeData: RouterData = { + name: "nytimes", + title: "纽约时报", + type: areaMap[area], + params: { + area: { + name: "地区分类", + type: areaMap, + }, + }, + link: "https://www.nytimes.com/", + total: listData?.data?.length || 0, + ...listData, + }; + return routeData; +}; + +const getList = async (options: Options, noCache: boolean): Promise => { + const { area } = options; + const url = + area === "china" + ? "https://cn.nytimes.com/rss/" + : "https://rss.nytimes.com/services/xml/rss/nyt/World.xml"; + const result = await get({ + url, + noCache, + headers: { + userAgent: + "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Mobile Safari/537.36", + }, + }); + const list = await parseRSS(result.data); + return { + ...result, + data: list.map((v, i) => ({ + id: v.guid || i, + title: v.title || "", + desc: v.content?.trim() || "", + author: v.author, + timestamp: getTime(v.pubDate || 0), + hot: undefined, + url: v.link || "", + mobileUrl: v.link || "", + })), + }; +}; diff --git a/src/routes/smzdm.ts b/src/routes/smzdm.ts new file mode 100644 index 0000000..3fa7c2e --- /dev/null +++ b/src/routes/smzdm.ts @@ -0,0 +1,53 @@ +import type { ListContext, Options, RouterData } from "../types.js"; +import type { RouterType } from "../router.types.js"; +import { get } from "../utils/getData.js"; +import { getTime } from "../utils/getTime.js"; + +const typeMap: Record = { + "1": "今日热门", + "7": "周热门", + "30": "月热门", +}; + +export const handleRoute = async (c: ListContext, noCache: boolean) => { + const type = c.req.query("type") || "1"; + const listData = await getList({ type }, noCache); + const routeData: RouterData = { + name: "smzdm", + title: "什么值得买", + type: typeMap[type], + description: + "什么值得买是一个中立的、致力于帮助广大网友买到更有性价比网购产品的最热门推荐网站。", + link: "https://www.smzdm.com/top/", + params: { + type: { + name: "文章分类", + type: typeMap, + }, + }, + total: listData.data?.length || 0, + ...listData, + }; + return routeData; +}; + +const getList = async (options: Options, noCache: boolean) => { + const { type } = options; + const url = `https://post.smzdm.com/rank/json_more/?unit=${type}`; + const result = await get({ url, noCache }); + const list = result.data.data; + return { + ...result, + data: list.map((v: RouterType["smzdm"]) => ({ + id: v.article_id, + title: v.title, + desc: v.content, + cover: v.pic_url, + author: v.nickname, + hot: Number(v.collection_count), + timestamp: getTime(v.time_sort), + url: v.jump_link, + mobileUrl: v.jump_link, + })), + }; +}; diff --git a/src/routes/xueqiu.ts b/src/routes/xueqiu.ts deleted file mode 100644 index ca13b44..0000000 --- a/src/routes/xueqiu.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { RouterData } from "../types.js"; -import type { RouterType } from "../router.types.js"; -import { get } from "../utils/getData.js"; - -export const handleRoute = async (_: undefined, noCache: boolean) => { - const listData = await getList(noCache); - const routeData: RouterData = { - name: "xueqiu", - title: "雪球", - type: "热门话题", - description: "聪明的投资者都在这里", - link: "https://xueqiu.com/", - total: listData.data?.length || 0, - ...listData, - }; - return routeData; -}; - -const getList = async (noCache: boolean) => { - const url = `https://xueqiu.com/hot_event/list.json`; - const result = await get({ - url, - noCache, - headers: { - "User-Agent": - "Mozilla/5.0 (iPhone; CPU iPhone OS 14_2_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/605.1.15", - }, - }); - const list = result.data.list; - return { - ...result, - data: list.map((v: RouterType["xueqiu"]) => ({ - id: v.id, - title: v.tag?.startsWith("#") && v.tag?.endsWith("#") ? v.tag.slice(1, -1) : v.tag, - desc: v.content, - cover: v.pic, - author: undefined, - hot: v.hot, - timestamp: undefined, - url: undefined, - mobileUrl: undefined, - })), - }; -}; diff --git a/src/routes/yystv.ts b/src/routes/yystv.ts new file mode 100644 index 0000000..c615cb9 --- /dev/null +++ b/src/routes/yystv.ts @@ -0,0 +1,38 @@ +import type { RouterData } from "../types.js"; +import type { RouterType } from "../router.types.js"; +import { get } from "../utils/getData.js"; +import { getTime } from "../utils/getTime.js"; + +export const handleRoute = async (_: undefined, noCache: boolean) => { + const listData = await getList(noCache); + const routeData: RouterData = { + name: "yystv", + title: "游研社", + type: "全部文章", + description: + "游研社是以游戏内容为主的新媒体,出品内容包括大量游戏、动漫有关的研究文章和社长聊街机、社长说、游研剧场、老四强等系列视频内容。", + link: "https://www.yystv.cn/docs", + total: listData.data?.length || 0, + ...listData, + }; + return routeData; +}; + +const getList = async (noCache: boolean) => { + const url = "https://www.yystv.cn/home/get_home_docs_by_page"; + const result = await get({ url, noCache }); + const list = result.data.data; + return { + ...result, + data: list.map((v: RouterType["yystv"]) => ({ + id: v.id, + title: v.title, + cover: v.cover, + author: v.author, + hot: undefined, + timestamp: getTime(v.createtime), + url: `https://www.yystv.cn/p/${v.id}`, + mobileUrl: `https://www.yystv.cn/p/${v.id}`, + })), + }; +}; diff --git a/src/utils/getData.ts b/src/utils/getData.ts index aa2ebc2..3400aa0 100644 --- a/src/utils/getData.ts +++ b/src/utils/getData.ts @@ -54,7 +54,11 @@ export const get = async (options: Get) => { const cachedData = await getCache(url); if (cachedData) { logger.info("💾 [CHCHE] The request is cached"); - return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; + return { + fromCache: true, + updateTime: cachedData.updateTime, + data: cachedData.data, + }; } } // 缓存不存在时请求接口 @@ -66,7 +70,7 @@ export const get = async (options: Get) => { await setCache(url, { data, updateTime }, ttl); // 返回数据 logger.info(`✅ [${response?.status}] request was successful`); - return { fromCache: false, data, updateTime }; + return { fromCache: false, updateTime, data }; } catch (error) { logger.error("❌ [ERROR] request failed"); throw error; @@ -84,7 +88,7 @@ export const post = async (options: Post) => { const cachedData = await getCache(url); if (cachedData) { logger.info("💾 [CHCHE] The request is cached"); - return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; + return { fromCache: true, updateTime: cachedData.updateTime, data: cachedData.data }; } } // 缓存不存在时请求接口 @@ -98,7 +102,7 @@ export const post = async (options: Post) => { } // 返回数据 logger.info(`✅ [${response?.status}] request was successful`); - return { fromCache: false, data, updateTime }; + return { fromCache: false, updateTime, data }; } catch (error) { logger.error("❌ [ERROR] request failed"); throw error;