From 8a471cb489153d7657cd9049a43847d8c5d6c4eb Mon Sep 17 00:00:00 2001 From: Zichao Lin Date: Thu, 3 Sep 2026 23:52:31 +0800 Subject: [PATCH] =?UTF-8?q?fix(tg=5Fbot):=20=E6=94=BE=E5=AE=BD=E9=80=80?= =?UTF-8?q?=E8=AE=A2=E9=93=BE=E6=8E=A5=20URL=20=E9=95=BF=E5=BA=A6=E4=B8=8A?= =?UTF-8?q?=E9=99=90=EF=BC=8C=E9=95=BF=20tracking=20=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E4=B8=8D=E8=A2=AB=E8=AF=AF=E6=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测 D:\DOWNLOADS\mail_bot.db 中 ChatGPT 推广邮件的退订链接 (https://r.openai.com/asm/unsubscribe/?...) 长度 700+ 字符, 而 _link_buttons 的 len(url) < 200 校验会把它过滤掉,导致 即使 AI 提取出退订链接、显示层也修好了,按钮依然不显示。 上限 200 -> 2048(Telegram inline URL 按钮安全范围)。 新增回归测试 test_long_unsub_url_rendered / test_oversized_url_filtered, 共 9 个用例全部通过。 --- src/tg_bot.py | 5 +++-- tests/test_unsub_keyboard.py | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/tg_bot.py b/src/tg_bot.py index 2c8e21d..2593caa 100644 --- a/src/tg_bot.py +++ b/src/tg_bot.py @@ -217,8 +217,9 @@ def _link_buttons(links: list | None) -> list: rows = [] for link in unsub_links + other_links: url = link.get("url", "") - # 校验 URL:合法 http/https,无多重协议头,长度合理 - if not (url.startswith("http") and url.count("://") == 1 and len(url) < 200): + # 校验 URL:合法 http/https,无多重协议头,长度合理。 + # 退订链接常带长 tracking 参数(实测 OpenAI 的 >700 字符),上限放宽到 2048 + if not (url.startswith("http") and url.count("://") == 1 and len(url) < 2048): continue text = (link.get("text") or "").strip()[:30] if not text: diff --git a/tests/test_unsub_keyboard.py b/tests/test_unsub_keyboard.py index 8fe0692..486577b 100644 --- a/tests/test_unsub_keyboard.py +++ b/tests/test_unsub_keyboard.py @@ -75,7 +75,7 @@ def test_unsub_link_sorted_before_other_links(): def test_invalid_url_filtered(): - """非法 URL(非 http、多重协议头、超长)被过滤""" + """非法 URL(非 http、多重协议头)被过滤""" links = [ {"text": "退订", "url": "javascript:alert(1)"}, {"text": "退订", "url": "https://x.com/https://evil.com"}, @@ -83,4 +83,23 @@ def test_invalid_url_filtered(): ] rows = _link_buttons(links) assert len(rows) == 1 - assert rows[0][0]["url"] == "https://ok.example.com/unsub" \ No newline at end of file + assert rows[0][0]["url"] == "https://ok.example.com/unsub" + + +def test_long_unsub_url_rendered(): + """长 tracking 退订链接(如 OpenAI 的 >700 字符)必须渲染,不能被长度过滤误杀""" + url = "https://r.openai.com/asm/unsubscribe/?user_id=108370056&data=" + "x" * 700 + assert len(url) > 200 + links = [{"text": "取消订阅", "url": url}] + rows = _link_buttons(links) + assert len(rows) == 1 + assert rows[0][0]["url"] == url + assert "🔕" in rows[0][0]["text"] + + +def test_oversized_url_filtered(): + """超过 2048 的 URL 仍被过滤""" + url = "https://example.com/" + "x" * 2100 + links = [{"text": "退订", "url": url}] + rows = _link_buttons(links) + assert rows == [] \ No newline at end of file