Skip to content

Commit

Permalink
Poll/Votes support, closes #17
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanpdx committed Oct 2, 2022
1 parent d680579 commit 3999dbd
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 20 deletions.
35 changes: 34 additions & 1 deletion msgs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from asyncore import poll


failedToScan="Failed to scan your link! This may be due to an incorrect link, private/suspended account, deleted tweet, or Twitter itself might be having issues (Check here: https://api.twitterstat.us/)"
failedToScanExtra = "\n\nTwitter gave me this error: "
tweetNotFound="Tweet not found."
Expand All @@ -8,4 +11,34 @@ def genLikesDisplay(vnf):

def genQrtDisplay(qrt):
verifiedCheck = "☑️" if ('verified' in qrt and qrt['verified']) else ""
return ("\n─────────────\n ➤ QRT of " + qrt['handle'] + " (@" + qrt['screen_name'] + ")"+ verifiedCheck+":\n─────────────\n'" + qrt['desc'] + "'")
return ("\n─────────────\n ➤ QRT of " + qrt['handle'] + " (@" + qrt['screen_name'] + ")"+ verifiedCheck+":\n─────────────\n'" + qrt['desc'] + "'")

def genPollDisplay(poll):
pctSplit=10
output="\n\n"
for choice in poll["choices"]:
output+=choice["text"]+"\n"+("█"*int(choice["percent"]/pctSplit)) +" "+str(choice["percent"])+"%\n"
return output

def formatEmbedDesc(type,body,qrt,pollDisplay,likesDisplay):
# Trim the embed description to 248 characters, prioritizing poll and likes
output = ""
if pollDisplay==None:
pollDisplay=""

if type=="" or type=="Video":
output = body+pollDisplay
elif qrt=={}:
output= body+pollDisplay+likesDisplay
else:
qrtDisplay = genQrtDisplay(qrt)
output= body + qrtDisplay + likesDisplay
if len(output)>248:
# find out how many characters we need to remove
diff = len(output)-248
print("diff: "+str(diff))
# remove the characters from body, add ellipsis
body = body[:-(diff+1)]+"…"
return formatEmbedDesc(type,body,qrt,pollDisplay,likesDisplay)
else:
return output
18 changes: 17 additions & 1 deletion test_vx.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,23 @@
testVideoTweet="https://twitter.com/Twitter/status/1263145271946551300"
testMediaTweet="https://twitter.com/Twitter/status/1118295916874739714"
testMultiMediaTweet="https://twitter.com/Twitter/status/1293239745695211520"
testPollTweet="https://twitter.com/norm/status/651169346518056960"

textVNF_compare = {'tweet': 'https://twitter.com/jack/status/20', 'url': '', 'description': 'just setting up my twttr', 'screen_name': 'jack', 'type': 'Text', 'images': ['', '', '', '', ''], 'time': 'Tue Mar 21 20:50:14 +0000 2006', 'qrt': {}, 'nsfw': False}
videoVNF_compare={'tweet': 'https://twitter.com/Twitter/status/1263145271946551300', 'url': 'https://video.twimg.com/amplify_video/1263145212760805376/vid/1280x720/9jous8HM0_duxL0w.mp4?tag=13', 'description': 'Testing, testing...\n\nA new way to have a convo with exactly who you want. We’re starting with a small % globally, so keep your 👀 out to see it in action. https://t.co/pV53mvjAVT', 'thumbnail': 'http://pbs.twimg.com/media/EYeX7akWsAIP1_1.jpg', 'screen_name': 'Twitter', 'type': 'Video', 'images': ['', '', '', '', ''], 'time': 'Wed May 20 16:31:15 +0000 2020', 'qrt': {}, 'nsfw': False,'verified': True, 'size': {'width': 1920, 'height': 1080}}
testMedia_compare={'tweet': 'https://twitter.com/Twitter/status/1118295916874739714', 'url': '', 'description': 'On profile pages, we used to only show someone’s replies, not the original Tweet 🙄 Now we’re showing both so you can follow the conversation more easily! https://t.co/LSBEZYFqmY', 'thumbnail': 'https://pbs.twimg.com/media/D4TS4xeX4AA02DI.jpg', 'screen_name': 'Twitter', 'type': 'Image', 'images': ['https://pbs.twimg.com/media/D4TS4xeX4AA02DI.jpg', '', '', '', '1'], 'time': 'Tue Apr 16 23:31:38 +0000 2019', 'qrt': {}, 'nsfw': False, 'size': {}}
testMultiMedia_compare={'tweet': 'https://twitter.com/Twitter/status/1293239745695211520', 'url': '', 'description': 'We tested, you Tweeted, and now we’re rolling it out to everyone! https://t.co/w6Q3Q6DiKz', 'thumbnail': 'https://pbs.twimg.com/media/EfJ-C-JU0AAQL_C.jpg', 'screen_name': 'Twitter', 'type': 'Image', 'images': ['https://pbs.twimg.com/media/EfJ-C-JU0AAQL_C.jpg', 'https://pbs.twimg.com/media/EfJ-aHlU0AAU1kq.jpg', '', '', '2'], 'time': 'Tue Aug 11 17:35:57 +0000 2020', 'qrt': {}, 'nsfw': False, 'verified': True, 'size': {}}

