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

Discord Bot无法识别blackjack命令的技术求助

问题:Discord Bot 无法识别Blackjack命令,报错CommandNotFound

报错信息

[ERROR   ] discord.ext.commands.bot: Ignoring exception in command None
discord.ext.commands.errors.CommandNotFound: Command "blackjack" is not found

问题详情

每次运行代码都会遇到相同问题,已花费数小时调试仍无法解决。目前没有任何命令能产生输出,除此之外Bot似乎设置正确且能正常运行无报错。

相关代码

Blackjack Cog代码

import asyncio
import os
import random
from typing import List, Tuple, Union

import discord
from discord.ext import commands
from modules.card import Card
from modules.economy import Economy
from modules.helpers import *
from PIL import Image

class Blackjack(commands.Cog):
    def __init__(self, client: commands.Bot):
        self.client = client
        self.economy = Economy()
    
    def check_bet(
        self,
        ctx: commands.Context,
        bet: int=DEFAULT_BET,
    ):
        bet = int(bet)
        if bet <= 0:
            raise commands.errors.BadArgument()
        current = self.economy.get_entry(ctx.author.id)[1]
        if bet > current:
            raise InsufficientFundsException(current, bet)

    @staticmethod
    def hand_to_images(hand: List[Card]) -> List[Image.Image]:
        return ([
            Image.open(os.path.join(ABS_PATH, 'modules/cards/', card.image))
            for card in hand
        ])

    @staticmethod
    def center(*hands: Tuple[Image.Image]) -> Image.Image:
        """Creates blackjack table with cards placed"""
        bg: Image.Image = Image.open(
            os.path.join(ABS_PATH, 'modules/', 'table.png')
        )
        bg_center_x = bg.size[0] // 2
        bg_center_y = bg.size[1] // 2

        img_w = hands[0][0].size[0]
        img_h = hands[0][0].size[1]

        start_y = bg_center_y - (((len(hands)*img_h) + \
            ((len(hands) - 1) * 15)) // 2)
        for hand in hands:
            start_x = bg_center_x - (((len(hand)*img_w) + \
                ((len(hand) - 1) * 10)) // 2)
            for card in hand:
                bg.alpha_composite(card, (start_x, start_y))
                start_x += img_w + 10
            start_y += img_h + 15
        return bg

    def output(self, name, *hands: Tuple[List[Card]]) -> None:
        self.center(*map(self.hand_to_images, hands)).save(f'{name}.png')

    @staticmethod
    def calc_hand(hand: List[List[Card]]) -> int:
        """Calculates the sum of the card values and accounts for aces"""
        non_aces = [c for c in hand if c.symbol != 'A']
        aces = [c for c in hand if c.symbol == 'A']
        sum = 0
        for card in non_aces:
            if not card.down:
                if card.symbol in 'JQK': sum += 10
                else: sum += card.value
        for card in aces:
            if not card.down:
                if sum <= 10: sum += 11
                else: sum += 1
        return sum


    @commands.command(
        aliases=['bj'],
        brief="Play a simple game of blackjack.\nBet must be greater than $0",
        usage=f"blackjack [bet- default=${DEFAULT_BET}]"
    )
    async def blackjack(self, ctx: commands.Context, bet: int=DEFAULT_BET):
        self.check_bet(ctx, bet)
        deck = [Card(suit, num) for num in range(2,15) for suit in Card.suits]
        random.shuffle(deck) # Generate deck and shuffle it

        player_hand: List[Card] = []
        dealer_hand: List[Card] = []

        player_hand.append(deck.pop())
        dealer_hand.append(deck.pop())
        player_hand.append(deck.pop())
        dealer_hand.append(deck.pop().flip())

        player_score = self.calc_hand(player_hand)
        dealer_score = self.calc_hand(dealer_hand)

        async def out_table(**kwargs) -> discord.Message:
            """Sends a picture of the current table"""
            self.output(ctx.author.id, dealer_hand, player_hand)
            embed = make_embed(**kwargs)
            file = discord.File(
                f"{ctx.author.id}.png", filename=f"{ctx.author.id}.png"
            )
            embed.set_image(url=f"attachment://{ctx.author.id}.png")
            msg: discord.Message = await ctx.send(file=file, embed=embed)
            return msg
        
        def check(
            reaction: discord.Reaction,
            user: Union[discord.Member, discord.User]
        ) -> bool:
            return all((
                str(reaction.emoji) in ("🇸", "🇭"),  # correct emoji
                user == ctx.author,                  # correct user
                user != self.client.user,           # isn't the bot
                reaction.message == msg            # correct message
            ))

        standing = False

        while True:
            player_score = self.calc_hand(player_hand)
            dealer_score = self.calc_hand(dealer_hand)
            if player_score == 21:  # win condition
                bet = int(bet*1.5)
                self.economy.add_money(ctx.author.id, bet)
                result = ("Blackjack!", 'won')
                break
            elif player_score > 21:  # losing condition
                self.economy.add_money(ctx.author.id, bet*-1)
                result = ("Player busts", 'lost')
                break
            msg = await out_table(
                title="Your Turn",
                description=f"Your hand: {player_score}\n" \
                    f"Dealer's hand: {dealer_score}"
            )
            await msg.add_reaction("🇭")
            await msg.add_reaction("🇸")
            
            try:  # reaction command
                reaction, _ = await self.client.wait_for(
                    'reaction_add', timeout=60, check=check
                )
            except asyncio.TimeoutError:
                await msg.delete()

            if str(reaction.emoji) == "🇭":
                player_hand.append(deck.pop())
                await msg.delete()
                continue
            elif str(reaction.emoji) == "🇸":
                standing = True
                break

        if standing:
            dealer_hand[1].flip()
            player_score = self.calc_hand(player_hand)
            dealer_score = self.calc_hand(dealer_hand)

            while dealer_score < 17:  # dealer draws until 17 or greater
                dealer_hand.append(deck.pop())
                dealer_score = self.calc_hand(dealer_hand)

            if dealer_score == 21:  # winning/losing conditions
                self.economy.add_money(ctx.author.id, bet*-1)
                result = ('Dealer blackjack', 'lost')
            elif dealer_score > 21:
                self.economy.add_money(ctx.author.id, bet)
                result = ("Dealer busts", 'won')
            elif dealer_score == player_score:
                result = ("Tie!", 'kept')
            elif dealer_score > player_score:
                self.economy.add_money(ctx.author.id, bet*-1)
                result = ("You lose!", 'lost')
            elif dealer_score < player_score:
                self.economy.add_money(ctx.author.id, bet)
                result = ("You win!", 'won')

        color = (
            discord.Color.red() if result[1] == 'lost'
            else discord.Color.green() if result[1] == 'won'
            else discord.Color.blue()
        )
        try:
            await msg.delete()
        except:
            pass
        msg = await out_table(
            title=result[0],
            color=color,
            description=(
                f"**You {result[1]} ${bet}**\nYour hand: {player_score}\n" +
                f"Dealer's hand: {dealer_score}"
            )
        )
        os.remove(f'./{ctx.author.id}.png')

async def setup(client: commands.Bot):
    await client.add_cog(Blackjack(client))

主运行代码(修复前)

import discord
from discord.ext import commands
from modules.helpers import *
import asyncio

client = commands.Bot(
    command_prefix=PREFIX,
    owner_ids=OWNER_IDS,
    intents=discord.Intents.all()
)

client.remove_command('help')

import logging

handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
client.run(TOKEN, log_handler=handler)


async def load_extensions():
    for filename in os.listdir(COG_FOLDER):
        if filename.endswith('.py'):
            await client.load_extension(f'cogs.{filename[:-3]}')


async def main():
    async with client:
        await load_extensions()
        await client.start(TOKEN)

asyncio.run(main())

解决方案

问题出在主运行代码的两个关键错误:

  1. client.run()阻塞程序:client.run()是阻塞函数,执行后会占据主线程,后续的load_extensions()和main()完全不会运行,导致Cog根本没被加载。
  2. 缺失os模块导入:os.listdir(COG_FOLDER)需要依赖os模块,原代码未导入会触发报错。

修复后的主运行代码:

import discord
import os
from discord.ext import commands
from modules.helpers import *
import asyncio

client = commands.Bot(
    command_prefix=PREFIX,
    owner_ids=OWNER_IDS,
    intents=discord.Intents.all()
)

client.remove_command('help')

import logging

handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')


async def load_extensions():
    for filename in os.listdir(COG_FOLDER):
        if filename.endswith('.py'):
            await client.load_extension(f'cogs.{filename[:-3]}')


async def main():
    async with client:
        await load_extensions()
        await client.start(TOKEN, log_handler=handler)

asyncio.run(main())

修复说明:

  • 删除原代码中的client.run()调用,改用client.start()配合异步上下文管理器加载Cog。
  • 添加import os确保文件遍历功能正常。
  • 将日志处理器参数移到client.start()中,保证日志配置生效。

修复后程序会正常加载所有Cog,Blackjack命令即可被Bot识别。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 17:30:54