Python Bot按顺序发送消息

时间:2018-06-15 16:17:42

标签: python python-3.x discord discord.py

在Discord中,发送消息有2000个字符的限制,因此我们需要拆分并发送多条消息。我使用下面的代码,它可以工作,但消息不按指定的顺序发送,所以我在每条消息后使用sleep()。现在它有效,但有时候消息不遵循命令。由于混合顺序,在阅读长信息时会让人感到困惑。

@bot.command(pass_context=True)
async def ping(ctx):
    msg = "Message 1".format(ctx.message)
    await bot.say(msg)
    await sleep(.5)

    msg = "Message 2".format(ctx.message)
    await bot.say(msg)
    await sleep(.5)

    msg = "Message 3".format(ctx.message)
    await bot.say(msg)
    await sleep(.5)

    msg = "Message 4 {0.author.mention}".format(ctx.message)
    await bot.say(msg)

我需要在每条消息之后检查发送的消息,然后它应该在最后一条消息之后发送第二条消息。或者还有其他解决办法吗?

2 个答案:

答案 0 :(得分:2)

这看似简单易行,但实际上相当复杂。也可能建议使用bot.wait_for_message(...),但是该逻辑存在漏洞(机器人发送消息wait_for_message已准备就绪),因为它不适合执行任务。

我现在能想到的最好的方法是制作自定义的未来事件,并在发送消息后添加wait_for。未来应该注册一个on_message事件,检查机器人的消息是否已被发送。

import asyncio

def wait(check):
    f = asyncio.Future(loop=bot.loop)

    async def _wait(future, check):
        @bot.listen()
        async def on_message(msg):
            if check(msg):
                bot.remove_listener(on_message)
                future.set_result(msg)

    asyncio.ensure_future(_wait(f, check), loop=bot.loop)
    return f

def ping_check(content):
    def check(msg):
        if msg.content == content and msg.author == bot.user:
            return True
        return False
    return check

@bot.command(pass_context=True)
async def ping(ctx):
    msg = "Message 1 {0.author.mention}".format(ctx.message)
    f = wait(ping_check(msg))
    await bot.say(msg)
    await asyncio.wait_for(f, None, loop=bot.loop)

    msg = "Message 2 {0.author.mention}".format(ctx.message)
    f = wait(ping_check(msg))
    await bot.say(msg)
    await asyncio.wait_for(f, None, loop=bot.loop)

    msg = "Message 3 {0.author.mention}".format(ctx.message)
    f = wait(ping_check(msg))
    await bot.say(msg)
    await asyncio.wait_for(f, None, loop=bot.loop)

    msg = "Message 4 {0.author.mention}".format(ctx.message)
    f = wait(ping_check(msg))
    await bot.say(msg)
    await asyncio.wait_for(f, None, loop=bot.loop)

我进一步编辑了此解决方案以包含check()这使得wait()功能更加灵活,从而删除了之前的硬编码检查。

答案 1 :(得分:1)

只需在消息之间添加一点延迟:

from asyncio import sleep

@bot.command(pass_context=True)
async def ping(ctx):
    msg = "Message 1 {0.author.mention}".format(ctx.message)
    await bot.say(msg)
    await sleep(.5)

    msg = "Message 2 {0.author.mention}".format(ctx.message)
    await bot.say(msg)
    await sleep(.5)

    msg = "Message 3 {0.author.mention}".format(ctx.message)
    await bot.say(msg)
    await sleep(.5)

    msg = "Message 4 {0.author.mention}".format(ctx.message)
    await bot.say(msg)