3 Commits
Author SHA1 Message Date
can4hou6joeng4 3bf72e4b66 fix(douban): 图片代理按镜像回退,修复境外部署海报大量 500
imgN.doubanio.com 互为镜像但解析到不同线路:img1 当前解析到国内 IP
180.97.198.41,在境外主机上不可达。此时 fetch 是直接抛异常而不是返回
状态码,于是走进 catch 一律返回 500,首页会有相当比例的海报加载失败。

改为在 imgN.doubanio.com 之间按 img9 -> img3 -> img2 顺序回退,同一
路径换个镜像即可取到。同时保留最后一次的真实状态码,不再把上游的 403
或 404 也统一伪装成 500。
2026-07-31 18:32:34 +08:00
can4hou6joeng4 b63f94fed4 fix(sync): 丢弃缺少 videoId 的同步记录,避免整页崩溃
服务端同步恢复回来的记录不保证结构完整(旧结构或半截写入)。缺少 videoId
的记录会让 HistoryItem.tsx:24 与 FavoritesItem.tsx:21 在渲染期拼播放地址
时对 undefined 调用 toString(),抛出未捕获异常。由于 getVideoUrl() 是在
渲染 href 时调用的,React 会直接卸载整棵树,首页白屏且刷新无效——该账号
只能靠直接改库才能恢复。

新增 lib/utils/sync-records.ts 做可渲染性判定(要求 videoId、source、
title 齐备),在云端拉取入口 useCloudSync 与 HistoryList / FavoritesList
各过滤一次:脏数据进不来,已经落库的也渲染不出来。
2026-07-31 18:28:35 +08:00
can4hou6joeng4 81c46d754e fix(sync): 修复自托管下无法读取 Upstash 配置
app/api/user/{sync,config} 用 @upstash/redis/cloudflare 的
Redis.fromEnv() 创建客户端。该实现只读传入的 env 参数或 Cloudflare
全局绑定,从不回退到 process.env,因此在 Docker / Node 自托管下
url 与 token 恒为 undefined,两个接口必定返回 500,跨设备同步
(收藏、历史、设置)完全不可用。认证走的是 auth.ts 里的
new Redis({ url, token }),所以登录正常,只有用户数据读写失败。

把 auth.ts 中已有的双源回退抽成 lib/server/runtime-env.ts,Redis
客户端抽成 lib/server/redis.ts,两个路由改为惰性获取共享客户端。
惰性创建同时修正了另一个隐患:Cloudflare 的 per-request 绑定在
模块求值阶段不可达,而原先客户端是在模块作用域创建的。

未配置 Upstash 时返回 503 并给出明确说明,而不是当成请求失败。

Fixes #226
2026-07-31 10:12:40 +08:00