how save photo in telegram python bot? - python-3.x

i want to write a telegram bot that save photos .
this is my code , but its not working.
and i don't know what is my problem?
def image_handler(bot, update):
file = bot.getFile(update.message.photo.file_id)
print ("file_id: " + str(update.message.photo.file_id))
file.download('image.jpg')
updater.dispatcher.add_handler(MessageHandler(Filters.photo, image_handler))
updater.start_polling()
updater.idle()
pleas help me to solve my problem.

update.message.photo is an array of photos sizes (PhotoSize objects).
Use file = bot.getFile(update.message.photo[-1].file_id). This will get the image with biggest size available.

Here is my code
from telegram.ext import *
import telegram
def start_command(update, context):
name = update.message.chat.first_name
update.message.reply_text("Hello " + name)
update.message.reply_text("Please share your image")
def image_handler(update, context):
file = update.message.photo[0].file_id
obj = context.bot.get_file(file)
obj.download()
update.message.reply_text("Image received")
def main():
print("Started")
TOKEN = "your-token"
updater = Updater(TOKEN, use_context = True)
dp = updater.dispatcher
dp.add_handler(CommandHandler("start", start_command))
dp.add_handler(MessageHandler(Filters.photo, image_handler))
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()

Unlike the accepted answer suggests, you don't actually need the bot object to get the file:
file = update.message.photo[-1].get_file()
and then download the file:
path = file.download("output.jpg")
to use it for further processing or just have it on your device : )

Here is a vanilla python solution:
import requests
from PIL import Image
# for example, we get the last message
# update = requests.post(f'https://api.telegram.org/bot{TOKEN}/getUpdates').json()['result'][-1]
msg = update['message']
# check whether the message contains a photo
if msg.get('photo', None) == None:
return
# get the photo id with the biggest resolution
file_id = msg['photo'][-1]['file_id']
# get URL by id
file_path = requests.get(f'https://api.telegram.org/bot{TOKEN}/getFile?file_id={file_id}').json()['result']['file_path']
# open URL with Pillow
img = Image.open(requests.get(f'https://api.telegram.org/file/bot{TOKEN}/{file_path}', stream=True).raw)
# save on the disk if needed
img.save('photo.jpg')

#dp.message_handler(commands='start')
9 async def s_photo(message: types.Message):
10 """getting str type of json file"""
11photostr = await bot.get_user_profile_photos(message.from_user.id)
12 """parsing str to json"""
13 photojson = json.loads(photostr.as_json())
14 """giving file unic code to get_file method"""
15 photo = await bot.get_file(photojson['photo'][0][0]['file_id'])
16 """end downloading object with download method"""
17 downloadphoto = await photo.download('filename'+'.jpeg')

Related

Ubuntu 22.04: pyautogui.locateOnScreen is returning None. How to solve this?

