基于asyncio和websockets的Discord Bot无响应问题求助
Discord Bot 无法接收消息并回复的修复方案
问题根源分析
你的代码存在几个核心问题,导致Bot无法接收消息:
- 未正确处理Discord Gateway会话流程:缺少Identify(登录)、心跳维持等必要步骤,无法建立有效网关连接。
- 事件订阅权限缺失:未指定消息相关的Intents,Discord不会推送MESSAGE_CREATE事件。
- 发送消息的方式错误:通过新建WebSocket连接发送消息不符合Discord API规范,发送消息应使用REST接口。
修复步骤
1. 开启消息内容Intent
登录Discord开发者后台,进入你的Bot应用:
- 切换到「Bot」标签页
- 在「Privileged Gateway Intents」下开启「Message Content Intent」
- 保存设置
2. 修复网关连接与事件处理
需要完整实现网关连接的生命周期:Identify登录、心跳维持、Dispatch事件分发。
3. 改用REST API发送消息
发送消息需要向Discord的REST接口发送POST请求,而非新建WebSocket连接。
完整修复代码
import asyncio import websockets import json import aiohttp # 替换为你的Bot Token和应用ID BOT_TOKEN = "YOUR_BOT_TOKEN" APP_ID = "YOUR_APP_ID" session_id = "" heartbeat_interval = 0 ws = None async def heartbeat(): global heartbeat_interval while True: await asyncio.sleep(heartbeat_interval / 1000) if ws: await ws.send(json.dumps({"op": 1, "d": None})) print("💓 发送心跳") async def send_message(channel_id, content): url = f"https://discord.com/api/v9/channels/{channel_id}/messages" headers = { "Authorization": f"Bot {BOT_TOKEN}", "Content-Type": "application/json" } payload = {"content": content} async with aiohttp.ClientSession() as session: async with session.post(url, headers=headers, json=payload) as resp: if resp.status == 200: print("✅ 消息发送成功") else: print(f"❌ 消息发送失败,状态码: {resp.status}") print(await resp.text()) async def handle_event(event_type, event_data): global session_id if event_type == "READY": print(f"👥 {event_data['user']['username']} 已就绪!(ID: {event_data['user']['id']})") session_id = event_data['session_id'] elif event_type == "MESSAGE_CREATE": # 忽略Bot自身发送的消息 if event_data["author"]["bot"]: return message_content = event_data["content"] print(f"💬 收到消息: {message_content}") if message_content == "Hi!": await send_message(event_data["channel_id"], "Hello!") async def connect_gateway(): global ws, heartbeat_interval gateway_url = "wss://gateway.discord.gg/?v=9&encoding=json" async with websockets.connect(gateway_url) as websocket: ws = websocket # 接收Hello事件,获取心跳间隔 hello = await websocket.recv() hello_data = json.loads(hello) heartbeat_interval = hello_data["d"]["heartbeat_interval"] print(f"⏱️ 心跳间隔: {heartbeat_interval}ms") # 启动心跳任务 asyncio.create_task(heartbeat()) # 发送Identify,登录Bot identify_payload = { "op": 2, "d": { "token": BOT_TOKEN, "properties": { "$os": "linux", "$browser": "my_bot", "$device": "my_bot" }, "intents": 513 # 包含GUILD_MESSAGES和DIRECT_MESSAGES,如需更多可调整 } } await websocket.send(json.dumps(identify_payload)) # 持续接收网关事件 while True: try: message = await websocket.recv() data = json.loads(message) op_code = data["op"] if op_code == 0: # Dispatch事件 event_type = data["t"] event_data = data["d"] await handle_event(event_type, event_data) elif op_code == 11: # 心跳确认 print("💓 心跳确认") except websockets.exceptions.ConnectionClosed: print("🔌 网关连接断开,尝试重连...") await connect_gateway() break if __name__ == "__main__": asyncio.run(connect_gateway())
代码说明
- 心跳任务:维持网关连接,避免被Discord断开。
- Identify请求:携带Bot Token和Intents完成登录,Intents值
513对应服务器消息和私聊消息权限,如需其他事件可调整数值。 - 消息发送:使用aiohttp发送POST请求到Discord REST接口,符合官方API规范。
- 事件过滤:忽略Bot自身发送的消息,避免触发循环回复。
内容的提问来源于stack exchange,提问作者Forevor
相关产品推荐
相关产品推荐

