feat: refactor metadata structure

This commit is contained in:
Ou 2024-10-26 00:00:33 +08:00
parent ecc678a2bb
commit f66cee4333
5 changed files with 79 additions and 62 deletions

View File

@ -1,68 +1,54 @@
import { sources } from "./sources" import { sources } from "./sources"
import { typeSafeObjectEntries, typeSafeObjectFromEntries } from "./type.util" import { typeSafeObjectEntries, typeSafeObjectFromEntries } from "./type.util"
import type { Metadata } from "./types" import type { ColumnID, Metadata, SourceID } from "./types"
export const columnIds = ["focus", "realtime", "hottest", "china", "world", "tech", "finance"] as const export const columnIds = ["focus", "realtime", "hottest", "china", "world", "tech", "finance"] as const
const originMetadata: Metadata = { const columnName: Record<ColumnID, { zh: string }> = {
china: { china: {
name: "国内", zh: "国内",
sources: ["zhihu", "thepaper", "douyin", "bilibili-hot-search", "weibo", "toutiao", "tieba"],
}, },
world: { world: {
name: "国际", zh: "国际",
sources: ["zaobao", "cankaoxiaoxi", "kaopu"],
}, },
tech: { tech: {
name: "科技", zh: "科技",
sources: ["hackernews", "producthunt", "github-trending-today", "v2ex", "ithome", "coolapk", "solidot"],
}, },
finance: { finance: {
name: "财经", zh: "财经",
sources: [
"cls-telegraph",
"cls-depth",
"wallstreetcn",
"wallstreetcn-hot",
"wallstreetcn-news",
"xueqiu-hotstock",
"gelonghui",
"fastbull-express",
"fastbull-news",
],
}, },
focus: { focus: {
name: "关注", zh: "关注",
sources: [],
}, },
realtime: { realtime: {
name: "实时", zh: "实时",
sources: [],
}, },
hottest: { hottest: {
name: "最热", zh: "最热",
sources: [],
}, },
} }
export const metadata = typeSafeObjectFromEntries(typeSafeObjectEntries(originMetadata).map(([k, v]) => { export const metadata: Metadata = typeSafeObjectFromEntries(typeSafeObjectEntries(columnName).map(([k, v]) => {
switch (k) { switch (k) {
case "focus": case "focus":
return [k, v] return [k, {
name: v.zh,
sources: [] as SourceID[],
}]
case "hottest": case "hottest":
return [k, { return [k, {
...v, name: v.zh,
sources: typeSafeObjectEntries(sources).filter(([, v]) => v.type === "hottest" && !v.redirect).map(([k]) => k), sources: typeSafeObjectEntries(sources).filter(([, v]) => v.type === "hottest" && !v.redirect).map(([k]) => k),
}] }]
case "realtime": case "realtime":
return [k, { return [k, {
...v, name: v.zh,
sources: ["weibo", ...typeSafeObjectEntries(sources).filter(([, v]) => v.type === "realtime" && !v.redirect).map(([k]) => k)], sources: typeSafeObjectEntries(sources).filter(([, v]) => v.type === "realtime" && !v.redirect).map(([k]) => k),
}] }]
default: default:
return [k, { return [k, {
...v, name: v.zh,
sources: v.sources.filter(s => sources[s]), sources: typeSafeObjectEntries(sources).filter(([, v]) => v.column === k && !v.redirect).map(([k]) => k),
}] }]
} }
})) }))

View File

