AttributeError: 'NoneType' object has no attribute 'roles' Discord Self-Bot - discord

Am using discord.py library to create a Discord self-bot that reads through a .txt file I already have filled with Discord IDs and checks their role in a guild server, if the role matches the role am looking for then their ID is saved in a new notepad called 'roletrue.txt'. I have been stuck for quite some time now, any help is appreciated! I know it is against Terms of Services however I still do it.
Code:
import discord
client = discord.Client()
#client.event
async def on_ready():
# Read the file containing the Discord IDs
with open("ids.txt", "r") as f:
ids = f.read().split("\n")
# Get the guild and the role
guild = client.get_guild('GUILD_ID')
role = discord.utils.get(guild.roles, name="ROLE_NAME")
# Iterate through the IDs
for id in ids:
# Get the member from the guild
member = await guild.fetch_member(int(id))
if role in member.roles:
with open("roletrue.txt", "a") as f:
f.write(f"{id}\n")
print(f"Discord ID {id} has the role {role.name}.")
else:
print(f"Discord ID {id} does not have the role {role.name}.")
client.run("TOKEN", bot = False)
Error:
File "C:\Users\spath\AppData\Local\Programs\Python\Python311\Lib\site-packages\discord\client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "c:\Users\spath\OneDrive\Υπολογιστής\NFT Vict Scrape\checkroles.py", line 13, in on_ready
role = discord.utils.get(guild.roles, name="Customer")
^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'roles'
I tried rewriting the code from scratch and check discord library and searched online and couldn't find a answer for my problem.

Change
guild = client.get_guild("GUILD_ID")
to
guild = await client.fetch_guild("GUILD_ID")
Get only returns the guild object if it's cached - if it's returning None then it's not so use fetch instead.

You will have to use await in order to fetch guild id and the roles from it,
try using this:
guild = await client.fetch_guild("GUILD_ID")
or if it doesn't work, try using discord utils.

Related

TypeError: Guild._add_role() takes 2 positional arguments but 3 were given

I'm trying to add a role to myself using user id and role id, but am constantly getting an error.
client = discord.Client(intents=discord.Intents.default())
#client.event
async def on_ready():
guild = await client.fetch_guild(1053022209087656026)
await guild._add_role(487228854084304898, 1053027595056336997)
File "/home/osass/.local/lib/python3.10/site-packages/discord/client.py", line 409, in _run_event
await coro(*args, **kwargs)
File "/home/osass/Documents/Python/Ppl in irl bot.py", line 9, in on_ready
await guild._add_role(487228854084304898, 1053027595056336997)
TypeError: Guild._add_role() takes 2 positional arguments but 3 were given
I've only written the user id and role id, why is the error saying I've taken three positional arguments.
You must use this method to add a role to a member.
For exemple:
member = guild.get_member(user_id)
role = discord.utils.get(guild.roles, id=role_id)
await member.add_roles(role)

discord.py how to make the bot ban someone if they have a certain word in their name

I was wondering how I could ban someone if they had someone in their name. For example, I have people who join with the n word in their name and I wanted to know how I could ban them for having that in their name.
You can use the discord.Member object given by on_member_join to get the user's name, and filter names that way.
import discord
intents = discord.Intents.default()
intents.members = True #So you can use on_member_join event
client = discord.Client(intents=intents)
banlist = []
#client.event
async def on_member_join(member):
if any(banned in member.name for banned in banlist):
await member.ban()
return

guild.get_member_named(name) is returning 'NoneType' inspite of existence of such member

I have enabled intents all through my code and developer portal;got necessary permissions for the bot to 'see' the other members but still the method returns NoneType for almost all users(only exception is Dyno)
Now I need a complete check through my program and the permissions and settings
if it doesn't get sorted after the check then the question topic gets adjusted accordingly
import discord
import os
from discord.ext import commands
intents = discord.Intents.default()
intents.members = True
bot = commands.Bot(command_prefix='!',intents=intents)
#bot.event
async def on_ready():
print('We have logged in as {0.user}'.format(bot))
#bot.command()
async def ping(ctx,args1):
guild = bot.get_guild(ServerID)
member = guild.get_member_named(args1) #getting NoneType here
await ctx.send('member.mention') #Assuming the existence of member coz I know there is such one
bot.run(os.getenv('TOKEN'))
Try using
discord.utils.get(guild.members, name='theusernamehere') #replace"theusernamehere" with the person username
To get by id use this
discord.utils.get(guild.members, id='idhere') #replace "idhere" with the person id
or you can just use arg1: discord.Member

#commands.has_permissions(administrator=True) not working properly?

