Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion notifications/telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

from __future__ import annotations

import re

from notifications.events import NotificationPublisher, RenderedNotification

try:
Expand All @@ -12,6 +14,18 @@
_merge_strategy_plugin_i18n = None


_TELEGRAM_MARKET_SYMBOL_LINK_RE = re.compile(r"(?<![A-Za-z0-9_])([A-Z0-9]{1,12})\.([A-Z]{2,4})(?![A-Za-z0-9_])")
_TELEGRAM_MARKET_SYMBOL_LINK_JOINER = "\u2060"


def _break_telegram_market_symbol_auto_links(value) -> str:
text = str(value or "")
return _TELEGRAM_MARKET_SYMBOL_LINK_RE.sub(
lambda match: f"{match.group(1)}.{_TELEGRAM_MARKET_SYMBOL_LINK_JOINER}{match.group(2)}",
Comment on lines +23 to +24

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Skip URL spans when breaking symbol auto-links

When a Telegram message includes a real URL whose domain or path segment matches this pattern, such as https://EXAMPLE.COM/status or https://SOXL.US/chart, the global substitution inserts the word-joiner into the URL text and makes the sent link invalid/non-clickable. Since build_sender applies this sanitizer to the entire prefixed message, URL ranges need to be detected and left unchanged before rewriting standalone market symbols.

Useful? React with 👍 / 👎.

text,
)


SIGNAL_ICONS = {
"hold": "💎",
"entry": "🚀",
Expand Down Expand Up @@ -428,7 +442,11 @@ def send_tg_message(message):
url = f"https://api.telegram.org/bot{token}/sendMessage"
try:
prefixed = with_prefix_fn(message)
requests_module.post(url, json={"chat_id": chat_id, "text": prefixed}, timeout=10)
requests_module.post(
url,
json={"chat_id": chat_id, "text": _break_telegram_market_symbol_auto_links(prefixed)},
timeout=10,
)
except Exception as exc:
print(f"Telegram send failed: {type(exc).__name__}", flush=True)

Expand Down
4 changes: 2 additions & 2 deletions tests/test_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -404,12 +404,12 @@ def test_build_sender_posts_prefixed_message(self):
with_prefix_fn=build_prefixer("HK", "longbridge-quant-semiconductor-rotation-income-hk"),
requests_module=fake_requests,
)
sender("hello")
sender("SOXL.US and 00700.HK")
self.assertEqual(len(fake_requests.calls), 1)
url, payload, timeout = fake_requests.calls[0]
self.assertIn("token-1", url)
self.assertEqual(payload["chat_id"], "chat-1")
self.assertEqual(payload["text"], "[HK] hello")
self.assertEqual(payload["text"], "[HK] SOXL.\u2060US and 00700.\u2060HK")
self.assertEqual(timeout, 10)

def test_build_issue_notifier_logs_and_sends(self):
Expand Down