在 nextcord 中等待按钮按下或消息响应
Wait for either a button press or a message response in nextcord
我需要一个函数,我们称它为button_or_text
。如果按下按钮,此函数 return 会返回某个值,很可能是 str
。 return消息的 Message
对象已发送。
我尝试做的事情:
import nextcord
import nextcord.ext.commands as cmds
class Coggers(cmds.Cog):
def __init__(self, bot):
self.bot = bot
@cmds.command()
async def test(self, ctx: cmds.Context):
async def button_or_text():
class Buttons(nextcord.ui.View):
def __init__(self):
super().__init__()
self.value = None
@nextcord.ui.button(label="very mysterious button", style=nextcord.ButtonStyle.green)
async def very_mysterious_button(self, button: nextcord.ui.Button, interact: nextcord.Interaction):
self.stop()
# insert function that somehow cancels the wait_for()
# return "some value"
view = Buttons()
await ctx.send("press this very mysterious button or send a message?", view=view)
check = lambda msg: ctx.author.id == msg.author.id
message = await self.bot.wait_for("message", check=check)
return message.content
print(await button_or_text())
await ctx.send("end")
def setup(bot: cmds.Bot):
bot.add_cog(Coggers(bot))
这里我为函数做了一个wait_for
。如果按下按钮,则以某种方式取消 wait_for
然后 return 按下按钮的设置值。如果发送了消息,请以某种方式阻止 Buttons
对象监听然后 return Message
对象。
我正在摸索如何同时执行 wait_for
取消和 return,但我觉得这不是最好的方法,我想念更“优雅”的方式
有什么帮助吗?
如果没有关于您究竟想要实现什么的所有细节,很难给出一个全面的解决方案,但这里是如何同时等待两个事件中的第一个事件的一般思路:
async def await_input(self):
"""waits for valid user input (message, button) and returns the corresponding payload
"""
events = [
self.bot.client.wait_for('message', check=self._check_msg),
self.bot.client.wait_for('interaction', check=self._check_button)
]
# with asyncio.FIRST_COMPLETED, this triggers as soon as one of the events is fired
done, pending = await asyncio.wait(events, return_when=asyncio.FIRST_COMPLETED)
event = done.pop().result()
# cancel the other check
for future in pending:
future.cancel()
# check if the event has the `application_id` attribute to determine if it was the button press or a message
if hasattr(event, 'application_id'):
return 'button pressed' # or whatever you want to return there
else:
return event # this will be the message
您剩下要做的是实施 _check_msg
(这很可能是您已经拥有的 lambda)和 _check_button
以确保您只获得您感兴趣的输入in. 你可能还想为每个事件设置一个超时时间,除非你想无限期地等待
我需要一个函数,我们称它为button_or_text
。如果按下按钮,此函数 return 会返回某个值,很可能是 str
。 return消息的 Message
对象已发送。
我尝试做的事情:
import nextcord
import nextcord.ext.commands as cmds
class Coggers(cmds.Cog):
def __init__(self, bot):
self.bot = bot
@cmds.command()
async def test(self, ctx: cmds.Context):
async def button_or_text():
class Buttons(nextcord.ui.View):
def __init__(self):
super().__init__()
self.value = None
@nextcord.ui.button(label="very mysterious button", style=nextcord.ButtonStyle.green)
async def very_mysterious_button(self, button: nextcord.ui.Button, interact: nextcord.Interaction):
self.stop()
# insert function that somehow cancels the wait_for()
# return "some value"
view = Buttons()
await ctx.send("press this very mysterious button or send a message?", view=view)
check = lambda msg: ctx.author.id == msg.author.id
message = await self.bot.wait_for("message", check=check)
return message.content
print(await button_or_text())
await ctx.send("end")
def setup(bot: cmds.Bot):
bot.add_cog(Coggers(bot))
这里我为函数做了一个wait_for
。如果按下按钮,则以某种方式取消 wait_for
然后 return 按下按钮的设置值。如果发送了消息,请以某种方式阻止 Buttons
对象监听然后 return Message
对象。
我正在摸索如何同时执行 wait_for
取消和 return,但我觉得这不是最好的方法,我想念更“优雅”的方式
有什么帮助吗?
如果没有关于您究竟想要实现什么的所有细节,很难给出一个全面的解决方案,但这里是如何同时等待两个事件中的第一个事件的一般思路:
async def await_input(self):
"""waits for valid user input (message, button) and returns the corresponding payload
"""
events = [
self.bot.client.wait_for('message', check=self._check_msg),
self.bot.client.wait_for('interaction', check=self._check_button)
]
# with asyncio.FIRST_COMPLETED, this triggers as soon as one of the events is fired
done, pending = await asyncio.wait(events, return_when=asyncio.FIRST_COMPLETED)
event = done.pop().result()
# cancel the other check
for future in pending:
future.cancel()
# check if the event has the `application_id` attribute to determine if it was the button press or a message
if hasattr(event, 'application_id'):
return 'button pressed' # or whatever you want to return there
else:
return event # this will be the message
您剩下要做的是实施 _check_msg
(这很可能是您已经拥有的 lambda)和 _check_button
以确保您只获得您感兴趣的输入in. 你可能还想为每个事件设置一个超时时间,除非你想无限期地等待