[精讚] [會員登入]
530

【Discord bot】(ERROR)await self.bot.wait_for() 大坑

今天真的是採到大坑,只找到解決方法,具體原因不明

分享此文連結 //n.sfs.tw/16018

分享連結 【Discord bot】(ERROR)await self.bot.wait_for() 大坑@小編過路君子
(文章歡迎轉載,務必尊重版權註明連結來源)
2022-12-14 04:44:27 最後編修
2022-12-14 03:05:12 By 過路君子
 

哈囉大家好,這裡是對此相當疑惑的小編過路君子

網路上好像都沒有人跟小編遇到一樣的問題,是不是因為連續使用的關係?

 

 

這個問題也是搞得小編一頭霧水,目前小編測試在 2.0.0, 2.0.1, 2.1.0 版本上皆會發生此錯誤。

不知道是跟 bot.event 衝突了還是因為連續使用 wait_for() 這個函數才造成這個問題。

先前情提要一下,小編有自行撰寫 Discord 機器人錯誤響應的程式,如下:

import traceback

@bot.event
async def on_error(event, *args, **kwargs):
    channel = bot.get_channel(000000000000000000)
    await channel.send(traceback.format_exc())

@bot.event
async def on_command_error(ctx, error):
        channel = bot.get_channel(000000000000000000)
        await channel.send('\n'.join(error.args))

所以,等等小編所貼出的錯誤訊息都是由這兩個函數回傳出來的,那我們就開始吧!

 

首先,小編先簡單撰寫一個函數。

此函數會等待使用者在聊天頻道輸入訊息並且將其訊息儲存到變數中。

class replySomething(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def fillblank(self, ctx):
        await ctx.send(content="who?")
        name = (await self.bot.wait_for("message", check=self.bot.check, timeout=300)).content

        await ctx.send(content="age?")
        age = int((await self.bot.wait_for("message", check=self.bot.check, timeout=300)).content)

        await ctx.send(content="where?")
        address = (await self.bot.wait_for("message", check=self.bot.check, timeout=300)).content

 

那此函數是沒有任何的問題的,使用者的輸入皆可以成功被儲存至對應的變數中。

接下來就是問題的所在了,假設小編不小心在撰寫的時候引發一個錯誤(不限種類),例如拿整數去和陣列比較:

if age > [name, address]:
    age += 1

 

然後在 Discord 的聊天欄上去使用此指令,想當然爾,我們會吃到一個錯誤。

而這個錯誤是由 on_command_error 所拋出的,完整訊息如下:

Command raised an exception: TypeError: '>' not supported between instances of 'int' and 'list'

 

接著,我們就保持程式的原樣,不去做任何的修改並再次的執行程式。

這次我們雖然同樣吃了一個錯誤,但是這次卻是由 on_error 所拋出的,完整訊息如下:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/discord/client.py", line 409, in _run_event
    await coro(*args, **kwargs)
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 1392, in on_message
    await self.process_commands(message)
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 1389, in process_commands
    await self.invoke(ctx) # type: ignore
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 1347, in invoke
    await ctx.command.invoke(ctx)
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/core.py", line 978, in invoke
    await self.prepare(ctx)
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/core.py", line 882, in prepare
    if not await self.can_run(ctx):
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/core.py", line 1227, in can_run
    if not await ctx.bot.can_run(ctx):
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 482, in can_run
    return await discord.utils.async_all(f(ctx) for f in data)
  File "/usr/local/lib/python3.10/site-packages/discord/utils.py", line 660, in async_all
    for elem in gen:
  File "/usr/local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 482, in <genexpr>
    return await discord.utils.async_all(f(ctx) for f in data)
TypeError: 'Message' object is not callable

出錯的函數本人在這,出錯的位置在最下面那行的 return。

小編在這將其特別擷取出來:

async def can_run(self, ctx: Context[BotT], /, *, call_once: bool = False) -> bool:
    data = self._check_once if call_once else self._checks

    if len(data) == 0:
        return True

    return await discord.utils.async_all(f(ctx) for f in data)

 

真的是非常弔詭的問題,只要 on_command_error 被呼叫之後,第二次之後都會呼叫 on_error 了。

小編花了幾個小時在網路上亂撞,絲毫沒有半點裂縫,好像沒有人遇過跟小編一樣的問題。

 

後來取消用響應的方法的時候,也就是不使用 await wait_for() 之後,就一切正常了?!

所以如果各位剛好遇到相同的問題,而且又剛好看到小編這篇文章,那這邊有兩個臨時解決方案:

  1. 不要使用 await wait_for() 這個函數
  2. 不要使 on_message_error() 被執行到,換句話說,rasie Exception() 之類的函數不可用。

 

 

 

後記

小編其實也有跑到 discord bot 的 github 頁面去查看這個問題是否是已經被回報過了。

很遺憾的,似乎沒有人遇到跟小編一模一樣的問題,看來小編真的是幸運兒,意外的發現一個致命性的錯誤。

END

你可能感興趣的文章

【JDA/discord bot】取得頻道第一筆或最新(最後一筆)的歷史訊息 在不處理訊息的先後順序下取得相關的歷史訊息

【Maven】用Maven來託管Wildfly/jBoss的部屬(deploy)、解部屬(undeploy) 極簡版,給未來想要抄作業的小編自己,完整的一切設定檔,可以依照個人需求作增刪。

【Maven】如何創建一個簡單可部屬的WAR檔 滿重要的一個大功能,在使用JAVA網頁伺服器的時候一定會需要這個WAR檔來進行部屬

【Wickct】(link) <a> 如何新增超連結 簡單來說有兩種方式,小編個人比較偏好 的方法

【Maven】如何創建一個簡單可執行的JAR檔 滿重要的一個小功能,畢竟有時候是要傳遞的是JAR檔,而不是直接透過Maven直接部屬之類的

【Wicket】[URI]使用Java取得目前網址 這是個還滿常用的功能,可惜 Wicket 沒有內建函式可以快速取得我們要的部分,只能依靠我們自己後期的字串剖析

隨機好文

高捷少女:小穹與果仁巧克力㊦ 「如果妳跟一個女生同班三年,看過她午休流口水跟狼吞虎嚥地吃午餐,就算變成高捷代言人,也很難把她當女神的啦!」她說,小穹氣得搶走她義大利麵裡的蝦子,其他人笑得花枝招展。

高捷少女:美麗島的守護者④ 光之穹頂的某處垃圾桶底,一個四方形的機器持續發出聲音,機器的儀表板上顯示著「1:25:10」的字樣,外表被一層鞭炮所掩蓋。儀表板的數字每秒不斷減少,細微的嗶嗶聲也隨著數字的改變發出,但在熙來攘往的美麗

高捷少女:美麗島的守護者(終) 「我是她的師娘,妳一定就是艾米莉亞吧?小雅昨晚有跟我說到您。」「師娘?」艾米疑惑不解。

高捷少女:耐耐的新年驚喜① 耐耐拿出手機。「我回來囉。」她說。幾分鐘後,木門緩緩打開。當它完全開啟的那一刻,小穹手中的包包掉到地上;艾米揉揉雙眼,確定自己看見的景象;婕兒的三魂七魄飛到了九霄雲外。

高捷少女:耐耐的新年驚喜(終) 他的話說到一半,便被一陣響亮的哭聲打住了,是從產房中的傳來的。聽起來就像嬰兒的哭聲。 婕兒、小穹跟艾米也被哭聲吵醒,婕兒揉揉眼睛,看向呆若木雞的耐耐父女。「剛剛的聲音,該不會是……」