Python Telegram Bot - Send Image - python

I'd like to send a Image (via URL or Path), on request.
I use the source code here.
The code has already a sample to send an image (via URL or Path), but I don't get it since I'm new to Python.
Here's the sample code snippet:
elif text == '/image': #request
img = Image.new('RGB', (512, 512))
base = random.randint(0, 16777216)
pixels = [base+i*j for i in range(512) for j in range(512)] # generate sample image
img.putdata(pixels)
output = StringIO.StringIO()
img.save(output, 'JPEG')
reply(img=output.getvalue())
Some API infos can be found here.
Thanks for your patience.

To send a photo from URL:
bot.send_photo(chat_id=chat_id, photo='https://telegram.org/img/t_logo.png')
To send a photo from local Drive:
bot.send_photo(chat_id=chat_id, photo=open('tests/test.png', 'rb'))
Here is the reference documentation.

I was struggling to connect the python-telegram-bot examples with the above advice. Especially, while having context and update, I couldnt find chatid and bot. Now, my two cents:
pic=os.path.expanduser("~/a.png")
context.bot.send_photo(chat_id=update.effective_chat.id, photo=open(pic,'rb'))

Related

Why downloading Facebook images with requests.get() gives corrupted files?

I am a very new to Python and Facebook Graph API and hope you can help me out with this:
I have writted (in Python) a peace of code that uploads images tu a page on facebook (in a post, so it contains some text too) and this works as expected. Now I am trying to write a peace of code capable of downloading thhe image inside a post (given post_id). Unfortunately I always get "file corrupted " error.
Here is the code I use to download the image:
# this function uploads an image from a web url
ret = upload_img_to_fb(url)
# decode JSON from the request
post_id = json.loads(ret)
ret = get_json_from_fb_postID(post_id['post_id'])
perm_url = json.loads(ret)
print('Perm url = ' + perm_url['permalink_url'] + '\n')
img_response = requests.get(perm_url['permalink_url'])
image = open("foto4.jpg","wb")
image.write(img_response.content)
image.close()
Now, the print will print the following:
Perm url = https://www.facebook.com/102956292308044/photos/a.103716555565351/107173241886349/?type=3
which, acording to what I understood makes everything wrong because it is not a picture, even if a picture is displayed on the screen. So I right clicked the pic and opened it's link and I got:
https://scontent.fbzo1-2.fna.fbcdn.net/v/t39.30808-6/273008252_107171558553184_3697853178128736286_n.jpg?_nc_cat=103&ccb=1-5&_nc_sid=9267fe&_nc_ohc=d0ZvWSTzIogAX-PsuzN&_nc_ht=scontent.fbzo1-2.fna&oh=00_AT8GWh0wDHgB6tGCzHuPE2VZFus9EgWhllaJfVkZ-Nqtow&oe=620465E4
and if I pass this last link as parameter to img_response = requests.get() it works.
How do I get around this?

How to make python download an image from a URL but if the image is already downloaded it doesnt

