(discord.py) functions in a cog

Viewed 1599

I've been trying to develop a discord bot in python, and I want to make a bunch of "hidden" commands that don't show up in help. I want to make it so that whenever someone activates a hidden command, the bot sends them a pm. I tried to make a function to do it, but so far it doesn't work. Here is the code in the cog file:

import discord
from discord.ext import commands

class Hidden(commands.Cog):
  def __init__(self, client):
    self.client = client
  
  def hidden_message(ctx):
    ctx.author.send('You have found one of several hidden commands! :shushing_face:\nCan you find them all? :thinking:')

  @commands.command()
  async def example(self, ctx):
        
    await ctx.send('yes')

    hidden_message(ctx)

def setup(client):
  client.add_cog(Hidden(client))

When the example command is run, the bot responds normally, but the function isn't called. There are no error messages in the console. I'm still pretty new to python so could someone tell me what I'm doing wrong?

2 Answers

You need to use await when calling async functions like ctx.author.send, and so the function you're wrapping that with needs to be async too

async def hidden_message(self, ctx):
    await ctx.author.send('You have found one of several hidden commands! :shushing_face:\nCan you find them all? :thinking:')

And then

@commands.command()
async def example(self, ctx):
    await ctx.send('yes')
    await self.hidden_message(ctx)

Finally, to make a command hidden from the default help command, you can do

@commands.command(hidden=True)

In order to send a message, hidden_message would have to be a courotine, i.e. it uses async def instead of just def.

However, there is a second issue that arises because of how hidden_message is called. Calling hidden_message as hidden_message(ctx) would require the function to be defined in the global scope. Since it is a method of class Hidden, it needs to be called as such.

Highlighting the edits:

class Hidden(commands.Cog):
    ...
    async def hidden_message(self, ctx):
        ...

    @commands.command()
    async def example(self, ctx):
        await ctx.send("yes")
        await self.hidden_message(ctx)

Related