mirror of
https://github.com/ourongxing/newsnow.git
synced 2025-01-19 03:09:14 +08:00
parent
0f187da2f8
commit
d7c8a38d88
1
auto-imports.app.d.ts
vendored
1
auto-imports.app.d.ts
vendored
@ -39,6 +39,7 @@ declare global {
|
|||||||
const loadable: typeof import('jotai/utils')['loadable']
|
const loadable: typeof import('jotai/utils')['loadable']
|
||||||
const memo: typeof import('react')['memo']
|
const memo: typeof import('react')['memo']
|
||||||
const metadata: typeof import('./shared/metadata')['metadata']
|
const metadata: typeof import('./shared/metadata')['metadata']
|
||||||
|
const myFetch: typeof import('./src/utils/index')['myFetch']
|
||||||
const originSources: typeof import('./shared/sources')['originSources']
|
const originSources: typeof import('./shared/sources')['originSources']
|
||||||
const preprocessMetadata: typeof import('./src/atoms/primitiveMetadataAtom')['preprocessMetadata']
|
const preprocessMetadata: typeof import('./src/atoms/primitiveMetadataAtom')['preprocessMetadata']
|
||||||
const primitiveMetadataAtom: typeof import('./src/atoms/primitiveMetadataAtom')['primitiveMetadataAtom']
|
const primitiveMetadataAtom: typeof import('./src/atoms/primitiveMetadataAtom')['primitiveMetadataAtom']
|
||||||
|
@ -12,7 +12,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
access_token: string
|
access_token: string
|
||||||
token_type: string
|
token_type: string
|
||||||
scope: string
|
scope: string
|
||||||
} = await $fetch(
|
} = await myFetch(
|
||||||
`https://github.com/login/oauth/access_token`,
|
`https://github.com/login/oauth/access_token`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
@ -33,7 +33,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
avatar_url: string
|
avatar_url: string
|
||||||
email: string
|
email: string
|
||||||
notification_email: string
|
notification_email: string
|
||||||
} = await $fetch(`https://api.github.com/user`, {
|
} = await myFetch(`https://api.github.com/user`, {
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "application/vnd.github+json",
|
"Accept": "application/vnd.github+json",
|
||||||
"Authorization": `token ${response.access_token}`,
|
"Authorization": `token ${response.access_token}`,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import type { SourceID, SourceResponse } from "@shared/types"
|
import type { SourceID, SourceResponse } from "@shared/types"
|
||||||
import { getters } from "#/getters"
|
import { getters } from "#/getters"
|
||||||
import { getCacheTable } from "#/database/cache"
|
import { getCacheTable } from "#/database/cache"
|
||||||
|
import type { CacheInfo } from "#/types"
|
||||||
|
|
||||||
export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
||||||
try {
|
try {
|
||||||
@ -17,8 +18,9 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
|||||||
|
|
||||||
const cacheTable = await getCacheTable()
|
const cacheTable = await getCacheTable()
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
|
let cache: CacheInfo
|
||||||
if (cacheTable) {
|
if (cacheTable) {
|
||||||
const cache = await cacheTable.get(id)
|
cache = await cacheTable.get(id)
|
||||||
if (cache) {
|
if (cache) {
|
||||||
// interval 刷新间隔,对于缓存失效也要执行的。本质上表示本来内容更新就很慢,这个间隔内可能内容压根不会更新。
|
// interval 刷新间隔,对于缓存失效也要执行的。本质上表示本来内容更新就很慢,这个间隔内可能内容压根不会更新。
|
||||||
// 默认 10 分钟,是低于 TTL 的,但部分 Source 的更新间隔会超过 TTL,甚至有的一天更新一次。
|
// 默认 10 分钟,是低于 TTL 的,但部分 Source 的更新间隔会超过 TTL,甚至有的一天更新一次。
|
||||||
@ -52,17 +54,30 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = (await getters[id]()).slice(0, 30)
|
try {
|
||||||
logger.success(`fetch ${id} latest`)
|
const newData = (await getters[id]()).slice(0, 30)
|
||||||
if (cacheTable) {
|
if (cacheTable && newData) {
|
||||||
if (event.context.waitUntil) event.context.waitUntil(cacheTable.set(id, data))
|
if (event.context.waitUntil) event.context.waitUntil(cacheTable.set(id, newData))
|
||||||
else await cacheTable.set(id, data)
|
else await cacheTable.set(id, newData)
|
||||||
}
|
}
|
||||||
return {
|
logger.success(`fetch ${id} latest`)
|
||||||
status: "success",
|
return {
|
||||||
id,
|
status: "success",
|
||||||
updatedTime: now,
|
id,
|
||||||
items: data,
|
updatedTime: now,
|
||||||
|
items: newData,
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (cache!) {
|
||||||
|
return {
|
||||||
|
status: "cache",
|
||||||
|
id,
|
||||||
|
updatedTime: cache.updated,
|
||||||
|
items: cache.data,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
logger.error(e)
|
logger.error(e)
|
||||||
|
@ -4,7 +4,7 @@ import { load } from "cheerio"
|
|||||||
const quick = defineSource(async () => {
|
const quick = defineSource(async () => {
|
||||||
const baseURL = "https://www.36kr.com"
|
const baseURL = "https://www.36kr.com"
|
||||||
const url = `${baseURL}/newsflashes`
|
const url = `${baseURL}/newsflashes`
|
||||||
const response = await $fetch(url) as any
|
const response = await myFetch(url) as any
|
||||||
const $ = load(response)
|
const $ = load(response)
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
const $items = $(".newsflash-item")
|
const $items = $(".newsflash-item")
|
||||||
|
@ -12,7 +12,7 @@ interface Res {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const rawData: string = await $fetch(`https://top.baidu.com/board?tab=realtime`)
|
const rawData: string = await myFetch(`https://top.baidu.com/board?tab=realtime`)
|
||||||
const jsonStr = (rawData as string).match(/<!--s-data:(.*?)-->/s)
|
const jsonStr = (rawData as string).match(/<!--s-data:(.*?)-->/s)
|
||||||
const data: Res = JSON.parse(jsonStr![1])
|
const data: Res = JSON.parse(jsonStr![1])
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ interface WapRes {
|
|||||||
|
|
||||||
const hotSearch = defineSource(async () => {
|
const hotSearch = defineSource(async () => {
|
||||||
const url = "https://s.search.bilibili.com/main/hotword?limit=30"
|
const url = "https://s.search.bilibili.com/main/hotword?limit=30"
|
||||||
const res: WapRes = await $fetch(url)
|
const res: WapRes = await myFetch(url)
|
||||||
|
|
||||||
return res.list.map(k => ({
|
return res.list.map(k => ({
|
||||||
id: k.keyword,
|
id: k.keyword,
|
||||||
|
@ -11,7 +11,7 @@ interface Res {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const res = await Promise.all(["zhongguo", "guandian", "gj"].map(k => $fetch(`https://china.cankaoxiaoxi.com/json/channel/${k}/list.json`) as Promise<Res>))
|
const res = await Promise.all(["zhongguo", "guandian", "gj"].map(k => myFetch(`https://china.cankaoxiaoxi.com/json/channel/${k}/list.json`) as Promise<Res>))
|
||||||
return res.map(k => k.list).flat().map(k => ({
|
return res.map(k => k.list).flat().map(k => ({
|
||||||
id: k.data.id,
|
id: k.data.id,
|
||||||
title: k.data.title,
|
title: k.data.title,
|
||||||
|
@ -23,9 +23,10 @@ interface Depthes {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 失效
|
||||||
const depth = defineSource(async () => {
|
const depth = defineSource(async () => {
|
||||||
const apiUrl = `https://www.cls.cn/v3/depth/home/assembled/1000`
|
const apiUrl = `https://www.cls.cn/v3/depth/home/assembled/1000`
|
||||||
const res: Depthes = await $fetch(apiUrl, {
|
const res: Depthes = await myFetch(apiUrl, {
|
||||||
query: await getSearchParams(),
|
query: await getSearchParams(),
|
||||||
})
|
})
|
||||||
return res.data.depth_list.sort((m, n) => n.ctime - m.ctime).map((k) => {
|
return res.data.depth_list.sort((m, n) => n.ctime - m.ctime).map((k) => {
|
||||||
@ -40,13 +41,13 @@ const depth = defineSource(async () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// hot 失效
|
// hot 失效
|
||||||
|
|
||||||
const telegraph = defineSource(async () => {
|
const telegraph = defineSource(async () => {
|
||||||
const apiUrl = `https://www.cls.cn/nodeapi/updateTelegraphList`
|
const apiUrl = `https://www.cls.cn/nodeapi/updateTelegraphList`
|
||||||
const res: TelegraphRes = await $fetch(apiUrl, {
|
const res: TelegraphRes = await myFetch(apiUrl, {
|
||||||
query: await getSearchParams({ }),
|
query: await getSearchParams({ }),
|
||||||
|
timeout: 10000,
|
||||||
})
|
})
|
||||||
return res.data.roll_data.filter(k => !k.is_ad).map((k) => {
|
return res.data.roll_data.filter(k => !k.is_ad).map((k) => {
|
||||||
return {
|
return {
|
||||||
|
@ -23,7 +23,7 @@ interface Res {
|
|||||||
export default defineSource({
|
export default defineSource({
|
||||||
coolapk: async () => {
|
coolapk: async () => {
|
||||||
const url = "https://api.coolapk.com/v6/page/dataList?url=%2Ffeed%2FstatList%3FcacheExpires%3D300%26statType%3Dday%26sortField%3Ddetailnum%26title%3D%E4%BB%8A%E6%97%A5%E7%83%AD%E9%97%A8&title=%E4%BB%8A%E6%97%A5%E7%83%AD%E9%97%A8&subTitle=&page=1"
|
const url = "https://api.coolapk.com/v6/page/dataList?url=%2Ffeed%2FstatList%3FcacheExpires%3D300%26statType%3Dday%26sortField%3Ddetailnum%26title%3D%E4%BB%8A%E6%97%A5%E7%83%AD%E9%97%A8&title=%E4%BB%8A%E6%97%A5%E7%83%AD%E9%97%A8&subTitle=&page=1"
|
||||||
const r: Res = await $fetch(url, {
|
const r: Res = await myFetch(url, {
|
||||||
headers: await genHeaders(),
|
headers: await genHeaders(),
|
||||||
})
|
})
|
||||||
if (!r.data.length) throw new Error("Failed to fetch")
|
if (!r.data.length) throw new Error("Failed to fetch")
|
||||||
|
@ -12,7 +12,7 @@ interface Res {
|
|||||||
export default defineSource(async () => {
|
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 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 $fetch.raw("https://www.douyin.com/passport/general/login_guiding_strategy/?aid=6383")).headers.getSetCookie()
|
const cookie = (await $fetch.raw("https://www.douyin.com/passport/general/login_guiding_strategy/?aid=6383")).headers.getSetCookie()
|
||||||
const res: Res = await $fetch(url, {
|
const res: Res = await myFetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
cookie: cookie.join("; "),
|
cookie: cookie.join("; "),
|
||||||
},
|
},
|
||||||
|
@ -3,7 +3,7 @@ import type { NewsItem } from "@shared/types"
|
|||||||
|
|
||||||
const express = defineSource(async () => {
|
const express = defineSource(async () => {
|
||||||
const baseURL = "https://www.fastbull.cn"
|
const baseURL = "https://www.fastbull.cn"
|
||||||
const html: any = await $fetch(`${baseURL}/express-news`)
|
const html: any = await myFetch(`${baseURL}/express-news`)
|
||||||
const $ = cheerio.load(html)
|
const $ = cheerio.load(html)
|
||||||
const $main = $(".news-list")
|
const $main = $(".news-list")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
@ -27,7 +27,7 @@ const express = defineSource(async () => {
|
|||||||
|
|
||||||
const news = defineSource(async () => {
|
const news = defineSource(async () => {
|
||||||
const baseURL = "https://www.fastbull.cn"
|
const baseURL = "https://www.fastbull.cn"
|
||||||
const html: any = await $fetch(`${baseURL}/news`)
|
const html: any = await myFetch(`${baseURL}/news`)
|
||||||
const $ = cheerio.load(html)
|
const $ = cheerio.load(html)
|
||||||
const $main = $(".trending_type")
|
const $main = $(".trending_type")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -3,7 +3,7 @@ import type { NewsItem } from "@shared/types"
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const baseURL = "https://www.gelonghui.com"
|
const baseURL = "https://www.gelonghui.com"
|
||||||
const html: any = await $fetch("https://www.gelonghui.com/news/")
|
const html: any = await myFetch("https://www.gelonghui.com/news/")
|
||||||
const $ = cheerio.load(html)
|
const $ = cheerio.load(html)
|
||||||
const $main = $(".article-content")
|
const $main = $(".article-content")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -3,7 +3,7 @@ import type { NewsItem } from "@shared/types"
|
|||||||
|
|
||||||
const trending = defineSource(async () => {
|
const trending = defineSource(async () => {
|
||||||
const baseURL = "https://github.com"
|
const baseURL = "https://github.com"
|
||||||
const html: any = await $fetch("https://github.com/trending?spoken_language_code=")
|
const html: any = await myFetch("https://github.com/trending?spoken_language_code=")
|
||||||
const $ = cheerio.load(html)
|
const $ = cheerio.load(html)
|
||||||
const $main = $("main .Box div[data-hpc] > article")
|
const $main = $("main .Box div[data-hpc] > article")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -3,7 +3,7 @@ import type { NewsItem } from "@shared/types"
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const baseURL = "https://news.ycombinator.com"
|
const baseURL = "https://news.ycombinator.com"
|
||||||
const html: any = await $fetch(baseURL)
|
const html: any = await myFetch(baseURL)
|
||||||
const $ = cheerio.load(html)
|
const $ = cheerio.load(html)
|
||||||
const $main = $(".athing")
|
const $main = $(".athing")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -2,7 +2,7 @@ import * as cheerio from "cheerio"
|
|||||||
import type { NewsItem } from "@shared/types"
|
import type { NewsItem } from "@shared/types"
|
||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const response: any = await $fetch("https://www.ithome.com/list/")
|
const response: any = await myFetch("https://www.ithome.com/list/")
|
||||||
const $ = cheerio.load(response)
|
const $ = cheerio.load(response)
|
||||||
const $main = $("#list > div.fl > ul > li")
|
const $main = $("#list > div.fl > ul > li")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -23,7 +23,7 @@ export default defineSource(async () => {
|
|||||||
const timestamp = Date.now()
|
const timestamp = Date.now()
|
||||||
const url = `https://www.jin10.com/flash_newest.js?t=${timestamp}`
|
const url = `https://www.jin10.com/flash_newest.js?t=${timestamp}`
|
||||||
|
|
||||||
const rawData: string = await $fetch(url)
|
const rawData: string = await myFetch(url)
|
||||||
|
|
||||||
const jsonStr = (rawData as string)
|
const jsonStr = (rawData as string)
|
||||||
.replace(/^var\s+newest\s*=\s*/, "") // 移除开头的变量声明
|
.replace(/^var\s+newest\s*=\s*/, "") // 移除开头的变量声明
|
||||||
|
@ -7,7 +7,7 @@ type Res = {
|
|||||||
title: string
|
title: string
|
||||||
}[]
|
}[]
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const res = await Promise.all(["https://kaopucdn.azureedge.net/jsondata/news_list_beta_hans_0.json", "https://kaopucdn.azureedge.net/jsondata/news_list_beta_hans_1.json"].map(url => $fetch(url) as Promise<Res>))
|
const res = await Promise.all(["https://kaopucdn.azureedge.net/jsondata/news_list_beta_hans_0.json", "https://kaopucdn.azureedge.net/jsondata/news_list_beta_hans_1.json"].map(url => myFetch(url) as Promise<Res>))
|
||||||
return res.flat().filter(k => ["财新", "公视"].every(h => k.publisher !== h)).map((k) => {
|
return res.flat().filter(k => ["财新", "公视"].every(h => k.publisher !== h)).map((k) => {
|
||||||
return {
|
return {
|
||||||
id: k.link,
|
id: k.link,
|
||||||
|
@ -26,7 +26,7 @@ interface HotRankData {
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
// 获取快手首页HTML
|
// 获取快手首页HTML
|
||||||
const html = await $fetch("https://www.kuaishou.com/?isHome=1")
|
const html = await myFetch("https://www.kuaishou.com/?isHome=1")
|
||||||
// 提取window.__APOLLO_STATE__中的数据
|
// 提取window.__APOLLO_STATE__中的数据
|
||||||
const matches = (html as string).match(/window\.__APOLLO_STATE__\s*=\s*(\{.+?\});/)
|
const matches = (html as string).match(/window\.__APOLLO_STATE__\s*=\s*(\{.+?\});/)
|
||||||
if (!matches) {
|
if (!matches) {
|
||||||
|
@ -3,7 +3,7 @@ import type { NewsItem } from "@shared/types"
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const baseURL = "https://www.producthunt.com/"
|
const baseURL = "https://www.producthunt.com/"
|
||||||
const html: any = await $fetch(baseURL)
|
const html: any = await myFetch(baseURL)
|
||||||
const $ = cheerio.load(html)
|
const $ = cheerio.load(html)
|
||||||
const $main = $("[data-test^=post-item]")
|
const $main = $("[data-test^=post-item]")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -3,7 +3,7 @@ import type { NewsItem } from "@shared/types"
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const baseURL = "https://www.solidot.org"
|
const baseURL = "https://www.solidot.org"
|
||||||
const html: any = await $fetch(baseURL)
|
const html: any = await myFetch(baseURL)
|
||||||
const $ = cheerio.load(html)
|
const $ = cheerio.load(html)
|
||||||
const $main = $(".block_m")
|
const $main = $(".block_m")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -2,7 +2,7 @@ import * as cheerio from "cheerio"
|
|||||||
import type { NewsItem } from "@shared/types"
|
import type { NewsItem } from "@shared/types"
|
||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const response: any = await $fetch("https://sputniknews.cn/services/widget/lenta/")
|
const response: any = await myFetch("https://sputniknews.cn/services/widget/lenta/")
|
||||||
const $ = cheerio.load(response)
|
const $ = cheerio.load(response)
|
||||||
const $items = $(".lenta__item")
|
const $items = $(".lenta__item")
|
||||||
const news: NewsItem[] = []
|
const news: NewsItem[] = []
|
||||||
|
@ -10,7 +10,7 @@ interface Res {
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const url = "https://cache.thepaper.cn/contentapi/wwwIndex/rightSidebar"
|
const url = "https://cache.thepaper.cn/contentapi/wwwIndex/rightSidebar"
|
||||||
const res: Res = await $fetch(url)
|
const res: Res = await myFetch(url)
|
||||||
return res.data.hotNews
|
return res.data.hotNews
|
||||||
.map((k) => {
|
.map((k) => {
|
||||||
return {
|
return {
|
||||||
|
@ -14,7 +14,7 @@ interface Res {
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const url = "https://tieba.baidu.com/hottopic/browse/topicList"
|
const url = "https://tieba.baidu.com/hottopic/browse/topicList"
|
||||||
const res: Res = await $fetch(url)
|
const res: Res = await myFetch(url)
|
||||||
return res.data.bang_topic.topic_list
|
return res.data.bang_topic.topic_list
|
||||||
.map((k) => {
|
.map((k) => {
|
||||||
return {
|
return {
|
||||||
|
@ -11,7 +11,7 @@ interface Res {
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const url = "https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc"
|
const url = "https://www.toutiao.com/hot-event/hot-board/?origin=toutiao_pc"
|
||||||
const res: Res = await $fetch(url)
|
const res: Res = await myFetch(url)
|
||||||
return res.data
|
return res.data
|
||||||
.map((k) => {
|
.map((k) => {
|
||||||
return {
|
return {
|
||||||
|
@ -17,7 +17,8 @@ interface Res {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const share = defineSource(async () => {
|
const share = defineSource(async () => {
|
||||||
const res = await Promise.all(["create", "ideas", "programmer", "share"].map(k => $fetch(`https://www.v2ex.com/feed/${k}.json`) as Promise< Res>))
|
const res = await Promise.all(["create", "ideas", "programmer", "share"]
|
||||||
|
.map(k => myFetch(`https://www.v2ex.com/feed/${k}.json`) as Promise<Res>))
|
||||||
return res.map(k => k.items).flat().map(k => ({
|
return res.map(k => k.items).flat().map(k => ({
|
||||||
id: k.id,
|
id: k.id,
|
||||||
title: k.title,
|
title: k.title,
|
||||||
|
@ -33,7 +33,7 @@ interface HotRes {
|
|||||||
const live = defineSource(async () => {
|
const live = defineSource(async () => {
|
||||||
const apiUrl = `https://api-one.wallstcn.com/apiv1/content/lives?channel=global-channel&limit=30`
|
const apiUrl = `https://api-one.wallstcn.com/apiv1/content/lives?channel=global-channel&limit=30`
|
||||||
|
|
||||||
const res: LiveRes = await $fetch(apiUrl)
|
const res: LiveRes = await myFetch(apiUrl)
|
||||||
return res.data.items
|
return res.data.items
|
||||||
.map((k) => {
|
.map((k) => {
|
||||||
return {
|
return {
|
||||||
@ -50,7 +50,7 @@ const live = defineSource(async () => {
|
|||||||
const news = defineSource(async () => {
|
const news = defineSource(async () => {
|
||||||
const apiUrl = `https://api-one.wallstcn.com/apiv1/content/information-flow?channel=global-channel&accept=article&limit=30`
|
const apiUrl = `https://api-one.wallstcn.com/apiv1/content/information-flow?channel=global-channel&accept=article&limit=30`
|
||||||
|
|
||||||
const res: NewsRes = await $fetch(apiUrl)
|
const res: NewsRes = await myFetch(apiUrl)
|
||||||
return res.data.items
|
return res.data.items
|
||||||
.filter(k => k.resource_type !== "ad" && k.resource.type !== "live" && k.resource.uri)
|
.filter(k => k.resource_type !== "ad" && k.resource.type !== "live" && k.resource.uri)
|
||||||
.map(({ resource: h }) => {
|
.map(({ resource: h }) => {
|
||||||
@ -68,7 +68,7 @@ const news = defineSource(async () => {
|
|||||||
const hot = defineSource(async () => {
|
const hot = defineSource(async () => {
|
||||||
const apiUrl = `https://api-one.wallstcn.com/apiv1/content/articles/hot?period=all`
|
const apiUrl = `https://api-one.wallstcn.com/apiv1/content/articles/hot?period=all`
|
||||||
|
|
||||||
const res: HotRes = await $fetch(apiUrl)
|
const res: HotRes = await myFetch(apiUrl)
|
||||||
return res.data.day_items
|
return res.data.day_items
|
||||||
.map((h) => {
|
.map((h) => {
|
||||||
return {
|
return {
|
||||||
|
@ -27,7 +27,7 @@ interface Res {
|
|||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const url = "https://weibo.com/ajax/side/hotSearch"
|
const url = "https://weibo.com/ajax/side/hotSearch"
|
||||||
const res: Res = await $fetch(url)
|
const res: Res = await myFetch(url)
|
||||||
return res.data.realtime
|
return res.data.realtime
|
||||||
.filter(k => !k.is_ad)
|
.filter(k => !k.is_ad)
|
||||||
.map((k) => {
|
.map((k) => {
|
||||||
|
@ -16,7 +16,7 @@ interface StockRes {
|
|||||||
const hotstock = defineSource(async () => {
|
const hotstock = defineSource(async () => {
|
||||||
const url = "https://stock.xueqiu.com/v5/stock/hot_stock/list.json?size=30&_type=10&type=10"
|
const url = "https://stock.xueqiu.com/v5/stock/hot_stock/list.json?size=30&_type=10&type=10"
|
||||||
const cookie = (await $fetch.raw("https://xueqiu.com")).headers.getSetCookie()
|
const cookie = (await $fetch.raw("https://xueqiu.com")).headers.getSetCookie()
|
||||||
const res: StockRes = await $fetch(url, {
|
const res: StockRes = await myFetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
cookie: cookie.join("; "),
|
cookie: cookie.join("; "),
|
||||||
},
|
},
|
||||||
|
@ -2,10 +2,9 @@ import { Buffer } from "node:buffer"
|
|||||||
import * as cheerio from "cheerio"
|
import * as cheerio from "cheerio"
|
||||||
import iconv from "iconv-lite"
|
import iconv from "iconv-lite"
|
||||||
import type { NewsItem } from "@shared/types"
|
import type { NewsItem } from "@shared/types"
|
||||||
import { $fetch } from "ofetch"
|
|
||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const response: ArrayBuffer = await $fetch("https://www.kzaobao.com/top.html", {
|
const response: ArrayBuffer = await myFetch("https://www.kzaobao.com/top.html", {
|
||||||
responseType: "arrayBuffer",
|
responseType: "arrayBuffer",
|
||||||
})
|
})
|
||||||
const base = "https://www.kzaobao.com"
|
const base = "https://www.kzaobao.com"
|
||||||
|
@ -22,7 +22,7 @@ interface Res {
|
|||||||
export default defineSource({
|
export default defineSource({
|
||||||
zhihu: async () => {
|
zhihu: async () => {
|
||||||
const url = "https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=20&desktop=true"
|
const url = "https://www.zhihu.com/api/v3/feed/topstory/hot-lists/total?limit=20&desktop=true"
|
||||||
const res: Res = await $fetch(url)
|
const res: Res = await myFetch(url)
|
||||||
return res.data
|
return res.data
|
||||||
.map((k) => {
|
.map((k) => {
|
||||||
return {
|
return {
|
||||||
|
9
server/utils/fetch.ts
Normal file
9
server/utils/fetch.ts
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { $fetch } from "ofetch"
|
||||||
|
|
||||||
|
export const myFetch = $fetch.create({
|
||||||
|
headers: {
|
||||||
|
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36",
|
||||||
|
},
|
||||||
|
timeout: 5000,
|
||||||
|
retry: 3,
|
||||||
|
})
|
@ -1,11 +1,10 @@
|
|||||||
import { XMLParser } from "fast-xml-parser"
|
import { XMLParser } from "fast-xml-parser"
|
||||||
import { $fetch } from "ofetch"
|
|
||||||
import type { RSSInfo } from "../types"
|
import type { RSSInfo } from "../types"
|
||||||
|
|
||||||
export async function rss2json(url: string): Promise<RSSInfo | undefined> {
|
export async function rss2json(url: string): Promise<RSSInfo | undefined> {
|
||||||
if (!/^https?:\/\/[^\s$.?#].\S*/i.test(url)) return
|
if (!/^https?:\/\/[^\s$.?#].\S*/i.test(url)) return
|
||||||
|
|
||||||
const data = await $fetch(url)
|
const data = await myFetch(url)
|
||||||
|
|
||||||
const xml = new XMLParser({
|
const xml = new XMLParser({
|
||||||
attributeNamePrefix: "",
|
attributeNamePrefix: "",
|
||||||
|
@ -35,7 +35,7 @@ export function defineRSSHubSource(route: string, RSSHubOptions?: RSSHubOption,
|
|||||||
Object.entries(RSSHubOptions).forEach(([key, value]) => {
|
Object.entries(RSSHubOptions).forEach(([key, value]) => {
|
||||||
url.searchParams.set(key, value.toString())
|
url.searchParams.set(key, value.toString())
|
||||||
})
|
})
|
||||||
const data: RSSHubResponse = await $fetch(url)
|
const data: RSSHubResponse = await myFetch(url)
|
||||||
return data.items.map(item => ({
|
return data.items.map(item => ({
|
||||||
title: item.title,
|
title: item.title,
|
||||||
url: item.url,
|
url: item.url,
|
||||||
|
@ -2,7 +2,6 @@ import type { NewsItem, SourceID, SourceResponse } from "@shared/types"
|
|||||||
import { useQuery } from "@tanstack/react-query"
|
import { useQuery } from "@tanstack/react-query"
|
||||||
import { AnimatePresence, motion, useInView } from "framer-motion"
|
import { AnimatePresence, motion, useInView } from "framer-motion"
|
||||||
import type { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities"
|
import type { SyntheticListenerMap } from "@dnd-kit/core/dist/hooks/utilities"
|
||||||
import { ofetch } from "ofetch"
|
|
||||||
import { useWindowSize } from "react-use"
|
import { useWindowSize } from "react-use"
|
||||||
import { OverlayScrollbar } from "../common/overlay-scrollbar"
|
import { OverlayScrollbar } from "../common/overlay-scrollbar"
|
||||||
import { refetchSourcesAtom } from "~/atoms"
|
import { refetchSourcesAtom } from "~/atoms"
|
||||||
@ -63,8 +62,7 @@ function NewsCard({ id, inView, handleListeners }: NewsCardProps) {
|
|||||||
const jwt = safeParseString(localStorage.getItem("jwt"))
|
const jwt = safeParseString(localStorage.getItem("jwt"))
|
||||||
if (jwt) headers.Authorization = `Bearer ${jwt}`
|
if (jwt) headers.Authorization = `Bearer ${jwt}`
|
||||||
}
|
}
|
||||||
const response: SourceResponse = await ofetch(url, {
|
const response: SourceResponse = await myFetch(url, {
|
||||||
timeout: 10000,
|
|
||||||
headers,
|
headers,
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -91,6 +89,7 @@ function NewsCard({ id, inView, handleListeners }: NewsCardProps) {
|
|||||||
return prev
|
return prev
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
retry: false,
|
||||||
staleTime: 1000 * 60 * 5,
|
staleTime: 1000 * 60 * 5,
|
||||||
enabled: inView,
|
enabled: inView,
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { PrimitiveMetadata } from "@shared/types"
|
import type { PrimitiveMetadata } from "@shared/types"
|
||||||
import { ofetch } from "ofetch"
|
|
||||||
import { useDebounce, useMount } from "react-use"
|
import { useDebounce, useMount } from "react-use"
|
||||||
import { useLogin } from "./useLogin"
|
import { useLogin } from "./useLogin"
|
||||||
import { useToast } from "./useToast"
|
import { useToast } from "./useToast"
|
||||||
@ -8,7 +7,7 @@ import { safeParseString } from "~/utils"
|
|||||||
async function uploadMetadata(metadata: PrimitiveMetadata) {
|
async function uploadMetadata(metadata: PrimitiveMetadata) {
|
||||||
const jwt = safeParseString(localStorage.getItem("jwt"))
|
const jwt = safeParseString(localStorage.getItem("jwt"))
|
||||||
if (!jwt) return
|
if (!jwt) return
|
||||||
await ofetch("/api/me/sync", {
|
await myFetch("/api/me/sync", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${jwt}`,
|
Authorization: `Bearer ${jwt}`,
|
||||||
@ -23,7 +22,7 @@ async function uploadMetadata(metadata: PrimitiveMetadata) {
|
|||||||
async function downloadMetadata(): Promise<PrimitiveMetadata | undefined> {
|
async function downloadMetadata(): Promise<PrimitiveMetadata | undefined> {
|
||||||
const jwt = safeParseString(localStorage.getItem("jwt"))
|
const jwt = safeParseString(localStorage.getItem("jwt"))
|
||||||
if (!jwt) return
|
if (!jwt) return
|
||||||
const { data, updatedTime } = await ofetch("/api/me/sync", {
|
const { data, updatedTime } = await myFetch("/api/me/sync", {
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${jwt}`,
|
Authorization: `Bearer ${jwt}`,
|
||||||
},
|
},
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
import type { MaybePromise } from "@shared/type.util"
|
import type { MaybePromise } from "@shared/type.util"
|
||||||
|
|
||||||
|
import { $fetch } from "ofetch"
|
||||||
|
|
||||||
export function safeParseString(str: any) {
|
export function safeParseString(str: any) {
|
||||||
try {
|
try {
|
||||||
return JSON.parse(str)
|
return JSON.parse(str)
|
||||||
@ -35,3 +37,8 @@ export class Timer {
|
|||||||
clearTimeout(this.timerId)
|
clearTimeout(this.timerId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const myFetch = $fetch.create({
|
||||||
|
timeout: 10000,
|
||||||
|
retry: 0,
|
||||||
|
})
|
||||||
|
@ -26,9 +26,6 @@ export default defineConfig({
|
|||||||
imports: [{
|
imports: [{
|
||||||
from: "h3",
|
from: "h3",
|
||||||
imports: h3Exports.filter(n => !/^[A-Z]/.test(n) && n !== "use"),
|
imports: h3Exports.filter(n => !/^[A-Z]/.test(n) && n !== "use"),
|
||||||
}, {
|
|
||||||
from: "ofetch",
|
|
||||||
imports: ["$fetch", "ofetch"],
|
|
||||||
}],
|
}],
|
||||||
dirs: ["server/utils", "shared"],
|
dirs: ["server/utils", "shared"],
|
||||||
dts: false,
|
dts: false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user