Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 96d1d3dd10 |
@@ -290,12 +290,14 @@ class AlertFormatter:
|
||||
wallet_line += f" \\(Age: {age_hours:.0f}h\\)"
|
||||
lines.append(wallet_line)
|
||||
|
||||
# Risk score
|
||||
lines.append(f"*Risk Score:* {assessment.weighted_score:.2f} \\({risk_level}\\)")
|
||||
# Risk score — every numeric literal here must be escaped because
|
||||
# MarkdownV2 treats `.` as a special character and rejects unescaped
|
||||
# ones with `Bad Request: can't parse entities`.
|
||||
score_str = self._escape_telegram_markdown(f"{assessment.weighted_score:.2f}")
|
||||
lines.append(f"*Risk Score:* {score_str} \\({risk_level}\\)")
|
||||
|
||||
# Market
|
||||
market_title = trade.event_title or trade.market_slug or "Unknown Market"
|
||||
# Escape special Telegram markdown characters
|
||||
market_title_escaped = self._escape_telegram_markdown(market_title)
|
||||
if "market" in links:
|
||||
lines.append(f"*Market:* [{market_title_escaped}]({links['market']})")
|
||||
@@ -303,14 +305,16 @@ class AlertFormatter:
|
||||
lines.append(f"*Market:* {market_title_escaped}")
|
||||
|
||||
# Trade details
|
||||
usdc_value = format_usdc(trade.notional_value).replace("$", "\\$")
|
||||
lines.append(
|
||||
f"*Trade:* {trade.side} {trade.outcome} @ \\${trade.price:.3f} \\| {usdc_value}"
|
||||
)
|
||||
usdc_value = self._escape_telegram_markdown(format_usdc(trade.notional_value))
|
||||
price_str = self._escape_telegram_markdown(f"{trade.price:.3f}")
|
||||
side_escaped = self._escape_telegram_markdown(trade.side)
|
||||
outcome_escaped = self._escape_telegram_markdown(trade.outcome)
|
||||
lines.append(f"*Trade:* {side_escaped} {outcome_escaped} @ \\${price_str} \\| {usdc_value}")
|
||||
|
||||
# Signals
|
||||
if signals:
|
||||
lines.append(f"*Signals:* {', '.join(signals)}")
|
||||
signals_escaped = [self._escape_telegram_markdown(s) for s in signals]
|
||||
lines.append(f"*Signals:* {', '.join(signals_escaped)}")
|
||||
|
||||
# Links
|
||||
lines.append("")
|
||||
|
||||
@@ -409,12 +409,27 @@ class TestTelegramMarkdown:
|
||||
assert "`0x1234...5678`" in result.telegram_markdown
|
||||
|
||||
def test_telegram_includes_risk_score(self, high_risk_assessment: RiskAssessment) -> None:
|
||||
"""Test that Telegram message includes risk score."""
|
||||
"""Test that Telegram message includes risk score, MarkdownV2-escaped."""
|
||||
formatter = AlertFormatter()
|
||||
result = formatter.format(high_risk_assessment)
|
||||
assert "0.82" in result.telegram_markdown
|
||||
# MarkdownV2 requires `.` to be escaped, so 0.82 becomes 0\.82.
|
||||
assert "0\\.82" in result.telegram_markdown
|
||||
assert "HIGH" in result.telegram_markdown
|
||||
|
||||
def test_telegram_escapes_all_decimals(self, high_risk_assessment: RiskAssessment) -> None:
|
||||
"""Telegram MarkdownV2 rejects unescaped `.` in dynamic numeric
|
||||
fields (risk score, price, USDC amount). All must be present in
|
||||
their escaped form."""
|
||||
formatter = AlertFormatter()
|
||||
result = formatter.format(high_risk_assessment)
|
||||
md = result.telegram_markdown
|
||||
for unescaped in ("0.82", "0.075", "15,000.00"):
|
||||
assert unescaped not in md, (
|
||||
f"unescaped {unescaped!r} would be rejected by Telegram MarkdownV2: {md!r}"
|
||||
)
|
||||
for escaped in ("0\\.82", "0\\.075", "15,000\\.00"):
|
||||
assert escaped in md, f"missing escaped {escaped!r} in {md!r}"
|
||||
|
||||
def test_telegram_includes_links(self, high_risk_assessment: RiskAssessment) -> None:
|
||||
"""Test that Telegram message includes links."""
|
||||
formatter = AlertFormatter()
|
||||
|
||||
Reference in New Issue
Block a user