Skip to content

Commit 985a850

Browse files
committed
fix(notify): use Discord Bot API directly instead of gateway /api/message
Gateway doesn't expose a REST /api/message endpoint. Switch to direct Discord Bot API (discord.com/api/v10/channels/{id}/messages) with bot token read from openclaw.json. Supports proxy from openclaw.json channels.discord.proxy config. Verified: notification with structured summary delivered successfully.
1 parent b753534 commit 985a850

1 file changed

Lines changed: 49 additions & 13 deletions

File tree

scripts/web/notify.py

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,32 @@ def _summary_formatter(run_id: str, state: Dict[str, Any]) -> str:
258258

259259
# ── Discord 通知 ────────────────────────────────────────────────────
260260

261+
def _get_discord_bot_token() -> str:
262+
"""从 openclaw.json 读取 Discord bot token"""
263+
try:
264+
cfg_path = Path.home() / ".openclaw" / "openclaw.json"
265+
if cfg_path.exists():
266+
import json as _json
267+
cfg = _json.loads(cfg_path.read_text())
268+
return str(cfg.get("channels", {}).get("discord", {}).get("token", ""))
269+
except Exception:
270+
pass
271+
return ""
272+
273+
274+
def _get_discord_proxy() -> str:
275+
"""从 openclaw.json 读取 Discord proxy"""
276+
try:
277+
cfg_path = Path.home() / ".openclaw" / "openclaw.json"
278+
if cfg_path.exists():
279+
import json as _json
280+
cfg = _json.loads(cfg_path.read_text())
281+
return str(cfg.get("channels", {}).get("discord", {}).get("proxy", ""))
282+
except Exception:
283+
pass
284+
return ""
285+
286+
261287
async def notify_discord(
262288
message: str,
263289
*,
@@ -266,7 +292,7 @@ async def notify_discord(
266292
node: Optional[str] = None,
267293
buttons: bool = False,
268294
):
269-
"""向 Discord 发送通知
295+
"""向 Discord 频道发送通知(直接使用 Discord Bot API)
270296
271297
Args:
272298
message: 消息内容
@@ -279,22 +305,32 @@ async def notify_discord(
279305
channel = _get_notify_channel()
280306
if not channel:
281307
return False
282-
gateway_url = _get_gateway_url()
308+
309+
bot_token = _get_discord_bot_token()
310+
if not bot_token:
311+
logger.warning("Discord notify skipped: no bot token")
312+
return False
313+
314+
proxy = _get_discord_proxy()
283315
try:
284-
async with httpx.AsyncClient(timeout=10) as client:
285-
payload = {
286-
"action": "send",
287-
"channel": "discord",
288-
"target": f"channel:{channel}",
289-
"message": message,
290-
}
316+
client_kwargs: Dict[str, Any] = {"timeout": 10}
317+
if proxy:
318+
client_kwargs["proxy"] = proxy
291319

320+
async with httpx.AsyncClient(**client_kwargs) as client:
292321
resp = await client.post(
293-
f"{gateway_url}/api/message",
294-
json=payload,
295-
headers=build_gateway_headers(),
322+
f"https://discord.com/api/v10/channels/{channel}/messages",
323+
json={"content": message},
324+
headers={
325+
"Authorization": f"Bot {bot_token}",
326+
"Content-Type": "application/json",
327+
},
296328
)
297-
return resp.status_code == 200
329+
if resp.status_code in (200, 201):
330+
return True
331+
else:
332+
logger.warning("Discord API error: %s %s", resp.status_code, resp.text[:200])
333+
return False
298334
except Exception as e:
299335
logger.warning("Discord notify failed: %s", e)
300336
return False

0 commit comments

Comments
 (0)