Discord.py, Required argument that is missing - python-3.x

from discord.utils import get
import discord
TOKEN = '########' #Taken out
BOT_PREFIX = '!'
ROLE = 'Bot'
bot = commands.Bot(command_prefix=BOT_PREFIX)
#bot.event
async def on_ready():
print("Logged in as: " + bot.user.name + "\n")
#bot.command(pass_context=True)
#commands.has_role("Sergeant") # This must be exactly the name of the appropriate role
async def addrole(ctx, members):
member = ctx.message.author
role = get(member.server.roles, name="Test")
await bot.add_roles(member, role)
bot.run(TOKEN)
So the code above is what I use.
Traceback (most recent call last):
File "C:\Users\Joshua\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\ext\commands\bot.py", line 892, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Joshua\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\ext\commands\core.py", line 790, in invoke
await self.prepare(ctx)
File "C:\Users\Joshua\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\ext\commands\core.py", line 751, in prepare
await self._parse_arguments(ctx)
File "C:\Users\Joshua\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\ext\commands\core.py", line 670, in _parse_arguments
transformed = await self.transform(ctx, param)
File "C:\Users\Joshua\AppData\Local\Programs\Python\Python37-32\lib\site-packages\discord\ext\commands\core.py", line 516, in transform
raise MissingRequiredArgument(param)
discord.ext.commands.errors.MissingRequiredArgument: author is a required argument that is missing.
And this is the error, I belive this is todo with the rewrite but honestly I can't get to grips with it. If anyboby could shine some light on this I would really appreciate it.

Alright, so first you need to import commands from discord at the top of your file. Your bot variable calls this when grabbing the prefix:
from discord.ext import commands
Next, you no longer need pass_content=True in #bot.command(), as context is now always passed. The documentation stating that can be found here.
I noticed that you are checking if the author has a role by name. Although this does work, a better method is checking if the author has the permissions to manage roles, or if he/she is an administrator. That is typed like so:
#commands.has_permissions(administrator=True)
A full list of the different arguments that you can pass into that decorator are found here.
Now regarding your error message, you have a parameter called members in your command function. Since this is a positional parameter, you must provide it when typing your command in discord. However, its not doing anything in your code, so you can remove it:
async def addrole(ctx):
More info on command parameters can be found here.
In you variable named member, you can change ctx.message.author to ctx.author.
In the role variable, when attempting to get the roles on your server, we no longer use member.server.roles. It has been changed to guild, as shown in the docs. Here's how you would type it:
role = get(member.guild.roles, name="Test")
And the final change is adding the role to the member. The rewrite version of discord.py removed a lot of functionality from bot. The add_roles function is now called from a member object, so this would be written like so:
await member.add_roles(role)
We're taking your member variable (ctx.author, which is a member object) and adding a role (the role variable, which fetches a role object with the name Test) to that member. Docs on it are found here.
So your code should look something like this:
from discord.ext import commands
from discord.utils import get
import discord
TOKEN = '########' # Taken out
BOT_PREFIX = '!'
ROLE = 'Bot'
bot = commands.Bot(command_prefix=BOT_PREFIX)
#bot.event
async def on_ready():
print(f"Logged in as: {bot.user.name}")
#bot.command()
#commands.has_permissions(administrator=True)
async def addrole(ctx):
member = ctx.author
role = get(member.guild.roles, name="Test")
await member.add_roles(role)
bot.run(TOKEN)
I hope this helps with your problem :-)
Here's some links that can help you get a better grip on how discord.py-rewrite works:
Migrating to the rewrite branch
Discord.py Rewrite API

Related

Pycord mute command doesn't throw error but doesn't add role

