sean teo
sean teo

Reputation: 77

Why don't nested commands work for discord.py?

I'm trying to make a votekick bot for discord that will mute the person from voice. However, there is a Command not found error when I run the Yes and No functions. So far, this is what I have:

@bot.command(name='votekick')
@commands.has_role('Player')
async def votekick(ctx, user: discord.Member):
    await ctx.send('A votekick against {} has started. Type .yes to vote to mute this person and .no if you don\'t want this person to be muted.'.format(user.name))

    server = ctx.message.guild
    role_id = 805035493573394452

    for member in server.members:
        if role_id in member.roles:
            member.add_roles(get(member.guild.roles, name='able'))

    arole = get(member.guild.roles, name='able')
    yes=0
    no=0
    while len(arole.members) > 0:
        @bot.command(name='yes')
        @commands.has_role('able')
        async def voteyes(ctx):
            author=ctx.message.author
            message=ctx.message
            await bot.delete_message(message)
            await ctx.send('Player {} has voted.'.format(author.display_name))
            author.remove_roles(get(author.guild.roles, name='able'))
            global yes
            yes=yes+1

        @bot.command(name='no')
        @commands.has_role('able')
        async def voteno(ctx):
            author = ctx.message.author
            message = ctx.message
            await bot.delete_message(message)
            await ctx.send('Player {} has voted.'.format(author.display_name))
            author.remove_roles(get(author.guild.roles, name='able'))
            global no
            no = no+1
    if yes > no:
        return None
    else:

        await user.edit(mute=True)

Can anyone tell me what is wrong? Thanks in advance!

Upvotes: 0

Views: 411

Answers (1)

Just for fun
Just for fun

Reputation: 4225

There are some things that are wrong here:

  1. Nested commands dont work that way
  2. You need to get the role after each vote to get the new members, as old one will have members constant, it won't update automatically
  3. You probably want to use wait_for here as it will be easier than making several commands
  4. Role ID will not be in member.roles, as it returns a list of Role objects, not role IDs
  5. Bot.delete_message() is not a thing, its Message.delete()
  6. You want to check if yes > no then mute the person, you are doing the opposite

Below is the revised code:

@bot.command(name='votekick')
@commands.has_role('Player')
async def votekick(ctx, user: discord.Member):
    await ctx.send('A votekick against {} has started. Type .yes to vote to mute this person and .no if you don\'t want this person to be muted.'.format(user.name))
    server = ctx.message.guild
    role_id = 805035493573394452
    role = get(member.guild.roles, name='able')
    for i in server.members:
        if role_id in [z.id for z in i.roles]:
            await i.add_roles(role)
    
    role = get(member.guild.roles, name='able')
    yes, no = 0, 0
    while len(role.members) > 0:
        msg = await bot.wait_for("message", check=lambda m: m.guild.id == ctx.guild.id)
        if msg.content == ".yes":
            await msg.delete()
            role = get(member.guild.roles, name='able')
            await msg.author.remove_roles(role)
            await ctx.send(f'Player {msg.author.display_name} has voted.')
            yes += 1
        elif msg.content == ".no":
            await msg.delete()
            role = get(member.guild.roles, name='able')
            await msg.author.remove_roles(role)
            await ctx.send(f'Player {msg.author.display_name} has voted.')
            no += 1
    if yes > no:
        return await user.edit(mute=True)
    return

Upvotes: 2

Related Questions