Get member object from mentioned user - python

I have a discord bot written in python, one of the commands pulls up stats for a user that you ping with >stats #user. I want the bot to repeat the mentioned user's name without pinging them but can't figure out how.
#client.command()
async def stats(ctx,a):
b = str(a)
b = b.replace("<","")
b = b.replace(">","")
b = b.replace("!","")
user = b.replace("#","")
path = 'users/'+user+'.txt'
file = open(path,'r')
lines = file.read()
lines2 = lines.splitlines()
file.close()
await ctx.channel.send('Stats for '+a+'\nExp: '+lines2[0]+'\nMessages Sent: '+lines2[1])
Currently, the bot does say the user's name, but pings them, which results in the user being pinged twice. Once during initiation of the command and once it is carried out. I looked into other questions but couldn't find an answer that worked for me.

I ignored the code where you read from file and focused only on parts you need to change:
#client.command()
async def stats(ctx, a : discord.Member): #here you identify "a" as discord.Member object
await ctx.channel.send(f'Stats for {a.name}') #then you can get name
Check out discord.Member in docs to learn what can you do with it.

Related

How to create invite when bot joins server

I am trying to create a discord bot and I want it to create an invite to any server it joins. All I need help with is one line of code. I need to actually create the invite but I get:
Atribute Error: 'Guild' object has no attribute 'channel'
It happens on this line:
invite = await guild.channel.create_invite(reason=None, max_age=0, max_uses=0, temporary=False, unique=True)
The full block:
#client.event
async def on_guild_join(guild):
invite = await guild.channel.create_invite(reason=None, max_age=0, max_uses=0, temporary=False, unique=True)
with open("invites.json", "r") as f:
invites = json.load(f)
invites[guild.name] = invite # This line might have an issue but i havent got to test it yet
with open("invites.json", "w") as f:
json.dump(invites, f)
I know how to create an invite with a command but theres no ctx on on_guild_join (i dont think). Would i just have to add 'ctx' somewhere in the event arguments?
there is an issue with your code that is explained in the Error you are getting. You are trying to get a channel from a Guild, although they are stored by another name text_channels. You can access this list and select any one, and then create_invite on the particular channel.
Here is how your code should look like:
#client.event
async def on_guild_join(guild):
invite = await guild.text_channels[0].create_invite(reason=None, max_age=0, max_uses=0, temporary=False, unique=True)
print(invite)
with open("invites.json", "r") as f:
invites = json.load(f)
invites[guild.name] = invite
with open("invites.json", "w") as f:
json.dump(invites, f)
You need to specify channle to create an invite.
For example:
#client.event
async def on_guild_join(guild):
try:
invite = await guild.text_channels[0].create_invite(reason=None, max_age=0, max_uses=0, temporary=False, unique=True)
except IndexError:
pass
This code creates an invite to the first of text channels in guild.
Hey i know its old post but i found an answer for this problem (Its workin for me so..)
Its easy, you can use the code that #Monka posted. But you need to edit this line
invites[guild.name] = invite
to:
invites[str(guild.name)] = invite
New to stackoverflow so sorry for formatting.. Hope you understand it :D

discord.py retrieving data from json file not responding

Sorry for the unclear question title. I don't know any other way to put it.
I made a command that says p!channel [channel_id] which basically makes a channel where my bot will respond with "e". I want the command to store the channel_id and guild_id into a json file called channel.json, and when a user sends a message, it will check if the message is in the channel_id channel, and if it is in the channel, will send "e". However, it's not responding and no error codes are showing up. Can someone help? Code is below:
def get_channel(client,message):
with open("channel.json", "r") as f:
e = json.load(f)
return e[str(message.guild.id)]
#client.command()
#commands.has_permissions()
async def channel(ctx, *, channelid):
with open("channel.json", "r") as f:
e = json.load(f)
e[str(ctx.guild.id)] = channelid
with open("channel.json", "w") as f:
json.dump(e,f)
await ctx.send(f"Successfully setup <#{channelid}>")
#client.event
async def on_message(message):
if message.channel.id == get_channel:
await message.channel.send('e')
There are several immediate problems that are keeping this from functioning.
You're only referencing get_channel, not calling it. The channel's ID isn't equal to the function itself, so the message is never sent. You want get_channel(client, message).
Your on_message event ensures that your command never gets called.
You attempt to use ctx.send() instead of ctx.channel.send().
Channel IDs are integers, but command arguments are always read in as strings. Without converting the argument to an integer, comparing it against a channel's ID will always return False.
In addition, there are several things you could improve:
The get_channel function doesn't ever use client, so you could alter your function definition to simply get_channel(message).
Furthermore, channel IDs are globally unique, so you don't need to save the guild ID in order to unambiguously identify a channel.
It would be more efficient not to read the whole file every time you need to check for an ID.
The has_permissions check doesn't check anything if you supply it no arguments, so in your code it does nothing.
You probably don't want your bot to respond to its own messages.
Here's an improved version that reads a saved file on startup, if one exists. It then keeps the IDs as a set in memory, and only opens the file when it needs to add a new ID.
from discord.ext import commands
import json
client = commands.Bot(command_prefix='p!')
try:
with open('channels.json') as f:
client.ids = set(json.load(f))
print("Loaded channels file")
except FileNotFoundError:
client.ids = set()
print("No channels file found")
#client.command()
async def channel(ctx, channel_id):
try:
channel_id = int(channel_id)
except ValueError:
await ctx.channel.send("Channel must be all digits")
return
if channel_id in client.ids:
await ctx.channel.send(f"Channel <#{channel_id}> is already set up.")
return
client.ids.add(channel_id)
with open('channels.json', 'w') as f:
json.dump(list(client.ids), f)
await ctx.channel.send(f"Successfully set up <#{channel_id}>")
#client.event
async def on_message(message):
if message.channel.id in client.ids and message.author != client.user:
await message.channel.send('e')
# Pass processing on to the bot's command(s)
await client.process_commands(message)
client.run(TOKEN)

