pref: server

This commit is contained in:
Ou 2024-10-05 23:55:30 +08:00
parent 309ab3b2e1
commit a03907d331
13 changed files with 64 additions and 104 deletions

View File

@ -8,7 +8,6 @@ export class Cache {
}
async init() {
const last = performance.now()
await this.db.prepare(`
CREATE TABLE IF NOT EXISTS cache (
id TEXT PRIMARY KEY,
@ -16,20 +15,18 @@ export class Cache {
data TEXT
);
`).run()
console.log(`init: `, performance.now() - last)
logger.success(`init cache table`)
}
async set(key: string, value: NewsItem[]) {
const now = Date.now()
const last = performance.now()
await this.db.prepare(
`INSERT OR REPLACE INTO cache (id, data, updated) VALUES (?, ?, ?)`,
).run(key, JSON.stringify(value), now)
console.log(`set ${key}: `, performance.now() - last)
logger.success(`set ${key} cache`)
}
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 r = row
? {
@ -37,7 +34,7 @@ export class Cache {
data: JSON.parse(row.data),
}
: undefined
console.log(`get ${key}: `, performance.now() - last)
logger.success(`get ${key} cache`)
return r
}

View File

@ -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,
}

View File

@ -1,7 +1,7 @@
import { Interval, TTL } from "@shared/consts"
import type { SourceResponse } from "@shared/types"
import { sources } from "@shared/data"
import { fallback, sourcesFn } from "#/sources"
import { sourcesFn } from "#/sources"
import { Cache } from "#/cache"
export default defineEventHandler(async (event): Promise<SourceResponse> => {
@ -10,7 +10,7 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
const query = getQuery(event)
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 cacheStore = db ? new Cache(db) : undefined
const now = Date.now()
@ -42,33 +42,18 @@ export default defineEventHandler(async (event): Promise<SourceResponse> => {
}
}
if (sourcesFn[id]) {
const last = performance.now()
const data = await sourcesFn[id]()
console.log(`fetch: ${id}`, performance.now() - last)
if (cacheStore) event.waitUntil(cacheStore.set(id, data))
return {
status: "success",
data: {
updatedTime: now,
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,
},
}
const data = await sourcesFn[id]()
logger.success(`fetch ${id} latest`)
if (cacheStore) event.waitUntil(cacheStore.set(id, data))
return {
status: "success",
data: {
updatedTime: now,
items: data,
},
}
} catch (e: any) {
console.error(e)
logger.error(e)
return {
status: "error",
message: e.message ?? e,

View File

@ -1,3 +0,0 @@
import { defineRSSHubSource } from "#/utils"
export default defineRSSHubSource("/36kr/newsflashes")

View File

@ -1,5 +0,0 @@
import { defineRSSHubSource } from "#/utils"
export default defineRSSHubSource("/36kr/hot-list", {
sorted: false,
})

View File

@ -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,
}))
}

View File

@ -1,18 +1,14 @@
import type { NewsItem, SourceID } from "@shared/types"
import peopledaily from "./peopledaily"
import weibo from "./weibo"
import zaobao from "./zaobao"
import krQ from "./36kr-quick"
import wallstreetcn from "./wallstreetcn"
// import kr from "./36kr"
export { fallback } from "./fallback"
export const sourcesFn = {
peopledaily,
"peopledaily": defineRSSSource("https://feedx.net/rss/people.xml"),
weibo,
"douyin": defineFallbackSource("douyin"),
zaobao,
wallstreetcn,
"36kr-quick": krQ,
"toutiao": defineFallbackSource("toutiao"),
"wallstreetcn": defineRSSHubSource("/wallstreetcn/live"),
"36kr-quick": defineRSSHubSource("/36kr/newsflashes"),
// "36kr": kr,
} as Record<SourceID, () => Promise<NewsItem[]>>

View File

@ -1,3 +0,0 @@
import { defineRSSSource } from "#/utils"
export default defineRSSSource("https://feedx.net/rss/people.xml")

View File

@ -1,3 +0,0 @@
import { defineRSSHubSource } from "#/utils"
export default defineRSSHubSource("/wallstreetcn/live")

View File

@ -1,5 +1,3 @@
import { defineSource } from "#/utils"
interface Res {
ok: number // 1 is ok
data: {

View File

@ -3,8 +3,6 @@ import * as cheerio from "cheerio"
import iconv from "iconv-lite"
import type { NewsItem } from "@shared/types"
import { $fetch } from "ofetch"
import { tranformToUTC } from "#/utils/date"
import { defineSource } from "#/utils"
export default defineSource(async () => {
const response: ArrayBuffer = await $fetch("https://www.kzaobao.com/top.html", {

View File

@ -1,10 +1,42 @@
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[]> {
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[]> {
return async () => {
const data = await rss2json(url)

11
server/utils/logger.ts Normal file
View File

@ -0,0 +1,11 @@
import { createConsola } from "consola"
export const logger = createConsola({
level: 4,
formatOptions: {
columns: 80,
colors: true,
compact: false,
date: true,
},
})