My bot is on multiple servers, and I´m trying to setup a member list for each server. The code is supposed to check for a role update (All servers use the same role as a member role) and then post a list of members in a specific channel. Right now the code works up until updatemsg() is called. I get an error saying the guild can't be an integer. How would I fix this error?
def updatemsg():
role = "OfficialMember"
guild = 754778020639932516
channel = guild.get_channel(754778311573635213)
channel.send("\n".join(str(member) for member in role.members))
#bot.event
async def on_member_update(before, after):
if len(before.roles) < len(after.roles):
if newRole.name == "OfficialMember":
print("MemList Updated")
updatemsg()
else:
print("Not OfficialMember Role")
Related
I'm new to python, so can someone help me with my code, because it is not working properly. When the user that I want joins it doesn't give it a role. I want to make it work for a specific user only to give a role when joining discord server.
#client.event
async def on_member_join(member):
member = get(member.id, id=member_id)
role = get(member.guild.roles, id=role_id)
await member.id(member)
await member.add_roles(role)
I don't even know why you're making this so complicated.
Since you already have the member as an "argument" you can work with it and don't have to define member again.
We can get the ID of member very easily with member.id. If we want to compare this with a real ID, we do the following:
if member.id = TheIDHere:
# Do what you want to do
The function for the role is correct, yet I cannot find a use for await member.id(member). What is the point of this/has it any use?
How you add the role at the end is also correct, but the code must be indented properly and best you work with an if / else statement, otherwise the bot will still give an error at the end in the console if always the wrong member joins.
The whole code:
#client.event
async def on_member_join(member):
role = discord.utils.get(member.guild.roles, id=IDOfTheRole) # Get the role from member.guild and the id
if member.id == TheIDHere: # If the member.id matches
await member.add_roles(role) # Add the role for the specific user
else: # If it does not match
return # Do nothing
You may also need to enable the members Intent, here are some good posts on that:
https://discordpy.readthedocs.io/en/stable/intents.html
How do I get the discord.py intents to work?
I want to make a leave command for my bot. This is my code so far.
#commands.command()
async def leave(self, ctx):
"""Remove me from the server. ;("""
guild = discord.utils.get(client.guilds, name=ctx.guild.name) # Get the guild by name
if guild is None:
print("No guild with that name found.") # No guild found
return
await guild.leave() # Guild found
await ctx.send(f"I left: {guild.name}!")
Yes, I its in cogs and the cogs work perfectly.
The problem - it uses guild names to remove the bot. Anyone can make a guild with the same name, use this command, and get my bot removed from the original guild.
I want my bot to check if there are multiple guilds with the same name, and if there are, it returns "Multiple guilds with the same name found! Please kick the bot manually."
If this is not possible, please suggest another solution.
You can check if the bot is in multiple guilds with the same guild-name the command was executed in, with a simple count mechanism.
guildsWithName = [guild.name for guild in client.guilds].count(ctx.guild.name)
Then check, if guildsWithName > 1:
if guildsWithName > 1:
print("Multiple guilds with same name found. Please remove manually.")
return
However your code seem a little overcomplicated. What your leave() function does, is leave the guild the command was executed in, but will fail, if there are multiple guilds with the same name, as discord.utils.get() always returns
the first element in the iterable that meets all the traits passed
Quote from the docs.
You could just use ctx.guild.leave() instead.
However this is what you requested:
#commands.command()
async def leave(self, ctx):
"""Remove me from the server. ;("""
guildsWithName = [guild.name for guild in client.guilds].count(ctx.guild.name)
if guildsWithName > 1:
print("Multiple guilds with same name found. Please remove manually.")
return
guild = discord.utils.get(client.guilds, name=ctx.guild.name) # Get the guild by name
if guild is None:
print("No guild with that name found.") # No guild found
return
await guild.leave() # Guild found
await ctx.send(f"I left: {guild.name}!")
Easier, more efficient and safer will be just using:
#commands.command()
async def leave(self, ctx):
"""Remove me from the server. ;("""
await ctx.guild.leave()
Maybe give it a try, and see if it fits your demands.
You can use ctx.guild.id instead as all guilds have a unique id
I want to do something like that:
If someone writes the command !GiveRole to the Bot in PM's, the next thing should be the Server ID, after that the Role, would something like that be possible, because i know that it is not hard to give someone a role with the bot, but is it possible to do it with the PM's and Server ID?
Thanks.
Try this, but I'm not sure if it's gonna work.
#bot.command()
async def giverole(ctx, guild, role):
if isinstance(ctx.channel, discord.DMChannel) == False: # Checking if this is a DM Channel
return
guild = bot.get_guild(int(guild)) # Getting guild
if guild is None: # Checking if the guild exists
await ctx.send("Invalid guild ID!")
return
role = guild.get_role(int(role)) # Getting role
if role is None: # Checking if the role exists
await ctx.send("Invalid role ID!")
return
await guild.get_member(ctx.guild.id).add_roles(role) # Give role to member
await ctx.send(f"You received **{role.name}** role!")
I have a discord bot where you can activate your key with !activate.
At the event i want the bot to give the message.author the PREMIUM MEMBER role at my discord.
How can i make that work
I'm using #client.event and not ctx.
Thanks for your answers!
Try this
def check_activation_key(activation_key):
# do your check here, return True or False
#client.event
async def on_message(message):
if message.content.startswith('!activate ') and message.channel == message.author.dm_channel: # !activate, dms only
activation_key = message.content[10:]
if check_activation_key(activation_key):
guild = client.get_guild(ID_OF_SERVER_TO_ASSIGN_ROLE_IN) # right click and "copy id"
role = guild.get_role(ID_OF_ROLE_TO_ASSIGN) # right click and "copy id"
await guild.get_member(message.author.id).add_roles(role)
if message.content.startswith('!unactivate') and message.channel == message.author.dm_channel:
guild = client.get_guild(ID_OF_SERVER_TO_TAKE_ROLE_IN)
if ('PREMIUM MEMBER' in [role.name for role in guild.get_member(message.author.id).roles]):
await guild.get_member(message.author.id).remove_roles(guild.get_role(ID_OF_ROLE_GOES_HERE))
else:
await message.channel.send('You did not verify yet')
A drawback is that this does not support multiple servers, only 1, but you can make different activator commands with different server IDs.
Get the ID of a guild by right clicking the icon/banner and choosing "copy id". Get the ID of a role by right clicking a role (either in server settings or in someones profile) and choosing "copy id".
You'll need the guild object that the bot is in, so then it knows where to get the role from. Additionally, the message.author object will return a User, not a Member, but we'll need the Member object in order to add a role.
#client.event
async def on_message(message):
if message.content.lower().startswith("!activate") and not message.guild:
guild = client.get_guild(112233445566778899) # the guild's ID
role = discord.utils.get(guild.roles, name="PREMIUM MEMBER") # or you can use id=
member = await guild.fetch_member(message.author.id)
await member.add_roles(role)
References:
Guild.fetch_member()
Client.get_guild()
utils.get()
Guild.roles
Member.add_roles()
I simply want my bot to add a role to a user in discord. Although the syntax seems simply, apparently I'm doing something wrong.I'm new to python, so I'd appreciate some pointers in the right direction!
bot = commands.Bot(command_prefix='!')
def getdiscordid(discordname):
for guild in bot.guilds:
for member in guild.members:
if member.name == discordname:
return member.id
#bot.command(name='role')
async def role(ctx):
await ctx.message.channel.send("Testing roles")
discordid = getdiscordid("Waldstein")
print ("id: " , discordid)
member = bot.get_user(discordid)
print ("member: ", member)
role = get(ctx.message.guild.roles, name="Egg")
print("role: ", role.name)
await member.add_roles(role)
print("done")
# error handler
#bot.event
async def on_command_error(ctx, error):
if isinstance(error, commands.errors.CheckFailure):
await ctx.send(error)
bot.run(TOKEN)
In this example he successfully retrieves the member, he can't find the Egg role, and doesn't add the role. [Edit: I corrected the line to retrieve the role, that works but still no added role. Added the error handler]
The key issue is that add_roles() adds roles to a Member object not a user.
Made a couple of tweaks...
Changed the get id to get member and return the member object.
changed the name of the command to add_role() to avoid using role as the command and a variable.
changed to await member.add_roles(role)
Try:
def get_member(discordname):
for guild in bot.guilds:
for member in guild.members:
if member.name == discordname:
return member
#bot.command(name='add_role')
async def add_role(ctx):
await ctx.message.channel.send("Testing roles")
member = get_member("Waldstein")
print(f'member is {member} type {type(member)}')
role = get(ctx.guild.roles, name="Egg")
print("role: ", role.name)
await member.add_roles(role)
print("done")
For the answer's sake, I'm writing the whole discord.utils.get instead of just get. Here's your command rewritten:
import discord
#bot.command()
async def role(ctx):
await ctx.send("Testing roles!")
member = discord.utils.get(bot.get_all_members(), name="Waldstein")
# be careful when getting objects via their name, as if there are duplicates,
# then it might not return the one you expect
print(f"id: {member.id}")
print(f"member: {member}")
role = discord.utils.get(ctx.guild.roles, name="Egg") # you can do it by ID as well
print(f"role: {role.name}")
await member.add_roles(role) # adding to a member object, not a user
print("Done!")
If this doesn't work, try printing out something like so:
print(ctx.guild.roles)
and it should return each role that the bot can see. This way you can manually debug it.
One thing that might cause this issue is that if the bot doesn't have the necessary permissions, or if its role is below the role you're attempting to get i.e. Egg is in position 1 in the hierarchy, and the bot's highest role is in position 2.
References:
Guild.roles
Client.get_all_members()
Member.add_roles()
utils.get()
commands.Context - I noticed you were using some superfluous code, take a look at this to see all the attributes of ctx