discord.py机器人新增等级系统后可启动但不响应命令如何修复
问题原因与修复方案
你的代码存在多个语法、逻辑与discord.py框架使用错误,是导致机器人无响应的核心原因,具体问题和修复方法如下:
核心问题
- 自定义
on_message事件后未调用await bot.process_commands(message),discord.py默认在自定义on_message事件后不会自动处理命令,必须手动添加该语句才能让注册的命令生效。 - 事件/命令写法错误:你使用了Cog类专属的
@commands.Cog.listener()装饰器和self参数,但这些代码并没有写在Cog类中,导致on_message事件根本没有被注册到机器人实例,带self参数的命令也无法正常调用。 - 缩进错误:等级计算逻辑、等级卡片生成逻辑的缩进完全错误,部分代码永远不会执行,甚至会触发死循环。
- 重复实例化客户端:同时创建了
discord.Client()和commands.Bot()两个客户端实例,资源冲突且完全冗余,commands.Bot本身就是Client的子类,无需额外定义client。 - 同步请求阻塞事件循环:
on_ready中使用同步的urllib.request发送保活请求,会阻塞整个异步事件循环,导致机器人无法响应后续事件。 - 拼写错误:Embed的
title参数被拼写为tittle,会触发参数错误。
修正后的代码
import os import discord from discord.ext import commands from dotenv import load_dotenv import aiohttp import asyncio import pymongo from pymongo import MongoClient # 删掉冗余的discord.Client实例 talk_channels = [] cluster = MongoClient('mongodb+srv://endercraft46:<你的数据库密码>@enderbot.93khp.mongodb.net/myFirstDatabase?retryWrites=true&w=majority') levelling = cluster["discord"]["levelling"] bot = Bot(command_prefix="!", intents=discord.Intents.all()) @bot.event async def on_ready(): print('Ready') # 换成异步保活请求避免阻塞 async with aiohttp.ClientSession() as session: while True: async with session.get("https://Enderbotpy.endercraft26.repl.co") as resp: pass await asyncio.sleep(500) ############################LEVELSYS################################################### # 改成bot.event装饰器,删掉self参数 @bot.event async def on_message(message): # 首先处理命令,不要漏掉 await bot.process_commands(message) if message.author.bot: return stats = levelling.find_one({"id" : message.author.id}) if stats is None: newuser = {"id" : message.author.id, "xp" : 100} levelling.insert_one(newuser) else: xp = stats["xp"] + 5 levelling.update_one({"id":message.author.id}, {"$set":{"xp":xp}}) lvl = 0 while True: if xp < ((50*(lvl**2))+(50*lvl)): break # 修复缩进,lvl递增放在break前面 lvl += 1 xp_needed = ((50*((lvl-1)**2))+(50*(lvl-1))) current_lvl_xp = xp - xp_needed if current_lvl_xp == 0: await message.channel.send(f'felicidades {message.author.mention}, subiste de nivel a **nivel: {lvl}**!') # 删掉self参数 @bot.command() async def rank(ctx): stats = levelling.find_one({"id" : ctx.author.id}) if stats is None: embed = discord.Embed(description='no has enviado ningun mensaje, por lo tanto, no tienes rango') await ctx.send(embed=embed) return xp = stats["xp"] lvl = 0 rank = 0 while True: if xp < ((50*(lvl**2))+(50*lvl)): break lvl += 1 xp_needed = ((50*((lvl-1)**2))+(50*(lvl-1))) current_lvl_xp = xp - xp_needed max_lvl_xp = 50*(lvl**2)+50*lvl - xp_needed boxes = int((current_lvl_xp / max_lvl_xp)*20) rankings = levelling.find().sort("xp",-1) for x in rankings: rank += 1 if stats["id"] == x["id"]: break # 修复缩进,embed定义放在循环外面 embed = discord.Embed(title="{}'s level stats".format(ctx.author.name)) embed.add_field(name="Name", value=ctx.author.mention, inline=True) embed.add_field(name="XP", value=f"{current_lvl_xp}/{max_lvl_xp}") embed.add_field(name="Rank", value=f"{rank}/{ctx.guild.member_count}") embed.add_field(name="Progress Bar [lvl]", value=boxes * ":blue_square:" + (20-boxes) * ":white_large_square:", inline=False) await ctx.send(embed=embed) # 最后添加bot.run()启动机器人,替换为你自己的Token bot.run(os.getenv("DISCORD_BOT_TOKEN"))
内容的提问来源于stack exchange,提问作者endercraft46
相关产品推荐
相关产品推荐