testPoll_comparePoll={"name":"poll2choice_text_only","binding_values":{"choice1_label":{"type":"STRING","string_value":"Mean one thing"},"choice2_label":{"type":"STRING","string_value":"Mean multiple things"},"end_datetime_utc":{"type":"STRING","string_value":"2015-10-06T22:57:24Z"},"counts_are_final":{"type":"BOOLEAN","boolean_value":True},"choice2_count":{"type":"STRING","string_value":"33554"},"choice1_count":{"type":"STRING","string_value":"124875"},"last_updated_datetime_utc":{"type":"STRING","string_value":"2015-10-06T22:57:31Z"},"duration_minutes":{"type":"STRING","string_value":"1440"}}}
testPoll_comparePollVNF={'total_votes': 158429, 'choices': [{'text': 'Mean one thing', 'votes': 124875, 'percent': 78.8}, {'text': 'Mean multiple things', 'votes': 33554, 'percent': 21.2}]}

def compareDict(original,compare):
for key in original:
assert key in compare
assert compare[key]==original[key]
if type(compare[key]) is not dict:
assert compare[key]==original[key]
else:
compareDict(original[key],compare[key])

## Tweet retrieve tests ##
def test_textTweetExtract():
Expand Down Expand Up @@ -66,6 +73,11 @@ def test_multimediaTweetExtract():
assert video["media_url_https"]=="https://pbs.twimg.com/media/EfJ-aHlU0AAU1kq.jpg"
assert video["type"]=="photo"

def test_pollTweetExtract():
tweet = twExtract.extractStatus("https://twitter.com/norm/status/651169346518056960")
assert 'card' in tweet
compareDict(testPoll_comparePoll,tweet['card'])

## VNF conversion test ##

def test_textTweetVNF():
Expand All @@ -85,6 +97,10 @@ def test_multimediaTweetVNF():
vnf = twitfix.link_to_vnf_from_unofficial_api(testMultiMediaTweet)
compareDict(testMultiMedia_compare,vnf)

def test_pollTweetVNF():
vnf = twitfix.link_to_vnf_from_unofficial_api(testPollTweet)
compareDict(testPoll_comparePollVNF,vnf['poll'])

## Test adding to cache ; cache should be empty ##
def test_addToCache():
cache.clearCache()
Expand Down
61 changes: 43 additions & 18 deletions twitfix.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ def embed_video(video_link, image=0): # Return Embed from any tweet link
return message(msgs.failedToScan+msgs.failedToScanExtra+e)
return message(msgs.failedToScan)

def tweetInfo(url, tweet="", desc="", thumb="", uploader="", screen_name="", pfp="", tweetType="", images="", hits=0, likes=0, rts=0, time="", qrt={}, nsfw=False,ttl=None,verified=False,size={}): # Return a dict of video info with default values
def tweetInfo(url, tweet="", desc="", thumb="", uploader="", screen_name="", pfp="", tweetType="", images="", hits=0, likes=0, rts=0, time="", qrt={}, nsfw=False,ttl=None,verified=False,size={},poll=None): # Return a dict of video info with default values
if (ttl==None):
ttl = getDefaultTTL()
vnf = {
Expand All @@ -269,8 +269,11 @@ def tweetInfo(url, tweet="", desc="", thumb="", uploader="", screen_name="", pfp
"nsfw" : nsfw,
"ttl" : ttl,
"verified" : verified,
"size" : size
"size" : size,
"poll" : poll
}
if (poll is None):
del vnf['poll']
return vnf

def link_to_vnf_from_tweet_data(tweet,video_link):
Expand Down Expand Up @@ -323,6 +326,11 @@ def link_to_vnf_from_tweet_data(tweet,video_link):
for eurl in tweet['entities']['urls']:
text = text.replace(eurl["url"],eurl["expanded_url"])

if 'card' in tweet and tweet['card']['name'].startswith('poll'):
poll=getPollObject(tweet['card'])
else:
poll=None

vnf = tweetInfo(
url,
video_link,
Expand All @@ -338,7 +346,8 @@ def link_to_vnf_from_tweet_data(tweet,video_link):
images=imgs,
nsfw=nsfw,
verified=tweet['user']['verified'],
size=size
size=size,
poll=poll
)

return vnf
Expand Down Expand Up @@ -404,19 +413,14 @@ def embed(video_link, vnf, image):
urlLink = urllib.parse.quote(video_link)
likeDisplay = msgs.genLikesDisplay(vnf)

try:
if vnf['type'] == "":
desc = desc
elif vnf['type'] == "Video":
desc = desc
elif vnf['qrt'] == {}: # Check if this is a QRT and modify the description
desc = (desc + likeDisplay)
else:
qrtDisplay = msgs.genQrtDisplay(vnf["qrt"])
desc = (desc + qrtDisplay + likeDisplay)
except:
vnf['likes'] = 0; vnf['rts'] = 0; vnf['time'] = 0
print(' ➤ [ X ] Failed QRT check - old VNF object')
if 'poll' in vnf:
pollDisplay= msgs.genPollDisplay(vnf['poll'])
else:
pollDisplay=""

desc=msgs.formatEmbedDesc(vnf['type'],desc,vnf['qrt'],pollDisplay,likeDisplay)

print(len(desc))
appNamePost = ""
if vnf['type'] == "Text": # Change the template based on tweet type
template = 'text.html'
Expand All @@ -426,10 +430,10 @@ def embed(video_link, vnf, image):
image = vnf['images'][image]
template = 'image.html'
if vnf['type'] == "Video":
urlDesc = urllib.parse.quote(textwrap.shorten(desc, width=220, placeholder="..."))
#urlDesc = urllib.parse.quote(textwrap.shorten(desc, width=220, placeholder="..."))
template = 'video.html'
if vnf['type'] == "":
urlDesc = urllib.parse.quote(textwrap.shorten(desc, width=220, placeholder="..."))
#urlDesc = urllib.parse.quote(textwrap.shorten(desc, width=220, placeholder="..."))
template = 'video.html'

color = "#7FFFD4" # Green
Expand Down Expand Up @@ -477,6 +481,27 @@ def embedCombinedVnf(video_link,vnf):
return getTemplate('image.html',vnf,desc,image,video_link,color,urlDesc,urlUser,urlLink,appNameSuffix=" - View original tweet for full quality")


def getPollObject(card):
poll={"total_votes":0,"choices":[]}
choiceCount=0
if (card["name"]=="poll2choice_text_only"):
choiceCount=2
elif (card["name"]=="poll3choice_text_only"):
choiceCount=3
elif (card["name"]=="poll4choice_text_only"):
choiceCount=4

for i in range(0,choiceCount):
choice = {"text":card["binding_values"][f"choice{i+1}_label"]["string_value"],"votes":int(card["binding_values"][f"choice{i+1}_count"]["string_value"])}
poll["total_votes"]+=choice["votes"]
poll["choices"].append(choice)
# update each choice with a percentage
for choice in poll["choices"]:
choice["percent"] = round((choice["votes"]/poll["total_votes"])*100,1)

return poll


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]:
Expand Down

0 comments on commit 3999dbd

Please sign in to comment.