同步命令执行异常:Discord-VK转发Bot无法兼顾命令与转发
让VK-Discord转发Bot同时支持命令与消息转发
你的代码核心问题在于longpoll.listen()是同步阻塞的循环——在异步函数disbot()里直接运行这个同步循环会独占整个事件循环,导致Discord的命令处理逻辑完全无法执行。下面是修复方案:
修改思路
- 将VK长轮询的监听逻辑放到独立线程中运行,避免阻塞Discord的异步事件循环
- 跨线程调用Discord的异步发送消息方法时,使用
asyncio.run_coroutine_threadsafe()来安全调度异步任务
修复后的完整代码
import vk_api from vk_api.longpoll import VkEventType, VkLongPoll import discord from discord.ext import commands import asyncio import threading client = commands.Bot(command_prefix='!', intents=discord.Intents.all()) @client.event async def on_ready(): print('The bot is connected to Discord!') @client.event async def on_message(message): if message.author == client.user: return await client.process_commands(message) @client.command(pass_context=True) async def hi(ctx: commands.Context): await ctx.send('Hi!') # VK相关配置(替换为你的实际信息) login = '你的VK登录账号' password = '你的VK密码' api_version = '5.131' # 替换为正确的VK API版本 chat_id = 1 # 要监听的VK聊天ID discord_channel_id = 1234567890 # 替换为目标Discord频道ID discord_token = '你的Discord Bot Token' vk_session = vk_api.VkApi(login, password, api_version=api_version) vk_session.auth() vk = vk_session.get_api() def vk_listener(): longpoll = VkLongPoll(vk_session) for event in longpoll.listen(): if event.type == VkEventType.MESSAGE_NEW and event.from_chat and event.chat_id == chat_id: user_id = event.user_id message_text = event.text attachments = event.attachments user_info = vk.users.get(user_ids=user_id) user_name = f"{user_info[0]['first_name']} {user_info[0]['last_name']}" # 构建要发送的消息内容 if '@all' in message_text: msg_content = f"{user_name} » {message_text} @everyone" else: msg_content = f"{user_name} » {message_text}" if 'attach1_type' in attachments: msg_content += " [Attachment]" # 跨线程调度Discord发送消息的异步任务 async def send_to_discord(): await client.wait_until_ready() channel = client.get_channel(discord_channel_id) if channel: await channel.send(msg_content) asyncio.run_coroutine_threadsafe(send_to_discord(), client.loop) async def main(): # 启动VK监听线程 threading.Thread(target=vk_listener, daemon=True).start() await client.start(discord_token) asyncio.run(main())
关键修改说明
- 新增
vk_listener()同步函数,将VK的长轮询逻辑移到这里,然后用线程启动这个函数,彻底避免阻塞Discord的事件循环 - 使用
asyncio.run_coroutine_threadsafe()将发送Discord消息的异步任务提交到Discord的事件循环中执行,保证跨线程调用的安全性 - 修正了原代码中的占位符提示,明确标注需要替换的配置项
内容的提问来源于stack exchange,提问作者Ghot_347
相关产品推荐
相关产品推荐