I am using pycord for this so I can use slash commands.
Here is my code:
import discord, os
from dotenv import load_dotenv
from discord.ext import commands
load_dotenv(f'{os.getcwd()}/token.env')
bot = commands.Bot()
token = str(os.getenv('TOKEN'))
#bot.slash_command(description = 'mutes member of choice')
#commands.has_permissions(administrator = True)
async def mute(ctx, member: discord.Member):
guild = ctx.guild
mutedRole = discord.utils.get(guild.roles, name="Muted")
if not mutedRole:
mutedRole = await guild.create_role(name="Muted")
for channel in guild.channels:
await channel.set_permissions(mutedRole, speak=False, send_messages=False, read_message_history=True, read_messages=False)
await member.add_roles(mutedRole)
await ctx.send(f"Muted {member.mention}")
#mute.error
async def permserror(ctx, error):
if isinstance(error, commands.MissingPermissions):
ctx.respond('Sorry! You dont have permission.')
#bot.event
async def on_ready():
print(f'Client ready as {bot.user}')
bot.run(token)
This isn't my full code, but the other commands don't seem necessary for my problem.
Anyway, when I try to use this command, it doesn't throw an error in the console, but the application doesn't respond and it doesn't add the role.
I put a print statement between each line of code, and it seems to stop just before it adds the role.
How can I fix this?
Update: My previous code did not run so I have updated it.
This doesn't actually have to do with the code of the program. All you have to do is move the bot role to the top and it'll work. The error is 403 Forbidden (error code: 50013): Missing Permissions. Also, you have to reinvite the bot and add applications.commands if you haven't already.

Discord.py API get user data from IP

I've been looking into the Discord API source code and I was wondering if you could get a user's data. Not just returning their username. There is nothing that I could find in the API's docks.
This is the furthest I got:
data = await discord.client.Client.fetch_user_profile(discord.client.Client.fetch_user_profile, id)
But I keep on getting the error:
CommandInvokeError: Command raised an exception: AttributeError: 'function' object has no attribute '_connection'
Caused by a what I think may be a function and a variable having the same name. Are there any ways to fix this, or any other methods to get a users data that works. Preferably without having to change the source code. Thanks for any help in advance.
And just in case you need it, here is the entirety of my code:
#import libarys
import discord
from discord.ext import commands
import os
#setup bot
bot = commands.Bot(command_prefix='&', owner_id=MyID, case_insensitive=True)
#bot.event
async def on_ready():
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name='for &help'))
print(f'\n\nLogged in as: {bot.user} - {bot.user.id}\nVersion: {discord.__version__}\n')
#find user data command
#bot.command()
async def find(ctx, id: int):
member = await ctx.guild.fetch_member(id)
data = await discord.client.Client.fetch_user_profile(discord.client.Client.fetch_user_profile, id)
print(member, data)
#connect bot
bot.run(os.environ.get('TOKEN'), bot=True, reconnect=True)
EDIT: This code is just a mock up to get a working concept, I don't care to make it more refined yet.
This is a really bad code, I don't even know how you came up with that code. You're not supposed to refer to the class itself but to the instance, your code fixed
#bot.command()
async def find(ctx, id: int):
member = await ctx.guild.fetch_member(id)
data = await bot.fetch_user_profile(id)
print(member, data)
Also note that the fetch_user_profile method it's deprecated since version 1.7 and bot accounts cannot use this endpoint
Reference:
Client.fetch_user_profile

discord.py - Join/Leave messages error, doesn't work

Again, my code is not catching up, I have no idea why ...
The console shows no error.
Here is my code:
#bot.event
async def on_member_join(member):
channel = bot.get_channel(792786709350973454)
author = ctx.message.author
ico = author.avatar_url
embed = discord.Embed(
color = discord.Color.red(),
)
embed.set_author(name=(f'• Hello {member} on my server!!'))
embed.add_field(name='Warning,', value='read the regulations!', inline=False)
embed.set_footer(text="dBot created by Diablo#4700", icon_url=ico)
await channel.send(embed=embed)
There are more then one problems in the code snippet. I'll list them all here with fixes.
Firstly the main problem, you are declaring an author variable with ctx.author.name What is ctx here? ctx is passed in commands only. This is an event. It uses member as parameter only you can't use ctx here.
Secondly, the next problem which isn't really playing a part in stopping the command output but is a problem that you are sending member in your embed author message. Again member is an object and you can't use it directly you have to put the attribute after member that you need like, member.name, member.mention, member.avatar_url
Fixed Code:
#bot.event
async def on_member_join(member):
channel = bot.get_channel(792786709350973454)
# author = ctx.message.author # first problem, you don't really need this line
ico = member.avatar_url # since above line is useless you would change this line too
embed = discord.Embed(
color = discord.Color.red(),
)
embed.set_author(name=f'• Hello {member.name} on my server!!') # second problem was here.
embed.add_field(name='Warning,', value='read the regulations!', inline=False)
embed.set_footer(text="dBot created by Diablo#4700", icon_url=ico)
await channel.send(embed=embed)
I have labelled the errors with comments.
(IMPORTANT) Intents:
Just in case you are not aware, You need privileged gateway intents in order to track member events. Make sure to enable both intents from bot section in your application from Developers Portal of Discord and then in your code at the top (where you are initializing bot)...
import discord
from discord.ext import commands
client= commands.Bot(command_prefix="prefix", intents=discord.Intents.all())
...
# rest of the code
References:
on_member_join event
context or ctx
Intents Discord.Py

