mirror of
https://github.com/ourongxing/newsnow.git
synced 2025-01-19 11:19:14 +08:00
pref: server
This commit is contained in:
parent
309ab3b2e1
commit
a03907d331
@ -8,7 +8,6 @@ export class Cache {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
const last = performance.now()
|
|
||||||
await this.db.prepare(`
|
await this.db.prepare(`
|
||||||
CREATE TABLE IF NOT EXISTS cache (
|
CREATE TABLE IF NOT EXISTS cache (
|
||||||
id TEXT PRIMARY KEY,
|
id TEXT PRIMARY KEY,
|
||||||
@ -16,20 +15,18 @@ export class Cache {
|
|||||||
data TEXT
|
data TEXT
|
||||||
);
|
);
|
||||||
`).run()
|
`).run()
|
||||||
console.log(`init: `, performance.now() - last)
|
logger.success(`init cache table`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async set(key: string, value: NewsItem[]) {
|
async set(key: string, value: NewsItem[]) {
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
const last = performance.now()
|
|
||||||
await this.db.prepare(
|
await this.db.prepare(
|
||||||
`INSERT OR REPLACE INTO cache (id, data, updated) VALUES (?, ?, ?)`,
|
`INSERT OR REPLACE INTO cache (id, data, updated) VALUES (?, ?, ?)`,
|
||||||
).run(key, JSON.stringify(value), now)
|
).run(key, JSON.stringify(value), now)
|
||||||
console.log(`set ${key}: `, performance.now() - last)
|
logger.success(`set ${key} cache`)
|
||||||
}
|
}
|
||||||
|
|
||||||
async get(key: string): Promise<CacheInfo> {
|
async get(key: string): Promise<CacheInfo> {
|
||||||
const last = performance.now()
|
|
||||||
const row: any = await this.db.prepare(`SELECT id, data, updated FROM cache WHERE id = ?`).get(key)
|
const row: any = await this.db.prepare(`SELECT id, data, updated FROM cache WHERE id = ?`).get(key)
|
||||||
const r = row
|
const r = row
|
||||||
? {
|
? {
|
||||||
@ -37,7 +34,7 @@ export class Cache {
|
|||||||
data: JSON.parse(row.data),
|
data: JSON.parse(row.data),
|
||||||
}
|
}
|
||||||
: undefined
|
: undefined
|
||||||
console.log(`get ${key}: `, performance.now() - last)
|
logger.success(`get ${key} cache`)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
// 创建配置对象
|
|
||||||
export const config = {
|
|
||||||
PORT: 6688,
|
|
||||||
DISALLOW_ROBOT: true,
|
|
||||||
CACHE_TTL: 3600,
|
|
||||||
REQUEST_TIMEOUT: 6000,
|
|
||||||
ALLOWED_DOMAIN: "*",
|
|
||||||
USE_LOG_FILE: true,
|
|
||||||
RSS_MODE: false,
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
import { Interval, TTL } from "@shared/consts"
|
import { Interval, TTL } from "@shared/consts"
|
||||||
import type { SourceResponse } from "@shared/types"
|
import type { SourceResponse } from "@shared/types"
|
||||||
import { sources } from "@shared/data"
|
import { sources } from "@shared/data"
|
||||||
import { fallback, sourcesFn } from "#/sources"
|
import { sourcesFn } from "#/sources"
|
||||||
import { Cache } from "#/cache"
|
import { Cache } from "#/cache"
|
||||||
|
|
||||||
export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
||||||
@ -10,7 +10,7 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
|||||||
const query = getQuery(event)
|
const query = getQuery(event)
|
||||||
const latest = query.latest !== undefined && query.latest !== "false"
|
const latest = query.latest !== undefined && query.latest !== "false"
|
||||||
|
|
||||||
if (!id || !sources[id]) throw new Error("Invalid source id")
|
if (!id || !sources[id] || !sourcesFn[id]) throw new Error("Invalid source id")
|
||||||
const db = useDatabase()
|
const db = useDatabase()
|
||||||
const cacheStore = db ? new Cache(db) : undefined
|
const cacheStore = db ? new Cache(db) : undefined
|
||||||
const now = Date.now()
|
const now = Date.now()
|
||||||
@ -42,10 +42,8 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sourcesFn[id]) {
|
|
||||||
const last = performance.now()
|
|
||||||
const data = await sourcesFn[id]()
|
const data = await sourcesFn[id]()
|
||||||
console.log(`fetch: ${id}`, performance.now() - last)
|
logger.success(`fetch ${id} latest`)
|
||||||
if (cacheStore) event.waitUntil(cacheStore.set(id, data))
|
if (cacheStore) event.waitUntil(cacheStore.set(id, data))
|
||||||
return {
|
return {
|
||||||
status: "success",
|
status: "success",
|
||||||
@ -54,21 +52,8 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
|
|||||||
items: data,
|
items: data,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
const last = performance.now()
|
|
||||||
const data = await fallback(id)
|
|
||||||
console.log(`fetch: ${id}`, performance.now() - last)
|
|
||||||
if (cacheStore) event.waitUntil(cacheStore.set(id, data))
|
|
||||||
return {
|
|
||||||
status: "success",
|
|
||||||
data: {
|
|
||||||
updatedTime: now,
|
|
||||||
items: data,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.error(e)
|
logger.error(e)
|
||||||
return {
|
return {
|
||||||
status: "error",
|
status: "error",
|
||||||
message: e.message ?? e,
|
message: e.message ?? e,
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
import { defineRSSHubSource } from "#/utils"
|
|
||||||
|
|
||||||
export default defineRSSHubSource("/36kr/newsflashes")
|
|
@ -1,5 +0,0 @@
|
|||||||
import { defineRSSHubSource } from "#/utils"
|
|
||||||
|
|
||||||
export default defineRSSHubSource("/36kr/hot-list", {
|
|
||||||
sorted: false,
|
|
||||||
})
|
|
@ -1,33 +0,0 @@
|
|||||||
import type { NewsItem } from "@shared/types"
|
|
||||||
|
|
||||||
export interface Res {
|
|
||||||
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 async function fallback(id: string): Promise<NewsItem[]> {
|
|
||||||
const url = `https://smzdk.top/api/${id}/new`
|
|
||||||
const res: Res = await $fetch(url)
|
|
||||||
if (res.code !== 200 || !res.data) throw new Error(res.message)
|
|
||||||
return res.data.map(item => ({
|
|
||||||
extra: {
|
|
||||||
date: item.time,
|
|
||||||
},
|
|
||||||
id: item.url,
|
|
||||||
title: item.title,
|
|
||||||
url: item.url,
|
|
||||||
mobileUrl: item.mobileUrl,
|
|
||||||
}))
|
|
||||||
}
|
|
@ -1,18 +1,14 @@
|
|||||||
import type { NewsItem, SourceID } from "@shared/types"
|
import type { NewsItem, SourceID } from "@shared/types"
|
||||||
import peopledaily from "./peopledaily"
|
|
||||||
import weibo from "./weibo"
|
import weibo from "./weibo"
|
||||||
import zaobao from "./zaobao"
|
import zaobao from "./zaobao"
|
||||||
import krQ from "./36kr-quick"
|
|
||||||
import wallstreetcn from "./wallstreetcn"
|
|
||||||
// import kr from "./36kr"
|
|
||||||
|
|
||||||
export { fallback } from "./fallback"
|
|
||||||
|
|
||||||
export const sourcesFn = {
|
export const sourcesFn = {
|
||||||
peopledaily,
|
"peopledaily": defineRSSSource("https://feedx.net/rss/people.xml"),
|
||||||
weibo,
|
weibo,
|
||||||
|
"douyin": defineFallbackSource("douyin"),
|
||||||
zaobao,
|
zaobao,
|
||||||
wallstreetcn,
|
"toutiao": defineFallbackSource("toutiao"),
|
||||||
"36kr-quick": krQ,
|
"wallstreetcn": defineRSSHubSource("/wallstreetcn/live"),
|
||||||
|
"36kr-quick": defineRSSHubSource("/36kr/newsflashes"),
|
||||||
// "36kr": kr,
|
// "36kr": kr,
|
||||||
} as Record<SourceID, () => Promise<NewsItem[]>>
|
} as Record<SourceID, () => Promise<NewsItem[]>>
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
import { defineRSSSource } from "#/utils"
|
|
||||||
|
|
||||||
export default defineRSSSource("https://feedx.net/rss/people.xml")
|
|
@ -1,3 +0,0 @@
|
|||||||
import { defineRSSHubSource } from "#/utils"
|
|
||||||
|
|
||||||
export default defineRSSHubSource("/wallstreetcn/live")
|
|
@ -1,5 +1,3 @@
|
|||||||
import { defineSource } from "#/utils"
|
|
||||||
|
|
||||||
interface Res {
|
interface Res {
|
||||||
ok: number // 1 is ok
|
ok: number // 1 is ok
|
||||||
data: {
|
data: {
|
||||||
|
@ -3,8 +3,6 @@ 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"
|
import { $fetch } from "ofetch"
|
||||||
import { tranformToUTC } from "#/utils/date"
|
|
||||||
import { defineSource } from "#/utils"
|
|
||||||
|
|
||||||
export default defineSource(async () => {
|
export default defineSource(async () => {
|
||||||
const response: ArrayBuffer = await $fetch("https://www.kzaobao.com/top.html", {
|
const response: ArrayBuffer = await $fetch("https://www.kzaobao.com/top.html", {
|
||||||
|
@ -1,10 +1,42 @@
|
|||||||
import { RSSHubBase } from "@shared/consts"
|
import { RSSHubBase } from "@shared/consts"
|
||||||
import type { NewsItem, RSSHubInfo } from "@shared/types"
|
import type { NewsItem, RSSHubInfo, SourceID } from "@shared/types"
|
||||||
|
|
||||||
export function defineSource(source: () => Promise<NewsItem[]>): () => Promise<NewsItem[]> {
|
export function defineSource(source: () => Promise<NewsItem[]>): () => Promise<NewsItem[]> {
|
||||||
return source
|
return source
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface FallbackRes {
|
||||||
|
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 function defineFallbackSource(id: SourceID): () => Promise<NewsItem[]> {
|
||||||
|
return async () => {
|
||||||
|
const url = `https://smzdk.top/api/${id}/new`
|
||||||
|
const res: FallbackRes = await $fetch(url)
|
||||||
|
if (res.code !== 200 || !res.data) throw new Error(res.message)
|
||||||
|
return res.data.map(item => ({
|
||||||
|
extra: {
|
||||||
|
date: item.time,
|
||||||
|
},
|
||||||
|
id: item.url,
|
||||||
|
title: item.title,
|
||||||
|
url: item.url,
|
||||||
|
mobileUrl: item.mobileUrl,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
export function defineRSSSource(url: string): () => Promise<NewsItem[]> {
|
export function defineRSSSource(url: string): () => Promise<NewsItem[]> {
|
||||||
return async () => {
|
return async () => {
|
||||||
const data = await rss2json(url)
|
const data = await rss2json(url)
|
||||||
|
11
server/utils/logger.ts
Normal file
11
server/utils/logger.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { createConsola } from "consola"
|
||||||
|
|
||||||
|
export const logger = createConsola({
|
||||||
|
level: 4,
|
||||||
|
formatOptions: {
|
||||||
|
columns: 80,
|
||||||
|
colors: true,
|
||||||
|
compact: false,
|
||||||
|
date: true,
|
||||||
|
},
|
||||||
|
})
|
Loading…
x
Reference in New Issue
Block a user