I am trying to make a simple moderator bot.
the code looks something like this.
import discord
from discord.ext import commands
from random import choice
import os
client = commands.Bot(command_prefix=commands.when_mentioned_or("%"), description='A simple Moderator bot')
def colour():
l = [ 1752220, 3066993, 3447003, 10181046, 15844367, 15105570, 15158332, 3426654, 16580705 ]
return choice(l)
#client.event
async def on_ready():
change_status.start()
print("The Bot is online!")
#client.command()
#commands.has_permissions(administrator=True)
async def kick(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.kick(reason = reason)
await ctx.send("Kicked the user.")
#client.command()
#commands.has_permissions(administrator=True)
async def ban(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.ban(reason = reason)
await ctx.send("Banned the user")
#client.command()
#commands.has_permissions(administrator=True)
async def warn(ctx, user : discord.Member = None, *,reason = "No reason provided"):
await user.send(f"You have been **Warned** by **{ctx.author.name}** in the **{ctx.guild.name}** for the reason: **{reason}** ")
await ctx.send("Warned the user")
client.run(os.environ['token'])
In this only warn command is working successfully rest all the commands throws an error which looks like this.
Ignoring exception in command kick:
Traceback (most recent call last):
File "main.py", line 140, in kick
await user.kick(reason = reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/member.py", line 524, in kick
await self.guild.kick(self, reason=reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/guild.py", line 1886, in kick
await self._state.http.kick(user.id, self.id, reason=reason)
File "/app/.heroku/python/lib/python3.6/site-packages/discord/http.py", line 241, in request
raise Forbidden(r, data)
discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions
It is throwing a missing permission but I am the owner of the server and even added the bot as an admistrator.
Even tried by making an administrator role and giving all the permissions to it but still no luck.
This error is coming again and again.
Even if anyone know how to check between multiple roles like if anyone has administrator or kick member permission then do this, please let me know how to do that.
Thanks in advance for the help.
If any more information needed, do let me know.
The error you are getting on the last line from your console; discord.errors.Forbidden: 403 Forbidden (error code: 50013): Missing Permissions Is because the bot is missing permissions to perform these actions against the given permissions the bot currently has.
This could occur from the following;
Sufficient Bot permissions haven't been enabled from the invite link
The member has a higher or equal role than the bot
The #everyone role has no permissions
Moreover, these issues aren't at fault with the code you have written and is something that can be fixed in your server with the role hierarchy or bot invite link permissions.
I would also recommend comparing roles to make sure users can't attempt moderation on a higher level member in the first place, this could also help to mitigate the problem
With this, you can use >= and the top_role attribute which would compare the roles that the user compared to the member you are attempting to take moderation on, if your permissions are lower than the member you are attempting to moderate, it will prevent the rest of the code running. Here is a simple way of doing this,
if member.top_role >= ctx.author.top_role:
await ctx.send(f"You can only moderate members below your role")
return

Discord.py Give role if member customstatus contains hi

Im working on a Loop that checks every 5 seconds if user Status contain "hi" if so it should give the user a role.
I dont really know how to do it, But maybe someone can help.
My code:
#Here is a little base for the Command i asked...
#I hope it can help you
#tasks.loop(seconds=15)
async def status_role():
if "hi" in ???.lower()
#here comes the code
#(Idk what the code is so i asked you guys :D)
member = ctx.message.author
role = get(member.server.roles, name="Friendly dude")
await bot.add_roles(member, role)
Looking at your new error, you're getting an IndexError because one of your members doesn't have an activity set, so activities[0] doesn't exist. Use an if-statement to check this. To see if a tuple is empty, you can just do if tuple (as empty lists/tuples are falsy), so the code below should solve that:
#tasks.loop(seconds=15)
async def status_role():
guild = client.get_guild(your guilds id)
role = get(guild.roles, name='Friendly dude')
for member in guild.members:
if member.activities and 'hi' in member.activities[0].name.lower():
await member.add_roles(role)
In addition to the fragment in the answer above.
EDIT: Apparently you didn't get my above ^ sentence saying it was meant to be combined with the other answer, so I've edited my answer & combined it myself. This should be the correct answer to your question.
Still same error
Unhandled exception in internal background task 'status_role'.
Traceback (most recent call last):
File "C:\Users\lequi\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\tasks\__init__.py", line 101, in _loop
await self.coro(*args, **kwargs)
File "C:\Users\lequi\Desktop\Programs\Clipox\ClipoxMain\main.py", line 136, in status_role
[await member.add_roles(role) for member in guild.members if 'hi' in member.activities[0].name.lower()]
File "C:\Users\lequi\Desktop\Programs\Clipox\ClipoxMain\main.py", line 136, in <listcomp>
[await member.add_roles(role) for member in guild.members if 'hi' in member.activities[0].name.lower()]
IndexError: tuple index out of range
You can use member.activities. This will return you a list of member's activities. As far as I know, you can get custom status with member.avtivities[0].name. This'll return you a string of member's custom activity.
Also, you can't use ctx.message.author. You need to iterate through members in the guild to check every one of their's activity.
So you can simply do:
#tasks.loop(seconds=15)
async def status_role():
guild = client.get_guild(your guilds id)
role = get(guild.roles, name='Friendly dude')
[await member.add_roles(role) for member in guild.members if 'hi' in member.activities[0].name.lower()]
EDIT
There're some updates about Intents in the discord.py 1.5.x. You need to define it before defining client = discord.Bot(prefix='') to get guilds, channels etc.
import discord
intents = discord.Intents().all()
client = discord.Bot(prefix='', intents=intents)
EDIT 2
If member has no status, it'll return an empty tuple, that's why you get IndexError. To prevent this, you can add a simple if block to your code.
async def status_role():
guild = client.get_guild(your guilds id)
role = get(guild.roles, name='Friendly dude')
[await member.add_roles(role) for member in guild.members if member.activities[0] and 'hi' in member.activities[0].name.lower()]

Resources