diff --git a/src/router.types.ts b/src/router.types.ts index 40f60d9..7867bca 100644 --- a/src/router.types.ts +++ b/src/router.types.ts @@ -42,12 +42,14 @@ export type RouterType = { bilibili: { bvid: string; title: string; - desc: string; - pic: string; - owner: { + desc?: string; + pic?: string; + author?: string; + video_review?: number; + owner?: { name: string; }; - stat: { + stat?: { view: number; }; short_link_v2?: string; diff --git a/src/routes/bilibili.ts b/src/routes/bilibili.ts index 253d95b..9d05aa8 100644 --- a/src/routes/bilibili.ts +++ b/src/routes/bilibili.ts @@ -53,19 +53,50 @@ const getList = async (options: Options, noCache: boolean) => { }, noCache, }); - const list = result.data.data.list; - return { - fromCache: result.fromCache, - updateTime: result.updateTime, - data: list.map((v: RouterType["bilibili"]) => ({ - id: v.bvid, - title: v.title, - desc: v.desc, - cover: v.pic.replace(/http:/, "https:"), - author: v.owner.name, - hot: v.stat.view, - url: v.short_link_v2 || `https://www.bilibili.com/video/${v.bvid}`, - mobileUrl: `https://m.bilibili.com/video/${v.bvid}`, - })), - }; + // 是否触发风控 + if (result.data?.data?.list?.length > 0) { + const list = result.data.data.list; + return { + fromCache: result.fromCache, + updateTime: result.updateTime, + data: list.map((v: RouterType["bilibili"]) => ({ + id: v.bvid, + title: v.title, + desc: v.desc || "该视频暂无简介", + cover: v.pic.replace(/http:/, "https:"), + author: v.owner.name, + hot: v.stat.view, + url: v.short_link_v2 || `https://www.bilibili.com/video/${v.bvid}`, + mobileUrl: `https://m.bilibili.com/video/${v.bvid}`, + })), + }; + } + // 采用备用接口 + else { + const url = `https://api.bilibili.com/x/web-interface/ranking?jsonp=jsonp?rid=${type}&type=1&callback=__jp0`; + const result = await get({ + url, + headers: { + Referer: `https://www.bilibili.com/ranking/all`, + "User-Agent": + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36", + }, + noCache, + }); + const list = result.data.data.list; + return { + fromCache: result.fromCache, + updateTime: result.updateTime, + data: list.map((v: RouterType["bilibili"]) => ({ + id: v.bvid, + title: v.title, + desc: v.desc || "该视频暂无简介", + cover: v.pic.replace(/http:/, "https:"), + author: v.author, + hot: v.video_review, + url: `https://www.bilibili.com/video/${v.bvid}`, + mobileUrl: `https://m.bilibili.com/video/${v.bvid}`, + })), + }; + } }; diff --git a/src/routes/zhihu-daily.ts b/src/routes/zhihu-daily.ts index 5bae87b..2f26c2c 100644 --- a/src/routes/zhihu-daily.ts +++ b/src/routes/zhihu-daily.ts @@ -1,44 +1,44 @@ -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 { fromCache, data, updateTime } = await getList(noCache); - const routeData: RouterData = { - name: "zhihu-daily", - title: "知乎日报", - type: "推荐榜", - description: "每天三次,每次七分钟", - link: "https://daily.zhihu.com/", - total: data?.length || 0, - updateTime, - fromCache, - data, - }; - return routeData; -}; - -const getList = async (noCache: boolean) => { - const url = `https://daily.zhihu.com/api/4/news/latest`; - const result = await get({ - url, - noCache, - headers: { - Referer: "https://daily.zhihu.com/api/4/news/latest", - Host: "daily.zhihu.com", - }, - }); - const list = result.data.stories.filter((el: RouterType["zhihu-daily"]) => el.type === 0); - return { - fromCache: result.fromCache, - updateTime: result.updateTime, - data: list.map((v: RouterType["zhihu-daily"]) => ({ - id: v.id, - title: v.title, - cover: v.images[0], - author: v.hint, - url: v.url, - mobileUrl: v.url, - })), - }; -}; +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 { fromCache, data, updateTime } = await getList(noCache); + const routeData: RouterData = { + name: "zhihu-daily", + title: "知乎日报", + type: "推荐榜", + description: "每天三次,每次七分钟", + link: "https://daily.zhihu.com/", + total: data?.length || 0, + updateTime, + fromCache, + data, + }; + return routeData; +}; + +const getList = async (noCache: boolean) => { + const url = `https://daily.zhihu.com/api/4/news/latest`; + const result = await get({ + url, + noCache, + headers: { + Referer: "https://daily.zhihu.com/api/4/news/latest", + Host: "daily.zhihu.com", + }, + }); + const list = result.data.stories.filter((el: RouterType["zhihu-daily"]) => el.type === 0); + return { + fromCache: result.fromCache, + updateTime: result.updateTime, + data: list.map((v: RouterType["zhihu-daily"]) => ({ + id: v.id, + title: v.title, + cover: v.images[0], + author: v.hint, + url: v.url, + mobileUrl: v.url, + })), + }; +}; diff --git a/src/utils/getData.ts b/src/utils/getData.ts index 459b7e4..f83d69d 100644 --- a/src/utils/getData.ts +++ b/src/utils/getData.ts @@ -1,100 +1,100 @@ -import type { Get, Post } from "../types.ts"; -import { config } from "../config.js"; -import { getCache, setCache, delCache } from "./cache.js"; -import logger from "./logger.js"; -import axios from "axios"; - -// 基础配置 -const request = axios.create({ - // 请求超时设置 - timeout: config.REQUEST_TIMEOUT, - withCredentials: true, -}); - -// 请求拦截 -request.interceptors.request.use( - (request) => { - if (!request.params) request.params = {}; - // 发送请求 - return request; - }, - (error) => { - logger.error("请求失败,请稍后重试"); - return Promise.reject(error); - }, -); - -// 响应拦截 -request.interceptors.response.use( - (response) => { - return response; - }, - (error) => { - // 继续传递错误 - return Promise.reject(error); - }, -); - -// GET -export const get = async (options: Get) => { - const { url, headers, params, noCache, ttl = config.CACHE_TTL, originaInfo = false } = options; - logger.info("发起 GET 请求", options); - try { - // 检查缓存 - if (noCache) delCache(url); - else { - const cachedData = getCache(url); - if (cachedData) { - logger.info("采用缓存", { url }); - return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; - } - } - // 缓存不存在时请求接口 - logger.info("请求接口", { url }); - const response = await request.get(url, { headers, params }); - const responseData = response?.data || response; - // 存储新获取的数据到缓存 - const updateTime = new Date().toISOString(); - const data = originaInfo ? response : responseData; - setCache(url, { data, updateTime }, ttl); - // 返回数据 - logger.info("接口调用成功", { status: response?.statusText }); - return { fromCache: false, data, updateTime }; - } catch (error) { - logger.error("GET 请求出错", error); - throw error; - } -}; - -// POST -export const post = async (options: Post) => { - const { url, headers, body, noCache, ttl = config.CACHE_TTL, originaInfo = false } = options; - logger.info("发起 POST 请求", options); - try { - // 检查缓存 - if (noCache) delCache(url); - else { - const cachedData = getCache(url); - if (cachedData) { - logger.info("采用缓存", { url }); - return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; - } - } - // 缓存不存在时请求接口 - logger.info("请求接口", { url }); - const response = await request.post(url, body, { headers }); - const responseData = response?.data || response; - // 存储新获取的数据到缓存 - const updateTime = new Date().toISOString(); - const data = originaInfo ? response : responseData; - if (!noCache) { - setCache(url, { data, updateTime }, ttl); - } - // 返回数据 - logger.info("接口调用成功", { status: response?.statusText }); - return { fromCache: false, data, updateTime }; - } catch (error) { - logger.error("POST 请求出错", error); - throw error; - } -}; +import type { Get, Post } from "../types.ts"; +import { config } from "../config.js"; +import { getCache, setCache, delCache } from "./cache.js"; +import logger from "./logger.js"; +import axios from "axios"; + +// 基础配置 +const request = axios.create({ + // 请求超时设置 + timeout: config.REQUEST_TIMEOUT, + withCredentials: true, +}); + +// 请求拦截 +request.interceptors.request.use( + (request) => { + if (!request.params) request.params = {}; + // 发送请求 + return request; + }, + (error) => { + logger.error("请求失败,请稍后重试"); + return Promise.reject(error); + }, +); + +// 响应拦截 +request.interceptors.response.use( + (response) => { + return response; + }, + (error) => { + // 继续传递错误 + return Promise.reject(error); + }, +); + +// GET +export const get = async (options: Get) => { + const { url, headers, params, noCache, ttl = config.CACHE_TTL, originaInfo = false } = options; + logger.info("发起 GET 请求", options); + try { + // 检查缓存 + if (noCache) delCache(url); + else { + const cachedData = getCache(url); + if (cachedData) { + logger.info("采用缓存", { url }); + return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; + } + } + // 缓存不存在时请求接口 + logger.info("请求接口", { url }); + const response = await request.get(url, { headers, params }); + const responseData = response?.data || response; + // 存储新获取的数据到缓存 + const updateTime = new Date().toISOString(); + const data = originaInfo ? response : responseData; + setCache(url, { data, updateTime }, ttl); + // 返回数据 + logger.info("接口调用成功", { status: response?.statusText }); + return { fromCache: false, data, updateTime }; + } catch (error) { + logger.error("GET 请求出错", error); + throw error; + } +}; + +// POST +export const post = async (options: Post) => { + const { url, headers, body, noCache, ttl = config.CACHE_TTL, originaInfo = false } = options; + logger.info("发起 POST 请求", options); + try { + // 检查缓存 + if (noCache) delCache(url); + else { + const cachedData = getCache(url); + if (cachedData) { + logger.info("采用缓存", { url }); + return { fromCache: true, data: cachedData.data, updateTime: cachedData.updateTime }; + } + } + // 缓存不存在时请求接口 + logger.info("请求接口", { url }); + const response = await request.post(url, body, { headers }); + const responseData = response?.data || response; + // 存储新获取的数据到缓存 + const updateTime = new Date().toISOString(); + const data = originaInfo ? response : responseData; + if (!noCache) { + setCache(url, { data, updateTime }, ttl); + } + // 返回数据 + logger.info("接口调用成功", { status: response?.statusText }); + return { fromCache: false, data, updateTime }; + } catch (error) { + logger.error("POST 请求出错", error); + throw error; + } +};