My OS is Ubuntu 22.04, Python 3.10.4.
I am trying to create a code to automate Whatsapp send message.
Have installed latest version of pyautogui.
Following is the code I am running:
import pyautogui as pt
import paperclip as pc
# from pynput.mouse import Controller, Button
from time import sleep
# mouse = Controller()
class WhatsApp:
def __init__(self, speed=5, click_speed=.3):
self.speed = speed
self.click_speed = click_speed
self.message = ''
self.last_message = ''
def nav_green_dot(self):
try:
# position = pt.locateOnScreen('clip_pic.png', confidence = .7)
# position = pt.locateOnScreen('clip_pic.png')
# print(position)
print(pt.locateOnScreen('clip_pic.png'))
# pt.moveTo(position[0:2], duration = self.speed)
# pt.moveRel(-100, 0, duration = self.speed)
except Exception as e:
print ('Exception (nav_green_dot): ', e)
wa_bot = WhatsApp(speed = .5, click_speed = .4)
sleep(5)
wa_bot.nav_green_dot()
At print(pt.locateOnScreen('clip_pic.png')) I am getting None.
Attached is the picture I am trying to capture.
I have already opencv-python installed as well.
I also have whatsapp web page opened in a chrome browser.
I tested in firefox as well.
The output error is not clear in what direction I should go.
What am I missing?
Finding image on screen for only one time may be None you need to check repeatedly for it. And if it is found you can end the loop you are using to find it. You should use python's multithreading for it. here is an updated version of your code
import pyautogui as pt
import paperclip as pc
# from pynput.mouse import Controller, Button
from time import sleep
import threading
# mouse = Controller()
FOUND_IMAGE = False
def checkFunction():
global FOUND_IMAGE
while True:
img = pt.locateOnScreen('img.png')
if img != None:
FOUND_IMAGE = True
break
checkThread = threading.Thread(target=checkFunction) # creating therad
checkThread.start() # starting therad
class WhatsApp:
def __init__(self, speed=5, click_speed=.3):
self.speed = speed
self.click_speed = click_speed
self.message = ''
self.last_message = ''
def nav_green_dot(self):
try:
# position = pt.locateOnScreen('clip_pic.png', confidence = .7)
# position = pt.locateOnScreen('clip_pic.png')
# print(position)
print(FOUND_IMAGE)
# pt.moveTo(position[0:2], duration = self.speed)
# pt.moveRel(-100, 0, duration = self.speed)
except Exception as e:
print ('Exception (nav_green_dot): ', e)
wa_bot = WhatsApp(speed = .5, click_speed = .4)
sleep(5)
wa_bot.nav_green_dot()
For any queries have a look at this question or this Post

Cannot write CSV file from python

I'm been trying to create a csv file from this code, but it fails every time, I have tried different ways to place it inside the code but nothing has work so far.
I'm new to python and to Stack overflow.
If somebody can explain what I'm doing wrong it will be helpful.
Thanks in advance for any help.
from time import sleep
import os
import sys
from bleson import get_provider, Observer, UUID16
import csv
GOVEE_BT_mac_OUI_PREFIX = "A4:C1:38"
H5075_UPDATE_UUID16 = UUID16(0xEC88)
govee_devices = {}
# ###########################################################################
FORMAT_PRECISION = ".2f"
# Decode H5075 Temperature into degrees Fahrenheit
def decode_temp_in_f(encoded_data):
return format((((encoded_data / 10000) * 1.8) + 32), FORMAT_PRECISION)
# Decode H5075 percent humidity
def decode_humidity(encoded_data):
return format(((encoded_data % 1000) / 10), FORMAT_PRECISION)
#focus here
with open('temp.csv','w',newline='') as record:
record = csv.writer(record)
record.writerow(['Device Name','Device Address','Temp','Humidity'])
def print_values(mac):
govee_device = govee_devices[mac]
print(govee_device['name'],govee_device['address'],govee_device['tempInF'],govee_device['humidity'],govee_device['battery'])
record.writerow(govee_device['name'])
# On BLE advertisement callback
def on_advertisement(advertisement):
if advertisement.address.address.startswith(GOVEE_BT_mac_OUI_PREFIX):
mac = advertisement.address.address
if mac not in govee_devices:
govee_devices[mac] = {}
if H5075_UPDATE_UUID16 in advertisement.uuid16s:
# HACK: Proper decoding is done in bleson > 0.10
name = advertisement.name.split("'")[0]
encoded_data = int(advertisement.mfg_data.hex()[6:12], 16)
battery = int(advertisement.mfg_data.hex()[12:14], 16)
govee_devices[mac]["address"] = mac
govee_devices[mac]["name"] = name
govee_devices[mac]["mfg_data"] = advertisement.mfg_data
govee_devices[mac]["data"] = encoded_data
govee_devices[mac]["tempInF"] = decode_temp_in_f(encoded_data)
govee_devices[mac]["humidity"] = decode_humidity(encoded_data)
govee_devices[mac]["battery"] = battery
print_values(mac)
if advertisement.rssi is not None and advertisement.rssi != 0:
govee_devices[mac]["rssi"] = advertisement.rssi
# ###########################################################################
adapter = get_provider().get_adapter()
observer = Observer(adapter)
observer.on_advertising_data = on_advertisement
try:
while True:
observer.start()
sleep(2)
observer.stop()
except KeyboardInterrupt:
try:
observer.stop()
sys.exit(0)
except SystemExit:
observer.stop()
os._exit(0)
Error that Im getting is:
File "/home/pi/GoveeWatcher-master/python/goveeWatcher.py", line 37, in print_values
record.writerow(govee_device['name'])
ValueError: I/O operation on closed file.
I would be tempted to put the CSV writing functionality inside of the print_values function so it opens the file, writes the data, and then closes the file on each value that is found by the observer.
For example:
#focus here
def print_values(mac):
govee_device = govee_devices[mac]
print(govee_device['name'], govee_device['tempInF'])
with open('temp.csv','a',newline='') as record:
writer = csv.DictWriter(record, fieldnames=govee_device.keys())
writer.writerow(govee_device)

