91 lines
4.0 KiB
Python
91 lines
4.0 KiB
Python
import re
|
|
import io
|
|
from configHandler import config
|
|
|
|
pathregex = re.compile("\\w{1,15}\\/(status|statuses)\\/(\\d{2,20})")
|
|
endTCOregex = re.compile("(^.*?) +https:\/\/t.co\/.*?$")
|
|
|
|
def getTweetIdFromUrl(url):
|
|
match = pathregex.search(url)
|
|
if match is not None:
|
|
return match.group(2)
|
|
else:
|
|
return None
|
|
|
|
def stripEndTCO(text):
|
|
# remove t.co links at the end of a string
|
|
match = endTCOregex.search(text)
|
|
if match is not None:
|
|
return match.group(1)
|
|
else:
|
|
return text
|
|
|
|
# https://stackoverflow.com/a/55977438
|
|
class BytesIOWrapper(io.BufferedReader):
|
|
"""Wrap a buffered bytes stream over TextIOBase string stream."""
|
|
|
|
def __init__(self, text_io_buffer, encoding=None, errors=None, **kwargs):
|
|
super(BytesIOWrapper, self).__init__(text_io_buffer, **kwargs)
|
|
self.encoding = encoding or text_io_buffer.encoding or 'utf-8'
|
|
self.errors = errors or text_io_buffer.errors or 'strict'
|
|
|
|
def _encoding_call(self, method_name, *args, **kwargs):
|
|
raw_method = getattr(self.raw, method_name)
|
|
val = raw_method(*args, **kwargs)
|
|
return val.encode(self.encoding, errors=self.errors)
|
|
|
|
def read(self, size=-1):
|
|
return self._encoding_call('read', size)
|
|
|
|
def read1(self, size=-1):
|
|
return self._encoding_call('read1', size)
|
|
|
|
def peek(self, size=-1):
|
|
return self._encoding_call('peek', size)
|
|
|
|
def fixMedia(mediaInfo):
|
|
# This is for the iOS Discord app, which has issues when serving URLs ending in .mp4 (https://github.com/dylanpdx/BetterTwitFix/issues/210)
|
|
if 'video.twimg.com' not in mediaInfo['url'] or 'convert?url=' in mediaInfo['url'] or 'originalUrl' in mediaInfo:
|
|
return mediaInfo
|
|
mediaInfo["originalUrl"] = mediaInfo['url']
|
|
mediaInfo['url'] = mediaInfo['url'].replace("https://video.twimg.com",f"{config['config']['url']}/tvid").replace(".mp4","")
|
|
return mediaInfo
|
|
|
|
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
|
|
# if both don't have media, return the main tweet => embedding qrt text will be handled in the embed description
|
|
# if both have media, return the main tweet => priority is given to the main tweet's media
|
|
# if only the QRT has media, return the QRT => show the QRT's media, not the main tweet's
|
|
# if only the main tweet has media, return the main tweet => show the main tweet's media, embedding QRT text will be handled in the embed description
|
|
if tweetData['qrt'] is None:
|
|
return tweetData
|
|
if tweetData['qrt']['hasMedia'] and not tweetData['hasMedia']:
|
|
return tweetData['qrt']
|
|
return tweetData
|
|
|
|
def determineMediaToEmbed(tweetData,embedIndex = -1):
|
|
if tweetData['allSameType'] and tweetData['media_extended'][0]['type'] == "image" and embedIndex == -1 and tweetData['combinedMediaUrl'] != None:
|
|
return {"url":tweetData['combinedMediaUrl'],"type":"image"}
|
|
else:
|
|
# this means we have mixed media or video, and we're only going to embed one
|
|
if embedIndex == -1: # if the user didn't specify an index, we'll just use the first one
|
|
embedIndex = 0
|
|
media = tweetData['media_extended'][embedIndex]
|
|
media=fixMedia(media)
|
|
suffix=""
|
|
if len(tweetData["media_extended"]) > 1:
|
|
suffix = f' • Media {embedIndex+1}/{len(tweetData["media_extended"])}'
|
|
else:
|
|
suffix = ''
|
|
media["suffix"] = suffix
|
|
if media['type'] == "image":
|
|
return media
|
|
elif media['type'] == "video" or media['type'] == "gif":
|
|
if media['type'] == "gif":
|
|
if config['config']['gifConvertAPI'] != "" and config['config']['gifConvertAPI'] != "none":
|
|
vurl=media['originalUrl'] if 'originalUrl' in media else media['url']
|
|
media['url'] = config['config']['gifConvertAPI'] + "/convert?url=" + vurl
|
|
suffix += " • GIF"
|
|
media["suffix"] = suffix
|
|
return media |