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

Discord机器人wait_for未按指定条件筛选消息问题排查

Discord Bot wait_for 校验失效问题排查与修复

问题描述

使用wait_for等待满足以下条件的消息时,机器人会响应任意消息并执行后续命令,无报错:

  • 消息来自特定作者(ID: 282859044593598464)
  • 提及指定用户(ID: 994347081294684240)
  • 包含计算后的总金额(商品价格×数量+税费)

核心问题分析

  1. 缩进错误导致逻辑混乱
    原代码中if type == "netflix":块未缩进在buy函数内部,导致该代码块在机器人启动时执行(而非命令调用时),且内部函数check无法被外部正确访问,引发wait_for执行时机错误。

  2. 分支逻辑错误
    elif type == "spotify" or "crunchyroll"写法不符合Python语法,"crunchyroll"会被视为布尔值True,导致所有非Netflix的请求都走Spotify逻辑分支;若type为其他值,check函数无返回值(默认返回None),wait_for会将None视为False,引发异常等待行为。

  3. 字符串包含判断逻辑错误
    int(nettax + netfprice) in message.content是无效判断:in操作符要求左右两侧同为字符串类型,整数与字符串的包含判断永远返回False,导致符合条件的消息无法通过校验。

  4. 冗余计算与数据不一致风险
    check函数内重复查询数据库计算金额,不仅冗余,还可能因数据库数据变化,导致与buy命令内计算的金额不一致,引发校验失败。

修复后的完整代码

import asyncio
import discord
import sqlite3
from discord.ext import commands
from typing import Optional

# 假设bot和tax函数已定义
bot = commands.Bot(command_prefix="!", intents=discord.Intents.all())

async def tax(args):
    # 替换为实际税费计算逻辑
    return args * 0.1

@bot.slash_command()
@commands.cooldown(1, 60, commands.BucketType.user)
async def buy(message, type: str, amount: Optional[int] = 1):
    if amount < 0:
        await message.respond("You cannot buy negative amount of accounts")
        return
    member = message.author
    con = sqlite3.connect("db.sqlite")
    c = con.cursor()

    # 提前计算总金额,避免重复查询数据库
    total_amount = None
    if type == "netflix":
        c.execute("SELECT price FROM netflix")
        netprice = c.fetchone()[0]
        newnet = netprice * amount
        withtax = await tax(args=newnet)
        total_amount = newnet + withtax
    elif type in ("spotify", "crunchyroll"):
        c.execute("SELECT price FROM spotify")
        spotprice = c.fetchone()[0]
        newspot = spotprice * amount
        spotytax = await tax(args=newspot)
        total_amount = newspot + spotytax
    else:
        await message.respond("Invalid service type")
        con.close()
        return

    # Netflix库存检查
    if type == "netflix":
        c.execute('SELECT COUNT(*) FROM netflix')
        net_stock = c.fetchone()[0]
        if net_stock < amount:
            await message.respond(f"We do not have this amount of accounts in the stock")
            con.close()
            return

    # 发送转账提示Embed
    embed = discord.Embed(title="Transfer", description=f"Please transfer: {total_amount}")
    embed.add_field(
        name=f"c <@994347081294684240> {total_amount}",
        value="**Copy paste the message for no error**"
    )
    embed.set_footer(text=f"Sidtho Host. | Requested by - {message.author}")
    print("Sent embed, Waiting for receiving the credits")
    await message.respond(embed=embed)

    # 定义校验函数,捕获外部计算好的总金额
    async def check(msg):
        try:
            return (msg.author.id == 282859044593598464 and
                    msg.mentions[0].id == 994347081294684240 and
                    str(total_amount) in msg.content)
        except IndexError:
            # 未提及目标用户时返回False
            return False

    # 等待符合条件的消息,处理超时
    try:
        await bot.wait_for('message', check=check, timeout=60)
    except asyncio.TimeoutError:
        await message.respond("Timeout: No valid payment message received.")
        con.close()
        return

    # 交付账号并更新数据库
    if type == "netflix":
        c.execute("SELECT email, password FROM netflix")
        netres = c.fetchmany(size=amount)
        embed = discord.Embed(title=f"حساب {type}", description="")
        embed.add_field(name="Sidtho Host.", value=" ", inline=False)
        for email, password in netres:
            embed.add_field(name=f"Email: {email}", value=f"Password: {password}", inline=False)
        await member.send(embed=embed)
        # 批量删除已交付账号
        for email, password in netres:
            c.execute("DELETE FROM netflix WHERE email=? AND password=?", (email, password))
        con.commit()
    elif type in ("spotify", "crunchyroll"):
        c.execute(f"SELECT email, password FROM {type}")
        res = c.fetchmany(size=amount)
        embed = discord.Embed(title=f"حساب {type}", description="")
        embed.add_field(name="Sidtho Host.", value=" ", inline=False)
        for email, password in res:
            embed.add_field(name=f"Email: {email}", value=f"Password: {password}", inline=False)
        await member.send(embed=embed)
        for email, password in res:
            c.execute(f"DELETE FROM {type} WHERE email=? AND password=?", (email, password))
        con.commit()

    con.close()

# 运行机器人
bot.run("YOUR_BOT_TOKEN")

修复说明

  1. 修正缩进:将所有业务逻辑缩进在buy函数内部,确保命令调用时才执行对应代码。
  2. 优化分支判断:使用type in ("spotify", "crunchyroll")替代错误的or写法,增加无效类型的提示。
  3. 修复包含判断:将总金额转为字符串后再判断是否存在于消息内容中,保证校验逻辑正确。
  4. 消除冗余计算:提前计算总金额,check函数直接捕获该变量,避免重复查询数据库,保证金额一致性。
  5. 完善错误处理:添加return提前终止无效请求,捕获TimeoutError处理超时情况,避免程序异常。
  6. 规范数据库操作:库存检查改为直接统计数量,交付后批量删除账号并提交事务,使用后关闭数据库连接避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:05:14