Discord.py Showing User Badges

I am trying to do a command that shows a user's badges. This is my code:
#bot.command(pass_context=True)
async def test(ctx, user: discord.Member):
test = discord.Embed(title=f"{user.name} User's Badges", description=f"{user.public_flags}", color=0xff0000 )
await ctx.channel.send(embed=test)
And the bot is responding like this
<PublicUserFlags value=64>
I want it to respond like this
Hype Squad ...
How do I do that?
You could do str(user.public_flags.all()) to obtain a string value of all the badges an user has. Although this is an improvement, your output will still be something like: [<UserFlags.hypesquad_brilliance: 128>]. But the advantage here is that the words hypesquad and brilliance are clearly indicated in the string. Now, all you have to do is to remove [<UserFlags., _ and : 128>] from the string.
Here is a way to re-define your code:
#client.command(pass_context=True)
async def test(ctx, user: discord.Member):
# Remove unnecessary characters
hypesquad_class = str(user.public_flags.all()).replace('[<UserFlags.', '').replace('>]', '').replace('_',
' ').replace(
':', '').title()
# Remove digits from string
hypesquad_class = ''.join([i for i in hypesquad_class if not i.isdigit()])
# Output
test = discord.Embed(title=f"{user.name} User's Badges", description=f"{hypesquad_class}", color=0xff0000)
await ctx.channel.send(embed=test)
user.public_flags is not the way to access the user's profile.
From the documentation, you need to use user.profile() to get attributes like premium,
staff, hypesquad.
Since discord.py 1.7 it is impossible to get info from the user's profile using await user.profile(). In the documentation it states that this functionality is deprecated. If you try it you get an error Forbidden: 403 Forbidden (error code: 20001): Bots cannot use this endpoint
Here a little correction from the code from #GGBerry
#client.command(pass_context=True)
async def test(ctx, user: discord.Member):
userFlags = user.public_flags.all()
for flag in userFlags:
print(flag.name)
user.public_flags.all() returns a list, that can be iterated. In the list are flag object from the type discord.UserFlag. This object contains all sorts of badges. Here is the documentation for the UserFlags: https://discordpy.readthedocs.io/en/stable/api.html?highlight=userflag#discord.UserFlags

Discord.py get user returns none

I want ban any member from message with this code;
elif "$ban" in message.content:
msg = message.content
msgsplit = msg.split() #banid[-1] gets last index of message array
banidstr = msgsplit[-1]
banid = int(banidstr)
member = bot.get_user(int(banid))
print(member)
It look like spaghetti but for testing. "print (member)" line returns none but "print (banid)" returns user ID. What can i do?
I think this post might help.
I also recommend you to use discord.ext.commands.Bot(), where making commands is a lot easier:
from discord.ext import commands
bot = commands.Bot(command_prefix='?')
#bot.command()
async def echo(ctx, *, message):
await ctx.send(message)
# Command will be invoked by user like '?echo this is the bot speaking'
# And the bot will then send 'this is the bot speaking'
Yes guys it worked;
async def ceza(ctx, *, message):
cezaname=bot.get_user(int(message))
print(cezaname)
This, printing username by id properly.

How to make the command can be disabled on certain servers discord py

I want to make a list with a list of id discord servers that want to disable some of the functions of my bot.
For example: the on_member_join method will not send a message when a person enters the server, and on the other where this function is enabled, it will send that the person has connected to the server. But I don't know how to properly store the id and use it. At the moment there is this:
async def serverid(ctx):
sid = ctx.message.guild.id
await ctx.send(sid)
sid = 705735563696799723 (id server dependent)
that's roughly what I want to get in the end
async def test(ctx):
f = open('/app/commands/servers.txt', 'r')
servers_sid = f.readlines()
now_sid = ctx.message.guild.id
if now_sid == servers_sid: #i know servers_sid = ['id'] or something similar this is what i have a problem with
await ctx.send('Command disabled')
else:
#command execution
i know servers_sid = ['id'] or something similar this is what i have a problem with
You should use splitlines so that you will not carry the \n. I made the check to be not in if it is not in the file then it will just end
async def test(ctx):
with open('/app/commands/servers.txt', 'r') as f:
servers_sid = f.read().splitlines()
now_sid = str(ctx.message.guild.id)
if now_sid not in servers_sid:
await ctx.send('Command disabled')
return
await ctx.send('This is working')
#command execution
I am assuming you txt file is like this.
123
456
789

Categories

Resources