Skip to content

fix: 修复 GUI 安装/打包、rla2json 读取 archive、RLA 非严格容错与凭据泄漏 - #1

Open
luoxiadesu wants to merge 2 commits into
mainfrom
fix/p0-gui-atbunch-rla-secrets
Open

luoxiadesu wants to merge 2 commits into
mainfrom
fix/p0-gui-atbunch-rla-secrets

Conversation

@luoxiadesu

Copy link
Copy Markdown

摘要 / 动机

本轮针对几类“装不上 / 必崩 / 泄密”的问题做集中修复,均可在 0.8.2(f41761e)上复现:

  1. GUI 装不上、CI 构建失败:GooeyEx>=0.1.1 并未发布到 PyPI(PyPI 上只有 0.0.1–0.1.0),pip install "sssekai[gui]" 无法解析依赖;未装 GooeyEx 时 sssekai-gui 直接抛 ImportError 堆栈。criware extra 依赖的 PyCriCodecsEx 同样不在 PyPI,且代码中无任何导入。
  2. rla2json 读 archive 必崩:RLH 头从 TextAsset 读出后被编码为 bytes,却按 dict 下标访问,抛 TypeError: byte indices must be integers or slices, not str。只有 archive 路径受影响。
  3. 非严格模式反而中断导出:rla2json 的 --strict 默认关闭;遇到无法解析的包时,read_rla_frames 的非严格分支缺少 continue,落到未赋值的 split_info,抛 UnboundLocalError 终止整次导出。
  4. 截断 payload 被静默“缩短”:strict=False 下不完整数组被当成正常帧返回(例如 MotionData 返回空 poses),导出的 JSON 缺帧且无提示。
  5. 凭据进入日志 / 异常输出:auth_credential、X-Session-Token 会出现在 logger.debug("Set config: %s")、logger.info("Saving cache: %s") 以及 repr(dataclasses.asdict(cache.database)) 中。
  6. abserve 默认对局域网开放:默认 --host 0.0.0.0,把本地缓存暴露给同网段。
  7. 文档给出的命令不可用:README 指引的 pip install sssekai[gui] 不可安装;apphash --format markdown 生成的 Python 示例使用不存在的 ab_version= 关键字,复制即 TypeError。

改动内容

打包与 GUI

  • setup.py:38-45:移除 gui 与 criware 两个 extra,仅保留 il2cpp;注释说明原因。sssekai-gui console script 保留。
  • README.md:23-30:GUI 改为从上游 git 手动安装 GooeyEx(含版本校验方法),或使用 Releases 的 CLI。
  • sssekai/__gui__.py:8-18:缺少 GooeyEx 时向 stderr 打印可执行指引并 SystemExit(1),不再输出堆栈。
  • .github/workflows/python-publish.yml:84-88:删除 release_gui 输入与 GUI 打包步骤,改为注释说明本地构建方式。
  • .vscode/launch.json:删除 3 个指向不存在目录的调试配置。

兼容性:pip install "sssekai[gui]" 不再报错但也不会装任何 GUI 依赖(pip 对未知 extra 不告警)。GUI 源码与 sssekai-gui.spec 保留。

RLA 解析

  • rla2json.py:60:读取 RLH 后先 json.loads(header.decode("utf-8"))。
  • fmt/rla.py:38-42:新增 StreamingDataTruncatedException,区分“截断/损坏”与“解码器自身 bug”。
  • fmt/rla.py:240-254:非严格模式下不完整数组抛该异常而非返回短数组;strict=True 行为不变。
  • fmt/rla.py:471-493:新增 DECODE_ERRORS 白名单(含 zlib.error、gzip.BadGzipFile、struct.error 等),只有坏包错误被跳过;TypeError/AttributeError 仍会抛出,避免掩盖解码器 bug。
  • fmt/rla.py:501-505:外层解析失败补 continue,修复 UnboundLocalError。
  • fmt/rla.py:518-547:split 组在长度校验前先行清理;非严格模式下长度不符或 base64 损坏的 split 包跳过。

兼容性(行为变化):

  • strict=True(API 默认)不变。
  • strict=False 语义由“返回不完整包”改为“丢弃整帧并继续”;rla2json 默认非严格,坏帧会从输出消失而非产生残缺 JSON。
  • 外部若直接调用 decode_streaming_data(strict=False),需捕获 StreamingDataTruncatedException。

