mirror of
https://github.com/ourongxing/newsnow.git
synced 2025-01-19 03:09:14 +08:00
feat: new source
This commit is contained in:
parent
d285f37eeb
commit
3b66d0f081
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 4.7 KiB |
@ -13,7 +13,7 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
||||
const isValid = (id: SourceID) => !id || !sources[id] || !sourcesGetters[id]
|
||||
|
||||
if (isValid(id)) {
|
||||
const redirectID = sources?.[id].redirect
|
||||
const redirectID = sources?.[id]?.redirect
|
||||
if (redirectID) id = redirectID
|
||||
if (isValid(id)) throw new Error("Invalid source id")
|
||||
}
|
||||
|
@ -9,28 +9,12 @@ interface Res {
|
||||
}
|
||||
}
|
||||
|
||||
async function getDyCookies() {
|
||||
try {
|
||||
const cookisUrl = "https://www.douyin.com/passport/general/login_guiding_strategy/?aid=6383"
|
||||
const data = await $fetch.raw(cookisUrl)
|
||||
const pattern = /passport_csrf_token=(.*); Path/s
|
||||
const matchResult = data.headers.get("set-cookie")?.[0]?.match(pattern)
|
||||
if (matchResult && matchResult.length > 1) {
|
||||
const cookieData = matchResult[1]
|
||||
return cookieData
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`获取抖音 Cookie 出错: ${error}`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
export default defineSource(async () => {
|
||||
const url = "https://www.douyin.com/aweme/v1/web/hot/search/list/?device_platform=webapp&aid=6383&channel=channel_pc_web&detail_list=1"
|
||||
const cookie = await getDyCookies()
|
||||
const cookie = (await $fetch.raw("https://www.douyin.com/passport/general/login_guiding_strategy/?aid=6383")).headers.getSetCookie()
|
||||
const res: Res = await $fetch(url, {
|
||||
headers: {
|
||||
Cookie: `passport_csrf_token=${cookie}`,
|
||||
cookie: cookie.join("; "),
|
||||
},
|
||||
})
|
||||
return res.data.word_list
|
||||
|
@ -12,7 +12,7 @@ export default defineSource(async () => {
|
||||
// https://www.kzaobao.com/shiju/20241002/170659.html
|
||||
const url = a.attr("href")
|
||||
const title = a.find("h2").text()
|
||||
const info = $(el).find(".about-stocks").text()
|
||||
const info = $(el).find(".time > span:nth-child(1)").text()
|
||||
// 第三个 p
|
||||
const relatieveTime = $(el).find(".time > span:nth-child(3)").text()
|
||||
if (url && title && relatieveTime) {
|
||||
@ -27,5 +27,5 @@ export default defineSource(async () => {
|
||||
})
|
||||
}
|
||||
})
|
||||
return news.sort((m, n) => n.extra!.date > m.extra!.date ? 1 : -1)
|
||||
return news
|
||||
})
|
||||
|
@ -14,6 +14,8 @@ import cls from "./cls"
|
||||
import sputniknewscn from "./sputniknewscn"
|
||||
import xueqiu from "./xueqiu"
|
||||
import gelonghui from "./gelonghui"
|
||||
import tieba from "./tieba"
|
||||
import thepaper from "./thepaper"
|
||||
import type { SourceGetter } from "#/types"
|
||||
|
||||
export const sourcesGetters = {
|
||||
@ -24,6 +26,7 @@ export const sourcesGetters = {
|
||||
zhihu,
|
||||
coolapk,
|
||||
cankaoxiaoxi,
|
||||
thepaper,
|
||||
sputniknewscn,
|
||||
...wallstreetcn,
|
||||
...xueqiu,
|
||||
@ -31,5 +34,6 @@ export const sourcesGetters = {
|
||||
douyin,
|
||||
...cls,
|
||||
toutiao,
|
||||
tieba,
|
||||
...kr36,
|
||||
} as Record<SourceID, SourceGetter> & Partial<Record<DisabledSourceID, SourceGetter>>
|
||||
|
23
server/sources/thepaper.ts
Normal file
23
server/sources/thepaper.ts
Normal file
@ -0,0 +1,23 @@
|
||||
interface Res {
|
||||
data: {
|
||||
hotNews: {
|
||||
contId: string
|
||||
name: string
|
||||
pubTimeLong: string
|
||||
}[]
|
||||
}
|
||||
}
|
||||
|
||||
export default defineSource(async () => {
|
||||
const url = "https://cache.thepaper.cn/contentapi/wwwIndex/rightSidebar"
|
||||
const res: Res = await $fetch(url)
|
||||
return res.data.hotNews
|
||||
.map((k) => {
|
||||
return {
|
||||
id: k.contId,
|
||||
title: k.name,
|
||||
url: `https://www.thepaper.cn/newsDetail_forward_${k.contId}`,
|
||||
mobileUrl: `https://m.thepaper.cn/newsDetail_forward_${k.contId}`,
|
||||
}
|
||||
})
|
||||
})
|
26
server/sources/tieba.ts
Normal file
26
server/sources/tieba.ts
Normal file
@ -0,0 +1,26 @@
|
||||
interface Res {
|
||||
data: {
|
||||
bang_topic: {
|
||||
topic_list: {
|
||||
topic_id: string
|
||||
topic_name: string
|
||||
create_time: number
|
||||
topic_url: string
|
||||
|
||||
}[]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default defineSource(async () => {
|
||||
const url = "https://tieba.baidu.com/hottopic/browse/topicList"
|
||||
const res: Res = await $fetch(url)
|
||||
return res.data.bang_topic.topic_list
|
||||
.map((k) => {
|
||||
return {
|
||||
id: k.topic_id,
|
||||
title: k.topic_name,
|
||||
url: k.topic_url,
|
||||
}
|
||||
})
|
||||
})
|
@ -26,7 +26,7 @@ const hotstock = defineSource(async () => {
|
||||
url: `https://xueqiu.com/s/${k.code}`,
|
||||
title: k.name,
|
||||
extra: {
|
||||
info: `${k.percent}%`,
|
||||
info: `${k.percent}% ${k.exchange}`,
|
||||
},
|
||||
}))
|
||||
})
|
||||
|
@ -57,21 +57,4 @@ export interface SourceOption {
|
||||
hiddenDate?: boolean
|
||||
}
|
||||
|
||||
export interface FallbackResponse {
|
||||
code: number
|
||||
message: string
|
||||
name: string
|
||||
title: string
|
||||
subtitle: string
|
||||
total: number
|
||||
updateTime: string
|
||||
data: {
|
||||
title: string
|
||||
desc: string
|
||||
time?: string
|
||||
url: string
|
||||
mobileUrl: string
|
||||
}[]
|
||||
}
|
||||
|
||||
export type SourceGetter = () => Promise<NewsItem[]>
|
||||
|
@ -141,6 +141,7 @@ function toDurations(matches: string[]) {
|
||||
export const parseDate = (date: string | number, ...options: any) => dayjs(date, ...options).toDate()
|
||||
|
||||
export function parseRelativeDate(date: string, timezone: string = "Asia/Shanghai") {
|
||||
if (date === "刚刚") return new Date()
|
||||
// 预处理日期字符串 date
|
||||
|
||||
const theDate = toDate(date)
|
||||
|
@ -1,29 +1,12 @@
|
||||
import type { AllSourceID, SourceID } from "@shared/types"
|
||||
import type { AllSourceID } from "@shared/types"
|
||||
import defu from "defu"
|
||||
import type { FallbackResponse, RSSHubOption, RSSHubInfo as RSSHubResponse, SourceGetter, SourceOption } from "#/types"
|
||||
import type { RSSHubOption, RSSHubInfo as RSSHubResponse, SourceGetter, SourceOption } from "#/types"
|
||||
|
||||
type X = SourceGetter | Partial<Record<AllSourceID, SourceGetter>>
|
||||
export function defineSource<T extends X>(source: T): T {
|
||||
return source
|
||||
}
|
||||
|
||||
export function defineFallbackSource(id: SourceID, option?: SourceOption): SourceGetter {
|
||||
return async () => {
|
||||
const url = `https://smzdk.top/api/${id}/new`
|
||||
const res: FallbackResponse = await $fetch(url)
|
||||
if (res.code !== 200 || !res.data) throw new Error(res.message)
|
||||
return res.data.map(item => ({
|
||||
extra: {
|
||||
date: !option?.hiddenDate && item.time,
|
||||
},
|
||||
id: item.url,
|
||||
title: item.title,
|
||||
url: item.url,
|
||||
mobileUrl: item.mobileUrl,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
export function defineRSSSource(url: string, option?: SourceOption): SourceGetter {
|
||||
return async () => {
|
||||
const data = await rss2json(url)
|
||||
|
@ -7,7 +7,7 @@ export const columnIds = ["focus", "realtime", "hottest", "china", "world", "tec
|
||||
const originMetadata: Metadata = {
|
||||
china: {
|
||||
name: "国内",
|
||||
sources: ["weibo", "douyin", "toutiao", "zhihu"],
|
||||
sources: ["zhihu", "thepaper"],
|
||||
},
|
||||
world: {
|
||||
name: "国际",
|
||||
|
@ -96,7 +96,9 @@ export const originSources = {
|
||||
},
|
||||
"tieba": {
|
||||
name: "百度贴吧",
|
||||
disable: true,
|
||||
title: "热议",
|
||||
type: "hottest",
|
||||
color: "blue",
|
||||
home: "https://tieba.baidu.com",
|
||||
},
|
||||
"toutiao": {
|
||||
@ -114,7 +116,9 @@ export const originSources = {
|
||||
"thepaper": {
|
||||
name: "澎湃新闻",
|
||||
interval: Time.Common,
|
||||
disable: true,
|
||||
type: "hottest",
|
||||
title: "热榜",
|
||||
color: "gray",
|
||||
home: "https://www.thepaper.cn",
|
||||
},
|
||||
"sputniknewscn": {
|
||||
|
Loading…
x
Reference in New Issue
Block a user