Checking if a Reddit post is a video or not

I'm making a bot that downloads posts from a subreddit I selected, but I only want to download photos. My code already makes sure that the post is not a text but I'm not able to check if the video or not. If the post is a video, the program should just skip it.
Here is my code so far:
from InstagramAPI import InstagramAPI
import praw
import requests
import urllib.request
import time
import keyboard
from PIL import Image
import math
#make a reddit acount and look up how to find this stuff. its called PRAW
reddit = praw.Reddit(client_id='***',
client_secret='***',
username='',
password='',
user_agent='chrome')
def DLimage(url, filePath, fileName):
fullPath = filePath + fileName + '.jpg'
urllib.request.urlretrieve(url, fullPath)
#folder path to store downloaded images
filePath = "/Users/***/AppBot/WTF/"
subreddit = reddit.subreddit('videos') #subreddit to take images from
waitTime = 2 #to prevent reddit badgateway error. DONt change
numRounds = 100 #how many posts
postFrequency = 600 # how often to post in seconds.
numPics = 100 #how many pics per post
for x in range(numRounds):
new_memes = subreddit.top('all') #.hot/.rising/.new reddit sorting algorithm
authors = []
photoAlbum = []
print("Round/post number:", x)
for subbmission in new_memes:
if subbmission.preview == True: #checking if post is only text.
#print("Post was text, skipping to next post.")
pass
else:
continue
url = subbmission.url
time.sleep(waitTime)
fileName = str(subbmission)
fullPath = filePath + fileName + '.jpg'
#print(fullPath)
time.sleep(waitTime)
#print(url)
try:
DLimage(url, filePath, fileName)
except:
print("scratch that, next post.")
continue
time.sleep(waitTime)
img = Image.open(fullPath)
width, height = img.size
#img = img.resize((1000, 1020), Image.NEAREST) #image resize. width/height
img = img.convert("RGB")
img.save(fullPath)
time.sleep(postFrequency)

Python watchdog module duplicate events (edit: was not an watchdog issue)

