mirror of
https://github.com/imsyy/DailyHotApi.git
synced 2026-01-12 05:04:56 +08:00
✨ feat: 新增 数字尾巴 & 什么值得买 & 游研社
This commit is contained in:
13
.prettierrc.js
Normal file
13
.prettierrc.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
export default {
|
||||||
|
// see https://prettier.io/docs/en/options.html
|
||||||
|
// 优先使用单引号
|
||||||
|
singleQuote: false,
|
||||||
|
// 尾随逗号
|
||||||
|
trailingComma: "all",
|
||||||
|
// 缩进空格数
|
||||||
|
tabWidth: 2,
|
||||||
|
// 使用分号
|
||||||
|
semi: true,
|
||||||
|
// 换行符
|
||||||
|
printWidth: 100,
|
||||||
|
};
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/prettierrc",
|
|
||||||
"singleQuote": false,
|
|
||||||
"trailingComma": "all",
|
|
||||||
"tabWidth": 2,
|
|
||||||
"semi": true,
|
|
||||||
"printWidth": 100
|
|
||||||
}
|
|
||||||
35
src/router.types.d.ts
vendored
35
src/router.types.d.ts
vendored
@@ -315,13 +315,6 @@ export type RouterType = {
|
|||||||
message: string;
|
message: string;
|
||||||
replynum: number;
|
replynum: number;
|
||||||
};
|
};
|
||||||
xueqiu: {
|
|
||||||
pic: string;
|
|
||||||
tag: string;
|
|
||||||
id: number;
|
|
||||||
hot: number;
|
|
||||||
content: string;
|
|
||||||
};
|
|
||||||
guokr: {
|
guokr: {
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
@@ -342,4 +335,32 @@ export type RouterType = {
|
|||||||
json: string[];
|
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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
39
src/routes/dgtle.ts
Normal file
39
src/routes/dgtle.ts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
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: "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}`,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
};
|
||||||
59
src/routes/nytimes.ts
Normal file
59
src/routes/nytimes.ts
Normal file
@@ -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<string, string> = {
|
||||||
|
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<RouterResType> => {
|
||||||
|
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 || "",
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
};
|
||||||
53
src/routes/smzdm.ts
Normal file
53
src/routes/smzdm.ts
Normal file
@@ -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<string, string> = {
|
||||||
|
"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,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -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,
|
|
||||||
})),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
38
src/routes/yystv.ts
Normal file
38
src/routes/yystv.ts
Normal file
@@ -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}`,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -54,7 +54,11 @@ export const get = async (options: Get) => {
|
|||||||
const cachedData = await getCache(url);
|
const cachedData = await getCache(url);
|
||||||
if (cachedData) {
|
if (cachedData) {
|
||||||
logger.info("💾 [CHCHE] The request is cached");
|
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);
|
await setCache(url, { data, updateTime }, ttl);
|
||||||
// 返回数据
|
// 返回数据
|
||||||
logger.info(`✅ [${response?.status}] request was successful`);
|
logger.info(`✅ [${response?.status}] request was successful`);
|
||||||
return { fromCache: false, data, updateTime };
|
return { fromCache: false, updateTime, data };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("❌ [ERROR] request failed");
|
logger.error("❌ [ERROR] request failed");
|
||||||
throw error;
|
throw error;
|
||||||
@@ -84,7 +88,7 @@ export const post = async (options: Post) => {
|
|||||||
const cachedData = await getCache(url);
|
const cachedData = await getCache(url);
|
||||||
if (cachedData) {
|
if (cachedData) {
|
||||||
logger.info("💾 [CHCHE] The request is cached");
|
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`);
|
logger.info(`✅ [${response?.status}] request was successful`);
|
||||||
return { fromCache: false, data, updateTime };
|
return { fromCache: false, updateTime, data };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error("❌ [ERROR] request failed");
|
logger.error("❌ [ERROR] request failed");
|
||||||
throw error;
|
throw error;
|
||||||
|
|||||||
Reference in New Issue
Block a user