Skip to content

feat: 把 PyPtt.TwoFactorAuthRequired 標成 TWO_FACTOR_AUTH_REQUIRED,別被 LoginError 吃掉 - #24

Merged
PttCodingMan merged 1 commit into
mainfrom
fix/two-factor-auth-error-code
Aug 8, 2026
Merged

feat: 把 PyPtt.TwoFactorAuthRequired 標成 TWO_FACTOR_AUTH_REQUIRED,別被 LoginError 吃掉#24
PttCodingMan merged 1 commit into
mainfrom
fix/two-factor-auth-error-code

Conversation

@PttCodingMan

Copy link
Copy Markdown
Member

背景

PTT 於 2026-08-04 上線兩階段驗證 (2FA)。PyPtt 2.3.6 新增了 TwoFactorAuthRequired,遇到 2FA 畫面時丟出,訊息會告訴使用者:PTT 的 2FA 可設為「僅新 IP 需驗證」,同一 IP 再次登入會跳過,所以先從這台機器用一般 BBS 客戶端手動登入完成一次驗證即可。

問題是這個訊息到不了使用者手上。TwoFactorAuthRequired 繼承 PyPtt.LoginError,而 _handle_ptt_exception 是依 EXCEPTION_MAPPING插入順序isinstance 線性掃描(src/utils.py),LoginError 排在前面會先命中,指引訊息就被換成泛用的「登入失敗」/LOGIN_FAILED

實測佐證:同一個開了 2FA 的帳號,用工作區版 PyPtt 2.3.6 直接登入會在 0.18 秒拋出 TwoFactorAuthRequired;透過本 MCP server 則只拿到 LOGIN_FAILED

改了什麼

  • src/utils.py — 在掃描迴圈之前加顯式 isinstance 分支。放迴圈前而非塞進 dict,是因為 dict 順序是隱性契約,顯式分支的意圖不會被後人重排時弄壞
  • message 直接透傳 str(e)不在本 repo 複製指引文字——那段字在 PyPtt 的 i18n 語言檔裡,複製會造成兩處不同步,也會失去語系切換能力
  • src/api_ptt.py — docstring 的錯誤碼清單新增 TWO_FACTOR_AUTH_REQUIRED(grep 確認全庫只有這一處清單)
  • src/_version.py — 0.3.0 → 0.3.1

驗證

  • pytest src/ → 20 passed
  • 新測試斷言 code == "TWO_FACTOR_AUTH_REQUIRED"message 為 PyPtt 原文而非「登入失敗」
  • 回歸測試LoginError 仍須回 LOGIN_FAILED,避免反過來把父類搶走
  • 反證測試:把顯式分支刪掉重跑 → AssertionError: assert 'LOGIN_FAILED' == 'TWO_FACTOR_AUTH_REQUIRED',確認測試真的保護到這件事
  • flake8 / mypy 無新增問題

附註

requirements.txt 未 pin pyptt,Dockerfile 每次建置裝最新版且 workflow 設 no-cache: true,所以 merge 後的 image 會自動帶到 PyPtt 2.3.6。實作中對屬性存取加了 getattr 短路保險,舊版共存時不會炸。

🤖 Generated with Claude Code

https://claude.ai/code/session_017UbZgc9a53f3sLyAg3DNbF

…ginError 吃掉

PyPtt 2.3.6 新增 TwoFactorAuthRequired,用於偵測到 PTT 兩階段驗證畫面。
它繼承 LoginError,而 _handle_ptt_exception 是依 EXCEPTION_MAPPING 的插入
順序做 isinstance 線性掃描,LoginError 會先命中,把「請先從這台機器手動
登入完成一次驗證」的指引訊息換成泛用的「登入失敗」。

- utils.py 在掃描迴圈之前加顯式分支。放在迴圈前而非塞進 dict,是因為
  dict 順序是隱性契約,顯式分支的意圖不會被後人重排時弄壞
- message 直接透傳 str(e),不在本 repo 複製指引文字 — 那段字在 PyPtt 的
  i18n 語言檔裡,複製會兩處不同步,也會失去語系切換
- 補 LoginError 仍回 LOGIN_FAILED 的回歸測試,避免反過來搶走父類

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017UbZgc9a53f3sLyAg3DNbF
@PttCodingMan
PttCodingMan merged commit 4584147 into main Aug 8, 2026
1 check passed
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.

1 participant