@ -19,12 +19,14 @@ export const originSources = {
sub: { sub: {
share: { share: {
title: "最新分享", title: "最新分享",
column: "tech",
}, },
}, },
}, },
"zhihu": { "zhihu": {
name: "知乎", name: "知乎",
type: "hottest", type: "hottest",
column: "china",
color: "blue", color: "blue",
home: "https://www.zhihu.com", home: "https://www.zhihu.com",
}, },
@ -32,6 +34,7 @@ export const originSources = {
name: "微博", name: "微博",
title: "实时热搜", title: "实时热搜",
type: "hottest", type: "hottest",
column: "china",
color: "red", color: "red",
interval: Time.Realtime, interval: Time.Realtime,
home: "https://weibo.com", home: "https://weibo.com",
@ -40,12 +43,14 @@ export const originSources = {
name: "联合早报", name: "联合早报",
interval: Time.Common, interval: Time.Common,
type: "realtime", type: "realtime",
column: "world",
color: "red", color: "red",
home: "https://www.zaobao.com", home: "https://www.zaobao.com",
}, },
"coolapk": { "coolapk": {
name: "酷安", name: "酷安",
type: "hottest", type: "hottest",
column: "tech",
color: "green", color: "green",
title: "今日最热", title: "今日最热",
home: "https://coolapk.com", home: "https://coolapk.com",
@ -53,6 +58,7 @@ export const originSources = {
"wallstreetcn": { "wallstreetcn": {
name: "华尔街见闻", name: "华尔街见闻",
color: "blue", color: "blue",
column: "finance",
home: "https://wallstreetcn.com/", home: "https://wallstreetcn.com/",
sub: { sub: {
quick: { quick: {
@ -86,6 +92,7 @@ export const originSources = {
"douyin": { "douyin": {
name: "抖音", name: "抖音",
type: "hottest", type: "hottest",
column: "china",
color: "gray", color: "gray",
home: "https://www.douyin.com", home: "https://www.douyin.com",
}, },
@ -97,6 +104,7 @@ export const originSources = {
"tieba": { "tieba": {
name: "百度贴吧", name: "百度贴吧",
title: "热议", title: "热议",
column: "china",
type: "hottest", type: "hottest",
color: "blue", color: "blue",
home: "https://tieba.baidu.com", home: "https://tieba.baidu.com",
@ -104,12 +112,14 @@ export const originSources = {
"toutiao": { "toutiao": {
name: "今日头条", name: "今日头条",
type: "hottest", type: "hottest",
column: "china",
color: "red", color: "red",
home: "https://www.toutiao.com", home: "https://www.toutiao.com",
}, },
"ithome": { "ithome": {
name: "IT之家", name: "IT之家",
color: "red", color: "red",
column: "tech",
type: "realtime", type: "realtime",
home: "https://www.ithome.com", home: "https://www.ithome.com",
}, },
@ -117,6 +127,7 @@ export const originSources = {
name: "澎湃新闻", name: "澎湃新闻",
interval: Time.Common, interval: Time.Common,
type: "hottest", type: "hottest",
column: "china",
title: "热榜", title: "热榜",
color: "gray", color: "gray",
home: "https://www.thepaper.cn", home: "https://www.thepaper.cn",
@ -130,12 +141,14 @@ export const originSources = {
"cankaoxiaoxi": { "cankaoxiaoxi": {
name: "参考消息", name: "参考消息",
color: "red", color: "red",
column: "world",
interval: Time.Common, interval: Time.Common,
home: "https://china.cankaoxiaoxi.com", home: "https://china.cankaoxiaoxi.com",
}, },
"cls": { "cls": {
name: "财联社", name: "财联社",
color: "red", color: "red",
column: "finance",
home: "https://www.cls.cn", home: "https://www.cls.cn",
sub: { sub: {
telegraph: { telegraph: {
@ -153,6 +166,7 @@ export const originSources = {
name: "雪球", name: "雪球",
color: "blue", color: "blue",
home: "https://xueqiu.com", home: "https://xueqiu.com",
column: "finance",
sub: { sub: {
hotstock: { hotstock: {
title: "热门股票", title: "热门股票",
@ -165,6 +179,7 @@ export const originSources = {
name: "格隆汇", name: "格隆汇",
color: "blue", color: "blue",
title: "事件", title: "事件",
column: "finance",
type: "realtime", type: "realtime",
interval: Time.Realtime, interval: Time.Realtime,
home: "https://www.gelonghui.com", home: "https://www.gelonghui.com",
@ -173,6 +188,7 @@ export const originSources = {
name: "法布财经", name: "法布财经",
color: "emerald", color: "emerald",
home: "https://www.fastbull.cn", home: "https://www.fastbull.cn",
column: "finance",
sub: { sub: {
express: { express: {
title: "快讯", title: "快讯",
@ -188,18 +204,21 @@ export const originSources = {
"solidot": { "solidot": {
name: "Solidot", name: "Solidot",
color: "teal", color: "teal",
column: "tech",
home: "https://solidot.org", home: "https://solidot.org",
interval: Time.Slow, interval: Time.Slow,
}, },
"hackernews": { "hackernews": {
name: "Hacker News", name: "Hacker News",
color: "orange", color: "orange",
column: "tech",
type: "hottest", type: "hottest",
home: "https://news.ycombinator.com/", home: "https://news.ycombinator.com/",
}, },
"producthunt": { "producthunt": {
name: "Product Hunt", name: "Product Hunt",
color: "red", color: "red",
column: "tech",
type: "hottest", type: "hottest",
home: "https://www.producthunt.com/", home: "https://www.producthunt.com/",
}, },
@ -207,6 +226,7 @@ export const originSources = {
name: "Github", name: "Github",
color: "gray", color: "gray",
home: "https://github.com/", home: "https://github.com/",
column: "tech",
sub: { sub: {
"trending-today": { "trending-today": {
title: "Today", title: "Today",
@ -221,12 +241,14 @@ export const originSources = {
sub: { sub: {
"hot-search": { "hot-search": {
title: "热搜", title: "热搜",
column: "china",
type: "hottest", type: "hottest",
}, },
}, },
}, },
"kaopu": { "kaopu": {
name: "靠谱新闻", name: "靠谱新闻",
column: "world",
color: "gray", color: "gray",
desc: "不一定靠谱,多看多思考", desc: "不一定靠谱,多看多思考",
home: "https://kaopu.news/", home: "https://kaopu.news/",
@ -243,6 +265,7 @@ function genSources() {
type: source.type, type: source.type,
disable: source.disable, disable: source.disable,
desc: source.desc, desc: source.desc,
column: source.column,
home: source.home, home: source.home,
color: source.color ?? "primary", color: source.color ?? "primary",
interval: source.interval ?? Time.Default, interval: source.interval ?? Time.Default,

View File

@ -33,40 +33,48 @@ export interface PrimitiveMetadata {
action: "init" | "manual" | "sync" action: "init" | "manual" | "sync"
} }
export interface OriginSource { type ManualColumnID = Exclude<ColumnID, "focus" | "realtime" | "hottest">
export interface OriginSource extends Partial<Omit<Source, "name" | "redirect">> {
name: string name: string
title?: string
desc?: string
/**
*
*/
interval?: number
type?: "hottest" | "realtime"
/**
* @default false
*/
disable?: boolean
home?: string
color?: Color
sub?: Record<string, { sub?: Record<string, {
/**
* Subtitle
*/
title: string title: string
type?: "hottest" | "realtime" // type?: "hottest" | "realtime"
desc?: string // desc?: string
home?: string // column?: ManualColumnID
disable?: boolean // color?: Color
interval?: number // home?: string
}> // disable?: boolean
// interval?: number
} & Partial<Omit<Source, "title" | "name" | "redirect">>>
} }
export interface Source { export interface Source {
name: string name: string
title?: string /**
type?: "hottest" | "realtime" *
color: Color */
desc?: string
home?: string
disable?: boolean
interval: number interval: number
color: Color
/**
* Subtitle
*/
title?: string
desc?: string
/**
* Default normal timeline
*/
type?: "hottest" | "realtime"
column?: ManualColumnID
home?: string
/**
* @default false
*/
disable?: boolean
redirect?: SourceID redirect?: SourceID
} }

View File

@ -46,8 +46,8 @@ export function preprocessMetadata(target: PrimitiveMetadata) {
typeSafeObjectEntries(target.data) typeSafeObjectEntries(target.data)
.filter(([id]) => initialMetadata[id]) .filter(([id]) => initialMetadata[id])
.map(([id, s]) => { .map(([id, s]) => {
if (id === "focus") return [id, s.filter(k => sources[k])] if (id === "focus") return [id, s.filter(k => sources[k]).map(k => sources[k].redirect ?? k)]
const oldS = s.filter(k => initialMetadata[id].includes(k)) const oldS = s.filter(k => initialMetadata[id].includes(k)).map(k => sources[k].redirect ?? k)
const newS = initialMetadata[id].filter(k => !oldS.includes(k)) const newS = initialMetadata[id].filter(k => !oldS.includes(k))
return [id, [...oldS, ...newS]] return [id, [...oldS, ...newS]]
}), }),

View File

@ -9,5 +9,5 @@ export const Route = createFileRoute("/")({
function IndexComponent() { function IndexComponent() {
const focusSources = useAtomValue(focusSourcesAtom) const focusSources = useAtomValue(focusSourcesAtom)
return <Column id={focusSources.length ? "focus" : "realtime"} /> return <Column id={focusSources.length ? "focus" : "hottest"} />
} }