diff --git a/templates/user.html b/templates/user.html new file mode 100644 index 0000000..cf89445 --- /dev/null +++ b/templates/user.html @@ -0,0 +1,19 @@ +{% extends 'base.html' %} +{% block head %} + + + + + + + + + + + + + + + + + {% 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_api.py b/test_api.py index c0f24cf..58e752a 100644 --- a/test_api.py +++ b/test_api.py @@ -35,4 +35,10 @@ def test_api_include_rtf_nomedia(): resp = client.get(testMediaTweet.replace("https://twitter.com","https://api.vxtwitter.com")+"?include_rtf=ifnomedia",headers={"User-Agent":"test"}) jData = resp.get_json() assert resp.status_code==200 - assert not any(".rtf" in i for i in jData["mediaURLs"]) \ No newline at end of file + assert not any(".rtf" in i for i in jData["mediaURLs"]) + +def test_api_user(): + resp = client.get(testUser.replace("https://twitter.com","https://api.vxtwitter.com")+"?include_rtf=true",headers={"User-Agent":"test"}) + jData = resp.get_json() + assert resp.status_code==200 + assert jData["screen_name"]=="jack" \ No newline at end of file diff --git a/test_vx_embeds.py b/test_vx_embeds.py index d23f744..67fa44d 100644 --- a/test_vx_embeds.py +++ b/test_vx_embeds.py @@ -40,6 +40,11 @@ def test_embed_FromScratch(): client.get(testMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"}) client.get(testMultiMediaTweet.replace("https://twitter.com",""),headers={"User-Agent":"test"}) +def test_embed_User(): + cache.clearCache() + resp = client.get(testUser.replace("https://twitter.com",""),headers={"User-Agent":"test"}) + assert resp.status_code==200 + def test_embed_FromCache(): cache.clearCache() twitfix.getTweetData(testTextTweet) diff --git a/twitfix.py b/twitfix.py index 8bc082a..ca46813 100644 --- a/twitfix.py +++ b/twitfix.py @@ -16,7 +16,7 @@ import twExtract as twExtract from cache import addVnfToLinkCache,getVnfFromLinkCache import vxlogging as log from utils import getTweetIdFromUrl, pathregex -from vxApi import getApiResponse +from vxApi import getApiResponse, getApiUserResponse from urllib.parse import urlparse from PyRTF.Elements import Document from PyRTF.document.section import Section @@ -138,6 +138,17 @@ def renderArticleTweetEmbed(tweetData,appnameSuffix=""): color=config['config']['color'] ) +def renderUserEmbed(userData,appnameSuffix=""): + return render_template("user.html", + user=userData, + host=config['config']['url'], + desc=userData["description"], + urlEncodedDesc=urllib.parse.quote(userData["description"]), + link=f'https://twitter.com/{userData["screen_name"]}', + appname=config['config']['appname'], + color=config['config']['color'] + ) + @app.route('/robots.txt') def robots(): return "User-agent: *\nDisallow: /" @@ -181,6 +192,11 @@ def getTweetData(twitter_url,include_txt="false",include_rtf="false"): addVnfToLinkCache(twitter_url,tweetData) return tweetData +def getUserData(twitter_url): + rawUserData = twExtract.extractUser(twitter_url,workaroundTokens=config['config']['workaroundTokens'].split(',')) + userData = getApiUserResponse(rawUserData) + return userData + def determineEmbedTweet(tweetData): # Determine which tweet, i.e main or QRT, to embed the media from. # if there is no QRT, return the main tweet => default behavior @@ -196,6 +212,7 @@ def determineEmbedTweet(tweetData): @app.route('/') # Default endpoint used by everything def twitfix(sub_path): + isApiRequest=request.url.startswith("https://api.vx") or request.url.startswith("http://api.vx") if sub_path in staticFiles: if 'path' not in staticFiles[sub_path] or staticFiles[sub_path]["path"] == None: staticFiles[sub_path]["path"] = sub_path @@ -204,9 +221,26 @@ def twitfix(sub_path): sub_path = "i/" + sub_path match = pathregex.search(sub_path) if match is None: + # test for .com/username + if sub_path.count("/") == 0: + username=sub_path + extra=None + else: + # get first subpath + username=sub_path.split("/")[0] + extra = sub_path.split("/")[1] + if extra in [None,"with_replies","media","likes","highlights","superfollows","media"] and username != "" and username != None: + userData = getUserData(f"https://twitter.com/{username}") + if isApiRequest: + if userData is None: + abort(404) + return userData + else: + if userData is None: + return message(msgs.failedToScan) + return renderUserEmbed(userData) abort(404) twitter_url = f'https://twitter.com/i/status/{getTweetIdFromUrl(sub_path)}' - isApiRequest=request.url.startswith("https://api.vx") or request.url.startswith("http://api.vx") include_txt="false" include_rtf="false" diff --git a/vxApi.py b/vxApi.py index 726dec2..b183ffc 100644 --- a/vxApi.py +++ b/vxApi.py @@ -3,6 +3,21 @@ from datetime import datetime from configHandler import config from utils import stripEndTCO +def getApiUserResponse(user): + return { + "id": user["id"], + "screen_name": user["screen_name"], + "name": user["name"], + "profile_image_url": user["profile_image_url_https"], + "description": user["description"], + "location": user["location"], + "followers_count": user["followers_count"], + "following_count": user["friends_count"], + "tweet_count": user["statuses_count"], + "created_at": user["created_at"], + "protected": user["protected"], + } + def getApiResponse(tweet,include_txt=False,include_rtf=False): tweetL = tweet["legacy"] if "user_result" in tweet["core"]: