Sending a PNG image from a SleekXMPP client to Pidgin - python

I have googled a lot but unfortunately could not come up with a working solution. I have a Python client using SleekXMPP modules and I would like to send a PNG file to a Pidgin client.
AFAIK, there is no Jingle extension implemented yet but a few methods using IBB, OOB and BOB did not work for me. I have tried XEPs 0047, 0231, 0095, and 0096 for negotiating.
I set my Pidgin to auto-accept files from a certain JID.
Is there any way doing that using SleekXMPP?
p.s. The book XMPP: The definitive guide did not give me any clue too :/
Thanks.
CODE
def upload_files_tgz(self, archivename, files, removearch=True):
# tar file name and mimetype (b for binary)
bfilename = "{0}.tar.gz".format(archivename)
bfilemime = "application/x-gzip";
# create a compressed tgz archive
tar = tarfile.open(bfilename, "w:gz" )
if files:
for f in files:
tar.add(f)
tar.close()
with open(bfilename, "rb") as compressed_file:
bin_output = compressed_file.read()
cid = self.xmpp_bot['xep_0231'].set_bob(bin_output, bfilemime)
msg = self.xmpp_bot.Message()
msg['to'] = self.get_xmpp_server_full_jid()
msg['bob']['cid'] = cid
msg['bob']['type'] = bfilemime
msg['bob']['data'] = bin_output
msg.send()
if removearch == True:
os.remove(bfilename)
def upload_image(self, filename, mimetype='image/png', message=None):
m = self.xmpp_bot.Message()
m['to'] = self.get_xmpp_server_full_jid()
m['type'] = 'chat'
with open(filename, 'rb') as img_file:
img = img_file.read()
if img:
cid = self.xmpp_bot['xep_0231'].set_bob(img, mimetype)
if message:
m['body'] = message
m['html']['body'] = '<img src="cid:%s" />' % cid
m.send()

Related

Send html with embedded images in Python

I want to send html with images embedded but I get received my images as attachments.
This is my code:
msg_root = MIMEMultipart('related')
msg_root['From'] = username
msg_root['To'] = receiver
msg_root['Subject'] = data_contacts[1][i]
msg_root.preamble = data_contacts[2][i]
msg_alternative = MIMEMultipart('alternative')
msg_root.attach(msg_alternative)
with open(f'{data_contacts[3][i]}.html', 'r') as file:
contents = file.readlines()
contents = ''.join(contents)
pattern = r'src="(.*?)"'
match = set(findall(pattern, contents))
ids = {}
for index, path in enumerate(match):
ids[path] = f"image_{index}"
for path in match:
contents = sub(rf"{path}", rf"cid:{ids[path]}", contents)
with open(f'{data_contacts[3][i]}_modified.html', 'w') as file:
file.write(contents)
print(contents)
msg_text = MIMEText(contents, 'html')
msg_alternative.attach(msg_text)
self.message_label.setText(f'Sending to...({i+1}/{len(data_contacts[0])})')
sleep(t)
list_images = listdir('images')
for image in list_images:
with open(f'images/{image}', 'rb') as file:
msgImage = MIMEImage(file.read())
path = f'images/{image}'
try:
print(f'f: {ids[path]}')
msgImage.add_header('Content-ID', f'<{ids[path]}>')
msgImage.add_header('Content-Disposition', 'inline', filename=path)
msg_root.attach(msgImage)
except:
get_exception()
smtp.sendmail(username, receiver, msg_root.as_string())
self.message_label.setText('Sent')
sleep(t)
self.notifyProgress.emit(int((i+1)*100/(len(data_contacts[0]))))
Tried to use MIMEMultipart('alternative'), to attach the html right away after defining msg_root multipart. Nothing worked. The funny part is that it worked in the past, don't remember if with exactly same code, maybe little changes, but worked, do i miss smth ?
My html is:
<html>
<body>
<image src="images/background.png">
</body>
</html>
And what i receive as email:

How do I download videos from Pexels API?

I have this code that can pull images off of Pexels, but I don't know how to change it to video. I haven't seen anyone do this before and any help greatly appreciated. I tried switching all the photo tags to videos but that seemed not to work. I've also tried adding more libraries but that doesn't seem to work either.
import argparse
import json
import os
import time
import requests
import tqdm
from pexels_api import API
PEXELS_API_KEY = os.environ['PEXELS_KEY']
MAX_IMAGES_PER_QUERY = 100
RESULTS_PER_PAGE = 10
PAGE_LIMIT = MAX_IMAGES_PER_QUERY / RESULTS_PER_PAGE
def get_sleep(t):
def sleep():
time.sleep(t)
return sleep
def main(args):
sleep = get_sleep(args.sleep)
api = API(PEXELS_API_KEY)
query = args.query
page = 1
counter = 0
photos_dict = {}
# Step 1: Getting urls and meta information
while page <= PAGE_LIMIT:
api.search(query, page=page, results_per_page=RESULTS_PER_PAGE)
photos = api.get_entries()
for photo in tqdm.tqdm(photos):
photos_dict[photo.id] = vars(photo)['_Photo__photo']
counter += 1
if not api.has_next_page:
break
page += 1
sleep()
print(f"Finishing at page: {page}")
print(f"Images were processed: {counter}")
# Step 2: Downloading
if photos_dict:
os.makedirs(args.path, exist_ok=True)
# Saving dict
with open(os.path.join(args.path, f'{query}.json'), 'w') as fout:
json.dump(photos_dict, fout)
for val in tqdm.tqdm(photos_dict.values()):
url = val['src'][args.resolution]
fname = os.path.basename(val['src']['original'])
image_path = os.path.join(args.path, fname)
if not os.path.isfile(image_path): # ignore if already downloaded
response = requests.get(url, stream=True)
with open(image_path, 'wb') as outfile:
outfile.write(response.content)
else:
print(f"File exists: {image_path}")
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--query', type=str, required=True)
parser.add_argument('--path', type=str, default='./results_pexels')
parser.add_argument('--resolution', choices=['original', 'large2x', 'large',
'medium', 'small', 'portrait',
'landscape', 'tiny'], default='original')
parser.add_argument('--sleep', type=float, default=0.1)
args = parser.parse_args()
main(args)
sorry for bumping into the question. I just faced a similar situation when downloading the videos from Pexels using the python API, pexelsPy. This may be helpful:
I retrieved the ID of the videos and then created the downloading URL that has the following structure: "https://www.pexels.com/video/"+ ID +"/download".
See the following example:
def download_video(type_of_videos):
video_tag = random.choice(type_of_videos)
PEXELS_API = '-' #please add your API Key here
api = API(PEXELS_API)
retrieved_videos = read_already_download_files('downloaded_files.txt')
video_found_flag = True
num_page = 1
while video_found_flag:
api.search_videos(video_tag, page=num_page, results_per_page=10)
videos = api.get_videos()
for data in videos:
if data.width > data.height: #look for horizontal orientation videos
if data.url not in retrieved_videos:
# write_file('downloaded_files.txt', data.url)
url_video = 'https://www.pexels.com/video/' + str(data.id) + '/download' #create the url with the video id
r = requests.get(url_video)
with open(data.url.split('/')[-2]+'.mp4', 'wb') as outfile:
outfile.write(r.content)
return data.url.split('/')[-2]+'.mp4' #download the video
num_page += 1
download_video function takes an array of strings with several tags, e.g.: ['happy','sad','relax']. Then it randomly chooses one of these tags.
PEXELS_API should contain your API Key.
read_already_download_files('downloaded_files.txt'): Retrieves already downloaded files to check if the current found file is already downloaded.
from pypexels import PyPexels
import requests
api_key = 'api id'
# instantiate PyPexels object
py_pexel = PyPexels(api_key=api_key)
search_videos_page = py_pexel.videos_search(query="love", per_page=40)
# while True:
for video in search_videos_page.entries:
print(video.id, video.user.get('name'), video.url)
data_url = 'https://www.pexels.com/video/' + str(video.id) + '/download'
r = requests.get(data_url)
print(r.headers.get('content-type'))
with open('sample.mp4', 'wb') as outfile:
outfile.write(r.content)
# if not search_videos_page.has_next:
break
# search_videos_page = search_videos_page.get_next_page()
I just tried to do the same. When I was looking for it, I wanted a simple example. All other fancy stuff I was sure I could add myself. So, I built upon inou's answer. The shown example is very basic and requests one page with only 5 results using the 'Tiger' tag in the search query. I download the first video using its id provided by the response and simply write it to the source folder. The api is provided by pexelsPy and the request is executed using the standard requests package. To get access to the API, you need to create a key on pexels website (see here). Once you get your own API key, you should be able to simply substitute the shown example key and run the code as a test.
import pexelsPy
import requests
PEXELS_API = '16gv62567257256iu78krtuzwqsddudrtjberzabzwzjsrtgswnr'
api = pexelsPy.API(PEXELS_API)
api.search_videos('Tiger', page=1, results_per_page=5)
videos = api.get_videos()
url_video = 'https://www.pexels.com/video/' + str(videos[0].id) + '/download'
r = requests.get(url_video)
with open('test.mp4', 'wb') as outfile:
outfile.write(r.content)
You can download multiple videos with this code :
import pexelsPy
import requests
PEXELS_API = '-'
api = pexelsPy.API(PEXELS_API)
api.search_videos('nature', page=2, results_per_page=100, orientation='landscape')
videos = api.get_videos()
for i, video in enumerate(videos):
url_video = 'https://www.pexels.com/video/' + str(video.id) + '/download'
r = requests.get(url_video)
with open(f'test_{i}.mp4', 'wb') as outfile:
outfile.write(r.content)
This will download 100 videos, with each video being written to a separate file named test_0.mp4, test_1.mp4, ..., test_99.mp4.

YouTube video Downloader python

I made a youtube video download Manager. It download a video but i am facing one issue when i download same video, it doesn't download it again. how can i download it again with same title like pic.png and send pic1.png. How can i do that?
def Download(self):
video_url = self.lineEdit.text()
save_location = self.lineEdit_2.text()
if video_url == '' or save_location == '':
QMessageBox.warning(self, "Data Error", "Provide a Valid Video URL or save Location")
else:
video = pafy.new(video_url)
video_stream = video.streams
video_quality = self.comboBox.currentIndex()
download = video_stream[video_quality].download(filepath=save_location, callback=self.Handel_Progress, )
Ok, this one is interesting.
The real problem begins here.
download = video_stream[video_quality].download(filepath=save_location, callback=self.Handel_Progress, )
Here, you are calling download function of video_stream object which takes filepath as an argument for file location but does not take the filename, because, obviously, the file would be saved with the actual name.
Root Cause of your problem:
If you look into the definition of download function, you would find that if a file exists with the same name, it would not download the file at all.
Now comes the part, how do you make sure it downloads, no matter what:
There are two things you need to do:
Check if a file with same name exists or not, and if does, then add 1 in the end of the file name just before the extension. So if abc.mp4 exists, then save abc1.mp4.
[I will tell you how to handle the scenario when abc.mp4, abc1.mp4 and so on exists, but for now, let's get back to the problem.]
How to pass the file name (abc1.mp4) to the download method?
Following piece of code would handle both.
I have added comments for your understanding.
import os
import re
import pafy
from pafy.util import xenc
# this function is used by pafy to generate file name while saving,
# so im using the same function to get the file name which I will use to check
# if file exists or not
# DO NOT CHANGE IT
def generate_filename(title, extension):
max_length = 251
""" Generate filename. """
ok = re.compile(r'[^/]')
if os.name == "nt":
ok = re.compile(r'[^\\/:*?"<>|]')
filename = "".join(x if ok.match(x) else "_" for x in title)
if max_length:
max_length = max_length + 1 + len(extension)
if len(filename) > max_length:
filename = filename[:max_length - 3] + '...'
filename += "." + extension
return xenc(filename)
def get_file_name_for_saving(save_location, full_name):
file_path_with_name = os.path.join(save_location, full_name)
# file exists, add 1 in the end, otherwise return filename as it is
if os.path.exists(file_path_with_name):
split = file_path_with_name.split(".")
file_path_with_name = ".".join(split[:-1]) + "1." + split[-1]
return file_path_with_name
def Download(self):
video_url = self.lineEdit.text()
save_location = self.lineEdit_2.text()
if video_url == '' or save_location == '':
QMessageBox.warning(self, "Data Error", "Provide a Valid Video URL or save Location")
else:
# video file
video = pafy.new(video_url)
# available video streams
video_stream = video.streams
video_quality = self.comboBox.currentIndex()
# video title/name
video_name = video.title
# take out the extension of the file from video stream
extension = video_stream[video_quality].extension
# fullname with extension
full_name = generate_filename(video_name, extension)
final_path_with_file_name = get_file_name_for_saving(save_location, full_name)
download = video_stream[video_quality].download(filepath=final_path_with_file_name,
callback=self.Handel_Progress, )
Let me know if you face any issues.

Why can't I upload a glitched image to Tumblr with Python?

My goal is to have a program that downloads an image, glitches it and then uploads the glitched image. So far my code looks like this:
import urllib
import random
import pytumblr
from tumblr_keys import
from BeautifulSoup import BeautifulStoneSoup
# Authenticate via OAuth
client = pytumblr.TumblrRestClient(
consumer_key,
consumer_secret,
token_key,
token_secret
)
def download_an_image(image_url):
filename = image_url.split('/')[-1]
#filefinal = filename[:-4 ] + '.png'
urllib.urlretrieve(image_url, filename)
return filename
def get_random_start_and_end_points_in_file(file_data):
start_point = random.randint(2600, len(file_data))
end_point = start_point + random.randint(0, len(file_data) - start_point)
return start_point, end_point
def splice_a_chunk_in_a_file(file_data):
start_point, end_point = get_random_start_and_end_points_in_file(file_data)
section = file_data[start_point:end_point]
repeated = ''
for i in range(1, random.randint(1,2)):
repeated += section
new_start_point, new_end_point = get_random_start_and_end_points_in_file(file_data)
file_data = file_data[:new_start_point] + repeated + file_data[new_end_point:]
return file_data
def glitch_an_image(local_image):
file_handler = open(local_image, 'r')
file_data = file_handler.read()
file_handler.close()
for i in range(1, random.randint(0,2)):
file_data = splice_a_chunk_in_a_file(file_data)
file_handler = open(local_image, 'w')
file_handler.write(file_data)
file_handler.close
return local_image
if __name__ == '__main__':
image_url = "https://41.media.tumblr.com/179e82abf626f870cb0b8fe93919eb67/tumblr_o4t9wtxwO31vq0p00o1_1280.png"
local_image = download_an_image(image_url)
image_glitch_file = glitch_an_image(local_image)
client.create_photo('glitchingimages', state="published", tags=["glitch"], data= image_glitch_file)
To make sure the downloaded picture is always saved as a .png-file I tried running the second line in the "def download_an_image(image_url):" section. For some reason, Tumblr still would not let me upload the glitched image. I even tried uploading it and it gave me an error. But I was able to upload it to Flickr. Only if I export the .png-file as .png again, I can upload it to Tumblr.
Do you know a way to avoid exporting the image manually? Is there maybe a better way to make sure the downloaded image is save as a .png-file?
Thank you!

PYTHON/OUTLOOK Sending e-mails through PYTHON with DOCX

I have to send mails through python. It works. It is almost done. The only problem is that I have to keep the formatting too. So either I have to send e mail as HTML (and then rewrite template with html instead of .docx) OR copy .docx file with extension
Anybody has any ideas how to do this? Thanks guys.
import win32com.client as win32
import fileinput as fi
from docx import Document
outlook = win32.Dispatch('outlook.application')
path_in = 'maillist.csv'
input_file = open(path_in, 'r')
document = Document('template.docx')
document_html = open('template.html', 'r')
print(temp)
def filecount(fname):
for line in fi.input(fname):
pass
return fi.lineno()
print("Total mails %s" % (filecount(path_in)))
count = 0
for line in input_file:
if (count>16):
name = line.split(";")[0]
mail_adress = line.split(";")[1]
subject = line.split(";")[2]
print ("%s:%s:%s:" % (name, mail_adress, subject))
mail = outlook.CreateItem(0)
mail.To = mail_adress
mail.Subject = subject
mail.body = temp.replace("XXXNAMEXXX", name)
mail.send
else:
count+=1
Try adding the .RTFBody and/or .HTMLBody methods to the document objects :
document = Document('template.docx').RTFBody
document_html = open('template.html', 'r').HTMLBody
Also, I'm not sure if it makes much of a difference but, for convention's sake, I like to capitalize the first letter of the method for the mailItem object.
Let me know if that works.

Categories