凭据脱敏

  • abcache/__init__.py:17-32:RedactedStr(str 子类,repr 为 <redacted>,pickle 为普通 str)。
  • abcache/__init__.py:287-301:RedactedHeaders(dict 子类,repr 只显示条数,__deepcopy__ 保持类型以穿过 asdict,pickle 为普通 dict)。
  • 三个 dataclass 通过 __setattr__ 自动包装凭据字段;SSSekaiDatabase.__repr__ 排除 header 值;load() 后 redact_secrets() 重新包装。
  • auth.py:29-30:匿名注册改存 fromdict(SekaiUserData, ...) 结果(HEAD 存原始 dict,导致 SEKAI_CREDENTIAL 抛 AttributeError)。
  • 旧缓存兼容:新代码写出的缓存可被 HEAD 读取;HEAD 写出的旧缓存加载后自动归一化。

范围说明:本改动保证 repr() 与日志路径不泄漏;json.dumps(dataclasses.asdict(db)) 仍会输出明文(子类按内容编码)。当前生产代码无该路径。

CLI 与文档

  • __main__.py:181:abcache 帮助由“阅读 Wiki”改为“用 apphash 子命令”。
  • __main__.py:329-334:abserve --host 默认 0.0.0.0 → 127.0.0.1。
  • apphash.py:264:示例中 ab_version= 修正为 row_ab_version=。

兼容性:依赖 abserve 默认对外服务的用户需显式加 --host 0.0.0.0。

测试

新增 3 个文件、共 22 个测试,覆盖 RLH 头解析、RLA 容错全部分支(含 split 与 gzip)、脱敏(repr/asdict/日志/旧缓存归一化)。实测 pytest -q → 31 passed;6 条 warning 均为 UnityPy 的 UnityVersionFallbackWarning,与本次无关。

不包含 / 后续

  • 版本号未 bump(仍为 0.8.2),缓存格式未迁移——均有意为之。
  • P1 未做:下载器重试/续传、缓存格式演进。
  • GUI 可执行文件不再由 CI 产出。
  • README 中上游 404 链接作为署名保留。

🤖 Generated with Claude Code

GUI 与打包
- 移除 `gui` extra:GooeyEx>=0.1.1 未发布到 PyPI,0.1.0 在无 wx.App
  时导入即崩;改用从上游 git 手动安装的指引。
- 移除未被引用且不可安装的 `criware` extra。
- `sssekai-gui` 缺依赖时打印可执行指引并退出,不再抛 ImportError 堆栈。
- 发布工作流删除必然失败的 GUI 构建步骤,改为本地构建说明。
- 删除指向不存在目录的 .vscode 调试配置。

RLA 解析
- rla2json: RLH 头是 bytes,恢复 json.loads 后再取字段。
- read_rla_frames: 非严格模式下解析失败改为跳过(修复 UnboundLocalError)。
- split 包的长度不符、base64 损坏在非严格模式下跳过,并先清理缓冲组。
- 截断 payload 抛 StreamingDataTruncatedException,由调用方丢弃整帧,
  不再静默返回短数组。
- 解码错误收窄为白名单(含 zlib.error/gzip.BadGzipFile),
  TypeError 等实现 bug 仍会抛出。

凭据脱敏
- 新增 RedactedStr/RedactedHeaders,repr、asdict(deepcopy) 与日志不再
  输出 auth_credential、X-Session-Token。
- load() 后重新包装磁盘读出的明文;兼容旧缓存,pickle 仍写普通 str/dict。
- 旧缓存中 dict 形态的 sekai_user_data 归一化为 SekaiUserData,
  修复 SEKAI_CREDENTIAL 的 AttributeError 与 repr 泄漏。
- auth.py 存入 dataclass 而非原始响应 dict。

CLI 与文档
- abserve 默认监听 127.0.0.1。
- apphash 示例改用正确的 row_ab_version 关键字。
- abcache 帮助文本不再指向已下线的 Wiki。

测试
- 新增 22 个离线回归测试,覆盖 RLA 容错全部分支、脱敏路径与旧缓存兼容。

Co-Authored-By: Claude Code <[email protected]>
@MetaMikuAI
MetaMikuAI self-requested a review November 2, 2026 12:14

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants