feat(discord): split decisions/news into second webhook channel

Adds DISCORD_WEBHOOK_DECISIONS_URL env var. If set, decision and
news_alert posts go to that channel; all other events stay on the
main webhook. Falls back to main webhook if not configured.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
sylyx 2026-05-14 08:38:50 +02:00
parent be1adfb94c
commit 4e5051b8a8
2 changed files with 10 additions and 6 deletions

View File

@ -87,6 +87,7 @@ class Settings(BaseModel):
openrouter_api_key: str = "" openrouter_api_key: str = ""
cryptopanic_api_key: str = "" cryptopanic_api_key: str = ""
discord_webhook_url: str = "" discord_webhook_url: str = ""
discord_webhook_decisions_url: str = ""
db_path: str = "data/aitrader.db" db_path: str = "data/aitrader.db"
@ -113,6 +114,7 @@ def get_settings() -> Settings:
openrouter_api_key=os.getenv("OPENROUTER_API_KEY", ""), openrouter_api_key=os.getenv("OPENROUTER_API_KEY", ""),
cryptopanic_api_key=os.getenv("CRYPTOPANIC_API_KEY", ""), cryptopanic_api_key=os.getenv("CRYPTOPANIC_API_KEY", ""),
discord_webhook_url=os.getenv("DISCORD_WEBHOOK_URL", ""), discord_webhook_url=os.getenv("DISCORD_WEBHOOK_URL", ""),
discord_webhook_decisions_url=os.getenv("DISCORD_WEBHOOK_DECISIONS_URL", ""),
db_path=os.getenv("AITRADER_DB", "data/aitrader.db"), db_path=os.getenv("AITRADER_DB", "data/aitrader.db"),
) )
return settings return settings

View File

@ -22,16 +22,16 @@ def _enabled(settings: Settings) -> bool:
return bool(settings.discord.enabled and settings.discord_webhook_url) return bool(settings.discord.enabled and settings.discord_webhook_url)
def _post(settings: Settings, embed: dict[str, Any]) -> None: def _post(settings: Settings, embed: dict[str, Any], channel: str = "trades") -> None:
if not _enabled(settings): if not _enabled(settings):
return return
if channel == "decisions" and settings.discord_webhook_decisions_url:
url = settings.discord_webhook_decisions_url
else:
url = settings.discord_webhook_url
embed.setdefault("timestamp", datetime.now(timezone.utc).isoformat()) embed.setdefault("timestamp", datetime.now(timezone.utc).isoformat())
try: try:
r = requests.post( r = requests.post(url, json={"embeds": [embed]}, timeout=8)
settings.discord_webhook_url,
json={"embeds": [embed]},
timeout=8,
)
if r.status_code >= 400: if r.status_code >= 400:
log.warning("discord.post_failed", status=r.status_code, body=r.text[:200]) log.warning("discord.post_failed", status=r.status_code, body=r.text[:200])
except requests.RequestException as e: except requests.RequestException as e:
@ -88,6 +88,7 @@ def notify_decision(settings: Settings, symbol: str, ensemble, label_a: str, lab
{"name": "Rationale", "value": ensemble.rationale, "inline": False}, {"name": "Rationale", "value": ensemble.rationale, "inline": False},
], ],
}, },
channel="decisions",
) )
@ -227,4 +228,5 @@ def notify_news_alert(settings: Settings, symbol: str, headlines: list[dict[str,
"color": color, "color": color,
"description": top, "description": top,
}, },
channel="decisions",
) )