Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon into main

main
Bob Mottram 2020-08-04 21:10:25 +01:00
commit 095ab0a8d1
76 changed files with 392 additions and 97 deletions

View File

@ -14,6 +14,54 @@ from utils import fileLastModified
from utils import getLinkPrefixes from utils import getLinkPrefixes
def htmlReplaceQuoteMarks(content: str) -> str:
"""Replaces quotes with html formatting
"hello" becomes <q>hello</q>
"""
if '"' not in content:
if '&quot;' not in content:
return content
newContent = content
if '"' in content:
sections = content.split('"')
if len(sections) > 1:
newContent = ''
openQuote = True
markup = False
for ch in content:
currChar = ch
if ch == '<':
markup = True
elif ch == '>':
markup = False
elif ch == '"' and not markup:
if openQuote:
currChar = ''
else:
currChar = ''
openQuote = not openQuote
newContent += currChar
if '&quot;' in newContent:
openQuote = True
content = newContent
newContent = ''
ctr = 0
sections = content.split('&quot;')
noOfSections = len(sections)
for s in sections:
newContent += s
if ctr < noOfSections - 1:
if openQuote:
newContent += ''
else:
newContent += ''
openQuote = not openQuote
ctr += 1
return newContent
def dangerousMarkup(content: str) -> bool: def dangerousMarkup(content: str) -> bool:
"""Returns true if the given content contains dangerous html markup """Returns true if the given content contains dangerous html markup
""" """
@ -433,6 +481,7 @@ def removeHtml(content: str) -> str:
if '<' not in content: if '<' not in content:
return content return content
removing = False removing = False
content = content.replace('<q>', '"').replace('</q>', '"')
result = '' result = ''
for ch in content: for ch in content:
if ch == '<': if ch == '<':
@ -525,7 +574,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
by matching against known following accounts by matching against known following accounts
""" """
if content.startswith('<p>'): if content.startswith('<p>'):
return content return htmlReplaceQuoteMarks(content)
maxWordLength = 40 maxWordLength = 40
content = content.replace('\r', '') content = content.replace('\r', '')
content = content.replace('\n', ' --linebreak-- ') content = content.replace('\n', ' --linebreak-- ')
@ -608,7 +657,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
if longWordsList: if longWordsList:
content = removeLongWords(content, maxWordLength, longWordsList) content = removeLongWords(content, maxWordLength, longWordsList)
content = content.replace(' --linebreak-- ', '</p><p>') content = content.replace(' --linebreak-- ', '</p><p>')
return '<p>' + content + '</p>' return '<p>' + htmlReplaceQuoteMarks(content) + '</p>'
def getMentionsFromHtml(htmlText: str, def getMentionsFromHtml(htmlText: str,

110
daemon.py
View File

@ -928,7 +928,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.personCache, self.server.personCache,
self.server.allowDeletion, self.server.allowDeletion,
self.server.proxyType, version, self.server.proxyType, version,
self.server.debug) self.server.debug,
self.server.YTReplacementDomain)
def _postToOutboxThread(self, messageJson: {}) -> bool: def _postToOutboxThread(self, messageJson: {}) -> bool:
"""Creates a thread to send a post """Creates a thread to send a post
@ -2266,7 +2267,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion) self.server.projectVersion,
self.server.YTReplacementDomain)
if hashtagStr: if hashtagStr:
msg = hashtagStr.encode('utf-8') msg = hashtagStr.encode('utf-8')
self._set_headers('text/html', len(msg), self._set_headers('text/html', len(msg),
@ -3145,7 +3147,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.baseDir, self.server.session, self.server.baseDir,
deleteUrl, self.server.httpPrefix, deleteUrl, self.server.httpPrefix,
__version__, self.server.cachedWebfingers, __version__, self.server.cachedWebfingers,
self.server.personCache, callingDomain) self.server.personCache, callingDomain,
self.server.TYReplacementDomain)
if deleteStr: if deleteStr:
self._set_headers('text/html', len(deleteStr), self._set_headers('text/html', len(deleteStr),
cookie, callingDomain) cookie, callingDomain)
@ -3478,6 +3481,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.httpPrefix self.server.httpPrefix
projectVersion = \ projectVersion = \
self.server.projectVersion self.server.projectVersion
ytDomain = \
self.server.YTReplacementDomain
msg = \ msg = \
htmlIndividualPost(recentPostsCache, htmlIndividualPost(recentPostsCache,
maxRecentPosts, maxRecentPosts,
@ -3492,7 +3497,8 @@ class PubServer(BaseHTTPRequestHandler):
postJsonObject, postJsonObject,
httpPrefix, httpPrefix,
projectVersion, projectVersion,
likedBy) likedBy,
ytDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', len(msg), self._set_headers('text/html', len(msg),
cookie, callingDomain) cookie, callingDomain)
@ -3606,6 +3612,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.httpPrefix self.server.httpPrefix
projectVersion = \ projectVersion = \
self.server.projectVersion self.server.projectVersion
ytDomain = \
self.server.YTReplacementDomain
msg = \ msg = \
htmlPostReplies(recentPostsCache, htmlPostReplies(recentPostsCache,
maxRecentPosts, maxRecentPosts,
@ -3619,7 +3627,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.port, self.server.port,
repliesJson, repliesJson,
httpPrefix, httpPrefix,
projectVersion) projectVersion,
ytDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -3707,6 +3716,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.httpPrefix self.server.httpPrefix
projectVersion = \ projectVersion = \
self.server.projectVersion self.server.projectVersion
ytDomain = \
self.server.YTReplacementDomain
msg = \ msg = \
htmlPostReplies(recentPostsCache, htmlPostReplies(recentPostsCache,
maxRecentPosts, maxRecentPosts,
@ -3720,7 +3731,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.port, self.server.port,
repliesJson, repliesJson,
httpPrefix, httpPrefix,
projectVersion) projectVersion,
ytDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -3771,6 +3783,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.recentPostsCache self.server.recentPostsCache
cachedWebfingers = \ cachedWebfingers = \
self.server.cachedWebfingers self.server.cachedWebfingers
YTReplacementDomain = \
self.server.YTReplacementDomain
msg = \ msg = \
htmlProfile(defaultTimeline, htmlProfile(defaultTimeline,
recentPostsCache, recentPostsCache,
@ -3785,6 +3799,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.session,
cachedWebfingers, cachedWebfingers,
self.server.personCache, self.server.personCache,
YTReplacementDomain,
actorJson['roles'], actorJson['roles'],
None, None) None, None)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
@ -3831,6 +3846,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.recentPostsCache self.server.recentPostsCache
cachedWebfingers = \ cachedWebfingers = \
self.server.cachedWebfingers self.server.cachedWebfingers
YTReplacementDomain = \
self.server.YTReplacementDomain
msg = \ msg = \
htmlProfile(defaultTimeline, htmlProfile(defaultTimeline,
recentPostsCache, recentPostsCache,
@ -3845,6 +3862,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.session,
cachedWebfingers, cachedWebfingers,
self.server.personCache, self.server.personCache,
YTReplacementDomain,
actorJson['skills'], actorJson['skills'],
None, None) None, None)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
@ -3937,6 +3955,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.httpPrefix self.server.httpPrefix
projectVersion = \ projectVersion = \
self.server.projectVersion self.server.projectVersion
ytDomain = \
self.server.YTReplacementDomain
msg = \ msg = \
htmlIndividualPost(recentPostsCache, htmlIndividualPost(recentPostsCache,
maxRecentPosts, maxRecentPosts,
@ -3952,7 +3972,8 @@ class PubServer(BaseHTTPRequestHandler):
postJsonObject, postJsonObject,
httpPrefix, httpPrefix,
projectVersion, projectVersion,
likedBy) likedBy,
ytDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4035,7 +4056,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion, self.server.projectVersion,
self._isMinimal(nickname)) self._isMinimal(nickname),
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4126,7 +4148,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion, self.server.projectVersion,
self._isMinimal(nickname)) self._isMinimal(nickname),
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4216,7 +4239,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion, self.server.projectVersion,
self._isMinimal(nickname)) self._isMinimal(nickname),
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4307,7 +4331,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion, self.server.projectVersion,
self._isMinimal(nickname)) self._isMinimal(nickname),
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4396,7 +4421,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion, self.server.projectVersion,
self._isMinimal(nickname)) self._isMinimal(nickname),
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4461,7 +4487,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.port, self.server.port,
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion) self.server.projectVersion,
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4538,7 +4565,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion, self.server.projectVersion,
self._isMinimal(nickname)) self._isMinimal(nickname),
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4624,7 +4652,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.allowDeletion, self.server.allowDeletion,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion, self.server.projectVersion,
self._isMinimal(nickname)) self._isMinimal(nickname),
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4701,7 +4730,8 @@ class PubServer(BaseHTTPRequestHandler):
moderationFeed, moderationFeed,
True, True,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion) self.server.projectVersion,
self.server.YTReplacementDomain)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -4789,6 +4819,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.session,
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.YTReplacementDomain,
shares, shares,
pageNumber, sharesPerPage) pageNumber, sharesPerPage)
msg = msg.encode('utf-8') msg = msg.encode('utf-8')
@ -4869,6 +4900,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.session,
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.YTReplacementDomain,
following, following,
pageNumber, pageNumber,
followsPerPage).encode('utf-8') followsPerPage).encode('utf-8')
@ -4947,6 +4979,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.session,
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.YTReplacementDomain,
followers, followers,
pageNumber, pageNumber,
followsPerPage).encode('utf-8') followsPerPage).encode('utf-8')
@ -5001,6 +5034,7 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.session,
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.YTReplacementDomain,
None, None).encode('utf-8') None, None).encode('utf-8')
self._set_headers('text/html', self._set_headers('text/html',
len(msg), len(msg),
@ -5379,7 +5413,8 @@ class PubServer(BaseHTTPRequestHandler):
imgDescription, imgDescription,
self.server.useBlurHash) self.server.useBlurHash)
replaceYouTube(postJsonObject) replaceYouTube(postJsonObject,
self.server.YTReplacementDomain)
saveJson(postJsonObject, postFilename) saveJson(postJsonObject, postFilename)
print('Edited blog post, resaved ' + postFilename) print('Edited blog post, resaved ' + postFilename)
return 1 return 1
@ -6279,6 +6314,26 @@ class PubServer(BaseHTTPRequestHandler):
setConfigParam(self.server.baseDir, setConfigParam(self.server.baseDir,
'instanceTitle', 'instanceTitle',
fields['instanceTitle']) fields['instanceTitle'])
if fields.get('ytdomain'):
currYTDomain = self.server.YTReplacementDomain
if fields['ytdomain'] != currYTDomain:
newYTDomain = fields['ytdomain']
if '://' in newYTDomain:
newYTDomain = newYTDomain.split('://')[1]
if '/' in newYTDomain:
newYTDomain = newYTDomain.split('/')[0]
if '.' in newYTDomain:
setConfigParam(self.server.baseDir,
'youtubedomain',
newYTDomain)
self.server.YTReplacementDomain = \
newYTDomain
else:
setConfigParam(self.server.baseDir,
'youtubedomain', '')
self.server.YTReplacementDomain = None
currInstanceDescriptionShort = \ currInstanceDescriptionShort = \
getConfigParam(self.server.baseDir, getConfigParam(self.server.baseDir,
'instanceDescriptionShort') 'instanceDescriptionShort')
@ -6933,7 +6988,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.httpPrefix, self.server.httpPrefix,
self.server.projectVersion) self.server.projectVersion,
self.server.YTReplacementDomain)
if hashtagStr: if hashtagStr:
msg = hashtagStr.encode('utf-8') msg = hashtagStr.encode('utf-8')
self._login_headers('text/html', self._login_headers('text/html',
@ -6977,7 +7033,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.session, self.server.session,
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.port) self.server.port,
self.server.YTReplacementDomain)
if historyStr: if historyStr:
msg = historyStr.encode('utf-8') msg = historyStr.encode('utf-8')
self._login_headers('text/html', self._login_headers('text/html',
@ -7014,7 +7071,8 @@ class PubServer(BaseHTTPRequestHandler):
self.server.cachedWebfingers, self.server.cachedWebfingers,
self.server.personCache, self.server.personCache,
self.server.debug, self.server.debug,
self.server.projectVersion) self.server.projectVersion,
self.server.YTReplacementDomain)
if profileStr: if profileStr:
msg = profileStr.encode('utf-8') msg = profileStr.encode('utf-8')
self._login_headers('text/html', self._login_headers('text/html',
@ -7758,7 +7816,7 @@ class PubServer(BaseHTTPRequestHandler):
msg = \ msg = \
htmlUnblockConfirm(self.server.translate, htmlUnblockConfirm(self.server.translate,
self.server.baseDir, self.server.baseDir,
originPathStr, usersPath,
optionsActor, optionsActor,
optionsAvatarUrl).encode('utf-8') optionsAvatarUrl).encode('utf-8')
self._set_headers('text/html', len(msg), self._set_headers('text/html', len(msg),
@ -7772,7 +7830,7 @@ class PubServer(BaseHTTPRequestHandler):
msg = \ msg = \
htmlFollowConfirm(self.server.translate, htmlFollowConfirm(self.server.translate,
self.server.baseDir, self.server.baseDir,
originPathStr, usersPath,
optionsActor, optionsActor,
optionsAvatarUrl).encode('utf-8') optionsAvatarUrl).encode('utf-8')
self._set_headers('text/html', len(msg), self._set_headers('text/html', len(msg),
@ -8312,6 +8370,7 @@ def runDaemon(blogsInstance: bool, mediaInstance: bool,
instanceId: str, clientToServer: bool, instanceId: str, clientToServer: bool,
baseDir: str, domain: str, baseDir: str, domain: str,
onionDomain: str, i2pDomain: str, onionDomain: str, i2pDomain: str,
YTReplacementDomain: str,
port=80, proxyPort=80, httpPrefix='https', port=80, proxyPort=80, httpPrefix='https',
fedList=[], maxMentions=10, maxEmoji=10, fedList=[], maxMentions=10, maxEmoji=10,
authenticatedFetch=False, authenticatedFetch=False,
@ -8348,6 +8407,8 @@ def runDaemon(blogsInstance: bool, mediaInstance: bool,
print('ERROR: HTTP server failed to start. ' + str(e)) print('ERROR: HTTP server failed to start. ' + str(e))
return False return False
httpd.YTReplacementDomain = YTReplacementDomain
# This counter is used to update the list of blocked domains in memory. # This counter is used to update the list of blocked domains in memory.
# It helps to avoid touching the disk and so improves flooding resistance # It helps to avoid touching the disk and so improves flooding resistance
httpd.blocklistUpdateCtr = 0 httpd.blocklistUpdateCtr = 0
@ -8535,8 +8596,9 @@ def runDaemon(blogsInstance: bool, mediaInstance: bool,
httpd.ocapAlways, maxReplies, httpd.ocapAlways, maxReplies,
domainMaxPostsPerDay, accountMaxPostsPerDay, domainMaxPostsPerDay, accountMaxPostsPerDay,
allowDeletion, debug, maxMentions, maxEmoji, allowDeletion, debug, maxMentions, maxEmoji,
httpd.translate, httpd.translate, unitTest,
unitTest, httpd.acceptedCaps), daemon=True) httpd.YTReplacementDomain,
httpd.acceptedCaps), daemon=True)
print('Creating scheduled post thread') print('Creating scheduled post thread')
httpd.thrPostSchedule = \ httpd.thrPostSchedule = \
threadWithTrace(target=runPostSchedule, threadWithTrace(target=runPostSchedule,

View File

@ -50,6 +50,7 @@
--button-corner-radius: 15px; --button-corner-radius: 15px;
--timeline-border-radius: 30px; --timeline-border-radius: 30px;
--icons-side: right; --icons-side: right;
--title-color: #999;
} }
@font-face { @font-face {
@ -72,6 +73,10 @@ body, html {
font-size: var(--font-size); font-size: var(--font-size);
} }
h1 {
color: var(--title-color);
}
a, u { a, u {
color: var(--main-fg-color); color: var(--main-fg-color);
} }

View File

@ -115,6 +115,9 @@ parser.add_argument('--proxy', dest='proxyPort', type=int, default=None,
parser.add_argument('--path', dest='baseDir', parser.add_argument('--path', dest='baseDir',
type=str, default=os.getcwd(), type=str, default=os.getcwd(),
help='Directory in which to store posts') help='Directory in which to store posts')
parser.add_argument('--ytdomain', dest='YTReplacementDomain',
type=str, default=None,
help='Domain used to replace youtube.com')
parser.add_argument('--language', dest='language', parser.add_argument('--language', dest='language',
type=str, default=None, type=str, default=None,
help='Language code, eg. en/fr/de/es') help='Language code, eg. en/fr/de/es')
@ -1791,6 +1794,15 @@ registration = getConfigParam(baseDir, 'registration')
if not registration: if not registration:
registration = False registration = False
YTDomain = getConfigParam(baseDir, 'youtubedomain')
if YTDomain:
if '://' in YTDomain:
YTDomain = YTDomain.split('://')[1]
if '/' in YTDomain:
YTDomain = YTDomain.split('/')[0]
if '.' in YTDomain:
args.YTReplacementDomain = YTDomain
if setTheme(baseDir, themeName): if setTheme(baseDir, themeName):
print('Theme set to ' + themeName) print('Theme set to ' + themeName)
@ -1800,6 +1812,7 @@ runDaemon(args.blogsinstance, args.mediainstance,
registration, args.language, __version__, registration, args.language, __version__,
instanceId, args.client, baseDir, instanceId, args.client, baseDir,
domain, onionDomain, i2pDomain, domain, onionDomain, i2pDomain,
args.YTReplacementDomain,
port, proxyPort, httpPrefix, port, proxyPort, httpPrefix,
federationList, args.maxMentions, federationList, args.maxMentions,
args.maxEmoji, args.authenticatedFetch, args.maxEmoji, args.authenticatedFetch,

View File

@ -14,6 +14,7 @@ LcdSolid is public domain. See https://www.fontspace.com/lcd-solid-font-f11346
MarginaliaRegular is public domain. See https://www.fontspace.com/marginalia-font-f32466 MarginaliaRegular is public domain. See https://www.fontspace.com/marginalia-font-f32466
Octavius is created by Jack Oatley and described as "100% free to use, though credit is appreciated" https://www.dafont.com/octavius.font Octavius is created by Jack Oatley and described as "100% free to use, though credit is appreciated" https://www.dafont.com/octavius.font
RailModel is GPL. See https://www.fontspace.com/rail-model-font-f10741 RailModel is GPL. See https://www.fontspace.com/rail-model-font-f10741
Solidaric by Bob Mottram is under AGPL
SubZER0 is under GPL. See http://www.free-fonts-download.com/Techno/subzer0-font SubZER0 is under GPL. See http://www.free-fonts-download.com/Techno/subzer0-font
SundownerRegular is public domain. See https://www.fontspace.com/sundowner-font-f40837 SundownerRegular is public domain. See https://www.fontspace.com/sundowner-font-f40837
Warenhaus-Standard is public domain. See https://fontlibrary.org/en/font/warenhaus-typenhebel Warenhaus-Standard is public domain. See https://fontlibrary.org/en/font/warenhaus-typenhebel

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.9 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 969 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -1328,7 +1328,8 @@ def receiveAnnounce(recentPostsCache: {},
httpPrefix: str, domain: str, onionDomain: str, port: int, httpPrefix: str, domain: str, onionDomain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
personCache: {}, messageJson: {}, federationList: [], personCache: {}, messageJson: {}, federationList: [],
debug: bool, translate: {}) -> bool: debug: bool, translate: {},
YTReplacementDomain: str) -> bool:
"""Receives an announce activity within the POST section of HTTPServer """Receives an announce activity within the POST section of HTTPServer
""" """
if messageJson['type'] != 'Announce': if messageJson['type'] != 'Announce':
@ -1410,7 +1411,8 @@ def receiveAnnounce(recentPostsCache: {},
' -> ' + messageJson['object']) ' -> ' + messageJson['object'])
postJsonObject = downloadAnnounce(session, baseDir, httpPrefix, postJsonObject = downloadAnnounce(session, baseDir, httpPrefix,
nickname, domain, messageJson, nickname, domain, messageJson,
__version__, translate) __version__, translate,
YTReplacementDomain)
if postJsonObject: if postJsonObject:
if debug: if debug:
print('DEBUG: Announce post downloaded for ' + print('DEBUG: Announce post downloaded for ' +
@ -2055,7 +2057,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
queueFilename: str, destinationFilename: str, queueFilename: str, destinationFilename: str,
maxReplies: int, allowDeletion: bool, maxReplies: int, allowDeletion: bool,
maxMentions: int, maxEmoji: int, translate: {}, maxMentions: int, maxEmoji: int, translate: {},
unitTest: bool) -> bool: unitTest: bool, YTReplacementDomain: str) -> bool:
""" Anything which needs to be done after capabilities checks have passed """ Anything which needs to be done after capabilities checks have passed
""" """
actor = keyId actor = keyId
@ -2132,7 +2134,8 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
personCache, personCache,
messageJson, messageJson,
federationList, federationList,
debug, translate): debug, translate,
YTReplacementDomain):
if debug: if debug:
print('DEBUG: Announce accepted from ' + actor) print('DEBUG: Announce accepted from ' + actor)
@ -2207,7 +2210,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
return False return False
# replace YouTube links, so they get less tracking data # replace YouTube links, so they get less tracking data
replaceYouTube(postJsonObject) replaceYouTube(postJsonObject, YTReplacementDomain)
# list of indexes to be updated # list of indexes to be updated
updateIndexList = ['inbox'] updateIndexList = ['inbox']
@ -2289,7 +2292,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
if isImageMedia(session, baseDir, httpPrefix, if isImageMedia(session, baseDir, httpPrefix,
nickname, domain, postJsonObject, nickname, domain, postJsonObject,
translate): translate, YTReplacementDomain):
# media index will be updated # media index will be updated
updateIndexList.append('tlmedia') updateIndexList.append('tlmedia')
if isBlogPost(postJsonObject): if isBlogPost(postJsonObject):
@ -2411,9 +2414,10 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
domainMaxPostsPerDay: int, accountMaxPostsPerDay: int, domainMaxPostsPerDay: int, accountMaxPostsPerDay: int,
allowDeletion: bool, debug: bool, maxMentions: int, allowDeletion: bool, debug: bool, maxMentions: int,
maxEmoji: int, translate: {}, unitTest: bool, maxEmoji: int, translate: {}, unitTest: bool,
YTReplacementDomain: str,
acceptedCaps=["inbox:write", "objects:read"]) -> None: acceptedCaps=["inbox:write", "objects:read"]) -> None:
"""Processes received items and moves them to """Processes received items and moves them to the appropriate
the appropriate directories directories
""" """
currSessionTime = int(time.time()) currSessionTime = int(time.time())
sessionLastUpdate = currSessionTime sessionLastUpdate = currSessionTime
@ -2829,7 +2833,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
queueFilename, destination, queueFilename, destination,
maxReplies, allowDeletion, maxReplies, allowDeletion,
maxMentions, maxEmoji, maxMentions, maxEmoji,
translate, unitTest) translate, unitTest,
YTReplacementDomain)
else: else:
print('Queue: object capabilities check has failed') print('Queue: object capabilities check has failed')
if debug: if debug:
@ -2852,7 +2857,8 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
queueFilename, destination, queueFilename, destination,
maxReplies, allowDeletion, maxReplies, allowDeletion,
maxMentions, maxEmoji, maxMentions, maxEmoji,
translate, unitTest) translate, unitTest,
YTReplacementDomain)
if debug: if debug:
pprint(queueJson['post']) pprint(queueJson['post'])
print('No capability list within post') print('No capability list within post')

