From 39a9ffd5120f7d28711e071290ee00d495a477ef Mon Sep 17 00:00:00 2001 From: Dylan Date: Wed, 25 May 2022 00:49:22 +0100 Subject: [PATCH] Method to embed combined tweet images. WIP & may be CPU intensive --- combineImg.py | 13 +++++++- twitfix.py | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 2 deletions(-) diff --git a/combineImg.py b/combineImg.py index 3116c21..cf51bba 100644 --- a/combineImg.py +++ b/combineImg.py @@ -1,4 +1,6 @@ from PIL import Image, ImageOps, ImageFilter +import requests +from io import BytesIO # find the highest res image in an array of images def findImageWithMostPixels(imageArray): @@ -79,4 +81,13 @@ def genImage(imageArray): combined = combineImages(imageArray, *getTotalImgSize(imageArray)) combinedBG = combineImages(imageArray, *getTotalImgSize(imageArray),False) combinedBG = blurImage(combinedBG,50) - return Image.alpha_composite(combinedBG,combined) \ No newline at end of file + return Image.alpha_composite(combinedBG,combined) + +def genImageFromURL(urlArray): + # this method avoids storing the images in disk, instead they're stored in memory + # no cache means that they'll have to be downloaded again if the image is requested again + # TODO: cache? + imageArray = [] + for url in urlArray: + imageArray.append(Image.open(BytesIO(requests.get(url).content))) + return genImage(imageArray) \ No newline at end of file diff --git a/twitfix.py b/twitfix.py index b842cb8..79569c7 100644 --- a/twitfix.py +++ b/twitfix.py @@ -1,4 +1,4 @@ -from flask import Flask, render_template, request, redirect, Response, send_from_directory, url_for, send_file, make_response, jsonify +from flask import Flask, render_template, request, redirect, abort, Response, send_from_directory, url_for, send_file, make_response, jsonify from flask_cors import CORS import youtube_dl import textwrap @@ -10,7 +10,9 @@ import re import os import urllib.parse import urllib.request +import combineImg from datetime import date,datetime, timedelta +from io import BytesIO app = Flask(__name__) CORS(app) @@ -123,7 +125,14 @@ def twitfix(sub_path): else: print(" āž¤ [ R ] Redirect to MP4 using d.fxtwitter.com") return dir(sub_path) + elif request.url.startswith("https://c.vx"): + twitter_url = sub_path + if match.start() == 0: + twitter_url = "https://twitter.com/" + sub_path + + if user_agent in generate_embed_user_agents: + return embedCombined(twitter_url) elif request.url.endswith(".mp4") or request.url.endswith("%2Emp4"): twitter_url = "https://twitter.com/" + sub_path @@ -205,6 +214,23 @@ def favicon(): return send_from_directory(os.path.join(app.root_path, 'static'), 'favicon.ico',mimetype='image/vnd.microsoft.icon') +@app.route("/rendercombined.png") +def rendercombined(): + # get "imgs" from request arguments + imgs = request.args.get("imgs", "") + imgs = imgs.split(",") + if (len(imgs) == 0 or len(imgs)>4): + abort(400) + #check that each image starts with "https://pbs.twimg.com" + for img in imgs: + if not img.startswith("https://pbs.twimg.com"): + abort(400) + finalImg= combineImg.genImageFromURL(imgs) + imgIo = BytesIO() + finalImg.save(imgIo, 'PNG') + imgIo.seek(0) + return send_file(imgIo, mimetype='image/png') + def getDefaultTTL(): return datetime.today().replace(microsecond=0) + timedelta(days=1) @@ -489,6 +515,68 @@ def embed(video_link, vnf, image): urlLink = urlLink, tweetLink = vnf['tweet'] ) + +def embedCombined(video_link): + cached_vnf = getVnfFromLinkCache(video_link) + + if cached_vnf == None: + try: + vnf = link_to_vnf(video_link) + addVnfToLinkCache(video_link, vnf) + return embedCombinedVnf(video_link, vnf) + + except Exception as e: + print(e) + return message("Failed to scan your link! This may be due to an incorrect link, private account, or the twitter API itself might be having issues (Check here: https://api.twitterstat.us/)") + else: + return embedCombinedVnf(video_link, cached_vnf) + +def embedCombinedVnf(video_link,vnf): + if vnf['type'] != "Image": + return embed(video_link, vnf, 0) + desc = re.sub(r' http.*t\.co\S+', '', vnf['description']) + urlUser = urllib.parse.quote(vnf['uploader']) + urlDesc = urllib.parse.quote(desc) + urlLink = urllib.parse.quote(video_link) + likeDisplay = ("\n\nšŸ’– " + str(vnf['likes']) + " šŸ” " + str(vnf['rts']) + "\n") + + if vnf['qrt'] == {}: # Check if this is a QRT and modify the description + desc = (desc + likeDisplay) + else: + qrtDisplay = ("\nā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€\n āž¤ QRT of " + vnf['qrt']['handle'] + " (@" + vnf['qrt']['screen_name'] + "):\nā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€\n'" + vnf['qrt']['desc'] + "'") + desc = (desc + qrtDisplay + likeDisplay) + + color = "#7FFFD4" # Green + + if vnf['nsfw'] == True: + color = "#800020" # Red + image = "https://vxtwitter.com/rendercombined.png?imgs=" + for i in range(0,int(vnf['images'][4])): + image = image + vnf['images'][i] + "," + image = image[:-1] # Remove last comma + return render_template( + 'image.html', + likes = vnf['likes'], + rts = vnf['rts'], + time = vnf['time'], + screenName = vnf['screen_name'], + vidlink = vnf['url'], + pfp = vnf['pfp'], + vidurl = vnf['url'], + desc = desc, + pic = image, + user = vnf['uploader'], + video_link = video_link, + color = color, + appname = config['config']['appname'], + repo = config['config']['repo'], + url = config['config']['url'], + urlDesc = urlDesc, + urlUser = urlUser, + urlLink = urlLink, + tweetLink = vnf['tweet'] ) + + def tweetType(tweet): # Are we dealing with a Video, Image, or Text tweet? if 'extended_entities' in tweet: if 'video_info' in tweet['extended_entities']['media'][0]: