Errors with discord.py Polling Command - python-3.x

I want to basically make a poll command that takes the emojis a user puts in and uses it as a reaction but I also want to make it so there are multiple emojis allowed to be used so if there were to be more than 2 options it would work with this command.
Example:
!poll test :white_large_square: :black_large_square: :tired_face:
Traceback:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
TypeError: poll() missing 2 required keyword-only arguments: 'em1' and 'em2'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/bot.py", line 902, in invoke
await ctx.command.invoke(ctx)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 864, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/ext/commands/core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: poll() missing 2 required keyword-only arguments: 'em1' and 'em2'
Code:
async def poll(ctx, *, message, em1, em2, em3=None, em4=None, em5=None, em6=None, em7=None, em8=None, em9=None, em10=None):
authorperms = ctx.author.permissions_in(ctx.channel)
if authorperms.manage_messages:
emb = discord.Embed(title="📜Poll📜", color=discord.Color.red())
emb.add_field(name="Question", value=f"{message}")
emb.set_footer(text="Official GNAG Discord Bot Made by Lukeee#2222")
msg = await ctx.channel.send(embed=emb)
else:
embed = discord.Embed(title="Permission Denied.",
description="You don't have permission to execute this command.",
color=0xff0000)
embed.set_footer(text="Official GNAG Discord Bot Made by Lukeee#2222")
await ctx.send(embed=embed)
if em1:
await msg.add_reaction(em1)
if em2:
await msg.add_reaction(em2)
if em3:
await msg.add_reaction(em3)
else:
print("only 2 emojis ig. :C")
if em4:
await msg.add_reaction(em4)
else:
print("Only 3 emojis ig. :C")
if em5:
await msg.add_reaction(em5)
else:
print("Only 4 emojis ig. :C")
if em6:
await msg.add_reaction(em6)
else:
print("Only 5 emojis ig. :C")
if em7:
await msg.add_reaction(em7)
else:
print("Only 6 emojis ig. :C")
if em8:
await msg.add_reaction(em8)
else:
print("Only 7 emojis ig. :C")
if em9:
await msg.add_reaction(em9)
else:
print("Only 8 emojis ig. :C")
if em10:
await msg.add_reaction(em10)
else:
print("Only 9 emojis ig. :C")```

From the docs:
You can only have one keyword-only argument due to parsing ambiguities.
To simply fix your code delete the keyword-only argument (the *)
async def poll(ctx, message, em1, em2, em3=None, em4=None, em5=None, em6=None, em7=None, em8=None, em9=None, em10=None):

All you have to do is keep this code then just put your question in quotes ex: !poll "Cats Or Dogs?" :dog: :cat:

Related

Description wont show, and the thumbnail wont either

This is my code:
#client.event
async def on_command_error(ctx, error):
if isinstance(error, commands.MissingRequiredArgument):
emb = discord.Embed(color=0xda70d6,title = 'Issue with command', discription = 'Using the correct commands is helpful, if you dont know them use "_help"')
emb.set_author(name = 'Alert', icon_url='https://i.pinimg.com/474x/60/5e/ac/605eac3124c4885e067002cdd4ff684a.jpg')
emb.set_thumbnail('https://library.kissclipart.com/20191119/ww/kissclipart-help-icon-help-and-support-icon-92018307fcf5c4fa.png')
emb.set_footer('If you have any questions just DM the onwer Saly_Derek#0031 or Co-Owner Salty_Troye#0540')
await ctx.send(embed=emb)
When I use the command in my console I get this error:
Ignoring exception in on_command_error
Traceback (most recent call last):
File "/opt/virtualenvs/python3/lib/python3.8/site-packages/discord/client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "main.py", line 58, in on_command_error
emb.set_thumbnail('https://library.kissclipart.com/20191119/ww/kissclipart-help-icon-help-and-support-icon-92018307fcf5c4fa.png')
TypeError: set_thumbnail() takes 1 positional argument but 2 were given
But I don't know what's wrong or how to fix it.
Fixed my issue, this works 100%. My issue was for emb.set_thumbnail I never had "url = 'link'"
#client.event
async def on_command_error(ctx, error):
if isinstance(error, commands.MissingRequiredArgument):
emb = discord.Embed(color=0xda70d6,title = 'Issue with command', description = f'''using commands properly is helpful. Use command "_help"''')
emb.set_author(name = 'Alert', icon_url = 'https://i.pinimg.com/474x/60/5e/ac/605eac3124c4885e067002cdd4ff684a.jpg')
emb.set_thumbnail(url = 'https://library.kissclipart.com/20191119/ww/kissclipart-help-icon-help-and-support-icon-92018307fcf5c4fa.png')
emb.set_footer(text = f'If you have any questions just DM the onwer Saly_Derek#0031 or Co-Owner Salty_Troye#0540')
await ctx.send(embed=emb)```