Discordpy welcome bot

So, i tried to make a bot that send embed to specific channel everytime user join my server.
The code is look like this
import discord
import asyncio
import datetime
from discord.ext import commands
intents = discord.Intents()
intents.members = True
intents.messages = True
intents.presences = True
bot = commands.Bot(command_prefix="a!", intents=intents)
#bot.event
async def on_ready():
print('Bot is ready.')
#bot.event
async def on_member_join(ctx, member):
embed = discord.Embed(colour=0x1abc9c, description=f"Welcome {member.name} to {member.guild.name}!")
embed.set_thumbnail(url=f"{member.avatar_url}")
embed.set_author(name=member.name, icon_url=member.avatar_url)
embed.timestamp = datetime.datetime.utcnow()
channel = guild.get_channel(816353040482566164)
await channel.send(embed=embed)
and i got an error
Ignoring exception in on_member_join
Traceback (most recent call last):
File "C:\Users\Piero\AppData\Roaming\Python\Python39\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "C:\Users\Piero\Documents\Discord\a-chan\achan_bot\main.py", line 24, in on_member_join
channel = guild.get_channel(816353040482566164)
NameError: name 'guild' is not defined
Anyone know what is wrong in my code?
First of all, looking at the discord.py documention, ctx is not passed to the on_member_join event reference. However, you can use the attributes of member which is passed in order to get the values which you need.
#bot.event
async def on_member_join(member):
embed = discord.Embed(
colour=0x1abc9c,
description=f"Welcome {member.name} to {member.guild.name}!"
)
embed.set_thumbnail(url=f"{member.avatar_url}")
embed.set_author(name=member.name, icon_url=member.avatar_url)
embed.timestamp = datetime.datetime.utcnow()
channel = member.guild.get_channel(816353040482566164)
await channel.send(embed=embed)
Interestingly enough, you did this perfectly for getting the guild name, but it seems you forgot to do the same when retrieving channel.
You did not define guild.
To define your guild you can do the following:
guild = bot.get_guild(GuildID)
It's the same method you used to define your channel, just for your guild now.
For further information you can have a look at the docs: https://discordpy.readthedocs.io/en/latest/api.html#discord.Client.get_guild
Also take into account that we do not have a paramter like ctx in an on_member_join event.
The event just has the parameter member in your case:
#bot.event
async def on_member_join(member): #Removed ctx

Discord.py - passing an argument role functions

I wanted to create a command, like !iknow #user . A normal verification bot I think. Here's my code, I only pasted the important parts:
import discord
from discord.ext import commands
#client.command(pass_context=True)
async def iknow(ctx, arg):
await ctx.send(arg)
unknownrole = discord.utils.get(ctx.guild.roles, name = "Unknown")
await client.remove_roles(arg, unknownrole)
knownrole = discord.utils.get(ctx.guild.roles, name = "Verified")
await client.add_roles(arg, knownrole)
(The Unknown role is automatically passed when a user joins the server.)
The problem is: I get an error on line 6 (and I think I will get on line 9, too).
File
"/home/archit/.local/lib/python3.7/site-packages/discord/ext/commands/core.py",
line 83, in wrapped
ret = await coro(*args, **kwargs) File "mainbot.py", line 6, in iknow
await client.remove_roles(arg, unknownrole) AttributeError: 'Bot' object has no attribute 'remove_roles'
I just started learning python, so please don't bully me!
You're looking for Member.remove_roles and Member.add_roles.
You can also specify that arg must be of type discord.Member, which will automatically resolve your mention into the proper Member object.
Side note, it's no longer needed to specify pass_context=True when creating commands. This is done automatically, and context is always the first variable in the command coroutine.
import discord
from discord.ext import commands
client = commands.Bot(command_prefix='!')
#client.command()
async def iknow(ctx, arg: discord.Member):
await ctx.send(arg)
unknownrole = discord.utils.get(ctx.guild.roles, name="Unknown")
await arg.remove_roles(unknownrole)
knownrole = discord.utils.get(ctx.guild.roles, name="Verified")
await arg.add_roles(knownrole)
client.run('token')

Resources