I am creating a python script that will identify changes to a log file and print some data from the new logs.
I use watchdog to create an event handler and everything seems to work fine except from that, I get duplicate events every time I modify the file. I checked creation and delete, they both work as expected and trigger one time.
I have read the similar question which explains having a created and a modified event when I save a file but this is not my case. I just get two modification events.
Here is my code:
import os, sys, time
import subprocess
import threading
import win32print
from tkinter import filedialog
from tkinter import *
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
class Handler(FileSystemEventHandler):
# docstring for FileSystemEventHandler
def __init__(self, observer, filename, dirname):
# super(Handler, FileSystemEventHandler).__init__(self,)
self.observer = observer
self.filename = filename
self.dirname = dirname
print("Handler filename = " , self.filename)
print("Handler dirname = " , self.dirname)
def on_modified(self, event):
if self.filename == event.src_path:
print("The file was modified")
print (event.src_path)
# go get the last line and print the data
# try:
# hJob = win32print.StartDocPrinter (hPrinter, 1, ("test of raw data", None, "RAW"))
# try:
# win32print.StartPagePrinter (hPrinter)
# win32print.WritePrinter (hPrinter, raw_data)
# win32print.EndPagePrinter (hPrinter)
# finally:
# win32print.EndDocPrinter (hPrinter)
# finally:
# win32print.ClosePrinter (hPrinter)
def on_created(self, event):
print("A file was created (", event.src_path, ")")
def on_deleted(self, event):
print("A file was deleted (", event.src_path, ")")
if __name__ == "__main__":
Flags=2
Name=None
Level=1
printers = win32print.EnumPrinters(Flags, Name, Level)
print("\nChoose a printer to use:")
i=1
for p in printers:
print(i,')' , p[2])
i = i+1
if sys.version_info >= (3,):
raw_data = bytes ("This is a test", "utf-8")
else:
raw_data = "This is a test"
printer = int(input())
printer_name = printers[printer-1][2] #win32print.GetDefaultPrinter ()
print("You chose ", printer_name, "\nI will now print from the specified file with this printer")
hPrinter = win32print.OpenPrinter (printer_name)
# root = Tk()
# root.filename = filedialog.askopenfilename(initialdir = "/Desktop",title = "Select file",filetypes = (("log files","*.log"),("all files","*.*")))
file_path = "some_file_path" # root.filename
file_directory = os.path.dirname(file_path)
# print (file_path)
print (file_directory)
observer = Observer()
event_handler = Handler(observer, file_path, file_directory)
observer.schedule(event_handler, path=file_directory, recursive=False)
observer.start()
observer.join()
any ideas would be appreciated
EDIT:
After some debugging I found out that Windows10 is changing the file modification time twice every time I save it.
The proof of concept code is this:
prev_modification_time = os.path.getmtime(file_path)
while True:
current_mod_time = os.path.getmtime(file_path)
if prev_modification_time != current_mod_time :
print ("the file was modified, last modification time is: ", current_mod_time)
prev_modification_time = current_mod_time
pass
Final edit:
After testing my code on linux (Debian Stretch to be exact) it worked like a charm. So this combined with the previous edit probably shows that watchdog works fine and it is windows10 that has some issue. Should I post it on a different question or here?

Python: Facebook Graph API - batch request

I want to make a batch request getting campaigns for a specific ad account. I created a simple code based on this issue
but I've used some global arrays and I don't know if time.sleep(2) is necessary for this code. My code is as below:
from facebookads import FacebookAdsApi
from facebookads.api import FacebookRequest
import pandas as pd
import time
batch_body_responses = []
list_of_artists = [1]
def success_callback(response):
try:
pair = [response.json()['data']]
next = [response.json()['paging']['next']]
batch_body_responses.append(pair)
batch_body_responses.append(next)
except IndexError:
pass
except UnicodeEncodeError:
pass
def error_callback(response):
pass
def generate_batches(iterable, batch_size_limit):
# This function can be found in examples/batch_utils.py
batch = []
for item in iterable:
if len(batch) == batch_size_limit:
yield batch
batch = []
batch.append(item)
if len(batch):
yield batch
def get_id_list(art_search_list):
batches = []
your_app_id = '756885'
your_app_secret = '123456789'
your_access_token = 'EAA.....'
api = FacebookAdsApi.init(your_app_id, your_app_secret, your_access_token)
batch_limit = 25
for batch in generate_batches(art_search_list, batch_limit):
next_batch = api.new_batch()
for artt in batch:
requestss = [FacebookRequest(node_id='act_1234/campaigns',method="GET",endpoint="?fields=id,name")]
for req in requestss:
next_batch.add_request(req, success_callback, error_callback)
batches.append(next_batch)
for batch_request in batches:
batch_request.execute()
time.sleep(2)
print(batch_body_responses)
return batch_body_responses
df = pd.DataFrame(get_id_list(list_of_artists))
How can this code optimized by not using global arrays and how to execute without sleep statement and why it is needed sleep?

Resources