有没有办法在 Discord.py 中“隐藏”命令的参数

时间:2021-03-30 21:24:44

标签: python python-3.x discord.py

对于我的机器人,我想实现随机游戏(例如抛硬币),以及在此之上的投注系统。 例如,任何人都可以使用 //coin_toss 并且机器人会回答“正面”或“尾巴”,但是如果命令是 //bet 15 coin_toss,机器人也会回答“正面”或“尾巴”,但也会在“恭喜你赢了 X " 或 "你输了"。

    @commands.command()
    async def coin_toss(self, ctx: Context):
        outcomes = ("Heads", "Tails")
        result = outcomes[random.randint(0,1)]
        await ctx.reply(result)
        return result 

问题是我希望 //coin_toss 命令没有可以通过调用命令传递的参数,但我仍然希望通过 self.coin_toss(ctx, amount_to_bet=5) 调用它时传递参数例子。这也适用于调用 self.coin_toss

command: Command = utils.get(self.get_commands(), name=game_name)
result = await command(ctx, amount_to_bet)

现在我使用 *args 来“收集”用户试图传递的所有参数,但我不知道在通过频道中的消息调用命令时是否可以绕过。

    @commands.command(aliases=["pile_ou_face", "pof"])
    @has_user_role_from_config()
    async def coin_toss(self, ctx: Context, *args, amount_to_bet: float = 0):
        outcomes = ("Heads", "Tails")
        result = outcomes[random.randint(0,1)]
        await ctx.reply(result)
        return result 

有没有办法做到这一点?如果您想要更精确,请随时发表评论

1 个答案:

答案 0 :(得分:1)

我不确定这是否能回答您关于隐藏不和谐命令参数的问题,但我认为它可能会给您一些关于如何根据其他游戏命令实施 bet 命令而无需需要做这么多的参数解析。

我有两个建议。将 coin_toss 视为下注函数的子例程或实现 coin_toss 函数的共享逻辑实现。

抛硬币作为下注的子程序

import os
import random

from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()

DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")

bot = commands.Bot(command_prefix="//")


@bot.command()
async def coin_toss(ctx):
    outcomes = ("Heads", "Tails")
    result = outcomes[random.randint(0, 1)]
    await ctx.reply(result)
    return result


# Simulates your Utils Get Function
def get_commands():
    return [coin_toss]


def get_command_by_name(command_list, name):
    names = [c.name for c in command_list]
    if name not in names:
        return None
    else:
        return command_list[names.index(name)]


@bot.command()
async def bet(ctx, *args):
    if len(args) != 3:
        # Example //bet 15 Heads coin_toss
        await ctx.reply("Command is //bet amount outcome game_name")

    c = get_command_by_name(get_commands(), name=args[2])

    # Check Command Exists
    if c is None:
        await ctx.reply(f"Command {args[2]} does not exist")
    else:
        # Assumes result comes back as a string!!
        result = await c(ctx)
        # Compare case insensitive
        if result.lower() == args[1].lower():
            msg = f"Congratulation you won {args[0]}"
        else:
            msg = f'You lost your bet of {args[0]}'
        await ctx.reply(msg)


bot.run(DISCORD_TOKEN)

我在这里模拟了您的 get_commandsutils.get(self.get_commands(), name=value) 函数,因此请更新您的 bet 实现以反映您的函数实际执行情况。为了便于测试,我也在课堂之外完成了这项工作,但请进行必要的更改以将此代码合并到您当前的实现中。

这种方法的缺点是延迟。您发送了两个单独的回复,一次来自 coin_toss 函数,然后再次来自 bet,这可能会延迟用户体验。

具有共享逻辑实现的抛硬币

import os
import random

from discord.ext import commands
from dotenv import load_dotenv

load_dotenv()

DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")

bot = commands.Bot(command_prefix="//")


# Separated Game Logic from the Bot Command
def coin_toss_logic():
    outcomes = ("Heads", "Tails")
    result = outcomes[random.randint(0, 1)]
    return result


@bot.command()
async def coin_toss(ctx):
    await ctx.reply(coin_toss_logic())


# Simulates your Utils Get Function
def get_commands():
    return [coin_toss_logic]


def get_command_by_name(command_list, name):
    # Strip off the "_logic" portion of your command names
    # uses __name__ since not a command anymore
    # Requires a consistent naming convention!
    names = [c.__name__[:-6] for c in command_list]
    if name not in names:
        return None
    else:
        return command_list[names.index(name)]


@bot.command()
async def bet(ctx, *args):
    if len(args) != 3:
        # Example //bet 15 Heads coin_toss
        await ctx.reply("Command is //bet amount outcome game_name")

    c = get_command_by_name(get_commands(), name=args[2])

    # Check Command Exists
    if c is None:
        await ctx.reply(f"Command {args[2]} does not exist")
    else:
        # Assumes result comes back as a string!!
        # No await needed since it's not an asyc command
        result = c()
        # Need to add Result to msg since not handled by command anymore
        msg = f'{result}\n'
        # Compare case insensitive
        if result.lower() == args[1].lower():
            msg += f"Congratulation you won {args[0]}"
        else:
            msg += f'You lost your bet of {args[0]}'
        await ctx.reply(msg)


bot.run(DISCORD_TOKEN)

这种实现的好处是消息之间的延迟更少,但是,由于您基本上有两个独立的函数,它们都映射到相同的名称,因此需要做更多的工作。