Repository navigation
Expand file tree
/
Copy pathutils.py
More file actions
124 lines (109 loc) · 5.71 KB
/
Copy pathutils.py
File metadata and controls
124 lines (109 loc) · 5.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import re
import io
from configHandler import config
pathregex = re.compile("\\w{1,15}\\/(status|statuses)\\/(\\d{2,20})")
endTCOregex = re.compile("(^.*?)[ \n]+https:\/\/t.co\/.*?$",flags=re.DOTALL)
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 mediaToGifConvert(media):
if media['type'] != "gif":
raise Exception("non gif passed to mediaToGifConvert")
if "/convert.avif?url=" in media['url']:
return media
if config['config']['gifConvertAPI'] != "" and config['config']['gifConvertAPI'] != "none" and config['config']['gifConvertAPI'] != "local":
gcApi = config['config']['gifConvertAPI']
#if gcApi == "local": # TODO
#gcApi = f"{config['config']['url']}/gifconvert"
vurl=media['originalUrl'] if 'originalUrl' in media else media['url']
media['url'] = gcApi + "/convert.avif?url=" + vurl
return media
def determineMediaToEmbed(tweetData,embedIndex = -1,convertGif = True,isGeneratingActivity=False):
if tweetData['allSameType'] and tweetData['media_extended'][0]['type'] == "image" and embedIndex == -1 and tweetData['combinedMediaUrl'] != None:
return {"url":tweetData['combinedMediaUrl'],"type":"image"}
else:
userPickedImg=embedIndex != -1
# 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:
if userPickedImg:
suffix = f' • Media {embedIndex+1}/{len(tweetData["media_extended"])}'
else:
# basically, activity embeds (primarily on Discord) are handled by activity.py, and they support Images and gifs in the same embed
# but this would clash with the original embed which only supports one type of media at a time.
# Discord pulls the suffix from the original embed, and the rest of the data from the activity embed
# This would cause a post with only images and gifs to show "Tweet has additional media not displayed" even though all the media is there
# It's a hacky workaround because suffix can't be altered in the activity (afaik)
if (isGeneratingActivity and len([m for m in tweetData['media_extended'] if (m["type"] != "image" and m["type"] != "gif")]) > 0) or not isGeneratingActivity:
suffix = ' • Has additional media not displayed'
else:
suffix = ''
media["suffix"] = suffix
if media['type'] == "image":
return media
elif media['type'] == "video" or media['type'] == "gif":
if media['type'] == "gif" and convertGif:
media = mediaToGifConvert(media)
suffix += " • GIF"
media["suffix"] = suffix
return media
def indexOfAny(list,items,caseInsensitive=False):
if caseInsensitive:
list = [item.upper() for item in list]
items = [item.upper() for item in items]
for item in items:
try:
return list.index(item)
except:
continue
return -1