From 0858f6263b626c6252dd6e5d92f8cd8813e85598 Mon Sep 17 00:00:00 2001 From: Dylan Date: Thu, 2 May 2024 19:15:14 +0100 Subject: [PATCH] Bugfixes and more tests --- msgs.py | 5 ++- templates/video.html | 2 +- test_vx_embeds.py | 83 ++++++++++++++++++++++++++++++++++++++++++-- testgen.py | 3 +- twitfix.py | 30 ++++++++++++---- vxApi.py | 4 ++- vx_testdata.py | 2 ++ 7 files changed, 114 insertions(+), 15 deletions(-) diff --git a/msgs.py b/msgs.py index 8194a93..9704de8 100644 --- a/msgs.py +++ b/msgs.py @@ -30,9 +30,8 @@ def formatEmbedDesc(type,body,qrt,pollDisplay,likesDisplay): # Trim the embed description to 248 characters, prioritizing poll and likes qrtType=None - #if qrt!=None: - # qrtType=qrt["type"] - qrtType="Text" + if qrt!=None: + qrtType="Text" limit = videoDescLimit if type=="Text" or type=="Video" or (qrt!=None and (qrtType=="Text" or qrtType=="Video")) else tweetDescLimit diff --git a/templates/video.html b/templates/video.html index 825903e..04fa08a 100644 --- a/templates/video.html +++ b/templates/video.html @@ -18,5 +18,5 @@ - + {% endblock %} {% block body %} Redirecting you to the tweet in a moment. Or click here. {% endblock %} \ No newline at end of file diff --git a/test_vx_embeds.py b/test_vx_embeds.py index 06f2f9b..278045b 100644 --- a/test_vx_embeds.py +++ b/test_vx_embeds.py @@ -62,11 +62,53 @@ def test_embed_Suggestive(): assert "so i had a bot generate it for me" in str(resp.data) assert "FfF_gKwXgAIpnpD" in str(resp.data) -def test_embed_direct(): +def test_embed_video_direct(): resp = client.get(testVideoTweet.replace("https://twitter.com","")+".mp4",headers={"User-Agent":"test"}) assert resp.status_code==200 assert testVideoTweet_compare["mediaURLs"][0] in str(resp.data) +def test_embed_video_direct_subdomain(): + resp = client.get(testVideoTweet.replace("https://twitter.com","https://d.vxtwitter.com"),headers={"User-Agent":"test"}) + assert resp.status_code==200 + assert testVideoTweet_compare["mediaURLs"][0] in str(resp.data) + +def test_embed_img_direct(): + resp = client.get(testMediaTweet.replace("https://twitter.com","")+".png",headers={"User-Agent":"test"}) + assert resp.status_code==302 + assert testMediaTweet_compare["mediaURLs"][0] in str(resp.data) + +def test_embed_img_direct_subdomain(): + resp = client.get(testMediaTweet.replace("https://twitter.com","https://d.vxtwitter.com"),headers={"User-Agent":"test"}) + assert resp.status_code==302 + assert testMediaTweet_compare["mediaURLs"][0] in str(resp.data) + +def test_embed_multi_direct(): + # embed first item + resp = client.get(testMultiMediaTweet.replace("https://twitter.com","")+"/1.png",headers={"User-Agent":"test"}) + assert resp.status_code==302 # images should redirect + assert testMultiMediaTweet_compare["mediaURLs"][0] in str(resp.data) + + # embed second item + resp = client.get(testMultiMediaTweet.replace("https://twitter.com","")+"/2.mp4",headers={"User-Agent":"test"}) + assert resp.status_code==302 # images should redirect + assert testMultiMediaTweet_compare["mediaURLs"][1] in str(resp.data) + +def test_embed_multi_direct_subdomain(): + # generic embed + resp = client.get(testMultiMediaTweet.replace("https://twitter.com","https://d.vxtwitter.com"),headers={"User-Agent":"test"}) + assert resp.status_code==302 # images should redirect + assert testMultiMediaTweet_compare["mediaURLs"][0] in str(resp.data) + + # embed first item + resp = client.get(testMultiMediaTweet.replace("https://twitter.com","https://d.vxtwitter.com")+"/1",headers={"User-Agent":"test"}) + assert resp.status_code==302 # images should redirect + assert testMultiMediaTweet_compare["mediaURLs"][0] in str(resp.data) + + # embed second item + resp = client.get(testMultiMediaTweet.replace("https://twitter.com","https://d.vxtwitter.com")+"/2",headers={"User-Agent":"test"}) + assert resp.status_code==302 # images should redirect + assert testMultiMediaTweet_compare["mediaURLs"][1] in str(resp.data) + def test_embed_message404(): resp = client.get("https://twitter.com/jack/status/12345",headers={"User-Agent":"test"}) assert resp.status_code==200 @@ -79,4 +121,41 @@ def test_combine(): resp = client.get(f"/rendercombined.jpg?imgs={img1},{img2}",headers={"User-Agent":"test"}) assert resp.status_code==200 assert resp.headers["Content-Type"]=="image/jpeg" - assert len(resp.data)>1000 \ No newline at end of file + assert len(resp.data)>1000 + +def test_embed_combined(): + twt = twitfix.getTweetData(testMultiMediaTweet) + img1 = twt["mediaURLs"][0] + img2 = twt["mediaURLs"][1] + resp = client.get(testMultiMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"}) + assert resp.status_code==200 + assert f"/rendercombined.jpg?imgs={img1},{img2}" in str(resp.data) + +def test_embed_multimedia_single(): + twt = twitfix.getTweetData(testMultiMediaTweet) + img1 = twt["mediaURLs"][0] + img2 = twt["mediaURLs"][1] + resp = client.get(testMultiMediaTweet.replace("https://twitter.com","")+"/1",headers={"User-Agent":"test"}) + assert resp.status_code==200 + assert img1 in str(resp.data) and img2 not in str(resp.data) + resp = client.get(testMultiMediaTweet.replace("https://twitter.com","")+"/2",headers={"User-Agent":"test"}) + assert resp.status_code==200 + assert img1 not in str(resp.data) and img2 in str(resp.data) + +def test_embed_mixedMedia(): + twt = twitfix.getTweetData(testMixedMediaTweet) + img1 = twt["mediaURLs"][0] + img2 = twt["mediaURLs"][1] + resp = client.get(testMixedMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"}) + + # Check for default behavior with no index + assert resp.status_code==200 + assert img1 in str(resp.data) and img2 not in str(resp.data) + assert "Media 1/2" in str(resp.data) # make sure user knows there are multiple media + + resp = client.get(testMixedMediaTweet.replace("https://twitter.com","")+"/1",headers={"User-Agent":"test"}) + assert resp.status_code==200 + assert img1 in str(resp.data) and img2 not in str(resp.data) + resp = client.get(testMixedMediaTweet.replace("https://twitter.com","")+"/2",headers={"User-Agent":"test"}) + assert resp.status_code==200 + assert img1 not in str(resp.data) and img2 in str(resp.data) \ No newline at end of file diff --git a/testgen.py b/testgen.py index 9afef30..bb15c5c 100644 --- a/testgen.py +++ b/testgen.py @@ -9,7 +9,8 @@ tests = { "testQrtCeptionTweet":"https://twitter.com/CatherineShu/status/585253766271672320", "testQrtVideoTweet":"https://twitter.com/pdxdylan/status/1674561759422578690", "testNSFWTweet":"https://twitter.com/kuyacoy/status/1581185279376838657", - "testPollTweet": "https://twitter.com/norm/status/651169346518056960" + "testPollTweet": "https://twitter.com/norm/status/651169346518056960", + "testMixedMediaTweet":"https://twitter.com/bigbeerfest/status/1760638922084741177", } def getVNFFromLink(link): diff --git a/twitfix.py b/twitfix.py index 938d55c..f60ec04 100644 --- a/twitfix.py +++ b/twitfix.py @@ -156,16 +156,28 @@ def twitfix(sub_path): if 'qrtURL' in tweetData and tweetData['qrtURL'] is not None: qrt = getTweetData(tweetData['qrtURL']) tweetData['qrt'] = qrt - ###return tweetData + + if '?' in request.url: + requestUrlWithoutQuery = request.url.split("?")[0] + else: + requestUrlWithoutQuery = request.url + + directEmbed=False + if requestUrlWithoutQuery.startswith("https://d.vx") or requestUrlWithoutQuery.endswith(".mp4") or requestUrlWithoutQuery.endswith(".png"): + directEmbed = True + # remove the .mp4 from the end of the URL + if requestUrlWithoutQuery.endswith(".mp4") or requestUrlWithoutQuery.endswith(".png"): + sub_path = sub_path[:-4] embedIndex = -1 # if url ends with /1, /2, /3, or /4, we'll use that as the index if sub_path[-2:] in ["/1","/2","/3","/4"]: embedIndex = int(sub_path[-1])-1 sub_path = sub_path[:-2] + if request.url.startswith("https://api.vx"): # Directly return the API response if the request is from the API return tweetData - elif request.url.startswith("https://d.vx"): # direct embed + elif directEmbed: # direct embed # direct embeds should always prioritize the main tweet, so don't check for qrt # determine what type of media we're dealing with if not tweetData['hasMedia'] and qrt is None: @@ -179,8 +191,8 @@ def twitfix(sub_path): media = tweetData['media_extended'][embedIndex] if media['type'] == "image": return redirect(media['url'], 302) - elif media['type'] == "video" or media['type'] == "animated_gif": - return redirect(media['url'], 302) # TODO: might not work + elif media['type'] == "video" or media['type'] == "gif": + return render_template("rawvideo.html",media=media) else: # full embed embedTweetData = determineEmbedTweet(tweetData) if not embedTweetData['hasMedia']: @@ -192,10 +204,14 @@ def twitfix(sub_path): if embedIndex == -1: # if the user didn't specify an index, we'll just use the first one embedIndex = 0 media = embedTweetData['media_extended'][embedIndex] + if len(embedTweetData["media_extended"]) > 1: + suffix = f' - Media {embedIndex+1}/{len(embedTweetData["media_extended"])}' + else: + suffix = '' if media['type'] == "image": - return renderImageTweetEmbed(tweetData,media['url'] , appnameSuffix=f' - Media {embedIndex+1}/{len(embedTweetData["media_extended"])}') - elif media['type'] == "video" or media['type'] == "animated_gif": - return renderVideoTweetEmbed(tweetData,media) + return renderImageTweetEmbed(tweetData,media['url'] , appnameSuffix=suffix) + elif media['type'] == "video" or media['type'] == "gif": + return renderVideoTweetEmbed(tweetData,media,appnameSuffix=suffix) return tweetData diff --git a/vxApi.py b/vxApi.py index b8120cf..7a3d39d 100644 --- a/vxApi.py +++ b/vxApi.py @@ -98,9 +98,11 @@ def getApiResponse(tweet,include_txt=False,include_zip=False): if i["type"] != media_extended[0]["type"]: sameMedia = False break + else: + sameMedia = True combinedMediaUrl = None - if sameMedia and media_extended[0]["type"] == "image": + if sameMedia and media_extended[0]["type"] == "image" and len(media) > 1: host=config['config']['url'] combinedMediaUrl = f'{host}/rendercombined.jpg?imgs=' for i in media: diff --git a/vx_testdata.py b/vx_testdata.py index eccc5ba..5035d12 100644 --- a/vx_testdata.py +++ b/vx_testdata.py @@ -10,6 +10,7 @@ testQrtCeptionTweet="https://twitter.com/CatherineShu/status/585253766271672320" testQrtVideoTweet="https://twitter.com/pdxdylan/status/1674561759422578690" testNSFWTweet="https://twitter.com/kuyacoy/status/1581185279376838657" testPollTweet="https://twitter.com/norm/status/651169346518056960" +testMixedMediaTweet="https://twitter.com/bigbeerfest/status/1760638922084741177" testTextTweet_compare={'text': 'just setting up my twttr', 'date': 'Tue Mar 21 20:50:14 +0000 2006', 'tweetURL': 'https://twitter.com/jack/status/20', 'tweetID': '20', 'conversationID': '20', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1142974214} testVideoTweet_compare={'text': 'TikTok embeds on Discord/Telegram bait you with a fake play button, but to see the actual video you have to go to their website.\nAs a request from a friend, I made it so that if you add "vx" before "tiktok" on any link, it fixes that. https://t.co/QYpiVXUIrW', 'date': 'Fri Jun 24 18:17:31 +0000 2022', 'tweetURL': 'https://twitter.com/pdxdylan/status/1540398733669666818', 'tweetID': '1540398733669666818', 'conversationID': '1540398733669666818', 'mediaURLs': ['https://video.twimg.com/ext_tw_video/1540396699037929472/pu/vid/762x528/YxbXbT3X7vq4LWfC.mp4?tag=12'], 'media_extended': [{'url': 'https://video.twimg.com/ext_tw_video/1540396699037929472/pu/vid/762x528/YxbXbT3X7vq4LWfC.mp4?tag=12', 'type': 'video', 'size': {'width': 762, 'height': 528}, 'duration_millis': 13650, 'thumbnail_url': 'https://pbs.twimg.com/ext_tw_video_thumb/1540396699037929472/pu/img/l187Z6B9AHHxUKPV.jpg', 'altText': None}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1656094651} @@ -20,6 +21,7 @@ testQrtCeptionTweet_compare={'text': 'Testing retweetception ', 'date': 'Tue Apr testQrtVideoTweet_compare={'text': 'good', 'date': 'Thu Jun 29 23:33:29 +0000 2023', 'tweetURL': 'https://twitter.com/pdxdylan/status/1674561759422578690', 'tweetID': '1674561759422578690', 'conversationID': '1674561759422578690', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': 'https://twitter.com/i/status/1674197531301904388', 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1688081609} testNSFWTweet_compare={'text': "ngl, I'm scared on finding out the cute Sprigatito's final evolution..\n\nso i had a bot generate it for me.... and I'm forever scarred https://t.co/itMay87vcS", 'date': 'Sat Oct 15 07:28:42 +0000 2022', 'tweetURL': 'https://twitter.com/kuyacoy/status/1581185279376838657', 'tweetID': '1581185279376838657', 'conversationID': '1581185279376838657', 'mediaURLs': ['https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg', 'altText': None, 'type': 'image', 'size': {'width': 760, 'height': 926}, 'thumbnail_url': 'https://pbs.twimg.com/media/FfF_gKwXgAIpnpD.jpg'}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1665818922} testPollTweet_compare={'text': 'I know when that hotline bling, that can only:', 'date': 'Mon Oct 05 22:57:25 +0000 2015', 'tweetURL': 'https://twitter.com/norm/status/651169346518056960', 'tweetID': '651169346518056960', 'conversationID': '651169346518056960', 'mediaURLs': [], 'media_extended': [], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': False, 'combinedMediaUrl': None, 'pollData': {'options': [{'name': 'Mean one thing', 'votes': 124875, 'percent': 78.82}, {'name': 'Mean multiple things', 'votes': 33554, 'percent': 21.18}]}, 'date_epoch': 1444085845} +testMixedMediaTweet_compare={'text': 'Some of us here are definitely big nerds about beer, and could talk your ear off about it for days on end, but some of us are just "beer is nice" https://t.co/6MWBUABBEc', 'date': 'Thu Feb 22 12:13:24 +0000 2024', 'tweetURL': 'https://twitter.com/bigbeerfest/status/1760638922084741177', 'tweetID': '1760638922084741177', 'conversationID': '1760638922084741177', 'mediaURLs': ['https://pbs.twimg.com/media/GG8LwfuWoAANKhs.jpg', 'https://video.twimg.com/tweet_video/GG8LwqWX0AAZch0.mp4'], 'media_extended': [{'url': 'https://pbs.twimg.com/media/GG8LwfuWoAANKhs.jpg', 'altText': None, 'type': 'image', 'size': {'width': 858, 'height': 960}, 'thumbnail_url': 'https://pbs.twimg.com/media/GG8LwfuWoAANKhs.jpg'}, {'url': 'https://video.twimg.com/tweet_video/GG8LwqWX0AAZch0.mp4', 'type': 'gif', 'size': {'width': 500, 'height': 500}, 'duration_millis': 0, 'thumbnail_url': 'https://pbs.twimg.com/tweet_video_thumb/GG8LwqWX0AAZch0.jpg', 'altText': None}], 'possibly_sensitive': False, 'hashtags': [], 'qrtURL': None, 'allSameType': False, 'hasMedia': True, 'combinedMediaUrl': None, 'pollData': None, 'date_epoch': 1708604004} testUser="https://twitter.com/jack" testUserID = "https://twitter.com/i/user/12"