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
Related
I have two applications one main.py which is my main file and the other one is Loops.py in which I use Cogs and tasks inside them so there is a problem.I have a function to change the nickname of my bot every second to another name like this :
botsnick = cycle(['π','ππ','πππ','ππππ','πππππ','ππππππ¨','ππππππ¨π','ππππππ¨π π','ππππππ¨π ππ','ππππππ¨π πππ¬','ππππππ¨π πππ¬π'])
#tasks.loop(seconds=1)
async def change_nick():
server = client.get_guild(771043820157534228)
bots = server.get_member(848887911884521502)
await bots.edit(nick=next(botsnick))
It is working properly in main.py but as soon as I implement this code into Loops.py and inside Cog like this :
class Loops(commands.Cog):
def __init__(self,client):
self.client = client
self.change_nick.start()
botsnick = cycle(['π','ππ','πππ','ππππ','πππππ','ππππππ¨','ππππππ¨π','ππππππ¨π π','ππππππ¨π ππ','ππππππ¨π πππ¬','ππππππ¨π πππ¬π'])
#tasks.loop(seconds=1)
async def change_nick(self):
server = self.client.get_guild(771043820157534228)
bots = server.get_member(848887911884521502)
await bots.edit(nick=next(self.botsnick))
def setup(client):
client.add_cog(Loops(client))
I get this error :
bots = server.get_member(848887911884521502)
AttributeError: 'NoneType' object has no attribute 'get_member'
but there is no error in main.py if I use this fucntion there what is wrong?
get_member gets the Member from cache, since the loop starts immediately, your bot's internal cache isn't ready, as a result it doesn't find anything and returns None
Simple fix is to use await self.client.wait_until_ready() in a #yourtaskname.before_loop
client.wait_until_ready()
I want my discord.py bot to send a meme from hot posts of r/memes via PRAW. After this issue, I tried searching in the web and in the documentations, but I didn't find any method to view the image. Here is my code:
import praw
import discord
from discord.ext import commands
from discord import client
reddit = praw.Reddit(client_id="d",
client_secret="d",
user_agent="automoderatoredj by /u/taskuratik")
#boot
print("il bot si sta avviando... ")
token = "token"
client = commands.Bot(command_prefix=("/"))
#bot online
#client.event
async def on_ready():
print("il bot e' ora online")
#client.command()
async def meme(submission):
if reddit:
channel = client.get_channel(722491234991472742)
submission = reddit.subreddit("memes").hot(limit=1)
await channel.send(submission.url)
client.run(token)
Your code says:
submission = reddit.subreddit("memes").hot(limit=1)
await channel.send(submission.url)
Here, you assign a listing of one post to submission. As listing is an iterable (somewhat like a list) that contains one submission, rather than the submission itself. Unlike a list, you can't use an index to access a specific item, but there are other ways to get it. One way to get the submission is
for submission in reddit.subreddit("memes").hot(limit=1):
await channel.send(submission.url)
This allows you to change the limit and send more posts if you want.
Or, you could use next() to get the next (and only) item from the post listing:
submission = next(reddit.subreddit("memes").hot(limit=1))
await channel.send(submission.url)
This will always send just one submission, even if you change the limit parameter.
PRAW is blocking, aiohttp is not and frankly discord.py comes with aiohttp. Reddit offers an endpoint to return json data that you can prase with the json.loads() method to get raw json.
This is something I wrote to fetch images from subreddits
from aiohttp import ClientSession
from random import choice as c
from json import loads
async def get(session: object, url: object) -> object:
async with session.get(url) as response:
return await response.text()
async def reddit(sub: str):
type = ['new', 'top', 'hot', 'rising']
url = f"https://www.reddit.com/r/{sub}/{c(type)}.json?sort={c(type)}&limit=10"
async with ClientSession() as session:
data = await get(session, url)
data = loads(data)
data = data['data']['children']
url = [d['data']['url'] for d in data]
return c(url)
All you need to do is await reddit(sub= 'memes') to get the required url.
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
so I have an bot, written and based on Discord.py,
and I am encountering an very strange issue, I have my bot hosted on CentOs 6, 64 bit, and installed with python 3.6.3.
I am starting the bot through cd'ing it to the main folder and use python3.6 main.py.
See this code snippet:
#bot.command(aliases=["pokemon", "Pokemon", "POKEMON", "PoGo", "POGO", "PokeMonGo", "PokΓΒ©mon GO"], pass_context=True)
async def pokemongo(ctx):
gotrole = discord.utils.get(ctx.message.server.roles, name="1")
pogorole = discord.utils.get(ctx.message.server.roles, name="PokΓΒ©mon GO")
if gotrole in ctx.message.author.roles:
await bot.say("You already have a role! Contact support if you want to change!")
return
else:
await bot.add_roles(ctx.message.author, pogorole)
time.sleep(2)
await bot.add_roles(ctx.message.author, gotrole)
await bot.say("Got you the role, PokΓΒ©mon GO!")
That should totally work, what happens is that the user gets the role Pokemon GO and then the role 1, and then weirdly, the role Pokemon GO gets deleted, sometimes it does happens, sometimes it doesn't, and it's nothing to do with roles, permissions, the code between or below. This snippet is used for various other roles too, using the same template just differing in the commands name (async def) and the roles variable (pogorole in this case)
The weird part its completely random, and actually done by the bot, and not someone else, see the imported libraries below
import discord
from discord.ext import commands
from discord.utils import get
import os
import random
import sys
import asyncio
import aiohttp
import time
import psutil
And an other example of another snippet of code, using the same template:
#bot.command(pass_context=True)
async def fortnite(ctx):
gotrole = discord.utils.get(ctx.message.server.roles, name="1")
fortniterole = discord.utils.get(ctx.message.server.roles, name="Fortnite")
if gotrole in ctx.message.author.roles:
await bot.say("You already have a role! Contact support if you want to change!")
return
else:
await bot.add_roles(ctx.message.author, fortniterole)
time.sleep(2)
await bot.add_roles(ctx.message.author, gotrole)
await bot.say("Got you the role, fortnite!")
It does not error out and the role 1 does not change or gets removed from the user, its just the game role that randomly does, it doesn't have anything to do with internet or something similiar
I really hope there is an explanation to this, and would really love to hear some!
Cheers, Deadly
Try to add all roles at once.
await bot.add_roles(ctx.message.author, fortniterole, gotrole)
Or try to use asyncio.sleep instead of time.sleep. time.sleep is blocking bot entirely, since it is not async
await bot.add_roles(ctx.message.author, fortniterole)
await asyncio.sleep(2)
await bot.add_roles(ctx.message.author, gotrole)
I am using Discord.py version 1.0.0. I am trying to write an echo command that, when given a message, will echo the message and delete the command from the chat. Here is an example of my code.
client = Bot(description="Test bot", command_prefix="&", pm_help = False)
#bot.command(pass_context=True)
async def echo(ctx):
await client.send(ctx.message)
await client.delete_message(ctx.message)
The errors I receive tell me that ctx does not have an attribute called "delete_message". I have tried with just delete(). I have looked at others having something of a similar issue, however the solutions did not help me.
Any suggestions would be greatly appreciated.
In discord.py/rewrite (1.0.0), Delete is a method on the message, not on the client. This is the same for every function affecting a message/channel/guild etc.
Instead of doing
await client.delete_message(ctx.message)
try doing
await ctx.message.delete()
If you're on 1.0, you can lose pass_context and client.send should be ctx.send. You can also write the function signature of the command, using Keyword-Only Arguments, so that you only echo the message, ignoring the &echo
from discord.ext.commands import Bot
client = Bot(description="Test bot", command_prefix="&", pm_help = False)
#client.command()
async def echo(ctx, *, msg):
await ctx.send(msg)
await ctx.message.delete()
client.run('token')