CodeWritten
CodeWritten

Reputation: 13

discord.py message.author.id returns traceback

So I'm trying to make my discord.py bot only accept command execution from certain users for certain commands. I know now that ctx.author.id means bot author ID. I've heard message.author.id is supposed to work but using message.author.id throws a traceback, the infamous NameError error. Why and how do I fix it?

@bot.command(description="Restarts The Bot's source file, use if bot freezes etc, [OWNER]")
async def shutdown(ctx):
     if ctx.author.id == 436646726204653589 or 525334420467744768 or 218142353674731520:
        embed = discord.Embed(color = 0xff0000)
        embed.add_field(name="Shutdown Command Sent, Bot Rebooting in 3 seconds", value = str, inline = False)
        await ctx.send(embed=embed)
        await asyncio.sleep(3)
        await bot.close()
        os.execl(sys.executable, sys.executable, * sys.argv)
        os.system("py -3 theBot.py")

bot.run(TOKEN)

Upvotes: 1

Views: 3344

Answers (1)

Harmon758
Harmon758

Reputation: 5157

If you're using the commands extension and shutdown is a command, ctx is a Context object.
Context.author is the author of the command message and is shorthand for Message.author.
Both are User objects from which you can use User.id.

I'm not sure what exactly you mean by "bot author ID", but if you want to get the user ID of the bot's owner, you can use Bot.owner_id, or Bot.owner_ids if the bot application is team based, instead.
Otherwise, you can use Bot.user to get the ClientUser that represents the bot and then ClientUser.id to get its ID.

The "Not Defined error" should actually be a NameError telling you that the variable is not defined, and exactly as it's saying, message is undefined and you need to define it before you use it.
You can use Context.message to get the Message that triggered the command being executed.

Note, if ctx.author.id == 436646726204653589 or 525334420467744768 or 218142353674731520: will always enter the if statement as
ctx.author.id == 436646726204653589 or 525334420467744768 or 218142353674731520 will always be True. or has a lower precedence than ==. This means that this equivalently evaluates as
(ctx.author.id == 436646726204653589) or 525334420467744768 or 218142353674731520, and the integer, 525334420467744768, as well as 218142353674731520, will always evaluate as True.
Instead, you want to check for equality with each ID. This can be done by checking for membership in a tuple or set, e.g.
ctx.author.id in (436646726204653589, 525334420467744768, 218142353674731520) or ctx.author.id in {436646726204653589, 525334420467744768, 218142353674731520}, respectively.
See this How to test multiple variables against a value? question for more information.

Also, if you do not redefine str anywhere (which you should not do, as it's a built-in class), you're passing the class itself as the embed value and the output will be cast to a string and display as <class 'str'>.

Additionally, I'm not sure why you're attempting to execute the Python executable with itself with os.execl(sys.executable, sys.executable, * sys.argv), but os.execl immediately replaces the current process, so the next line will never be run.

Upvotes: 1

Related Questions