You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现多个Discord Bot间的通信?(Python+py-cord环境)

两个Discord Bot双向Websocket通信实现方案(基于py-cord + aiohttp)

一、修复aiohttp Websocket双向通信问题

你之前遇到的单向通信问题,大概率是没在两端正确实现双向消息监听逻辑。aiohttp的Websocket本身支持双向收发,只要两端都保持消息循环即可,下面是具体实现步骤:

1. 服务器端Bot(Websocket监听方)

在Bot启动流程中嵌入aiohttp的Websocket服务,注意和py-cord的异步事件循环兼容:

import discord
from discord.ext import commands
import aiohttp
from aiohttp import web

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)

# 存储活跃的Websocket连接
active_connections = set()

async def websocket_handler(request):
    ws = web.WebSocketResponse()
    await ws.prepare(request)
    active_connections.add(ws)
    print("新客户端连接")

    try:
        async for msg in ws:
            if msg.type == aiohttp.WSMsgType.TEXT:
                # 收到客户端消息后转发到Discord频道
                channel = bot.get_channel(123456789)  # 替换为你的目标频道ID
                await channel.send(f"Bot B发来消息: {msg.data}")
                # 回复客户端确认消息
                await ws.send_str(f"已收到消息: {msg.data}")
            elif msg.type == aiohttp.WSMsgType.ERROR:
                print(f"Websocket错误: {ws.exception()}")
    finally:
        active_connections.remove(ws)
        print("客户端断开连接")

    return ws

async def start_webserver():
    app = web.Application()
    app.add_routes([web.get('/ws', websocket_handler)])
    runner = web.AppRunner(app)
    await runner.setup()
    site = web.TCPSite(runner, '0.0.0.0', 8765)  # 监听所有地址,端口自定义为8765
    await site.start()
    print("Websocket服务器启动完成")

@bot.event
async def on_ready():
    print(f'服务器端Bot已登录: {bot.user}')
    # 启动Websocket服务器
    await start_webserver()

# 命令示例:从Discord发消息到客户端Bot
@bot.command()
async def send_to_botb(ctx, *, message):
    for ws in active_connections:
        await ws.send_str(f"服务器端Bot发来消息: {message}")
    await ctx.send("消息已发送到Bot B")

bot.run('你的服务器端Bot Token')

2. 客户端Bot(Websocket连接方)

客户端需在启动时建立Websocket连接,并开启后台任务持续监听消息,同时支持主动发送消息:

import discord
from discord.ext import commands
import aiohttp
import asyncio

intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='!', intents=intents)

ws_connection = None

async def websocket_listener():
    global ws_connection
    while True:
        try:
            async with aiohttp.ClientSession() as session:
                async with session.ws_connect('http://服务器IP:8765/ws') as ws:
                    ws_connection = ws
                    print("已连接到服务器端Bot的Websocket")
                    async for msg in ws:
                        if msg.type == aiohttp.WSMsgType.TEXT:
                            # 收到服务器消息后转发到Discord频道
                            channel = bot.get_channel(987654321)  # 替换为你的目标频道ID
                            await channel.send(f"服务器端Bot发来消息: {msg.data}")
                        elif msg.type == aiohttp.WSMsgType.CLOSED:
                            print("Websocket连接关闭,尝试重连")
                            break
                        elif msg.type == aiohttp.WSMsgType.ERROR:
                            print(f"Websocket错误: {ws.exception()}")
                            break
        except Exception as e:
            print(f"连接失败,10秒后重试: {e}")
            await asyncio.sleep(10)

@bot.event
async def on_ready():
    print(f'客户端Bot已登录: {bot.user}')
    # 启动Websocket监听后台任务
    bot.loop.create_task(websocket_listener())

# 命令示例:从Discord发消息到服务器端Bot
@bot.command()
async def send_to_bota(ctx, *, message):
    if ws_connection and not ws_connection.closed:
        await ws_connection.send_str(f"客户端Bot发来消息: {message}")
        await ctx.send("消息已发送到Bot A")
    else:
        await ctx.send("未连接到服务器端Bot,请稍后重试")

bot.run('你的客户端Bot Token')

关键注意事项

  • 两端必须在异步循环中持续监听消息:服务器端通过async for msg in ws循环接收,客户端通过后台任务保持监听,才能实现双向触发事件。
  • 添加重连机制:客户端捕获连接异常后自动重试,避免单次连接失败后无法恢复通信。
  • 端口权限:若Bot部署在云服务器,需确保自定义端口(如8765)已在防火墙/安全组中开放。

二、备选高效方案(若Websocket仍受网络限制)

如果遇到网络层面的限制,可考虑以下低延迟替代方案:

  • Redis Pub/Sub:利用Redis的发布订阅机制,两个Bot订阅同一个频道实现双向消息传递,稳定且延迟低,适合分布式部署场景。
  • 本地内存队列:若两个Bot运行在同一机器/进程,直接用asyncio.Queue在内存中传递消息,效率极高。

内容的提问来源于stack exchange,提问作者JL710

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 08:11:27