So say from a random api, lets say api.example.com as an example. It sends a random image once you go on it and sends the json for it. So like {"url": "api.example.com/img1.png"}. After de-jsonifying it how can i download the image and save it in some folder, but if its already downloaded so say the image name is taken it will not download it.
Edit: here is my code i done so far.
`
url = f"https://nekos.life/api/v2/img/neko"
response = requests.get(url)
response.raise_for_status()
jsonResponse = response.`json()
urll = (jsonResponse["url"])
urllib.request.urlretrieve(urll, "neko.png")`
as said in this article, i think [os.path][1] can do the job pretty well.
just try to use
os.path.exists(phot_path)
that should be it.
[1]: https://linuxize.com/post/python-check-if-file-exists/

I have been using pyimgur to upload pictures and I would like to know how to delete them

I have been using this code to upload pictures to imgur:
import pyimgur
CLIENT_ID = "Your_applications_client_id"
PATH = "A Filepath to an image on your computer"
im = pyimgur.Imgur(CLIENT_ID)
uploaded_image = im.upload_image(PATH, title="Uploaded with PyImgur")
print(uploaded_image.title)
print(uploaded_image.link)
print(uploaded_image.size)
print(uploaded_image.type)
I'm using the client ID from my Imgur account, but after I upload them they wont't appear among my user photos.
Do you know where are they stored and how can I delete them?
Many thanks in advance.
The answer was:
print(uploaded_image.deletebash)
and once you get that code:
imgur.com/delete/

Upload image to facebook using the Python API

I have searched the web far and wide for a still working example of uploading a photo to facebook through the Python API (Python for Facebook). Questions like this have been asked on stackoverflow before but non of the answers I have found work anymore.
What I got working is:
import facebook as fb
cfg = {
"page_id" : "my_page_id",
"access_token" : "my_access_token"
}
api = get_api(cfg)
msg = "Hello world!"
status = api.put_wall_post(msg)
where I have defined the get_api(cfg) function as this
graph = fb.GraphAPI(cfg['access_token'], version='2.2')
# Get page token to post as the page. You can skip
# the following if you want to post as yourself.
resp = graph.get_object('me/accounts')
page_access_token = None
for page in resp['data']:
if page['id'] == cfg['page_id']:
page_access_token = page['access_token']
graph = fb.GraphAPI(page_access_token)
return graph
And this does indeed post a message to my page.
However, if I instead want to upload an image everything goes wrong.
# Upload a profile photo for a Page.
api.put_photo(image=open("path_to/my_image.jpg",'rb').read(), message='Here's my image')
I get the dreaded GraphAPIError: (#324) Requires upload file for which non of the solutions on stackoverflow works for me.
If I instead issue the following command
api.put_photo(image=open("path_to/my_image.jpg",'rb').read(), album_path=cfg['page_id'] + "/picture")
I get GraphAPIError: (#1) Could not fetch picture for which I haven't been able to find a solution either.
Could someone out there please point me in the right direction of provide me with a currently working example? It would be greatly appreciated, thanks !
A 324 Facebook error can result from a few things depending on how the photo upload call was made
a missing image
an image not recognised by Facebook
incorrect directory path reference
A raw cURL call looks like
curl -F 'source=#my_image.jpg' 'https://graph.facebook.com/me/photos?access_token=YOUR_TOKEN'
As long as the above calls works, you can be sure the photo agrees with Facebook servers.
An example of how a 324 error can occur
touch meow.jpg
curl -F 'source=#meow.jpg' 'https://graph.facebook.com/me/photos?access_token=YOUR_TOKEN'
This can also occur for corrupted image files as you have seen.
Using .read() will dump the actual data
Empty File
>>> image=open("meow.jpg",'rb').read()
>>> image
''
Image File
>>> image=open("how.png",'rb').read()
>>> image
'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00...
Both of these will not work with the call api.put_photo as you have seen and Klaus D. mentioned the call should be without read()
So this call
api.put_photo(image=open("path_to/my_image.jpg",'rb').read(), message='Here's my image')
actually becomes
api.put_photo('\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00...', message='Here's my image')
Which is just a string, which isn't what is wanted.
One needs the image reference <open file 'how.png', mode 'rb' at 0x1085b2390>
I know this is old and doesn't answer the question with the specified API, however, I came upon this via a search and hopefully my solution will help travelers on a similar path.
Using requests and tempfile
A quick example of how I do it using the tempfile and requests modules.
Download an image and upload to Facebook
The script below should grab an image from a given url, save it to a file within a temporary directory and automatically cleanup after finished.
In addition, I can confirm this works running on a Flask service on Google Cloud Run. That comes with the container runtime contract so that we can store the file in-memory.
import tempfile
import requests
# setup stuff - certainly change this
filename = "your-desired-filename"
filepath = f"{directory}/{filename}"
image_url = "your-image-url"
act_id = "your account id"
access_token = "your access token"
# create the temporary directory
temp_dir = tempfile.TemporaryDirectory()
directory = temp_dir.name
# stream the image bytes
res = requests.get(image_url, stream=True)
# write them to your filename at your temporary directory
# assuming this works
# add logic for non 200 status codes
with open(filepath, "wb+") as f:
f.write(res.content)
# prep the payload for the facebook call
files = {
"filename": open(filepath, "rb"),
}
url = f"https://graph.facebook.com/v10.0/{act_id}/adimages?access_token={access_token}"
# send the POST request
res = requests.post(url, files=files)
res.raise_for_status()
if res.status_code == 200:
# get your image data back
image_upload_data = res.json()
temp_dir.cleanup()
if "images" in image_upload_data:
return image_upload_data["images"][filepath.split("/")[-1]]
return image_upload_data
temp_dir.cleanup() # paranoid: just in case an error isn't raised

(Py)Qt: problem with image downloading

guys
I want to display some images with their captions in QTextEdit. I have a dictionary with captions and corresponding URLs. The problem is when I post a request with QNetworkAccessManager and wait for a signal finished(QNetworkReply*), I get reply with image only. How can I determine a corresponding caption this image was requested for?
def _init_(self)
manager = QNetworkAccessManager(self);
self.connect(manager, SIGNAL("finished(QNetworkReply*)"), self.add_record)
for record in dict:
manager.get(QNetworkRequest(QUrl(status['caption'])))
def add_record(self, reply):
img = QImage()
img.loadFromData(reply.readAll())
self.textEdit.textCursor().insertImage(img)
#I don't know at this point for which caption
#I've received this image
#self.textEdit.append(record['text'] + '\n');
Are there any design patterns for this problem? I would appreciate any ideas
Assuming a recent Qt version, the QNetworkReply::request() will give you a pointer to the QNetworkRequest that triggered this reply.
So you can access the information you're after with QNetworkRequest::url().

Categories