Why does python output this ValueError after running my discord command twice, are there any possible fixes?

I'm currently trying to make a Discord boy command (using discord.py rewrite) that gets the top post from a sub reddit with all the relevant information (e.g. upvotes, awards, top comment etc.) I've gotten the command to work, but the command only works the first time I use it. After I use it a second time I get this error:
Traceback (most recent call last):
File "C:\Users\Optic\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
ret = await coro(*args, **kwargs)
File "C:/Users/Optic/PycharmProjects/DiscordBot/Lilliebot.py", line 155, in reddit
post_url, error, error_type, top_comment, upvote, awarded, title, sfw, url, thumbnail = Reddit.Redget(
ValueError: not enough values to unpack (expected 10, got 2)
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Optic\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\bot.py", line 903, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Optic\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 855, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Optic\AppData\Local\Programs\Python\Python38-32\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: ValueError: not enough values to unpack (expected 10, got 2)
I don't understand how this is really even possible. and its gotten my extremely frustrated.
this is my code for the actual command (its only one section, but the code is repeated a few times:
import praw
import prawcore
def Redget(inp, inptype):
try:
global post_url, thumbnail, upvote, url, awarded, sfw, top_comment, title, error, error_type, id
reddit = praw.Reddit(
client_id='my id',
client_secret='my secret',
username='please dont hack me',
password='thank you very much',
user_agent='here is a little guy waving: 0/'
)
if inptype.lower() == "hot":
subreddit = reddit.subreddit(inp)
post = subreddit.hot(limit=5)
count = 0
top_count = 0
try:
try:
for x in post:
if not x.stickied:
if count >= 1:
pass
else:
try:
url = x.url
upvote = x.ups
awarded = x.top_awarded_type
thumbnail = x.thumbnail
id = x.id
title = x.title
for top_level_comment in x.comments:
if top_count >= 1:
pass
else:
top_comment = top_level_comment.body
top_count = top_count + 1
if x.over_18:
sfw = False
else:
sfw = True
except AttributeError:
pass
count = count + 1
else:
pass
except prawcore.exceptions.NotFound:
error = True
except prawcore.exceptions.Redirect:
error = True
else:
error_type = True
post_url = f'https://reddit.com/r/{inp}/comments/{id}/'
return post_url, error
except NameError:
error = False
error_type = False
return post_url, error, error_type, top_comment, upvote, awarded, title, sfw, url, thumbnail
here is the code in my bot that does stuff with what is returned the things:
#bot.command()
async def reddit(ctx, type, subreddit):
requests_cache.install_cache(cach_name='reddit', backend='sqlite', expire_after=1800)
post_url, error, error_type, top_comment, upvote, awarded, title, sfw, url, thumbnail = Reddit.Redget(
subreddit,
type)
embed = discord.Embed(
title=title,
color=discord.Colour.orange()
)
embed.set_image(url=url)
if sfw is False:
await ctx.send('sorry, this post is nsfw, and this command doesn\'t allow nsfw posts.')
else:
await ctx.send(embed=embed)
await ctx.send(f'''```
Upvotes: {upvote}
Awards: {awarded}
Post: {post_url}```''')
await ctx.send(f'```top comment: {top_comment}```')
Any help solving this issue would be greatly appreciated. Btw. ive tried aPRAW and ive gotten even more confusing errors. Id like to stick to PRAW if that's possible. I really don't wanna re write all of my code.
thank you so much in advance.
Your function can return different number of values. This is a serious problem.
snipped from the bottom of the code you pasted
return post_url, error <--- returns two values (what is throwing your error)
except NameError:
error = False
error_type = False
return post_url, error, error_type, top_comment, upvote, awarded, title, sfw, url, thumbnail <--- returns more than two values, this is what you are expecting when you call the function
You need to make the function always return the same number of values. You could return some extra None values, or you could stuff the values into a dictionary or tuple and check whether they exist. Either of those solutions would work.

deliberately Raise and throw an exception in python

I have a use case where I need to raise an exception and again throw the exception. For this I'm using raise keyword in both try and catch. The code is as below
try:
username = input ("username:")
If Len(username) != 6:
raise Exception
except Exception:
raise Exception ("username is not valid")
Is this the right way to do like this? Is it compliant to coding standards to raise Exception in both try and except blocks?
I'm guessing this is a simplified version of your actual use case, in which case it is generally correct. A couple of notes:
You can use raise without anything after it to re-raise the same error.
try:
raise ValueError('message')
except ValueError:
run_something()
raise # will raise ValueError ('message')
Don't raise a general Exception and don't catch them either, be specific, otherwise this code will obscure other errors and will be difficult to debug. If nothing else suits you, make an exception of your own:
class MyException(Exception):
pass
Then you can use it:
raise MyException('my message')
In your use case, if I understood it correctly, all of this together would be:
class InvalidUsername(Exception):
pass
try:
username = input('username: ')
if len(username) > 6:
raise InvalidUsername('Username is too long')
if '!' in username:
raise InvalidUsername('Invalid character in username')
except InvalidUsername:
handle_invalid_user()
raise
Example in the console:
>>> try:
... username = input('username: ')
... if len(username) > 6:
... raise InvalidUsername('Username is too long')
... if '!' in username:
... raise InvalidUsername('Invalid character in username')
... except InvalidUsername:
... handle_invalid_user()
... raise
...
username: test1234
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
__main__.InvalidUsername: Username is too long
Or with an invalid character:
username: ofer!
Traceback (most recent call last):
File "<stdin>", line 6, in <module>
__main__.InvalidUsername: Invalid character in username
I was also looking to raise an exception when there is an error within the business logic from an external server and due to database connection.
I came across this arcticle to basically raise the exception especially when you are follwing an Controller-> Service -> Repository pattern.
https://flask.palletsprojects.com/en/2.1.x/errorhandling/
from flask import jsonify, request
class InvalidAPIUsage(Exception):
status_code = 400
def __init__(self, message, status_code=None, payload=None):
super().__init__()
self.message = message
if status_code is not None:
self.status_code = status_code
self.payload = payload
def to_dict(self):
rv = dict(self.payload or ())
rv['message'] = self.message
return rv
#app.errorhandler(InvalidAPIUsage)
def invalid_api_usage(e):
return jsonify(e.to_dict()), e.status_code
# an API app route for getting user information
# a correct request might be /api/user?user_id=420
#app.route("/api/user")
def user_api(user_id):
user_id = request.arg.get("user_id")
if not user_id:
raise InvalidAPIUsage("No user id provided!")
user = get_user(user_id=user_id)
if not user:
raise InvalidAPIUsage("No such user!", status_code=404)
return jsonify(user.to_dict())
[1]: https://flask.palletsprojects.com/en/2.1.x/errorhandling/
I hope this helps to developers who are developing enterprise level apps.

Is there any way of getting values from keys inside other keys?

(first post sorry if i do this wrong) So I am making a bot (on discord) for me and my friends using discord.py (since python is the easiest code ever) and I've came across this. I need to get values from keys INSIDE OTHER keys. How do I do this?
So I've tried to change res to res.text and res.json and res.content and I could only find the "data" but not "id","name" or "description" which I need.
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import requests, json
import asyncio
Client = discord.Client()
client = commands.Bot(command_prefix='?')
#client.event
async def on_ready():
print('started')
#client.command()
async def findfriends(ctx,userid):
res = requests.get("https://friends.roblox.com/v1/users/"+userid+"/friends")
var = json.loads(res.text)
def a(a):
ID = a['id']
return ID
def b(b):
Name = b['name']
return Name
def c(c):
description = c['description']
return description
data = var['data'] #I can get this working
print(data)
#cv = data['name'] #but this wont work
#id = a(var) #nor this
#name = b(var) #nor this
#desc = c(var) #nor this
#await ctx.send("\nID: " + id + "\nName: " + name + "\nDesc: " + desc) # this is just sending the message
client.run(BOT TOKEN HERE) #yes i did indeed add it but just for the question i removed it
As I said in the code, I can only get "data" working and not id,name or desc. For id name and desc it just throws an error
Ignoring exception in command findfriends:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
ret = await coro(*args, **kwargs)
File "C:/Users/Calculator/PycharmProjects/ryhrthrthrhrebnfbngfbfg/a.py", line 277, in findfriends
id = a(var) #nor this
File "C:/Users/Calculator/PycharmProjects/ryhrthrthrhrebnfbngfbfg/a.py", line 266, in a
ID = a['id']
KeyError: 'id'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\bot.py", line 863, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 728, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 88, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: KeyError: 'id'
and
Ignoring exception in command findfriends:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 79, in wrapped
ret = await coro(*args, **kwargs)
File "C:/Users/Calculator/PycharmProjects/ryhrthrthrhrebnfbngfbfg/a.py", line 274, in findfriends
data = var['data']['id'] #I can get this working
TypeError: list indices must be integers or slices, not str
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\bot.py", line 863, in invoke
await ctx.command.invoke(ctx)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 728, in invoke
await injected(*ctx.args, **ctx.kwargs)
File "C:\Users\Calculator\PycharmProjects\ryhrthrthrhrebnfbngfbfg\venv\lib\site-packages\discord\ext\commands\core.py", line 88, in wrapped
raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: list indices must be integers or slices, not str
The https://friends.roblox.com/v1/users/<userid>/friends endpoint returns a list of all the friends that the user has, which can be of varying size.
With var = json.loads(res.text) you are loading the response text into a json object, which contains the key data, which you access using data = var['data']. The new data variable now contains a list object, which is why cv = data['name'] fails to work as list objects do not take strings as keys, they are accessed using integers.
You need to iterate over the list to get all information on the friends. The below code goes through the list, pulls information for each item in the list and sends a message of the information once it has gone through all items.
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import requests, json
import asyncio
client = commands.Bot(command_prefix='?')
#client.event
async def on_ready():
print('started')
#client.command()
async def findfriends(ctx,userid):
res = requests.get("https://friends.roblox.com/v1/users/"+userid+"/friends")
var = json.loads(res.text)
data = var['data']
print(data)
friends_msg = 'Friends information:'
for friend in data:
id = friend['id']
name = friend['name']
desc = friend['description']
friends_msg = friends_msg + "\nID: " + id + "\nName: " + name + "\nDesc: " + desc
await ctx.send(friends_msg)
client.run(BOT TOKEN HERE)

Appeared at one moment from nowhere error in the discord.py

Sitting and studying information about the discord.py 0.16.12 I was interested in the function discord.Client.edit_role(server,role,parametrs*)
I ran into a problem(An hour before that everything worked)
Ignoring exception in on_ready
Traceback (most recent call last):
File "C:\Users\ROG\Desktop\trash\dsbt\venv\lib\site-packages\discord\client.py", line 307, in _run_event
yield from getattr(self, event)(*args, **kwargs)
File "C:/Users/ROG/Desktop/trash/dsbt/rainbown_rolle/testbd.py", line 10, in on_ready
await bot.edit_role(sr, rl, colour=discord.Colour(((rgb[0] << 16) + (rgb[1] << 8) + rgb[2])))
File "C:\Users\ROG\Desktop\trash\dsbt\venv\lib\site-packages\discord\client.py", line 2860, in edit_role
yield from self.http.edit_role(server.id, role.id, **payload)
File "C:\Users\ROG\Desktop\trash\dsbt\venv\lib\site-packages\discord\http.py", line 169, in request
print(data['retry_after'])
TypeError: string indices must be integers
Bot code
import discord
token="token"
bot=discord.Client()
#bot.event
async def on_ready():
rgb = [255, 0, 161]
sr= discord.utils.find(lambda m: m.id == '403945874780061707',bot.servers)
rl = discord.utils.find(lambda m: m.name == "Обыватель", sr.roles)
print(type(sr),type(rl))
await bot.edit_role(sr, rl, colour=discord.Colour(((rgb[0] << 16) + (rgb[1] << 8) + rgb[2])))
bot.run(token)
It looks like the endpoint returned some response body that was just text, not a json.
discord.py expects responses with status 429 (rate limited) to be a json it can turn into a dictionary. So it's trying to access the text like a dictionary, which fails.
According to this commit which fixes this issue for the rewrite branch, it may be that you've been banned by Cloudflare. Try updating your bot to the new version, but you will most likely have to host your bot somewhere else to get around whatever ban they have in place.

Resources