View File

@ -18,10 +18,12 @@ from shutil import rmtree
from shutil import move from shutil import move
def replaceYouTube(postJsonObject: {}) -> None: def replaceYouTube(postJsonObject: {}, replacementDomain: str) -> None:
"""Replace YouTube with invidio.us """Replace YouTube with a replacement domain
This denies Google some, but not all, tracking data This denies Google some, but not all, tracking data
""" """
if not replacementDomain:
return
if not isinstance(postJsonObject['object'], dict): if not isinstance(postJsonObject['object'], dict):
return return
if not postJsonObject['object'].get('content'): if not postJsonObject['object'].get('content'):
@ -30,7 +32,7 @@ def replaceYouTube(postJsonObject: {}) -> None:
return return
postJsonObject['object']['content'] = \ postJsonObject['object']['content'] = \
postJsonObject['object']['content'].replace('www.youtube.com', postJsonObject['object']['content'].replace('www.youtube.com',
'invidio.us') replacementDomain)
def removeMetaData(imageFilename: str, outputFilename: str) -> None: def removeMetaData(imageFilename: str, outputFilename: str) -> None:

View File

@ -44,7 +44,8 @@ def postMessageToOutbox(messageJson: {}, postToNickname: str,
federationList: [], sendThreads: [], federationList: [], sendThreads: [],
postLog: [], cachedWebfingers: {}, postLog: [], cachedWebfingers: {},
personCache: {}, allowDeletion: bool, personCache: {}, allowDeletion: bool,
proxyType: str, version: str, debug: bool) -> bool: proxyType: str, version: str, debug: bool,
YTReplacementDomain: str) -> bool:
"""post is received by the outbox """post is received by the outbox
Client to server message post Client to server message post
https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery https://www.w3.org/TR/activitypub/#client-to-server-outbox-delivery
@ -104,7 +105,7 @@ def postMessageToOutbox(messageJson: {}, postToNickname: str,
print('DEBUG: domain is blocked: ' + messageJson['actor']) print('DEBUG: domain is blocked: ' + messageJson['actor'])
return False return False
# replace youtube, so that google gets less tracking data # replace youtube, so that google gets less tracking data
replaceYouTube(messageJson) replaceYouTube(messageJson, YTReplacementDomain)
# https://www.w3.org/TR/activitypub/#create-activity-outbox # https://www.w3.org/TR/activitypub/#create-activity-outbox
messageJson['object']['attributedTo'] = messageJson['actor'] messageJson['object']['attributedTo'] = messageJson['actor']
if messageJson['object'].get('attachment'): if messageJson['object'].get('attachment'):

View File

@ -2418,14 +2418,16 @@ def isDM(postJsonObject: {}) -> bool:
def isImageMedia(session, baseDir: str, httpPrefix: str, def isImageMedia(session, baseDir: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
postJsonObject: {}, translate: {}) -> bool: postJsonObject: {}, translate: {},
YTReplacementDomain: str) -> bool:
"""Returns true if the given post has attached image media """Returns true if the given post has attached image media
""" """
if postJsonObject['type'] == 'Announce': if postJsonObject['type'] == 'Announce':
postJsonAnnounce = \ postJsonAnnounce = \
downloadAnnounce(session, baseDir, httpPrefix, downloadAnnounce(session, baseDir, httpPrefix,
nickname, domain, postJsonObject, nickname, domain, postJsonObject,
__version__, translate) __version__, translate,
YTReplacementDomain)
if postJsonAnnounce: if postJsonAnnounce:
postJsonObject = postJsonAnnounce postJsonObject = postJsonAnnounce
if postJsonObject['type'] != 'Create': if postJsonObject['type'] != 'Create':
@ -3153,7 +3155,7 @@ def rejectAnnounce(announceFilename: str):
def downloadAnnounce(session, baseDir: str, httpPrefix: str, def downloadAnnounce(session, baseDir: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
postJsonObject: {}, projectVersion: str, postJsonObject: {}, projectVersion: str,
translate: {}) -> {}: translate: {}, YTReplacementDomain: str) -> {}:
"""Download the post referenced by an announce """Download the post referenced by an announce
""" """
if not postJsonObject.get('object'): if not postJsonObject.get('object'):
@ -3289,7 +3291,7 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
rejectAnnounce(announceFilename) rejectAnnounce(announceFilename)
return None return None
postJsonObject = announcedJson postJsonObject = announcedJson
replaceYouTube(postJsonObject) replaceYouTube(postJsonObject, YTReplacementDomain)
if saveJson(postJsonObject, announceFilename): if saveJson(postJsonObject, announceFilename):
return postJsonObject return postJsonObject
return None return None

View File

@ -103,7 +103,8 @@ def updatePostSchedule(baseDir: str, handle: str, httpd,
httpd.allowDeletion, httpd.allowDeletion,
httpd.proxyType, httpd.proxyType,
httpd.projectVersion, httpd.projectVersion,
httpd.debug): httpd.debug,
httpd.YTReplacementDomain):
indexLines.remove(line) indexLines.remove(line)
os.remove(postFilename) os.remove(postFilename)
continue continue

