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