You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Discord.py开发的机器人无法响应命令的问题排查求助

Discord.py开发的机器人无法响应命令的问题排查求助

我现在在用discord.py开发一个Discord机器人,它能成功启动、在服务器上正常显示在线状态,命令也已经加载完成(从日志里能看到bot.commands输出了所有命令列表),但当我在Discord里输入命令时,机器人完全没有响应,就像没看到命令一样。

下面是我的核心代码文件:

主程序文件

import discord
from discord.ext import commands
from dotenv import load_dotenv
import os
from bot.commands import setup_commands
from bot.db import DB
import asyncio

load_dotenv()
TOKEN = os.getenv("DISCORD_TOKEN")

if not TOKEN:
    raise ValueError("Error: The DISCORD_TOKEN environment variable is missing. Make sure that .env contains DISCORD_TOKEN=<your_token>.")

intents = discord.Intents.all()
intents.messages = False  # Disable unnecessary permissions
intents.guilds = True
intents.message_content = True  # Enable guild-related events

# Create an instance of the bot
bot = commands.Bot(command_prefix='!', intents=intents, help_command=None)

# Create a database instance
db = DB()

@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}')
    print(f'Commands: {list(bot.commands)}')  # Output the list of commands


async def main():
    await db.init()  # Initialize the base before starting the bot
    await setup_commands(bot, db)  # Pass the same database instance to the commands
    await bot.start(TOKEN)

if __name__ == '__main__':
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("Shutting down the bot gracefully.")

数据库操作类(bot/db.py)

import aiosqlite
import asyncio
from contextlib import asynccontextmanager

class DB:
    def __init__(self):
        self.db_path = 'tasks.db'
        self.lock = asyncio.Lock()

    async def init(self):
        # Initializing the database.
        async with self.get_db() as db:
            await db.execute('''CREATE TABLE IF NOT EXISTS tasks (
                                id INTEGER PRIMARY KEY AUTOINCREMENT,
                                user_id INTEGER,
                                description TEXT,
                                status BOOLEAN DEFAULT 0)''')
            await db.execute("CREATE INDEX IF NOT EXISTS idx_user_id ON tasks(user_id);")
            await db.commit()

    @asynccontextmanager
    async def get_db(self):
        #Context manager to manage the database connection.
        conn = await aiosqlite.connect(self.db_path)
        conn.row_factory = aiosqlite.Row  # For easy key access
        try:
            yield conn
        finally:
            await conn.close()

    async def add_task(self, user_id, description):
        # Adding a new task.
        try:
            async with self.get_db() as db:
                await db.execute("INSERT INTO tasks (user_id, description) VALUES (?, ?)",
                                 (user_id, description))
                await db.commit()
        except Exception as e:
            print(f"Error when adding a task: {e}")

    async def get_tasks(self, user_id, limit=10, offset=0):
        # Get the list of tasks with pagination.
        try:
            async with self.get_db() as db:
                cursor = await db.execute("SELECT * FROM tasks WHERE user_id = ? LIMIT ? OFFSET ?",
                                          (user_id, limit, offset))
                return await cursor.fetchall()
        except Exception as e:
            print(f"Error when getting tasks: {e}")
            return []

    async def update_task_status(self, user_id, task_id, status):
        # Updating the task status.
        try:
            async with self.get_db() as db:
                cursor = await db.execute("SELECT id FROM tasks WHERE id = ? AND user_id = ?",
                                          (task_id, user_id))
                task = await cursor.fetchone()
                if not task:
                    return False  # Task not found
                await db.execute("UPDATE tasks SET status = ? WHERE id = ? AND user_id = ?",
                                 (status, task_id, user_id))
                await db.commit()
                return True  # Successfully updated
        except Exception as e:
            print(f"Error when updating task status: {e}")
            return False

    async def delete_task(self, user_id, task_id):
        # Deleting a task.
        try:
            async with self.get_db() as db:
                cursor = await db.execute("SELECT id FROM tasks WHERE id = ? AND user_id = ?",
                                          (task_id, user_id))
                task = await cursor.fetchone()
                if not task:
                    return False  # Task not found
                await db.execute("DELETE FROM tasks WHERE id = ? AND user_id = ?",
                                 (task_id, user_id))
                await db.commit()
                return True  # Successfully deleted
        except Exception as e:
            print(f"Error when deleting a task: {e}")
            return False

命令注册文件(bot/commands.py)

from discord.ext import commands
from .db import DB

async def setup_commands(bot, db):
    #Register commands and uses the passed DB instance
    
    @bot.command()
    @commands.cooldown(1, 5, commands.BucketType.user)
    async def add(ctx, *, task_desc):
        await db.add_task(ctx.author.id, task_desc)
        await ctx.send(f"Task added: {task_desc}")

    @bot.command()
    async def list(ctx):
        tasks = await db.get_tasks(ctx.author.id)
        if not tasks:
            await ctx.send("You have no tasks!")
            return
        response = '\n'.join([f"{t[0]}: {t[2]} ({'✓' if t[3] else '✗'})" for t in tasks])
        await ctx.send(response)

    @bot.command()
    async def done(ctx, task_id: str):
        if not task_id.isdigit():
            await ctx.send("Error: The task ID must be an integer.")
            return
        task_id = int(task_id)
        if await db.update_task_status(ctx.author.id, task_id, True):
            await ctx.send(f"Task {task_id} is complete!")
        else:
            await ctx.send(f"Error: Task {task_id} was not found.")

    @bot.command()
    async def delete(ctx, task_id: str):
        if not task_id.isdigit():
            await ctx.send("Error: The task ID must be an integer.")
            return
        task_id = int(task_id)
        if await db.delete_task(ctx.author.id, task_id):
            await ctx.send(f"Task {task_id} has been deleted!")
        else:
            await ctx.send(f"Error: Task {task_id} was not found.")

    @bot.command()
    async def help(ctx):
        help_text = (
            "**Available commands:**\n"
            "`!add description` - add new task.\n"
            "`!list` - show all tasks.\n"
            "`!done <number>` - mark task as done.\n"
            "`!delete <number>` - delete task.\n"
            "`!help` - show list of commands."
        )
        await ctx.send(help_text)

我已经尝试过这些排查步骤:

  • 配置了intents = discord.Intents.all(),并且单独开启了message_content = True
  • 确认命令已经加载(on_ready里打印的bot.commands能看到所有命令)
  • 检查过.env文件里的Token是正确的
  • 开启了DEBUG级别的日志,日志里没有报错信息
  • 确认机器人在服务器里拥有管理员权限

现在我想知道:为什么机器人不响应命令?该怎么修复这个问题?

备注:内容来源于stack exchange,提问作者Alex Krizhanovskyi

火山引擎 最新活动