View File

@ -64,6 +64,7 @@ from media import getAttachmentMediaType
from delete import sendDeleteViaServer from delete import sendDeleteViaServer
from inbox import validInbox from inbox import validInbox
from inbox import validInboxFilenames from inbox import validInboxFilenames
from content import htmlReplaceQuoteMarks
from content import dangerousMarkup from content import dangerousMarkup
from content import removeHtml from content import removeHtml
from content import addWebLinks from content import addWebLinks
@ -286,7 +287,7 @@ def createServerAlice(path: str, domain: str, port: int,
print('Server running: Alice') print('Server running: Alice')
runDaemon(False, False, 5, True, True, 'en', __version__, runDaemon(False, False, 5, True, True, 'en', __version__,
"instanceId", False, path, domain, "instanceId", False, path, domain,
onionDomain, i2pDomain, port, port, onionDomain, i2pDomain, None, port, port,
httpPrefix, federationList, maxMentions, maxEmoji, False, httpPrefix, federationList, maxMentions, maxEmoji, False,
noreply, nolike, nopics, noannounce, cw, ocapAlways, noreply, nolike, nopics, noannounce, cw, ocapAlways,
proxyType, maxReplies, proxyType, maxReplies,
@ -351,7 +352,7 @@ def createServerBob(path: str, domain: str, port: int,
print('Server running: Bob') print('Server running: Bob')
runDaemon(False, False, 5, True, True, 'en', __version__, runDaemon(False, False, 5, True, True, 'en', __version__,
"instanceId", False, path, domain, "instanceId", False, path, domain,
onionDomain, i2pDomain, port, port, onionDomain, i2pDomain, None, port, port,
httpPrefix, federationList, maxMentions, maxEmoji, False, httpPrefix, federationList, maxMentions, maxEmoji, False,
noreply, nolike, nopics, noannounce, cw, ocapAlways, noreply, nolike, nopics, noannounce, cw, ocapAlways,
proxyType, maxReplies, proxyType, maxReplies,
@ -393,7 +394,7 @@ def createServerEve(path: str, domain: str, port: int, federationList: [],
print('Server running: Eve') print('Server running: Eve')
runDaemon(False, False, 5, True, True, 'en', __version__, runDaemon(False, False, 5, True, True, 'en', __version__,
"instanceId", False, path, domain, "instanceId", False, path, domain,
onionDomain, i2pDomain, port, port, onionDomain, i2pDomain, None, port, port,
httpPrefix, federationList, maxMentions, maxEmoji, False, httpPrefix, federationList, maxMentions, maxEmoji, False,
noreply, nolike, nopics, noannounce, cw, ocapAlways, noreply, nolike, nopics, noannounce, cw, ocapAlways,
proxyType, maxReplies, allowDeletion, True, True, False, proxyType, maxReplies, allowDeletion, True, True, False,
@ -1923,8 +1924,28 @@ def testDangerousMarkup():
assert(not dangerousMarkup(content)) assert(not dangerousMarkup(content))
def runHtmlReplaceQuoteMarks():
print('htmlReplaceQuoteMarks')
testStr = 'The "cat" "sat" on the mat'
result = htmlReplaceQuoteMarks(testStr)
assert result == 'The “cat” “sat” on the mat'
testStr = 'The cat sat on the mat'
result = htmlReplaceQuoteMarks(testStr)
assert result == 'The cat sat on the mat'
testStr = '"hello"'
result = htmlReplaceQuoteMarks(testStr)
assert result == '“hello”'
testStr = '"hello" <a href="somesite.html">&quot;test&quot; html</a>'
result = htmlReplaceQuoteMarks(testStr)
assert result == '“hello” <a href="somesite.html">“test” html</a>'
def runAllTests(): def runAllTests():
print('Running tests...') print('Running tests...')
runHtmlReplaceQuoteMarks()
testDangerousMarkup() testDangerousMarkup()
testRemoveHtml() testRemoveHtml()
testSiteIsActive() testSiteIsActive()

View File

@ -25,7 +25,8 @@ def getThemesList() -> []:
and to lookup function names and to lookup function names
""" """
return ('Default', 'Blue', 'Hacker', 'Henge', 'HighVis', return ('Default', 'Blue', 'Hacker', 'Henge', 'HighVis',
'LCD', 'Light', 'Night', 'Purple', 'Starlight', 'Zen') 'LCD', 'Light', 'Night', 'Purple', 'Solidaric',
'Starlight', 'Zen')
def setThemeInConfig(baseDir: str, name: str) -> bool: def setThemeInConfig(baseDir: str, name: str) -> bool:
@ -274,7 +275,7 @@ def setThemeNight(baseDir: str):
removeTheme(baseDir) removeTheme(baseDir)
setThemeInConfig(baseDir, name) setThemeInConfig(baseDir, name)
fontStr = \ fontStr = \
"url('./fonts/CheGuevaraTextSans-Regular.woff2') format('woff2')" "url('./fonts/solidaric.woff2') format('woff2')"
themeParams = { themeParams = {
"font-size-button-mobile": "36px", "font-size-button-mobile": "36px",
"font-size": "32px", "font-size": "32px",
@ -302,7 +303,7 @@ def setThemeNight(baseDir: str):
"place-color": "#7961ab", "place-color": "#7961ab",
"event-color": "#7961ab", "event-color": "#7961ab",
"event-background": "#333", "event-background": "#333",
"*font-family": "'CheGuevaraTextSans-Regular'", "*font-family": "'solidaric'",
"*src": fontStr "*src": fontStr
} }
bgParams = { bgParams = {
@ -329,6 +330,7 @@ def setThemeStarlight(baseDir: str):
"text-entry-background": "#0f0d10", "text-entry-background": "#0f0d10",
"link-bg-color": "#0f0d10", "link-bg-color": "#0f0d10",
"main-link-color": "#ffc4bc", "main-link-color": "#ffc4bc",
"title-color": "#ffc4bc",
"main-visited-color": "#e1c4bc", "main-visited-color": "#e1c4bc",
"main-fg-color": "#ffc4bc", "main-fg-color": "#ffc4bc",
"main-bg-color-dm": "#0b0a0a", "main-bg-color-dm": "#0b0a0a",
@ -383,6 +385,7 @@ def setThemeHenge(baseDir: str):
"text-entry-background": "#383335", "text-entry-background": "#383335",
"link-bg-color": "#383335", "link-bg-color": "#383335",
"main-link-color": "white", "main-link-color": "white",
"title-color": "white",
"main-visited-color": "#e1c4bc", "main-visited-color": "#e1c4bc",
"main-fg-color": "white", "main-fg-color": "white",
"main-bg-color-dm": "#343335", "main-bg-color-dm": "#343335",
@ -433,6 +436,7 @@ def setThemeZen(baseDir: str):
"border-color": "#463b35", "border-color": "#463b35",
"border-width": "7px", "border-width": "7px",
"main-link-color": "#dddddd", "main-link-color": "#dddddd",
"title-color": "#dddddd",
"main-visited-color": "#dddddd", "main-visited-color": "#dddddd",
"button-background": "#463b35", "button-background": "#463b35",
"button-selected": "#26201d", "button-selected": "#26201d",
@ -492,6 +496,7 @@ def setThemeLCD(baseDir: str):
"border-color": "#33390d", "border-color": "#33390d",
"border-width": "5px", "border-width": "5px",
"main-link-color": "#9fb42b", "main-link-color": "#9fb42b",
"title-color": "#9fb42b",
"main-visited-color": "#9fb42b", "main-visited-color": "#9fb42b",
"button-selected": "black", "button-selected": "black",
"button-highlighted": "green", "button-highlighted": "green",
@ -559,6 +564,7 @@ def setThemePurple(baseDir: str):
"main-fg-color": "#f98bb0", "main-fg-color": "#f98bb0",
"border-color": "#3f2145", "border-color": "#3f2145",
"main-link-color": "#ff42a0", "main-link-color": "#ff42a0",
"title-color": "white",
"main-visited-color": "#f93bb0", "main-visited-color": "#f93bb0",
"button-selected": "#c042a0", "button-selected": "#c042a0",
"button-background": "#ff42a0", "button-background": "#ff42a0",
@ -602,6 +608,7 @@ def setThemeHacker(baseDir: str):
"main-fg-color": "#00ff00", "main-fg-color": "#00ff00",
"border-color": "#035103", "border-color": "#035103",
"main-link-color": "#2fff2f", "main-link-color": "#2fff2f",
"title-color": "#2fff2f",
"main-visited-color": "#3c8234", "main-visited-color": "#3c8234",
"button-selected": "#063200", "button-selected": "#063200",
"button-background": "#062200", "button-background": "#062200",
@ -655,6 +662,7 @@ def setThemeLight(baseDir: str):
"main-fg-color": "#2d2c37", "main-fg-color": "#2d2c37",
"border-color": "#c0cdd9", "border-color": "#c0cdd9",
"main-link-color": "#2a2c37", "main-link-color": "#2a2c37",
"title-color": "#2a2c37",
"main-visited-color": "#232c37", "main-visited-color": "#232c37",
"text-entry-foreground": "#111", "text-entry-foreground": "#111",
"text-entry-background": "white", "text-entry-background": "white",
@ -689,6 +697,60 @@ def setThemeLight(baseDir: str):
setThemeFromDict(baseDir, name, themeParams, bgParams) setThemeFromDict(baseDir, name, themeParams, bgParams)
def setThemeSolidaric(baseDir: str):
name = 'solidaric'
themeParams = {
"font-size-button-mobile": "36px",
"font-size": "32px",
"font-size2": "26px",
"font-size3": "40px",
"font-size4": "24px",
"font-size5": "22px",
"rgba(0, 0, 0, 0.5)": "rgba(0, 0, 0, 0.0)",
"main-bg-color": "white",
"main-bg-color-dm": "white",
"link-bg-color": "white",
"main-bg-color-reply": "white",
"main-bg-color-report": "white",
"main-header-color-roles": "#ebebf0",
"main-fg-color": "#2d2c37",
"border-color": "#c0cdd9",
"main-link-color": "#2a2c37",
"title-color": "#2a2c37",
"main-visited-color": "#232c37",
"text-entry-foreground": "#111",
"text-entry-background": "white",
"font-color-header": "black",
"dropdown-fg-color": "#222",
"dropdown-fg-color-hover": "#222",
"dropdown-bg-color": "white",
"dropdown-bg-color-hover": "lightgrey",
"color: #FFFFFE;": "color: black;",
"calendar-bg-color": "white",
"lines-color": "black",
"day-number": "black",
"day-number2": "#282c37",
"place-color": "black",
"event-color": "#282c37",
"today-foreground": "white",
"today-circle": "red",
"event-background": "lightblue",
"event-foreground": "white",
"title-text": "#282c37",
"title-background": "#ccc",
"gallery-text-color": "black",
"*font-family": "'solidaric'",
"*src": "url('./fonts/solidaric.woff2') format('woff2')"
}
bgParams = {
"login": "jpg",
"follow": "jpg",
"options": "jpg",
"search": "jpg"
}
setThemeFromDict(baseDir, name, themeParams, bgParams)
def setThemeImages(baseDir: str, name: str) -> None: def setThemeImages(baseDir: str, name: str) -> None:
"""Changes the profile background image """Changes the profile background image
and banner to the defaults and banner to the defaults

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "الخادم مشغول. الرجاء معاودة المحاولة في وقت لاحق", "The server is busy. Please try again later": "الخادم مشغول. الرجاء معاودة المحاولة في وقت لاحق",
"Receive calendar events from this account": "تلقي أحداث التقويم من هذا الحساب", "Receive calendar events from this account": "تلقي أحداث التقويم من هذا الحساب",
"Grayscale": "درجات الرمادي", "Grayscale": "درجات الرمادي",
"Liked by": "نال إعجاب" "Liked by": "نال إعجاب",
"Solidaric": "تضامن",
"YouTube Replacement Domain": "استبدال نطاق يوتيوب"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "El servidor està ocupat. Siusplau, intenta-ho més tard", "The server is busy. Please try again later": "El servidor està ocupat. Siusplau, intenta-ho més tard",
"Receive calendar events from this account": "Rep esdeveniments del calendari des daquest compte", "Receive calendar events from this account": "Rep esdeveniments del calendari des daquest compte",
"Grayscale": "Escala de grisos", "Grayscale": "Escala de grisos",
"Liked by": "M'agrada" "Liked by": "M'agrada",
"Solidaric": "Solidaritat",
"YouTube Replacement Domain": "Domini de substitució de YouTube"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "Mae'r gweinydd yn brysur. Rho gynnig Arni eto'n hwyrach", "The server is busy. Please try again later": "Mae'r gweinydd yn brysur. Rho gynnig Arni eto'n hwyrach",
"Receive calendar events from this account": "Derbyn digwyddiadau calendr o'r cyfrif hwn", "Receive calendar events from this account": "Derbyn digwyddiadau calendr o'r cyfrif hwn",
"Grayscale": "Graddlwyd", "Grayscale": "Graddlwyd",
"Liked by": "Hoffi" "Liked by": "Hoffi",
"Solidaric": "Undod",
"YouTube Replacement Domain": "Parth Amnewid YouTube"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "Der Server ist beschäftigt. Bitte versuchen Sie es später noch einmal", "The server is busy. Please try again later": "Der Server ist beschäftigt. Bitte versuchen Sie es später noch einmal",
"Receive calendar events from this account": "Erhalten Sie Kalenderereignisse von diesem Konto", "Receive calendar events from this account": "Erhalten Sie Kalenderereignisse von diesem Konto",
"Grayscale": "Graustufen", "Grayscale": "Graustufen",
"Liked by": "Gefallen von" "Liked by": "Gefallen von",
"Solidaric": "Solidarität",
"YouTube Replacement Domain": "YouTube-Ersatzdomain"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "The server is busy. Please try again later", "The server is busy. Please try again later": "The server is busy. Please try again later",
"Receive calendar events from this account": "Receive calendar events from this account", "Receive calendar events from this account": "Receive calendar events from this account",
"Grayscale": "Grayscale", "Grayscale": "Grayscale",
"Liked by": "Liked by" "Liked by": "Liked by",
"Solidaric": "Solidaric",
"YouTube Replacement Domain": "YouTube Replacement Domain"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "El servidor esta ocupado. Por favor, inténtelo de nuevo más tarde", "The server is busy. Please try again later": "El servidor esta ocupado. Por favor, inténtelo de nuevo más tarde",
"Receive calendar events from this account": "Recibe eventos de calendario de esta cuenta", "Receive calendar events from this account": "Recibe eventos de calendario de esta cuenta",
"Grayscale": "Escala de grises", "Grayscale": "Escala de grises",
"Liked by": "Apreciado por" "Liked by": "Apreciado por",
"Solidaric": "Solidaridad",
"YouTube Replacement Domain": "Dominio de reemplazo de YouTube"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "Le serveur est occupé. Veuillez réessayer plus tard", "The server is busy. Please try again later": "Le serveur est occupé. Veuillez réessayer plus tard",
"Receive calendar events from this account": "Recevoir des événements d'agenda de ce compte", "Receive calendar events from this account": "Recevoir des événements d'agenda de ce compte",
"Grayscale": "Niveaux de gris", "Grayscale": "Niveaux de gris",
"Liked by": "Aimé par" "Liked by": "Aimé par",
"Solidaric": "Solidarité",
"YouTube Replacement Domain": "Domaine de remplacement YouTube"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "Tá an freastalaí gnóthach. Bain triail eile as níos déanaí", "The server is busy. Please try again later": "Tá an freastalaí gnóthach. Bain triail eile as níos déanaí",
"Receive calendar events from this account": "Faigh imeachtaí féilire ón gcuntas seo", "Receive calendar events from this account": "Faigh imeachtaí féilire ón gcuntas seo",
"Grayscale": "Liathscála", "Grayscale": "Liathscála",
"Liked by": "Thaitin" "Liked by": "Thaitin",
"Solidaric": "Dlúthpháirtíocht",
"YouTube Replacement Domain": "Fearann Athsholáthair YouTube"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "सर्वर व्यस्त है। बाद में पुन: प्रयास करें", "The server is busy. Please try again later": "सर्वर व्यस्त है। बाद में पुन: प्रयास करें",
"Receive calendar events from this account": "इस खाते से कैलेंडर ईवेंट प्राप्त करें", "Receive calendar events from this account": "इस खाते से कैलेंडर ईवेंट प्राप्त करें",
"Grayscale": "ग्रेस्केल", "Grayscale": "ग्रेस्केल",
"Liked by": "द्वारा पसंद किया गया" "Liked by": "द्वारा पसंद किया गया",
"Solidaric": "एकजुटता",
"YouTube Replacement Domain": "YouTube रिप्लेसमेंट डोमेन"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "Il server è occupato. Per favore riprova più tardi", "The server is busy. Please try again later": "Il server è occupato. Per favore riprova più tardi",
"Receive calendar events from this account": "Ricevi eventi di calendario da questo account", "Receive calendar events from this account": "Ricevi eventi di calendario da questo account",
"Grayscale": "Scala di grigi", "Grayscale": "Scala di grigi",
"Liked by": "Mi è piaciuto" "Liked by": "Mi è piaciuto",
"Solidaric": "Solidarietà",
"YouTube Replacement Domain": "Dominio sostitutivo di YouTube"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "サーバーはビジーです。 後でもう一度やり直してください", "The server is busy. Please try again later": "サーバーはビジーです。 後でもう一度やり直してください",
"Receive calendar events from this account": "このアカウントからカレンダーイベントを受信します", "Receive calendar events from this account": "このアカウントからカレンダーイベントを受信します",
"Grayscale": "グレースケール", "Grayscale": "グレースケール",
"Liked by": "好き" "Liked by": "好き",
"Solidaric": "連帯",
"YouTube Replacement Domain": "YouTube交換ドメイン"
} }

View File

@ -248,5 +248,7 @@
"The server is busy. Please try again later": "The server is busy. Please try again later", "The server is busy. Please try again later": "The server is busy. Please try again later",
"Receive calendar events from this account": "Receive calendar events from this account", "Receive calendar events from this account": "Receive calendar events from this account",
"Grayscale": "Grayscale", "Grayscale": "Grayscale",
"Liked by": "Liked by" "Liked by": "Liked by",
"Solidaric": "Solidaric",
"YouTube Replacement Domain": "YouTube Replacement Domain"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "O servidor está ocupado. Por favor, tente novamente mais tarde", "The server is busy. Please try again later": "O servidor está ocupado. Por favor, tente novamente mais tarde",
"Receive calendar events from this account": "Receba eventos da agenda desta conta", "Receive calendar events from this account": "Receba eventos da agenda desta conta",
"Grayscale": "Escala de cinza", "Grayscale": "Escala de cinza",
"Liked by": "Curtida por" "Liked by": "Curtida por",
"Solidaric": "Solidariedade",
"YouTube Replacement Domain": "Domínio de substituição do YouTube"
} }

View File

@ -252,5 +252,7 @@
"The server is busy. Please try again later": "Сервер занят. Пожалуйста, попробуйте позже", "The server is busy. Please try again later": "Сервер занят. Пожалуйста, попробуйте позже",
"Receive calendar events from this account": "Получать события календаря от этого аккаунта", "Receive calendar events from this account": "Получать события календаря от этого аккаунта",
"Grayscale": "Оттенки серого", "Grayscale": "Оттенки серого",
"Liked by": "Понравилось" "Liked by": "Понравилось",
"Solidaric": "солидарность",
"YouTube Replacement Domain": "Запасной домен YouTube"
} }

View File

@ -251,5 +251,7 @@
"The server is busy. Please try again later": "服务器忙。 请稍后再试", "The server is busy. Please try again later": "服务器忙。 请稍后再试",
"Receive calendar events from this account": "从该帐户接收日历事件", "Receive calendar events from this account": "从该帐户接收日历事件",
"Grayscale": "灰阶", "Grayscale": "灰阶",
"Liked by": "喜欢的人" "Liked by": "喜欢的人",
"Solidaric": "团结互助",
"YouTube Replacement Domain": "YouTube替换域"
} }

View File

@ -57,6 +57,7 @@ from bookmarks import bookmarkedByPerson
from announce import announcedByPerson from announce import announcedByPerson
from blocking import isBlocked from blocking import isBlocked
from blocking import isBlockedHashtag from blocking import isBlockedHashtag
from content import htmlReplaceQuoteMarks
from content import removeTextFormatting from content import removeTextFormatting
from content import switchWords from content import switchWords
from content import getMentionsFromHtml from content import getMentionsFromHtml
@ -691,7 +692,8 @@ def htmlHashtagSearch(nickname: str, domain: str, port: int,
baseDir: str, hashtag: str, pageNumber: int, baseDir: str, hashtag: str, pageNumber: int,
postsPerPage: int, postsPerPage: int,
session, wfRequest: {}, personCache: {}, session, wfRequest: {}, personCache: {},
httpPrefix: str, projectVersion: str) -> str: httpPrefix: str, projectVersion: str,
YTReplacementDomain: str) -> str:
"""Show a page containing search results for a hashtag """Show a page containing search results for a hashtag
""" """
if hashtag.startswith('#'): if hashtag.startswith('#'):
@ -795,6 +797,7 @@ def htmlHashtagSearch(nickname: str, domain: str, port: int,
None, True, allowDeletion, None, True, allowDeletion,
httpPrefix, projectVersion, httpPrefix, projectVersion,
'search', 'search',
YTReplacementDomain,
showIndividualPostIcons, showIndividualPostIcons,
showIndividualPostIcons, showIndividualPostIcons,
False, False, False) False, False, False)
@ -951,7 +954,8 @@ def htmlHistorySearch(translate: {}, baseDir: str,
session, session,
wfRequest, wfRequest,
personCache: {}, personCache: {},
port: int) -> str: port: int,
YTReplacementDomain: str) -> str:
"""Show a page containing search results for your post history """Show a page containing search results for your post history
""" """
if historysearch.startswith('!'): if historysearch.startswith('!'):
@ -1022,6 +1026,7 @@ def htmlHistorySearch(translate: {}, baseDir: str,
None, True, allowDeletion, None, True, allowDeletion,
httpPrefix, projectVersion, httpPrefix, projectVersion,
'search', 'search',
YTReplacementDomain,
showIndividualPostIcons, showIndividualPostIcons,
showIndividualPostIcons, showIndividualPostIcons,
False, False, False) False, False, False)
@ -1501,6 +1506,16 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
' <textarea id="message" name="gitProjects" ' + \ ' <textarea id="message" name="gitProjects" ' + \
'style="height:100px">' + gitProjectsStr + '</textarea>' 'style="height:100px">' + gitProjectsStr + '</textarea>'
editProfileForm += \
' <br><b><label class="labels">' + \
translate['YouTube Replacement Domain'] + '</label></b>'
YTReplacementDomain = getConfigParam(baseDir, "youtubedomain")
if not YTReplacementDomain:
YTReplacementDomain = ''
editProfileForm += \
' <input type="text" name="ytdomain" value="' + \
YTReplacementDomain + '">'
editProfileForm += ' </div>' editProfileForm += ' </div>'
editProfileForm += ' <div class="container">' editProfileForm += ' <div class="container">'
editProfileForm += \ editProfileForm += \
@ -2290,7 +2305,8 @@ def htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
authorized: bool, ocapAlways: bool, authorized: bool, ocapAlways: bool,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
session, wfRequest: {}, personCache: {}, session, wfRequest: {}, personCache: {},
projectVersion: str) -> str: projectVersion: str,
YTReplacementDomain: str) -> str:
"""Shows posts on the profile screen """Shows posts on the profile screen
These should only be public posts These should only be public posts
""" """
@ -2323,6 +2339,7 @@ def htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
nickname, domain, port, item, nickname, domain, port, item,
None, True, False, None, True, False,
httpPrefix, projectVersion, 'inbox', httpPrefix, projectVersion, 'inbox',
YTReplacementDomain,
False, False, False, True, False) False, False, False, True, False)
if postStr: if postStr:
profileStr += postStr profileStr += postStr
@ -2566,6 +2583,7 @@ def htmlProfile(defaultTimeline: str,
baseDir: str, httpPrefix: str, authorized: bool, baseDir: str, httpPrefix: str, authorized: bool,
ocapAlways: bool, profileJson: {}, selected: str, ocapAlways: bool, profileJson: {}, selected: str,
session, wfRequest: {}, personCache: {}, session, wfRequest: {}, personCache: {},
YTReplacementDomain: str,
extraJson=None, extraJson=None,
pageNumber=None, maxItemsPerPage=None) -> str: pageNumber=None, maxItemsPerPage=None) -> str:
"""Show the profile page as html """Show the profile page as html
@ -2823,7 +2841,8 @@ def htmlProfile(defaultTimeline: str,
baseDir, httpPrefix, authorized, baseDir, httpPrefix, authorized,
ocapAlways, nickname, domain, port, ocapAlways, nickname, domain, port,
session, wfRequest, personCache, session, wfRequest, personCache,
projectVersion) + licenseStr projectVersion,
YTReplacementDomain) + licenseStr
if selected == 'following': if selected == 'following':
profileStr += \ profileStr += \
htmlProfileFollowing(translate, baseDir, httpPrefix, htmlProfileFollowing(translate, baseDir, httpPrefix,
@ -3602,7 +3621,8 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
avatarUrl: str, showAvatarOptions: bool, avatarUrl: str, showAvatarOptions: bool,
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
boxName: str, showRepeats=True, boxName: str, YTReplacementDomain: str,
showRepeats=True,
showIcons=False, showIcons=False,
manuallyApprovesFollowers=False, manuallyApprovesFollowers=False,
showPublicOnly=False, showPublicOnly=False,
@ -3729,7 +3749,8 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
postJsonAnnounce = \ postJsonAnnounce = \
downloadAnnounce(session, baseDir, httpPrefix, downloadAnnounce(session, baseDir, httpPrefix,
nickname, domain, postJsonObject, nickname, domain, postJsonObject,
projectVersion, translate) projectVersion, translate,
YTReplacementDomain)
if not postJsonAnnounce: if not postJsonAnnounce:
return '' return ''
postJsonObject = postJsonAnnounce postJsonObject = postJsonAnnounce
@ -4240,8 +4261,10 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
objectContent = removeTextFormatting(objectContent) objectContent = removeTextFormatting(objectContent)
objectContent = \ objectContent = \
switchWords(baseDir, nickname, domain, objectContent) switchWords(baseDir, nickname, domain, objectContent)
objectContent = htmlReplaceQuoteMarks(objectContent)
else: else:
objectContent = postJsonObject['object']['content'] objectContent = \
postJsonObject['object']['content']
if not postIsSensitive: if not postIsSensitive:
contentStr = objectContent + attachmentStr contentStr = objectContent + attachmentStr
@ -4350,7 +4373,8 @@ def htmlTimeline(defaultTimeline: str,
boxName: str, allowDeletion: bool, boxName: str, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
manuallyApproveFollowers: bool, manuallyApproveFollowers: bool,
minimal: bool) -> str: minimal: bool,
YTReplacementDomain: str) -> str:
"""Show the timeline as html """Show the timeline as html
""" """
accountDir = baseDir + '/accounts/' + nickname + '@' + domain accountDir = baseDir + '/accounts/' + nickname + '@' + domain
@ -4793,6 +4817,7 @@ def htmlTimeline(defaultTimeline: str,
allowDeletion, allowDeletion,
httpPrefix, projectVersion, httpPrefix, projectVersion,
boxName, boxName,
YTReplacementDomain,
boxName != 'dm', boxName != 'dm',
showIndividualPostIcons, showIndividualPostIcons,
manuallyApproveFollowers, manuallyApproveFollowers,
@ -4823,7 +4848,8 @@ def htmlShares(defaultTimeline: str,
session, baseDir: str, wfRequest: {}, personCache: {}, session, baseDir: str, wfRequest: {}, personCache: {},
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str) -> str: httpPrefix: str, projectVersion: str,
YTReplacementDomain: str) -> str:
"""Show the shares timeline as html """Show the shares timeline as html
""" """
manuallyApproveFollowers = \ manuallyApproveFollowers = \
@ -4835,7 +4861,7 @@ def htmlShares(defaultTimeline: str,
nickname, domain, port, None, nickname, domain, port, None,
'tlshares', allowDeletion, 'tlshares', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers, httpPrefix, projectVersion, manuallyApproveFollowers,
False) False, YTReplacementDomain)
def htmlInbox(defaultTimeline: str, def htmlInbox(defaultTimeline: str,
@ -4845,7 +4871,7 @@ def htmlInbox(defaultTimeline: str,
nickname: str, domain: str, port: int, inboxJson: {}, nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
minimal: bool) -> str: minimal: bool, YTReplacementDomain: str) -> str:
"""Show the inbox as html """Show the inbox as html
""" """
manuallyApproveFollowers = \ manuallyApproveFollowers = \
@ -4857,7 +4883,7 @@ def htmlInbox(defaultTimeline: str,
nickname, domain, port, inboxJson, nickname, domain, port, inboxJson,
'inbox', allowDeletion, 'inbox', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers, httpPrefix, projectVersion, manuallyApproveFollowers,
minimal) minimal, YTReplacementDomain)
def htmlBookmarks(defaultTimeline: str, def htmlBookmarks(defaultTimeline: str,
@ -4867,7 +4893,7 @@ def htmlBookmarks(defaultTimeline: str,
nickname: str, domain: str, port: int, bookmarksJson: {}, nickname: str, domain: str, port: int, bookmarksJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
minimal: bool) -> str: minimal: bool, YTReplacementDomain: str) -> str:
"""Show the bookmarks as html """Show the bookmarks as html
""" """
manuallyApproveFollowers = \ manuallyApproveFollowers = \
@ -4879,7 +4905,7 @@ def htmlBookmarks(defaultTimeline: str,
nickname, domain, port, bookmarksJson, nickname, domain, port, bookmarksJson,
'tlbookmarks', allowDeletion, 'tlbookmarks', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers, httpPrefix, projectVersion, manuallyApproveFollowers,
minimal) minimal, YTReplacementDomain)
def htmlInboxDMs(defaultTimeline: str, def htmlInboxDMs(defaultTimeline: str,
@ -4889,14 +4915,15 @@ def htmlInboxDMs(defaultTimeline: str,
nickname: str, domain: str, port: int, inboxJson: {}, nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
minimal: bool) -> str: minimal: bool, YTReplacementDomain: str) -> str:
"""Show the DM timeline as html """Show the DM timeline as html
""" """
return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts, return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts,
translate, pageNumber, translate, pageNumber,
itemsPerPage, session, baseDir, wfRequest, personCache, itemsPerPage, session, baseDir, wfRequest, personCache,
nickname, domain, port, inboxJson, 'dm', allowDeletion, nickname, domain, port, inboxJson, 'dm', allowDeletion,
httpPrefix, projectVersion, False, minimal) httpPrefix, projectVersion, False, minimal,
YTReplacementDomain)
def htmlInboxReplies(defaultTimeline: str, def htmlInboxReplies(defaultTimeline: str,
@ -4906,7 +4933,7 @@ def htmlInboxReplies(defaultTimeline: str,
nickname: str, domain: str, port: int, inboxJson: {}, nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
minimal: bool) -> str: minimal: bool, YTReplacementDomain: str) -> str:
"""Show the replies timeline as html """Show the replies timeline as html
""" """
return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts, return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts,
@ -4914,7 +4941,7 @@ def htmlInboxReplies(defaultTimeline: str,
itemsPerPage, session, baseDir, wfRequest, personCache, itemsPerPage, session, baseDir, wfRequest, personCache,
nickname, domain, port, inboxJson, 'tlreplies', nickname, domain, port, inboxJson, 'tlreplies',
allowDeletion, httpPrefix, projectVersion, False, allowDeletion, httpPrefix, projectVersion, False,
minimal) minimal, YTReplacementDomain)
def htmlInboxMedia(defaultTimeline: str, def htmlInboxMedia(defaultTimeline: str,
@ -4924,7 +4951,7 @@ def htmlInboxMedia(defaultTimeline: str,
nickname: str, domain: str, port: int, inboxJson: {}, nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
minimal: bool) -> str: minimal: bool, YTReplacementDomain: str) -> str:
"""Show the media timeline as html """Show the media timeline as html
""" """
return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts, return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts,
@ -4932,7 +4959,7 @@ def htmlInboxMedia(defaultTimeline: str,
itemsPerPage, session, baseDir, wfRequest, personCache, itemsPerPage, session, baseDir, wfRequest, personCache,
nickname, domain, port, inboxJson, 'tlmedia', nickname, domain, port, inboxJson, 'tlmedia',
allowDeletion, httpPrefix, projectVersion, False, allowDeletion, httpPrefix, projectVersion, False,
minimal) minimal, YTReplacementDomain)
def htmlInboxBlogs(defaultTimeline: str, def htmlInboxBlogs(defaultTimeline: str,
@ -4942,7 +4969,7 @@ def htmlInboxBlogs(defaultTimeline: str,
nickname: str, domain: str, port: int, inboxJson: {}, nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
minimal: bool) -> str: minimal: bool, YTReplacementDomain: str) -> str:
"""Show the blogs timeline as html """Show the blogs timeline as html
""" """
return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts, return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts,
@ -4950,7 +4977,7 @@ def htmlInboxBlogs(defaultTimeline: str,
itemsPerPage, session, baseDir, wfRequest, personCache, itemsPerPage, session, baseDir, wfRequest, personCache,
nickname, domain, port, inboxJson, 'tlblogs', nickname, domain, port, inboxJson, 'tlblogs',
allowDeletion, httpPrefix, projectVersion, False, allowDeletion, httpPrefix, projectVersion, False,
minimal) minimal, YTReplacementDomain)
def htmlModeration(defaultTimeline: str, def htmlModeration(defaultTimeline: str,
@ -4959,14 +4986,16 @@ def htmlModeration(defaultTimeline: str,
session, baseDir: str, wfRequest: {}, personCache: {}, session, baseDir: str, wfRequest: {}, personCache: {},
nickname: str, domain: str, port: int, inboxJson: {}, nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str) -> str: httpPrefix: str, projectVersion: str,
YTReplacementDomain: str) -> str:
"""Show the moderation feed as html """Show the moderation feed as html
""" """
return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts, return htmlTimeline(defaultTimeline, recentPostsCache, maxRecentPosts,
translate, pageNumber, translate, pageNumber,
itemsPerPage, session, baseDir, wfRequest, personCache, itemsPerPage, session, baseDir, wfRequest, personCache,
nickname, domain, port, inboxJson, 'moderation', nickname, domain, port, inboxJson, 'moderation',
allowDeletion, httpPrefix, projectVersion, True, False) allowDeletion, httpPrefix, projectVersion, True, False,
YTReplacementDomain)
def htmlOutbox(defaultTimeline: str, def htmlOutbox(defaultTimeline: str,
@ -4976,7 +5005,7 @@ def htmlOutbox(defaultTimeline: str,
nickname: str, domain: str, port: int, outboxJson: {}, nickname: str, domain: str, port: int, outboxJson: {},
allowDeletion: bool, allowDeletion: bool,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
minimal: bool) -> str: minimal: bool, YTReplacementDomain: str) -> str:
"""Show the Outbox as html """Show the Outbox as html
""" """
manuallyApproveFollowers = \ manuallyApproveFollowers = \
@ -4986,7 +5015,8 @@ def htmlOutbox(defaultTimeline: str,
itemsPerPage, session, baseDir, wfRequest, personCache, itemsPerPage, session, baseDir, wfRequest, personCache,
nickname, domain, port, outboxJson, 'outbox', nickname, domain, port, outboxJson, 'outbox',
allowDeletion, httpPrefix, projectVersion, allowDeletion, httpPrefix, projectVersion,
manuallyApproveFollowers, minimal) manuallyApproveFollowers, minimal,
YTReplacementDomain)
def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int, def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
@ -4994,7 +5024,8 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
baseDir: str, session, wfRequest: {}, personCache: {}, baseDir: str, session, wfRequest: {}, personCache: {},
nickname: str, domain: str, port: int, authorized: bool, nickname: str, domain: str, port: int, authorized: bool,
postJsonObject: {}, httpPrefix: str, postJsonObject: {}, httpPrefix: str,
projectVersion: str, likedBy: str) -> str: projectVersion: str, likedBy: str,
YTReplacementDomain: str) -> str:
"""Show an individual post as html """Show an individual post as html
""" """
iconsDir = getIconsDir(baseDir) iconsDir = getIconsDir(baseDir)
@ -5038,6 +5069,7 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
nickname, domain, port, postJsonObject, nickname, domain, port, postJsonObject,
None, True, False, None, True, False,
httpPrefix, projectVersion, 'inbox', httpPrefix, projectVersion, 'inbox',
YTReplacementDomain,
False, authorized, False, False, False) False, authorized, False, False, False)
messageId = postJsonObject['id'].replace('/activity', '') messageId = postJsonObject['id'].replace('/activity', '')
@ -5060,6 +5092,7 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject, postJsonObject,
None, True, False, None, True, False,
httpPrefix, projectVersion, 'inbox', httpPrefix, projectVersion, 'inbox',
YTReplacementDomain,
False, authorized, False, authorized,
False, False, False) + postStr False, False, False) + postStr
@ -5085,6 +5118,7 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
nickname, domain, port, item, nickname, domain, port, item,
None, True, False, None, True, False,
httpPrefix, projectVersion, 'inbox', httpPrefix, projectVersion, 'inbox',
YTReplacementDomain,
False, authorized, False, authorized,
False, False, False) False, False, False)
cssFilename = baseDir + '/epicyon-profile.css' cssFilename = baseDir + '/epicyon-profile.css'
@ -5102,7 +5136,8 @@ def htmlPostReplies(recentPostsCache: {}, maxRecentPosts: int,
translate: {}, baseDir: str, translate: {}, baseDir: str,
session, wfRequest: {}, personCache: {}, session, wfRequest: {}, personCache: {},
nickname: str, domain: str, port: int, repliesJson: {}, nickname: str, domain: str, port: int, repliesJson: {},
httpPrefix: str, projectVersion: str) -> str: httpPrefix: str, projectVersion: str,
YTReplacementDomain: str) -> str:
"""Show the replies to an individual post as html """Show the replies to an individual post as html
""" """
iconsDir = getIconsDir(baseDir) iconsDir = getIconsDir(baseDir)
@ -5116,6 +5151,7 @@ def htmlPostReplies(recentPostsCache: {}, maxRecentPosts: int,
nickname, domain, port, item, nickname, domain, port, item,
None, True, False, None, True, False,
httpPrefix, projectVersion, 'inbox', httpPrefix, projectVersion, 'inbox',
YTReplacementDomain,
False, False, False, False, False) False, False, False, False, False)
cssFilename = baseDir + '/epicyon-profile.css' cssFilename = baseDir + '/epicyon-profile.css'
@ -5203,7 +5239,8 @@ def htmlDeletePost(recentPostsCache: {}, maxRecentPosts: int,
session, baseDir: str, messageId: str, session, baseDir: str, messageId: str,
httpPrefix: str, projectVersion: str, httpPrefix: str, projectVersion: str,
wfRequest: {}, personCache: {}, wfRequest: {}, personCache: {},
callingDomain: str) -> str: callingDomain: str,
YTReplacementDomain: str) -> str:
"""Shows a screen asking to confirm the deletion of a post """Shows a screen asking to confirm the deletion of a post
""" """
if '/statuses/' not in messageId: if '/statuses/' not in messageId:
@ -5247,6 +5284,7 @@ def htmlDeletePost(recentPostsCache: {}, maxRecentPosts: int,
nickname, domain, port, postJsonObject, nickname, domain, port, postJsonObject,
None, True, False, None, True, False,
httpPrefix, projectVersion, 'outbox', httpPrefix, projectVersion, 'outbox',
YTReplacementDomain,
False, False, False, False, False) False, False, False, False, False)
deletePostStr += '<center>' deletePostStr += '<center>'
deletePostStr += \ deletePostStr += \
@ -6195,7 +6233,8 @@ def htmlProfileAfterSearch(recentPostsCache: {}, maxRecentPosts: int,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
profileHandle: str, profileHandle: str,
session, cachedWebfingers: {}, personCache: {}, session, cachedWebfingers: {}, personCache: {},
debug: bool, projectVersion: str) -> str: debug: bool, projectVersion: str,
YTReplacementDomain: str) -> str:
"""Show a profile page after a search for a fediverse address """Show a profile page after a search for a fediverse address
""" """
if '/users/' in profileHandle or \ if '/users/' in profileHandle or \
@ -6400,6 +6439,7 @@ def htmlProfileAfterSearch(recentPostsCache: {}, maxRecentPosts: int,
nickname, domain, port, nickname, domain, port,
item, avatarUrl, False, False, item, avatarUrl, False, False,
httpPrefix, projectVersion, 'inbox', httpPrefix, projectVersion, 'inbox',
YTReplacementDomain,
False, False, False, False, False) False, False, False, False, False)
i += 1 i += 1
if i >= 20: if i >= 20: