So i did a simple rewrite of this bot in python.
It fetches a link and uses an API to return an Imageurl.
Here's the relevant Code:
#bot.command(name='ss')
async def screenshot(context, *args):
if len(args) != 1:
await context.channel.send("Error Missing Inspection Link!")
return
await context.message.add_reaction("✅")
#Getting the Imageurl in a Class (sgg) in another Python File
sgg.getscreenshot(args[0])
while sgg.imglnk == "":
sleep(0.2)
e = discord.Embed(description=sgg.imglnk)
e.set_image(url=sgg.imglnk)
print(ppretty(e._image))
await context.channel.send(embed=e)
This does work sometimes, other times it doesn't. (See Image below)
I checked the Library and found out that the Imageurl is placed in the class member Embed._image.
So to see if i'm maybe getting a malformed URL or something i ppretty printed the class member.
It returned the correct URL for both tests.
https://s.swap.gg/rca4ofNZx.jpg
{'url': 'https://s.swap.gg/rca4ofNZx.jpg'}
https://s.swap.gg/DG-7kjyu6.jpg
{'url': 'https://s.swap.gg/DG-7kjyu6.jpg'}
So on to my question, does anyone have a clue why it sometimes correctly displays the Image and other times just doesn't?
Related
In a Python/Flask application, I have defined this endpoint that I expect to return 404 if a client tries to get an id that doesn't exist on my database.
For example:
#app.route('/plants/<int:plant_id>', methods=['GET'])
def get_plant(plant_id):
try:
plant = Plant.query.filter(Plant.id == plant_id).one_or_none()
if plant is None:
abort(404)
return jsonify({
'success': True,
'plant': plant.format()
})
except:
abort(422)
The problem is that when I try to execute it, it always seems to raise an exception and returns 422.
If I remove the try/except syntax, it works as expected and returns the 404. But I lose the capacity of handling exceptions... so it's not a solution for me.
Why am I doing wrong? How could I correctly trigger 404 without setting 404 as the except return?
Thanks!!
Ok, finally I was able to understand it and solve it. I post my findings here so maybe it could help someone in the future. :)
The answer is very basic, actually: every time I abort, I trigger an exception.
So, when I aborted, no matter the status code I used, I fell into my except statement, which was returning 422 by default.
What I did to solve it was to implement a custom RequestError, and every time I have a controlled error, I trigger my custom error, which output I can control separately.
This is the implementation of my custom error:
class RequestError(Exception):
def __init__(self, status):
self.status = status
def __str__(self):
return repr(self.status)
And I've changed my route implementation for something like this:
(note that I'm now handling first the custom error exception, and only then triggering a generic 422 error)
#app.route('/plants/<int:plant_id>', methods=['GET'])
def get_plant(plant_id):
try:
plant = Plant.query.filter(Plant.id == plant_id).one_or_none()
if plant is None:
raise RequestError(404)
return jsonify({
'success': True,
'plant': plant.format()
})
except RequestError as error:
abort(error.status)
except:
abort(422)
And that does it! \o/
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()
Ok, so heres the problem. I wanted made a command that would in general just cycle through some data and images. So I did, but a problem I ran into was the fact that when I try to edit the image inside the embed it would throw an error. discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: Object of type File is not JSON serializable
This makes sense, but I can't find a way around this issue. Is there a way to make this JSON serializable?
#client.command()
async def test(ctx):
file = discord.File('image1.png', filename="card.png")
embed = discord.Embed(title='Random Embed')
embed.set_image(url="attachment://card.png")
msg = await ctx.send(file=file, embed=embed)
await asyncio.sleep(1)
file = discord.File('image2.png', filename="card.png")
embed = discord.Embed(title='Title goes here', description='Description goes here', color=0x35363B)
embed.set_image(url="attachment://card.png")
embed.add_field(name='Stats:', value='Stats go here')
await msg.edit(file=file, embed=embed)
As far as I know, you can't edit File once sent
You can edit the image_url from the embed for set_thumbail or set_image
I would like to log into Steam to try my hand at some data collection but I don't really know how to go about logging in and getting past 2FA. My current code tries to log in and is supposed to save the result of that into an html file so I could see what was achieved. It currently returns a blank html file.
import scrapy
def authentication_failed(response):
pass
class LoginSpider(scrapy.Spider):
name = 'loginSpider'
start_urls = ['https://steamcommunity.com/login/home/?goto=']
def parse(self, response):
return scrapy.FormRequest.from_response(
response,
formdata={'username': 'user', 'password': 'pwd'},
callback=self.after_login
)
def after_login(self, response):
if authentication_failed(response):
self.logger.error("Login failed")
return
html = open("test.html", "w")
html.write(response.body.decode("utf-8"))
html.close()
To spare me asking another question, would getting through the Steam Guard 2FA system be as simple as asking the user to type the code in and then sending another FormRequest?
The website that I wanna crawl is using POST method to get data, instead of navigating to paginating url. Getting the first page looks great now, using this method:
def start_requests(self):
formdata = {
...
'PageIndex': '0',
...
}
return [
FormRequest('my-url', formdata=formdata, callback=self.parse)
]
I checked the next page and tried to yield the next page as following code:
current_page = 0
....
def parse(self, response):
next_page = Selector(response).css('a.viewmore').extract_first()
if next_page is not None:
self.current_page = self.current_page + 1
formdata = {
...
'PageIndex': self.current_page,
...
}
yield FormRequest('my-url', formdata=formdata, callback=self.parse)
This is where it is broken. I got the error log here, and I can only assume that the way I assign self.current_page causes the broken result.
I am using macOS, python3 (version 3.8.1), scrapy 1.8.0.Could anyone guide me on this one and help me to assign dynamic page number on POST request like this? Thanks in advance!
Update: I have figured out that the line self.current_page should be cast as following: 'PageIndex': str(self.current_page). This problem is solved!