mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon
commit
e5af948446
|
|
@ -77,7 +77,7 @@ def outboxAnnounce(recentPostsCache: {},
|
||||||
nickname, domain, debug)
|
nickname, domain, debug)
|
||||||
return True
|
return True
|
||||||
elif messageJson['type'] == 'Undo':
|
elif messageJson['type'] == 'Undo':
|
||||||
if not isinstance(messageJson['object'], dict):
|
if not hasObjectDict(messageJson):
|
||||||
return False
|
return False
|
||||||
if not messageJson['object'].get('type'):
|
if not messageJson['object'].get('type'):
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
2
inbox.py
2
inbox.py
|
|
@ -298,7 +298,7 @@ def inboxMessageHasParams(messageJson: {}) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# object should be a dict or a string
|
# object should be a dict or a string
|
||||||
if not isinstance(messageJson['object'], dict):
|
if not hasObjectDict(messageJson):
|
||||||
if not isinstance(messageJson['object'], str):
|
if not isinstance(messageJson['object'], str):
|
||||||
print('WARN: object from ' + str(messageJson['actor']) +
|
print('WARN: object from ' + str(messageJson['actor']) +
|
||||||
' should be a dict or string, but is actually: ' +
|
' should be a dict or string, but is actually: ' +
|
||||||
|
|
|
||||||
3
media.py
3
media.py
|
|
@ -18,6 +18,7 @@ from utils import getImageExtensions
|
||||||
from utils import getVideoExtensions
|
from utils import getVideoExtensions
|
||||||
from utils import getAudioExtensions
|
from utils import getAudioExtensions
|
||||||
from utils import getMediaExtensions
|
from utils import getMediaExtensions
|
||||||
|
from utils import hasObjectDict
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
from shutil import rmtree
|
from shutil import rmtree
|
||||||
from shutil import move
|
from shutil import move
|
||||||
|
|
@ -30,7 +31,7 @@ def replaceYouTube(postJsonObject: {}, replacementDomain: str) -> None:
|
||||||
"""
|
"""
|
||||||
if not replacementDomain:
|
if not replacementDomain:
|
||||||
return
|
return
|
||||||
if not isinstance(postJsonObject['object'], dict):
|
if not hasObjectDict(postJsonObject):
|
||||||
return
|
return
|
||||||
if not postJsonObject['object'].get('content'):
|
if not postJsonObject['object'].get('content'):
|
||||||
return
|
return
|
||||||
|
|
|
||||||
6
posts.py
6
posts.py
|
|
@ -1296,7 +1296,7 @@ def _postIsAddressedToFollowers(baseDir: str,
|
||||||
toList = []
|
toList = []
|
||||||
ccList = []
|
ccList = []
|
||||||
if postJsonObject['type'] != 'Update' and \
|
if postJsonObject['type'] != 'Update' and \
|
||||||
isinstance(postJsonObject['object'], dict):
|
hasObjectDict(postJsonObject):
|
||||||
if postJsonObject['object'].get('to'):
|
if postJsonObject['object'].get('to'):
|
||||||
toList = postJsonObject['object']['to']
|
toList = postJsonObject['object']['to']
|
||||||
if postJsonObject['object'].get('cc'):
|
if postJsonObject['object'].get('cc'):
|
||||||
|
|
@ -2169,7 +2169,7 @@ def _addFollowersToPublicPost(postJsonObject: {}) -> None:
|
||||||
if postJsonObject.get('cc'):
|
if postJsonObject.get('cc'):
|
||||||
return
|
return
|
||||||
postJsonObject['cc'] = postJsonObject['actor'] + '/followers'
|
postJsonObject['cc'] = postJsonObject['actor'] + '/followers'
|
||||||
elif isinstance(postJsonObject['object'], dict):
|
elif hasObjectDict(postJsonObject):
|
||||||
if not postJsonObject['object'].get('to'):
|
if not postJsonObject['object'].get('to'):
|
||||||
return
|
return
|
||||||
if len(postJsonObject['object']['to']) > 1:
|
if len(postJsonObject['object']['to']) > 1:
|
||||||
|
|
@ -2433,7 +2433,7 @@ def sendToNamedAddresses(session, baseDir: str,
|
||||||
if not postJsonObject.get('object'):
|
if not postJsonObject.get('object'):
|
||||||
return
|
return
|
||||||
isProfileUpdate = False
|
isProfileUpdate = False
|
||||||
if isinstance(postJsonObject['object'], dict):
|
if hasObjectDict(postJsonObject):
|
||||||
if _isProfileUpdate(postJsonObject):
|
if _isProfileUpdate(postJsonObject):
|
||||||
# use the original object, which has a 'to'
|
# use the original object, which has a 'to'
|
||||||
recipientsObject = postJsonObject
|
recipientsObject = postJsonObject
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ def isQuestion(postObjectJson: {}) -> bool:
|
||||||
if postObjectJson['type'] != 'Create' and \
|
if postObjectJson['type'] != 'Create' and \
|
||||||
postObjectJson['type'] != 'Update':
|
postObjectJson['type'] != 'Update':
|
||||||
return False
|
return False
|
||||||
if not isinstance(postObjectJson['object'], dict):
|
if not hasObjectDict(postObjectJson):
|
||||||
return False
|
return False
|
||||||
if not postObjectJson['object'].get('type'):
|
if not postObjectJson['object'].get('type'):
|
||||||
return False
|
return False
|
||||||
|
|
|
||||||
16
theme.py
16
theme.py
|
|
@ -366,16 +366,12 @@ def _setThemeFromDict(baseDir: str, name: str,
|
||||||
with open(filename, 'w+') as cssfile:
|
with open(filename, 'w+') as cssfile:
|
||||||
cssfile.write(css)
|
cssfile.write(css)
|
||||||
|
|
||||||
if bgParams.get('login'):
|
screenName = (
|
||||||
_setBackgroundFormat(baseDir, name, 'login', bgParams['login'])
|
'login', 'follow', 'options', 'search', 'welcome'
|
||||||
if bgParams.get('follow'):
|
)
|
||||||
_setBackgroundFormat(baseDir, name, 'follow', bgParams['follow'])
|
for s in screenName:
|
||||||
if bgParams.get('options'):
|
if bgParams.get(s):
|
||||||
_setBackgroundFormat(baseDir, name, 'options', bgParams['options'])
|
_setBackgroundFormat(baseDir, name, s, bgParams[s])
|
||||||
if bgParams.get('search'):
|
|
||||||
_setBackgroundFormat(baseDir, name, 'search', bgParams['search'])
|
|
||||||
if bgParams.get('welcome'):
|
|
||||||
_setBackgroundFormat(baseDir, name, 'welcome', bgParams['welcome'])
|
|
||||||
|
|
||||||
|
|
||||||
def _setBackgroundFormat(baseDir: str, name: str,
|
def _setBackgroundFormat(baseDir: str, name: str,
|
||||||
|
|
|
||||||
14
utils.py
14
utils.py
|
|
@ -1401,7 +1401,7 @@ def deletePost(baseDir: str, httpPrefix: str,
|
||||||
|
|
||||||
# remove from moderation index file
|
# remove from moderation index file
|
||||||
if hasObject:
|
if hasObject:
|
||||||
if isinstance(postJsonObject['object'], dict):
|
if hasObjectDict(postJsonObject):
|
||||||
if postJsonObject['object'].get('moderationStatus'):
|
if postJsonObject['object'].get('moderationStatus'):
|
||||||
if postJsonObject.get('id'):
|
if postJsonObject.get('id'):
|
||||||
postId = removeIdEnding(postJsonObject['id'])
|
postId = removeIdEnding(postJsonObject['id'])
|
||||||
|
|
@ -2536,3 +2536,15 @@ def getPortFromDomain(domain: str) -> int:
|
||||||
if portStr.isdigit():
|
if portStr.isdigit():
|
||||||
return int(portStr)
|
return int(portStr)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def validUrlPrefix(url: str) -> bool:
|
||||||
|
"""Does the given url have a valid prefix?
|
||||||
|
"""
|
||||||
|
if '/' not in url:
|
||||||
|
return False
|
||||||
|
prefixes = ('https:', 'http:', 'hyper:', 'i2p:', 'gnunet:')
|
||||||
|
for pre in prefixes:
|
||||||
|
if url.startswith(pre):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -117,8 +117,7 @@ def _htmlCalendarDay(personCache: {}, cssCache: {}, translate: {},
|
||||||
if '/users/' in actor:
|
if '/users/' in actor:
|
||||||
calActor = '/users/' + actor.split('/users/')[1]
|
calActor = '/users/' + actor.split('/users/')[1]
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
|
||||||
calendarStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
calendarStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
calendarStr += '<main><table class="calendar">\n'
|
calendarStr += '<main><table class="calendar">\n'
|
||||||
calendarStr += '<caption class="calendar__banner--month">\n'
|
calendarStr += '<caption class="calendar__banner--month">\n'
|
||||||
|
|
@ -369,20 +368,10 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
|
||||||
calendarStr += '</caption>\n'
|
calendarStr += '</caption>\n'
|
||||||
calendarStr += '<thead>\n'
|
calendarStr += '<thead>\n'
|
||||||
calendarStr += '<tr>\n'
|
calendarStr += '<tr>\n'
|
||||||
|
days = ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
|
||||||
|
for d in days:
|
||||||
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
||||||
translate['Sun'] + '</th>\n'
|
translate[d] + '</th>\n'
|
||||||
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
|
||||||
translate['Mon'] + '</th>\n'
|
|
||||||
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
|
||||||
translate['Tue'] + '</th>\n'
|
|
||||||
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
|
||||||
translate['Wed'] + '</th>\n'
|
|
||||||
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
|
||||||
translate['Thu'] + '</th>\n'
|
|
||||||
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
|
||||||
translate['Fri'] + '</th>\n'
|
|
||||||
calendarStr += ' <th scope="col" class="calendar__day__header">' + \
|
|
||||||
translate['Sat'] + '</th>\n'
|
|
||||||
calendarStr += '</tr>\n'
|
calendarStr += '</tr>\n'
|
||||||
calendarStr += '</thead>\n'
|
calendarStr += '</thead>\n'
|
||||||
calendarStr += '<tbody>\n'
|
calendarStr += '<tbody>\n'
|
||||||
|
|
|
||||||
|
|
@ -51,10 +51,8 @@ def _getLeftColumnShares(baseDir: str,
|
||||||
if '<' in sharedesc or '?' in sharedesc:
|
if '<' in sharedesc or '?' in sharedesc:
|
||||||
continue
|
continue
|
||||||
contactActor = item['actor']
|
contactActor = item['actor']
|
||||||
shareLink = actor + \
|
shareLink = actor + '?replydm=sharedesc:' + \
|
||||||
'?replydm=sharedesc:' + \
|
sharedesc.replace(' ', '_') + '?mention=' + contactActor
|
||||||
sharedesc.replace(' ', '_') + \
|
|
||||||
'?mention=' + contactActor
|
|
||||||
linksList.append(sharedesc + ' ' + shareLink)
|
linksList.append(sharedesc + ' ' + shareLink)
|
||||||
ctr += 1
|
ctr += 1
|
||||||
if ctr >= maxSharesInLeftColumn:
|
if ctr >= maxSharesInLeftColumn:
|
||||||
|
|
@ -89,16 +87,14 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
if os.path.isfile(leftColumnImageFilename):
|
if os.path.isfile(leftColumnImageFilename):
|
||||||
editImageClass = 'leftColEditImage'
|
editImageClass = 'leftColEditImage'
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
'\n <center>\n' + \
|
'\n <center>\n <img class="leftColImg" ' + \
|
||||||
' <img class="leftColImg" ' + \
|
|
||||||
'alt="" loading="lazy" src="/users/' + \
|
'alt="" loading="lazy" src="/users/' + \
|
||||||
nickname + '/' + leftImageFile + '" />\n' + \
|
nickname + '/' + leftImageFile + '" />\n' + \
|
||||||
' </center>\n'
|
' </center>\n'
|
||||||
|
|
||||||
if showBackButton:
|
if showBackButton:
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
' <div>' + \
|
' <div> <a href="' + timelinePath + '">' + \
|
||||||
' <a href="' + timelinePath + '">' + \
|
|
||||||
'<button class="cancelbtn">' + \
|
'<button class="cancelbtn">' + \
|
||||||
translate['Go Back'] + '</button></a>\n'
|
translate['Go Back'] + '</button></a>\n'
|
||||||
|
|
||||||
|
|
@ -112,14 +108,11 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
if editor:
|
if editor:
|
||||||
# show the edit icon
|
# show the edit icon
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
' <a href="' + \
|
' <a href="/users/' + nickname + '/editlinks" ' + \
|
||||||
'/users/' + nickname + '/editlinks" ' + \
|
|
||||||
'accesskey="' + accessKeys['menuEdit'] + '">' + \
|
'accesskey="' + accessKeys['menuEdit'] + '">' + \
|
||||||
'<img class="' + editImageClass + \
|
'<img class="' + editImageClass + '" loading="lazy" alt="' + \
|
||||||
'" loading="lazy" alt="' + \
|
|
||||||
translate['Edit Links'] + ' | " title="' + \
|
translate['Edit Links'] + ' | " title="' + \
|
||||||
translate['Edit Links'] + '" src="/' + \
|
translate['Edit Links'] + '" src="/icons/edit.png" /></a>\n'
|
||||||
'icons/edit.png" /></a>\n'
|
|
||||||
|
|
||||||
# RSS icon
|
# RSS icon
|
||||||
if nickname != 'news':
|
if nickname != 'news':
|
||||||
|
|
@ -134,10 +127,8 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
else:
|
else:
|
||||||
rssTitle = translate['RSS feed for this site']
|
rssTitle = translate['RSS feed for this site']
|
||||||
rssIconStr = \
|
rssIconStr = \
|
||||||
' <a href="' + rssUrl + '">' + \
|
' <a href="' + rssUrl + '"><img class="' + editImageClass + \
|
||||||
'<img class="' + editImageClass + \
|
'" loading="lazy" alt="' + rssTitle + '" title="' + rssTitle + \
|
||||||
'" loading="lazy" alt="' + rssTitle + \
|
|
||||||
'" title="' + rssTitle + \
|
|
||||||
'" src="/icons/logorss.png" /></a>\n'
|
'" src="/icons/logorss.png" /></a>\n'
|
||||||
if rssIconAtTop:
|
if rssIconAtTop:
|
||||||
htmlStr += rssIconStr
|
htmlStr += rssIconStr
|
||||||
|
|
@ -326,8 +317,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
||||||
theme, accessKeys)
|
theme, accessKeys)
|
||||||
else:
|
else:
|
||||||
if editor:
|
if editor:
|
||||||
htmlStr += '<br><br><br>\n'
|
htmlStr += '<br><br><br>\n<center>\n '
|
||||||
htmlStr += '<center>\n '
|
|
||||||
htmlStr += translate['Select the edit icon to add web links']
|
htmlStr += translate['Select the edit icon to add web links']
|
||||||
htmlStr += '\n</center>\n'
|
htmlStr += '\n</center>\n'
|
||||||
|
|
||||||
|
|
@ -376,7 +366,8 @@ def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
translate['Switch to timeline view'] + '" alt="' + \
|
translate['Switch to timeline view'] + '" alt="' + \
|
||||||
translate['Switch to timeline view'] + '" ' + \
|
translate['Switch to timeline view'] + '" ' + \
|
||||||
'accesskey="' + accessKeys['menuTimeline'] + '">\n'
|
'accesskey="' + accessKeys['menuTimeline'] + '">\n'
|
||||||
editLinksForm += '<img loading="lazy" class="timeline-banner" ' + \
|
editLinksForm += \
|
||||||
|
'<img loading="lazy" class="timeline-banner" ' + \
|
||||||
'alt = "" src="' + \
|
'alt = "" src="' + \
|
||||||
'/users/' + nickname + '/' + bannerFile + '" /></a>\n' + \
|
'/users/' + nickname + '/' + bannerFile + '" /></a>\n' + \
|
||||||
'</header>\n'
|
'</header>\n'
|
||||||
|
|
@ -411,8 +402,7 @@ def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str,
|
||||||
'<br>'
|
'<br>'
|
||||||
editLinksForm += \
|
editLinksForm += \
|
||||||
' <textarea id="message" name="editedLinks" ' + \
|
' <textarea id="message" name="editedLinks" ' + \
|
||||||
'style="height:80vh" spellcheck="false">' + \
|
'style="height:80vh" spellcheck="false">' + linksStr + '</textarea>'
|
||||||
linksStr + '</textarea>'
|
|
||||||
editLinksForm += \
|
editLinksForm += \
|
||||||
'</div>'
|
'</div>'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -253,8 +253,7 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
if faviconUrl:
|
if faviconUrl:
|
||||||
faviconLink = \
|
faviconLink = \
|
||||||
'<img loading="lazy" src="' + faviconUrl + '" ' + \
|
'<img loading="lazy" src="' + faviconUrl + '" ' + \
|
||||||
'alt="" ' + \
|
'alt="" ' + _getBrokenFavSubstitute() + '/>'
|
||||||
_getBrokenFavSubstitute() + '/>'
|
|
||||||
moderatedItem = item[5]
|
moderatedItem = item[5]
|
||||||
htmlStr += separatorStr
|
htmlStr += separatorStr
|
||||||
if moderatedItem and 'vote:' + nickname in item[2]:
|
if moderatedItem and 'vote:' + nickname in item[2]:
|
||||||
|
|
@ -270,8 +269,7 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
'<a href="' + url + '" target="_blank" ' + \
|
'<a href="' + url + '" target="_blank" ' + \
|
||||||
'rel="nofollow noopener noreferrer">' + \
|
'rel="nofollow noopener noreferrer">' + \
|
||||||
'<span class="newswireItemVotedOn">' + \
|
'<span class="newswireItemVotedOn">' + \
|
||||||
faviconLink + title + \
|
faviconLink + title + '</span></a>' + totalVotesStr
|
||||||
'</span></a>' + totalVotesStr
|
|
||||||
if moderator:
|
if moderator:
|
||||||
htmlStr += \
|
htmlStr += \
|
||||||
' ' + dateShown + '<a href="/users/' + nickname + \
|
' ' + dateShown + '<a href="/users/' + nickname + \
|
||||||
|
|
@ -312,8 +310,7 @@ def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
|
||||||
htmlStr += '<p class="newswireItem">' + \
|
htmlStr += '<p class="newswireItem">' + \
|
||||||
'<a href="' + url + '" target="_blank" ' + \
|
'<a href="' + url + '" target="_blank" ' + \
|
||||||
'rel="nofollow noopener noreferrer">' + \
|
'rel="nofollow noopener noreferrer">' + \
|
||||||
faviconLink + title + '</a>' + \
|
faviconLink + title + '</a>' + totalVotesStr
|
||||||
totalVotesStr
|
|
||||||
htmlStr += ' <span class="newswireDate">'
|
htmlStr += ' <span class="newswireDate">'
|
||||||
htmlStr += dateShown + '</span></p>\n'
|
htmlStr += dateShown + '</span></p>\n'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,8 +137,7 @@ def htmlConfirmRemoveSharedItem(cssCache: {}, translate: {}, baseDir: str,
|
||||||
if os.path.isfile(baseDir + '/follow.css'):
|
if os.path.isfile(baseDir + '/follow.css'):
|
||||||
cssFilename = baseDir + '/follow.css'
|
cssFilename = baseDir + '/follow.css'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
|
||||||
sharesStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
sharesStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
sharesStr += '<div class="follow">\n'
|
sharesStr += '<div class="follow">\n'
|
||||||
sharesStr += ' <div class="followAvatar">\n'
|
sharesStr += ' <div class="followAvatar">\n'
|
||||||
|
|
@ -186,8 +185,7 @@ def htmlConfirmFollow(cssCache: {}, translate: {}, baseDir: str,
|
||||||
if os.path.isfile(baseDir + '/follow.css'):
|
if os.path.isfile(baseDir + '/follow.css'):
|
||||||
cssFilename = baseDir + '/follow.css'
|
cssFilename = baseDir + '/follow.css'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
|
||||||
followStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
followStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
followStr += '<div class="follow">\n'
|
followStr += '<div class="follow">\n'
|
||||||
followStr += ' <div class="followAvatar">\n'
|
followStr += ' <div class="followAvatar">\n'
|
||||||
|
|
@ -232,8 +230,7 @@ def htmlConfirmUnfollow(cssCache: {}, translate: {}, baseDir: str,
|
||||||
if os.path.isfile(baseDir + '/follow.css'):
|
if os.path.isfile(baseDir + '/follow.css'):
|
||||||
cssFilename = baseDir + '/follow.css'
|
cssFilename = baseDir + '/follow.css'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
|
||||||
followStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
followStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
followStr += '<div class="follow">\n'
|
followStr += '<div class="follow">\n'
|
||||||
followStr += ' <div class="followAvatar">\n'
|
followStr += ' <div class="followAvatar">\n'
|
||||||
|
|
@ -279,8 +276,7 @@ def htmlConfirmUnblock(cssCache: {}, translate: {}, baseDir: str,
|
||||||
if os.path.isfile(baseDir + '/follow.css'):
|
if os.path.isfile(baseDir + '/follow.css'):
|
||||||
cssFilename = baseDir + '/follow.css'
|
cssFilename = baseDir + '/follow.css'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
|
||||||
blockStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
blockStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
blockStr += '<div class="block">\n'
|
blockStr += '<div class="block">\n'
|
||||||
blockStr += ' <div class="blockAvatar">\n'
|
blockStr += ' <div class="blockAvatar">\n'
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,17 @@ def _htmlFollowingDataList(baseDir: str, nickname: str,
|
||||||
listStr = '<datalist id="followingHandles">\n'
|
listStr = '<datalist id="followingHandles">\n'
|
||||||
followingFilename = \
|
followingFilename = \
|
||||||
baseDir + '/accounts/' + nickname + '@' + domain + '/following.txt'
|
baseDir + '/accounts/' + nickname + '@' + domain + '/following.txt'
|
||||||
|
msg = None
|
||||||
if os.path.isfile(followingFilename):
|
if os.path.isfile(followingFilename):
|
||||||
with open(followingFilename, 'r') as followingFile:
|
with open(followingFilename, 'r') as followingFile:
|
||||||
msg = followingFile.read()
|
msg = followingFile.read()
|
||||||
# add your own handle, so that you can send DMs
|
# add your own handle, so that you can send DMs
|
||||||
# to yourself as reminders
|
# to yourself as reminders
|
||||||
msg += nickname + '@' + domainFull + '\n'
|
msg += nickname + '@' + domainFull + '\n'
|
||||||
|
if msg:
|
||||||
# include petnames
|
# include petnames
|
||||||
petnamesFilename = \
|
petnamesFilename = \
|
||||||
baseDir + '/accounts/' + \
|
baseDir + '/accounts/' + nickname + '@' + domain + '/petnames.txt'
|
||||||
nickname + '@' + domain + '/petnames.txt'
|
|
||||||
if os.path.isfile(petnamesFilename):
|
if os.path.isfile(petnamesFilename):
|
||||||
followingList = []
|
followingList = []
|
||||||
with open(petnamesFilename, 'r') as petnamesFile:
|
with open(petnamesFilename, 'r') as petnamesFile:
|
||||||
|
|
@ -53,8 +54,7 @@ def _htmlFollowingDataList(baseDir: str, nickname: str,
|
||||||
if followingList:
|
if followingList:
|
||||||
for followingAddress in followingList:
|
for followingAddress in followingList:
|
||||||
if followingAddress:
|
if followingAddress:
|
||||||
listStr += \
|
listStr += '<option>@' + followingAddress + '</option>\n'
|
||||||
'<option>@' + followingAddress + '</option>\n'
|
|
||||||
listStr += '</datalist>\n'
|
listStr += '</datalist>\n'
|
||||||
return listStr
|
return listStr
|
||||||
|
|
||||||
|
|
@ -84,8 +84,7 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||||
dropDownContent += ' <label for="my-newPostDropdown"\n'
|
dropDownContent += ' <label for="my-newPostDropdown"\n'
|
||||||
dropDownContent += ' data-toggle="newPostDropdown">\n'
|
dropDownContent += ' data-toggle="newPostDropdown">\n'
|
||||||
dropDownContent += ' <img loading="lazy" alt="" title="" src="/' + \
|
dropDownContent += ' <img loading="lazy" alt="" title="" src="/' + \
|
||||||
'icons/' + scopeIcon + '"/><b>' + \
|
'icons/' + scopeIcon + '"/><b>' + scopeDescription + '</b></label>\n'
|
||||||
scopeDescription + '</b></label>\n'
|
|
||||||
|
|
||||||
if noDropDown:
|
if noDropDown:
|
||||||
dropDownContent += '</div></nav>\n'
|
dropDownContent += '</div></nav>\n'
|
||||||
|
|
@ -144,12 +143,6 @@ def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
|
||||||
'icons/scope_reminder.png"/><b>' + \
|
'icons/scope_reminder.png"/><b>' + \
|
||||||
translate['Reminder'] + '</b><br>' + \
|
translate['Reminder'] + '</b><br>' + \
|
||||||
translate['Scheduled note to yourself'] + '</a></li>\n'
|
translate['Scheduled note to yourself'] + '</a></li>\n'
|
||||||
# dropDownContent += \
|
|
||||||
# '<li><a href="' + pathBase + dropdownEventSuffix + \
|
|
||||||
# '"><img loading="lazy" alt="" title="" src="/' + \
|
|
||||||
# 'icons/scope_event.png"/><b>' + \
|
|
||||||
# translate['Event'] + '</b><br>' + \
|
|
||||||
# translate['Create an event'] + '</a></li>\n'
|
|
||||||
dropDownContent += \
|
dropDownContent += \
|
||||||
'<li><a href="' + pathBase + dropdownReportSuffix + \
|
'<li><a href="' + pathBase + dropdownReportSuffix + \
|
||||||
'" accesskey="' + accessKeys['reportButton'] + '">' + \
|
'" accesskey="' + accessKeys['reportButton'] + '">' + \
|
||||||
|
|
@ -230,8 +223,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
showPublicOnDropdown = False
|
showPublicOnDropdown = False
|
||||||
else:
|
else:
|
||||||
newPostText = \
|
newPostText = \
|
||||||
'<h1>' + \
|
'<h1>' + translate['Write your report below.'] + '</h1>\n'
|
||||||
translate['Write your report below.'] + '</h1>\n'
|
|
||||||
|
|
||||||
# custom report header with any additional instructions
|
# custom report header with any additional instructions
|
||||||
if os.path.isfile(baseDir + '/accounts/report.txt'):
|
if os.path.isfile(baseDir + '/accounts/report.txt'):
|
||||||
|
|
@ -319,7 +311,6 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
translate['Subject or Content Warning (optional)'] + '...'
|
translate['Subject or Content Warning (optional)'] + '...'
|
||||||
placeholderMentions = ''
|
placeholderMentions = ''
|
||||||
if inReplyTo:
|
if inReplyTo:
|
||||||
# mentionsAndContent = getMentionsString(content)
|
|
||||||
placeholderMentions = \
|
placeholderMentions = \
|
||||||
translate['Replying to'] + '...'
|
translate['Replying to'] + '...'
|
||||||
placeholderMessage = translate['Write something'] + '...'
|
placeholderMessage = translate['Write something'] + '...'
|
||||||
|
|
@ -582,8 +573,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
dateAndLocation += '<input type="text" name="category">\n'
|
dateAndLocation += '<input type="text" name="category">\n'
|
||||||
dateAndLocation += '</div>\n'
|
dateAndLocation += '</div>\n'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
|
||||||
newPostForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
newPostForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
|
|
||||||
newPostForm += \
|
newPostForm += \
|
||||||
|
|
@ -711,17 +701,11 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
submitText + '" ' + \
|
submitText + '" ' + \
|
||||||
'accesskey="' + accessKeys['submitButton'] + '"></td>\n'
|
'accesskey="' + accessKeys['submitButton'] + '"></td>\n'
|
||||||
|
|
||||||
newPostForm += ' </tr>\n'
|
newPostForm += ' </tr>\n</table>\n'
|
||||||
newPostForm += '</table>\n'
|
|
||||||
newPostForm += ' </div>\n'
|
newPostForm += ' </div>\n'
|
||||||
|
|
||||||
newPostForm += ' <div class="containerSubmitNewPost"><center>\n'
|
newPostForm += ' <div class="containerSubmitNewPost"><center>\n'
|
||||||
|
|
||||||
# newPostForm += \
|
|
||||||
# ' <a href="' + pathBase + \
|
|
||||||
# '/inbox"><button class="cancelbtn">' + \
|
|
||||||
# translate['Go Back'] + '</button></a>\n'
|
|
||||||
|
|
||||||
newPostForm += ' </center></div>\n'
|
newPostForm += ' </center></div>\n'
|
||||||
|
|
||||||
newPostForm += replyStr
|
newPostForm += replyStr
|
||||||
|
|
@ -777,14 +761,13 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
|
||||||
if not mediaInstance or replyStr:
|
if not mediaInstance or replyStr:
|
||||||
newPostForm += newPostImageSection
|
newPostForm += newPostImageSection
|
||||||
|
|
||||||
newPostForm += ' <div class="container">\n'
|
|
||||||
newPostForm += \
|
newPostForm += \
|
||||||
|
' <div class="container">\n' + \
|
||||||
' <input type="submit" name="submitPost" value="' + \
|
' <input type="submit" name="submitPost" value="' + \
|
||||||
submitText + '">\n'
|
submitText + '">\n' + \
|
||||||
newPostForm += ' </div>\n'
|
' </div>\n' + \
|
||||||
|
' </div>\n' + \
|
||||||
newPostForm += ' </div>\n'
|
'</form>\n'
|
||||||
newPostForm += '</form>\n'
|
|
||||||
|
|
||||||
if not reportUrl:
|
if not reportUrl:
|
||||||
newPostForm = \
|
newPostForm = \
|
||||||
|
|
|
||||||
|
|
@ -128,22 +128,24 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
||||||
if loginButton:
|
if loginButton:
|
||||||
profileHeaderStr += '<center>' + loginButton + '</center>\n'
|
profileHeaderStr += '<center>' + loginButton + '</center>\n'
|
||||||
|
|
||||||
profileHeaderStr += '<table class="timeline">\n'
|
profileHeaderStr += \
|
||||||
profileHeaderStr += ' <colgroup>\n'
|
'<table class="timeline">\n' + \
|
||||||
profileHeaderStr += ' <col span="1" class="column-left">\n'
|
' <colgroup>\n' + \
|
||||||
profileHeaderStr += ' <col span="1" class="column-center">\n'
|
' <col span="1" class="column-left">\n' + \
|
||||||
profileHeaderStr += ' <col span="1" class="column-right">\n'
|
' <col span="1" class="column-center">\n' + \
|
||||||
profileHeaderStr += ' </colgroup>\n'
|
' <col span="1" class="column-right">\n' + \
|
||||||
profileHeaderStr += ' <tbody>\n'
|
' </colgroup>\n' + \
|
||||||
profileHeaderStr += ' <tr>\n'
|
' <tbody>\n' + \
|
||||||
profileHeaderStr += ' <td valign="top" class="col-left">\n'
|
' <tr>\n' + \
|
||||||
|
' <td valign="top" class="col-left">\n'
|
||||||
profileHeaderStr += \
|
profileHeaderStr += \
|
||||||
getLeftColumnContent(baseDir, 'news', domainFull,
|
getLeftColumnContent(baseDir, 'news', domainFull,
|
||||||
httpPrefix, translate,
|
httpPrefix, translate,
|
||||||
False, False, None, rssIconAtTop, True,
|
False, False, None, rssIconAtTop, True,
|
||||||
True, theme, accessKeys)
|
True, theme, accessKeys)
|
||||||
profileHeaderStr += ' </td>\n'
|
profileHeaderStr += \
|
||||||
profileHeaderStr += ' <td valign="top" class="col-center">\n'
|
' </td>\n' + \
|
||||||
|
' <td valign="top" class="col-center">\n'
|
||||||
|
|
||||||
profileStr = profileHeaderStr
|
profileStr = profileHeaderStr
|
||||||
|
|
||||||
|
|
@ -177,10 +179,11 @@ def htmlFrontScreen(rssIconAtTop: bool,
|
||||||
False, None, False, False,
|
False, None, False, False,
|
||||||
False, True, authorized, True, theme,
|
False, True, authorized, True, theme,
|
||||||
defaultTimeline, accessKeys)
|
defaultTimeline, accessKeys)
|
||||||
profileFooterStr += ' </td>\n'
|
profileFooterStr += \
|
||||||
profileFooterStr += ' </tr>\n'
|
' </td>\n' + \
|
||||||
profileFooterStr += ' </tbody>\n'
|
' </tr>\n' + \
|
||||||
profileFooterStr += '</table>\n'
|
' </tbody>\n' + \
|
||||||
|
'</table>\n'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = \
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
getConfigParam(baseDir, 'instanceTitle')
|
||||||
|
|
|
||||||
|
|
@ -29,17 +29,19 @@ def getHashtagCategoriesFeed(baseDir: str,
|
||||||
if not hashtagCategories:
|
if not hashtagCategories:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
rssStr = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
|
rssStr = \
|
||||||
rssStr += "<rss version=\"2.0\">\n"
|
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" + \
|
||||||
rssStr += '<channel>\n'
|
"<rss version=\"2.0\">\n" + \
|
||||||
rssStr += ' <title>#categories</title>\n'
|
'<channel>\n' + \
|
||||||
|
' <title>#categories</title>\n'
|
||||||
|
|
||||||
rssDateStr = \
|
rssDateStr = \
|
||||||
datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S UT")
|
datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S UT")
|
||||||
|
|
||||||
for categoryStr, hashtagList in hashtagCategories.items():
|
for categoryStr, hashtagList in hashtagCategories.items():
|
||||||
rssStr += '<item>\n'
|
rssStr += \
|
||||||
rssStr += ' <title>' + categoryStr + '</title>\n'
|
'<item>\n' + \
|
||||||
|
' <title>' + categoryStr + '</title>\n'
|
||||||
listStr = ''
|
listStr = ''
|
||||||
for hashtag in hashtagList:
|
for hashtag in hashtagList:
|
||||||
if ':' in hashtag:
|
if ':' in hashtag:
|
||||||
|
|
@ -47,75 +49,18 @@ def getHashtagCategoriesFeed(baseDir: str,
|
||||||
if '&' in hashtag:
|
if '&' in hashtag:
|
||||||
continue
|
continue
|
||||||
listStr += hashtag + ' '
|
listStr += hashtag + ' '
|
||||||
rssStr += ' <description>' + listStr.strip() + '</description>\n'
|
rssStr += \
|
||||||
rssStr += ' <link/>\n'
|
' <description>' + listStr.strip() + '</description>\n' + \
|
||||||
rssStr += ' <pubDate>' + rssDateStr + '</pubDate>\n'
|
' <link/>\n' + \
|
||||||
rssStr += '</item>\n'
|
' <pubDate>' + rssDateStr + '</pubDate>\n' + \
|
||||||
|
'</item>\n'
|
||||||
|
|
||||||
rssStr += '</channel>\n'
|
rssStr += \
|
||||||
rssStr += '</rss>\n'
|
'</channel>\n' + \
|
||||||
|
'</rss>\n'
|
||||||
return rssStr
|
return rssStr
|
||||||
|
|
||||||
|
|
||||||
def _getHashtagDomainMax(domainHistogram: {}) -> str:
|
|
||||||
"""Returns the domain with the maximum number of hashtags
|
|
||||||
"""
|
|
||||||
maxCount = 1
|
|
||||||
maxDomain = None
|
|
||||||
for domain, count in domainHistogram.items():
|
|
||||||
if count > maxCount:
|
|
||||||
maxDomain = domain
|
|
||||||
maxCount = count
|
|
||||||
return maxDomain
|
|
||||||
|
|
||||||
|
|
||||||
def _getHashtagDomainHistogram(domainHistogram: {}, translate: {}) -> str:
|
|
||||||
"""Returns the html for a histogram of domains
|
|
||||||
from which hashtags are coming
|
|
||||||
"""
|
|
||||||
totalCount = 0
|
|
||||||
for domain, count in domainHistogram.items():
|
|
||||||
totalCount += count
|
|
||||||
if totalCount == 0:
|
|
||||||
return ''
|
|
||||||
|
|
||||||
htmlStr = ''
|
|
||||||
histogramHeaderStr = '<br><br><center>\n'
|
|
||||||
histogramHeaderStr += ' <h1>' + translate['Hashtag origins'] + '</h1>\n'
|
|
||||||
histogramHeaderStr += ' <table class="domainHistogram">\n'
|
|
||||||
histogramHeaderStr += ' <colgroup>\n'
|
|
||||||
histogramHeaderStr += ' <col span="1" class="domainHistogramLeft">\n'
|
|
||||||
histogramHeaderStr += ' <col span="1" class="domainHistogramRight">\n'
|
|
||||||
histogramHeaderStr += ' </colgroup>\n'
|
|
||||||
histogramHeaderStr += ' <tbody>\n'
|
|
||||||
histogramHeaderStr += ' <tr>\n'
|
|
||||||
|
|
||||||
leftColStr = ''
|
|
||||||
rightColStr = ''
|
|
||||||
|
|
||||||
for i in range(len(domainHistogram)):
|
|
||||||
domain = _getHashtagDomainMax(domainHistogram)
|
|
||||||
if not domain:
|
|
||||||
break
|
|
||||||
percent = int(domainHistogram[domain] * 100 / totalCount)
|
|
||||||
if histogramHeaderStr:
|
|
||||||
htmlStr += histogramHeaderStr
|
|
||||||
histogramHeaderStr = None
|
|
||||||
leftColStr += str(percent) + '%<br>'
|
|
||||||
rightColStr += domain + '<br>'
|
|
||||||
del domainHistogram[domain]
|
|
||||||
|
|
||||||
if htmlStr:
|
|
||||||
htmlStr += ' <td>' + leftColStr + '</td>\n'
|
|
||||||
htmlStr += ' <td>' + rightColStr + '</td>\n'
|
|
||||||
htmlStr += ' </tr>\n'
|
|
||||||
htmlStr += ' </tbody>\n'
|
|
||||||
htmlStr += ' </table>\n'
|
|
||||||
htmlStr += '</center>\n'
|
|
||||||
|
|
||||||
return htmlStr
|
|
||||||
|
|
||||||
|
|
||||||
def htmlHashTagSwarm(baseDir: str, actor: str, translate: {}) -> str:
|
def htmlHashTagSwarm(baseDir: str, actor: str, translate: {}) -> str:
|
||||||
"""Returns a tag swarm of today's hashtags
|
"""Returns a tag swarm of today's hashtags
|
||||||
"""
|
"""
|
||||||
|
|
@ -244,7 +189,6 @@ def htmlHashTagSwarm(baseDir: str, actor: str, translate: {}) -> str:
|
||||||
getContentWarningButton('alltags', translate, tagSwarmStr)
|
getContentWarningButton('alltags', translate, tagSwarmStr)
|
||||||
|
|
||||||
tagSwarmHtml = categorySwarmStr + tagSwarmStr.strip() + '\n'
|
tagSwarmHtml = categorySwarmStr + tagSwarmStr.strip() + '\n'
|
||||||
# tagSwarmHtml += _getHashtagDomainHistogram(domainHistogram, translate)
|
|
||||||
return tagSwarmHtml
|
return tagSwarmHtml
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -279,10 +223,11 @@ def htmlSearchHashtagCategory(cssCache: {}, translate: {},
|
||||||
htmlStr += '<img loading="lazy" class="timeline-banner" src="' + \
|
htmlStr += '<img loading="lazy" class="timeline-banner" src="' + \
|
||||||
actor + '/' + searchBannerFile + '" alt="" /></a>\n'
|
actor + '/' + searchBannerFile + '" alt="" /></a>\n'
|
||||||
|
|
||||||
htmlStr += '<div class="follow">'
|
htmlStr += \
|
||||||
htmlStr += '<center><br><br><br>'
|
'<div class="follow">' + \
|
||||||
htmlStr += '<h1><a href="' + actor + '/search"><b>'
|
'<center><br><br><br>' + \
|
||||||
htmlStr += translate['Category'] + ': ' + categoryStr + '</b></a></h1>'
|
'<h1><a href="' + actor + '/search"><b>' + \
|
||||||
|
translate['Category'] + ': ' + categoryStr + '</b></a></h1>'
|
||||||
|
|
||||||
hashtagsDict = getHashtagCategories(baseDir, True, categoryStr)
|
hashtagsDict = getHashtagCategories(baseDir, True, categoryStr)
|
||||||
if hashtagsDict:
|
if hashtagsDict:
|
||||||
|
|
@ -293,7 +238,8 @@ def htmlSearchHashtagCategory(cssCache: {}, translate: {},
|
||||||
'<a href="' + actor + '/tags/' + tagName + \
|
'<a href="' + actor + '/tags/' + tagName + \
|
||||||
'" class="hashtagswarm">' + tagName + '</a>\n'
|
'" class="hashtagswarm">' + tagName + '</a>\n'
|
||||||
|
|
||||||
htmlStr += '</center>'
|
htmlStr += \
|
||||||
htmlStr += '</div>'
|
'</center>' + \
|
||||||
|
'</div>'
|
||||||
htmlStr += htmlFooter()
|
htmlStr += htmlFooter()
|
||||||
return htmlStr
|
return htmlStr
|
||||||
|
|
|
||||||
|
|
@ -54,8 +54,7 @@ def headerButtonsTimeline(defaultTimeline: str,
|
||||||
# first button
|
# first button
|
||||||
if defaultTimeline == 'tlmedia':
|
if defaultTimeline == 'tlmedia':
|
||||||
tlStr += \
|
tlStr += \
|
||||||
'<a href="' + usersPath + \
|
'<a href="' + usersPath + '/tlmedia" tabindex="-1" ' + \
|
||||||
'/tlmedia" tabindex="-1" ' + \
|
|
||||||
'accesskey="' + accessKeys['menuMedia'] + '"' + \
|
'accesskey="' + accessKeys['menuMedia'] + '"' + \
|
||||||
'><button class="' + \
|
'><button class="' + \
|
||||||
mediaButton + '"><span>' + translate['Media'] + \
|
mediaButton + '"><span>' + translate['Media'] + \
|
||||||
|
|
@ -105,8 +104,7 @@ def headerButtonsTimeline(defaultTimeline: str,
|
||||||
if defaultTimeline != 'tlmedia':
|
if defaultTimeline != 'tlmedia':
|
||||||
if not minimal and not featuresHeader:
|
if not minimal and not featuresHeader:
|
||||||
tlStr += \
|
tlStr += \
|
||||||
'<a href="' + usersPath + \
|
'<a href="' + usersPath + '/tlmedia" tabindex="-1" ' + \
|
||||||
'/tlmedia" tabindex="-1" ' + \
|
|
||||||
'accesskey="' + accessKeys['menuMedia'] + '">' + \
|
'accesskey="' + accessKeys['menuMedia'] + '">' + \
|
||||||
'<button class="' + \
|
'<button class="' + \
|
||||||
mediaButton + '"><span>' + translate['Media'] + \
|
mediaButton + '"><span>' + translate['Media'] + \
|
||||||
|
|
@ -206,10 +204,8 @@ def headerButtonsTimeline(defaultTimeline: str,
|
||||||
if not featuresHeader:
|
if not featuresHeader:
|
||||||
# button for the outbox
|
# button for the outbox
|
||||||
tlStr += \
|
tlStr += \
|
||||||
'<a href="' + usersPath + \
|
'<a href="' + usersPath + '/outbox"><button class="' + \
|
||||||
'/outbox"><button class="' + \
|
sentButton + '" tabindex="-1"><span>' + translate['Sent'] + \
|
||||||
sentButton + '" tabindex="-1">' + \
|
|
||||||
'<span>' + translate['Sent'] + \
|
|
||||||
'</span></button></a>'
|
'</span></button></a>'
|
||||||
|
|
||||||
# add other buttons
|
# add other buttons
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,8 @@ def htmlGetLoginCredentials(loginParams: str,
|
||||||
password = None
|
password = None
|
||||||
register = False
|
register = False
|
||||||
for arg in loginArgs:
|
for arg in loginArgs:
|
||||||
if '=' in arg:
|
if '=' not in arg:
|
||||||
|
continue
|
||||||
if arg.split('=', 1)[0] == 'username':
|
if arg.split('=', 1)[0] == 'username':
|
||||||
nickname = arg.split('=', 1)[1]
|
nickname = arg.split('=', 1)[1]
|
||||||
if nickname.startswith('@'):
|
if nickname.startswith('@'):
|
||||||
|
|
@ -103,8 +104,7 @@ def htmlLogin(cssCache: {}, translate: {},
|
||||||
else:
|
else:
|
||||||
loginText = \
|
loginText = \
|
||||||
'<p class="login-text">' + \
|
'<p class="login-text">' + \
|
||||||
translate['Please enter some credentials'] + '</p>'
|
translate['Please enter some credentials'] + '</p>' + \
|
||||||
loginText += \
|
|
||||||
'<p class="login-text">' + \
|
'<p class="login-text">' + \
|
||||||
translate['You will become the admin of this site.'] + \
|
translate['You will become the admin of this site.'] + \
|
||||||
'</p>'
|
'</p>'
|
||||||
|
|
@ -132,8 +132,7 @@ def htmlLogin(cssCache: {}, translate: {},
|
||||||
|
|
||||||
TOSstr = \
|
TOSstr = \
|
||||||
'<p class="login-text"><a href="/about">' + \
|
'<p class="login-text"><a href="/about">' + \
|
||||||
translate['About this Instance'] + '</a></p>'
|
translate['About this Instance'] + '</a></p>' + \
|
||||||
TOSstr += \
|
|
||||||
'<p class="login-text"><a href="/terms">' + \
|
'<p class="login-text"><a href="/terms">' + \
|
||||||
translate['Terms of Service'] + '</a></p>'
|
translate['Terms of Service'] + '</a></p>'
|
||||||
|
|
||||||
|
|
@ -153,34 +152,32 @@ def htmlLogin(cssCache: {}, translate: {},
|
||||||
htmlHeaderWithWebsiteMarkup(cssFilename, instanceTitle,
|
htmlHeaderWithWebsiteMarkup(cssFilename, instanceTitle,
|
||||||
httpPrefix, domain,
|
httpPrefix, domain,
|
||||||
systemLanguage)
|
systemLanguage)
|
||||||
loginForm += '<br>\n'
|
|
||||||
loginForm += '<form method="POST" action="/login">\n'
|
|
||||||
loginForm += ' <div class="imgcontainer">\n'
|
|
||||||
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
loginForm += textModeLogoHtml + '\n'
|
|
||||||
loginForm += \
|
loginForm += \
|
||||||
|
'<br>\n' + \
|
||||||
|
'<form method="POST" action="/login">\n' + \
|
||||||
|
' <div class="imgcontainer">\n' + \
|
||||||
|
textModeLogoHtml + '\n' + \
|
||||||
' <img loading="lazy" src="' + loginImage + \
|
' <img loading="lazy" src="' + loginImage + \
|
||||||
'" alt="' + instanceTitle + '" class="loginimage">\n'
|
'" alt="' + instanceTitle + '" class="loginimage">\n' + \
|
||||||
loginForm += loginText + TOSstr + '\n'
|
loginText + TOSstr + '\n' + \
|
||||||
loginForm += ' </div>\n'
|
' </div>\n' + \
|
||||||
loginForm += '\n'
|
'\n' + \
|
||||||
loginForm += ' <div class="container">\n'
|
' <div class="container">\n' + \
|
||||||
loginForm += ' <label for="nickname"><b>' + \
|
' <label for="nickname"><b>' + \
|
||||||
translate['Nickname'] + '</b></label>\n'
|
translate['Nickname'] + '</b></label>\n' + \
|
||||||
loginForm += \
|
|
||||||
' <input type="text" ' + autocompleteStr + ' placeholder="' + \
|
' <input type="text" ' + autocompleteStr + ' placeholder="' + \
|
||||||
translate['Enter Nickname'] + '" name="username" required autofocus>\n'
|
translate['Enter Nickname'] + \
|
||||||
loginForm += '\n'
|
'" name="username" required autofocus>\n' + \
|
||||||
loginForm += ' <label for="password"><b>' + \
|
'\n' + \
|
||||||
translate['Password'] + '</b></label>\n'
|
' <label for="password"><b>' + \
|
||||||
loginForm += \
|
translate['Password'] + '</b></label>\n' + \
|
||||||
' <input type="password" ' + autocompleteStr + \
|
' <input type="password" ' + autocompleteStr + \
|
||||||
' placeholder="' + translate['Enter Password'] + \
|
' placeholder="' + translate['Enter Password'] + \
|
||||||
'" name="password" required>\n'
|
'" name="password" required>\n' + \
|
||||||
loginForm += loginButtonStr + registerButtonStr + '\n'
|
loginButtonStr + registerButtonStr + '\n' + \
|
||||||
loginForm += ' </div>\n'
|
' </div>\n' + \
|
||||||
loginForm += '</form>\n'
|
'</form>\n' + \
|
||||||
loginForm += \
|
|
||||||
'<a href="https://gitlab.com/bashrc2/epicyon">' + \
|
'<a href="https://gitlab.com/bashrc2/epicyon">' + \
|
||||||
'<img loading="lazy" class="license" title="' + \
|
'<img loading="lazy" class="license" title="' + \
|
||||||
translate['Get the source code'] + '" alt="' + \
|
translate['Get the source code'] + '" alt="' + \
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
||||||
__module_group__ = "Timeline"
|
__module_group__ = "Timeline"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from utils import validUrlPrefix
|
||||||
|
|
||||||
|
|
||||||
def loadPeertubeInstances(baseDir: str, peertubeInstances: []) -> None:
|
def loadPeertubeInstances(baseDir: str, peertubeInstances: []) -> None:
|
||||||
|
|
@ -110,6 +111,8 @@ def _addEmbeddedVideoFromSites(translate: {}, content: str,
|
||||||
|
|
||||||
if '"https://' in content:
|
if '"https://' in content:
|
||||||
if peertubeInstances:
|
if peertubeInstances:
|
||||||
|
# only create an embedded video for a limited set of
|
||||||
|
# peertube sites.
|
||||||
peerTubeSites = peertubeInstances
|
peerTubeSites = peertubeInstances
|
||||||
else:
|
else:
|
||||||
# A default selection of the current larger peertube sites,
|
# A default selection of the current larger peertube sites,
|
||||||
|
|
@ -160,9 +163,11 @@ def _addEmbeddedVideoFromSites(translate: {}, content: str,
|
||||||
else:
|
else:
|
||||||
siteStr = 'https://' + site
|
siteStr = 'https://' + site
|
||||||
siteStr = '"' + siteStr
|
siteStr = '"' + siteStr
|
||||||
if siteStr in content:
|
if siteStr not in content:
|
||||||
|
continue
|
||||||
url = content.split(siteStr)[1]
|
url = content.split(siteStr)[1]
|
||||||
if '"' in url:
|
if '"' not in url:
|
||||||
|
continue
|
||||||
url = url.split('"')[0].replace('/watch/', '/embed/')
|
url = url.split('"')[0].replace('/watch/', '/embed/')
|
||||||
content = \
|
content = \
|
||||||
content + "<center>\n<iframe loading=\"lazy\" " + \
|
content + "<center>\n<iframe loading=\"lazy\" " + \
|
||||||
|
|
@ -205,19 +210,14 @@ def _addEmbeddedAudio(translate: {}, content: str) -> str:
|
||||||
if not w.endswith(extension):
|
if not w.endswith(extension):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not (w.startswith('http') or w.startswith('dat:') or
|
if not validUrlPrefix(w):
|
||||||
w.startswith('hyper:') or w.startswith('i2p:') or
|
|
||||||
w.startswith('gnunet:') or
|
|
||||||
'/' in w):
|
|
||||||
continue
|
continue
|
||||||
url = w
|
|
||||||
content += '<center>\n<audio controls>\n'
|
|
||||||
content += \
|
content += \
|
||||||
'<source src="' + url + '" type="audio/' + \
|
'<center>\n<audio controls>\n' + \
|
||||||
extension.replace('.', '') + '">'
|
'<source src="' + w + '" type="audio/' + \
|
||||||
content += \
|
extension.replace('.', '') + '">' + \
|
||||||
translate['Your browser does not support the audio element.']
|
translate['Your browser does not support the audio element.'] + \
|
||||||
content += '</audio>\n</center>\n'
|
'</audio>\n</center>\n'
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -251,23 +251,17 @@ def _addEmbeddedVideo(translate: {}, content: str) -> str:
|
||||||
w = w[:-1]
|
w = w[:-1]
|
||||||
if not w.endswith(extension):
|
if not w.endswith(extension):
|
||||||
continue
|
continue
|
||||||
if not (w.startswith('http') or w.startswith('dat:') or
|
if not validUrlPrefix(w):
|
||||||
w.startswith('hyper:') or w.startswith('i2p:') or
|
|
||||||
w.startswith('gnunet:') or
|
|
||||||
'/' in w):
|
|
||||||
continue
|
continue
|
||||||
url = w
|
|
||||||
content += \
|
content += \
|
||||||
'<center><figure id="videoContainer" ' + \
|
'<center><figure id="videoContainer" ' + \
|
||||||
'data-fullscreen="false">\n' + \
|
'data-fullscreen="false">\n' + \
|
||||||
' <video id="video" controls ' + \
|
' <video id="video" controls ' + \
|
||||||
'preload="metadata">\n'
|
'preload="metadata">\n' + \
|
||||||
content += \
|
'<source src="' + w + '" type="video/' + \
|
||||||
'<source src="' + url + '" type="video/' + \
|
extension.replace('.', '') + '">\n' + \
|
||||||
extension.replace('.', '') + '">\n'
|
translate['Your browser does not support the video element.'] + \
|
||||||
content += \
|
'</video>\n</figure>\n</center>\n'
|
||||||
translate['Your browser does not support the video element.']
|
|
||||||
content += '</video>\n</figure>\n</center>\n'
|
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -398,9 +398,10 @@ def htmlPersonOptions(defaultTimeline: str,
|
||||||
'accesskey="' + accessKeys['enterNotes'] + '">' + \
|
'accesskey="' + accessKeys['enterNotes'] + '">' + \
|
||||||
personNotes + '</textarea>\n'
|
personNotes + '</textarea>\n'
|
||||||
|
|
||||||
optionsStr += ' </form>\n'
|
optionsStr += \
|
||||||
optionsStr += '</center>\n'
|
' </form>\n' + \
|
||||||
optionsStr += '</div>\n'
|
'</center>\n' + \
|
||||||
optionsStr += '</div>\n'
|
'</div>\n' + \
|
||||||
|
'</div>\n'
|
||||||
optionsStr += htmlFooter()
|
optionsStr += htmlFooter()
|
||||||
return optionsStr
|
return optionsStr
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ from posts import postIsMuted
|
||||||
from posts import getPersonBox
|
from posts import getPersonBox
|
||||||
from posts import downloadAnnounce
|
from posts import downloadAnnounce
|
||||||
from posts import populateRepliesJson
|
from posts import populateRepliesJson
|
||||||
|
from utils import hasObjectDict
|
||||||
from utils import updateAnnounceCollection
|
from utils import updateAnnounceCollection
|
||||||
from utils import isPGPEncrypted
|
from utils import isPGPEncrypted
|
||||||
from utils import isDM
|
from utils import isDM
|
||||||
|
|
@ -840,8 +841,7 @@ def _getPostTitleAnnounceHtml(baseDir: str,
|
||||||
postJsonObject)
|
postJsonObject)
|
||||||
else:
|
else:
|
||||||
titleStr += \
|
titleStr += \
|
||||||
_announceUnattributedHtml(translate,
|
_announceUnattributedHtml(translate, postJsonObject)
|
||||||
postJsonObject)
|
|
||||||
else:
|
else:
|
||||||
titleStr += \
|
titleStr += \
|
||||||
_announceUnattributedHtml(translate, postJsonObject)
|
_announceUnattributedHtml(translate, postJsonObject)
|
||||||
|
|
@ -1339,7 +1339,7 @@ def individualPostAsHtml(allowDownloads: bool,
|
||||||
|
|
||||||
_logPostTiming(enableTimingLog, postStartTime, '8')
|
_logPostTiming(enableTimingLog, postStartTime, '8')
|
||||||
|
|
||||||
if not isinstance(postJsonObject['object'], dict):
|
if not hasObjectDict(postJsonObject):
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
# if this post should be public then check its recipients
|
# if this post should be public then check its recipients
|
||||||
|
|
@ -1762,7 +1762,7 @@ def htmlIndividualPost(cssCache: {},
|
||||||
messageId = removeIdEnding(postJsonObject['id'])
|
messageId = removeIdEnding(postJsonObject['id'])
|
||||||
|
|
||||||
# show the previous posts
|
# show the previous posts
|
||||||
if isinstance(postJsonObject['object'], dict):
|
if hasObjectDict(postJsonObject):
|
||||||
while postJsonObject['object'].get('inReplyTo'):
|
while postJsonObject['object'].get('inReplyTo'):
|
||||||
postFilename = \
|
postFilename = \
|
||||||
locatePost(baseDir, nickname, domain,
|
locatePost(baseDir, nickname, domain,
|
||||||
|
|
|
||||||
|
|
@ -1601,64 +1601,66 @@ def _htmlEditProfileFiltering(baseDir: str, nickname: str, domain: str,
|
||||||
def _htmlEditProfileChangePassword(translate: {}) -> str:
|
def _htmlEditProfileChangePassword(translate: {}) -> str:
|
||||||
"""Change password section of edit profile screen
|
"""Change password section of edit profile screen
|
||||||
"""
|
"""
|
||||||
editProfileForm = ' <details><summary class="cw">' + \
|
editProfileForm = \
|
||||||
translate['Change Password'] + '</summary>\n'
|
' <details><summary class="cw">' + \
|
||||||
editProfileForm += ' <div class="container">\n'
|
translate['Change Password'] + '</summary>\n' + \
|
||||||
editProfileForm += \
|
' <div class="container">\n' + \
|
||||||
'<label class="labels">' + translate['Change Password'] + \
|
'<label class="labels">' + translate['Change Password'] + \
|
||||||
'</label><br>\n'
|
'</label><br>\n' + \
|
||||||
editProfileForm += ' <input type="text" name="password" ' + \
|
' <input type="text" name="password" ' + \
|
||||||
'value=""><br>\n'
|
'value=""><br>\n' + \
|
||||||
editProfileForm += \
|
|
||||||
'<label class="labels">' + translate['Confirm Password'] + \
|
'<label class="labels">' + translate['Confirm Password'] + \
|
||||||
'</label><br>\n'
|
'</label><br>\n' + \
|
||||||
editProfileForm += \
|
' <input type="text" name="passwordconfirm" value="">\n' + \
|
||||||
' <input type="text" name="passwordconfirm" value="">\n'
|
' </div></details>\n'
|
||||||
editProfileForm += ' </div></details>\n'
|
|
||||||
return editProfileForm
|
return editProfileForm
|
||||||
|
|
||||||
|
|
||||||
def _htmlEditProfileBackground(newsInstance: bool, translate: {}) -> str:
|
def _htmlEditProfileBackground(newsInstance: bool, translate: {}) -> str:
|
||||||
"""Background images section of edit profile screen
|
"""Background images section of edit profile screen
|
||||||
"""
|
"""
|
||||||
editProfileForm = ' <details><summary class="cw">' + \
|
|
||||||
translate['Background Images'] + '</summary>\n'
|
|
||||||
editProfileForm += ' <div class="container">\n'
|
|
||||||
idx = 'The files attached below should be no larger than ' + \
|
idx = 'The files attached below should be no larger than ' + \
|
||||||
'10MB in total uploaded at once.'
|
'10MB in total uploaded at once.'
|
||||||
editProfileForm += \
|
editProfileForm = \
|
||||||
|
' <details><summary class="cw">' + \
|
||||||
|
translate['Background Images'] + '</summary>\n' + \
|
||||||
|
' <div class="container">\n' + \
|
||||||
' <label class="labels">' + translate[idx] + '</label><br><br>\n'
|
' <label class="labels">' + translate[idx] + '</label><br><br>\n'
|
||||||
|
|
||||||
if not newsInstance:
|
if not newsInstance:
|
||||||
imageFormats = getImageFormats()
|
imageFormats = getImageFormats()
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <label class="labels">' + \
|
' <label class="labels">' + \
|
||||||
translate['Background image'] + '</label>\n'
|
translate['Background image'] + '</label>\n' + \
|
||||||
editProfileForm += ' <input type="file" id="image" name="image"'
|
' <input type="file" id="image" name="image"' + \
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
editProfileForm += \
|
||||||
translate['Timeline banner image'] + '</label>\n'
|
' <br><label class="labels">' + \
|
||||||
editProfileForm += ' <input type="file" id="banner" name="banner"'
|
translate['Timeline banner image'] + '</label>\n' + \
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
' <input type="file" id="banner" name="banner"' + \
|
||||||
|
' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
editProfileForm += \
|
||||||
translate['Search banner image'] + '</label>\n'
|
' <br><label class="labels">' + \
|
||||||
editProfileForm += ' <input type="file" id="search_banner" '
|
translate['Search banner image'] + '</label>\n' + \
|
||||||
editProfileForm += 'name="search_banner"'
|
' <input type="file" id="search_banner" ' + \
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
'name="search_banner"' + \
|
||||||
|
' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
editProfileForm += \
|
||||||
translate['Left column image'] + '</label>\n'
|
' <br><label class="labels">' + \
|
||||||
editProfileForm += ' <input type="file" id="left_col_image" '
|
translate['Left column image'] + '</label>\n' + \
|
||||||
editProfileForm += 'name="left_col_image"'
|
' <input type="file" id="left_col_image" ' + \
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
'name="left_col_image"' + \
|
||||||
|
' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
editProfileForm += ' <br><label class="labels">' + \
|
editProfileForm += \
|
||||||
translate['Right column image'] + '</label>\n'
|
' <br><label class="labels">' + \
|
||||||
editProfileForm += ' <input type="file" id="right_col_image" '
|
translate['Right column image'] + '</label>\n' + \
|
||||||
editProfileForm += 'name="right_col_image"'
|
' <input type="file" id="right_col_image" ' + \
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
'name="right_col_image"' + \
|
||||||
|
' accept="' + imageFormats + '">\n'
|
||||||
|
|
||||||
editProfileForm += ' </div></details>\n'
|
editProfileForm += ' </div></details>\n'
|
||||||
return editProfileForm
|
return editProfileForm
|
||||||
|
|
@ -1696,48 +1698,45 @@ def _htmlEditProfileContactInfo(nickname: str,
|
||||||
' <input type="text" name="matrixAddress" value="' + \
|
' <input type="text" name="matrixAddress" value="' + \
|
||||||
matrixAddress + '">\n'
|
matrixAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">SSB</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">SSB</label><br>\n' + \
|
||||||
' <input type="text" name="ssbAddress" value="' + \
|
' <input type="text" name="ssbAddress" value="' + \
|
||||||
ssbAddress + '">\n'
|
ssbAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Tox</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">Tox</label><br>\n' + \
|
||||||
' <input type="text" name="toxAddress" value="' + \
|
' <input type="text" name="toxAddress" value="' + \
|
||||||
toxAddress + '">\n'
|
toxAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Briar</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">Briar</label><br>\n' + \
|
||||||
' <input type="text" name="briarAddress" value="' + \
|
' <input type="text" name="briarAddress" value="' + \
|
||||||
briarAddress + '">\n'
|
briarAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Jami</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">Jami</label><br>\n' + \
|
||||||
' <input type="text" name="jamiAddress" value="' + \
|
' <input type="text" name="jamiAddress" value="' + \
|
||||||
jamiAddress + '">\n'
|
jamiAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">Cwtch</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">Cwtch</label><br>\n' + \
|
||||||
' <input type="text" name="cwtchAddress" value="' + \
|
' <input type="text" name="cwtchAddress" value="' + \
|
||||||
cwtchAddress + '">\n'
|
cwtchAddress + '">\n'
|
||||||
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
'<label class="labels">' + \
|
'<label class="labels">' + \
|
||||||
translate['PGP Fingerprint'] + '</label><br>\n'
|
translate['PGP Fingerprint'] + '</label><br>\n' + \
|
||||||
editProfileForm += \
|
|
||||||
' <input type="text" name="openpgp" value="' + \
|
' <input type="text" name="openpgp" value="' + \
|
||||||
PGPfingerprint + '">\n'
|
PGPfingerprint + '">\n' + \
|
||||||
editProfileForm += \
|
'<label class="labels">' + translate['PGP'] + '</label><br>\n' + \
|
||||||
'<label class="labels">' + translate['PGP'] + '</label><br>\n'
|
|
||||||
editProfileForm += \
|
|
||||||
' <textarea id="message" placeholder=' + \
|
' <textarea id="message" placeholder=' + \
|
||||||
'"-----BEGIN PGP PUBLIC KEY BLOCK-----" name="pgp" ' + \
|
'"-----BEGIN PGP PUBLIC KEY BLOCK-----" name="pgp" ' + \
|
||||||
'style="height:600px" spellcheck="false">' + \
|
'style="height:600px" spellcheck="false">' + \
|
||||||
PGPpubKey + '</textarea>\n'
|
PGPpubKey + '</textarea>\n' + \
|
||||||
editProfileForm += '<a href="/users/' + nickname + \
|
'<a href="/users/' + nickname + \
|
||||||
'/followingaccounts"><label class="labels">' + \
|
'/followingaccounts"><label class="labels">' + \
|
||||||
translate['Following'] + '</label></a><br>\n'
|
translate['Following'] + '</label></a><br>\n' + \
|
||||||
editProfileForm += ' </div></details>\n'
|
' </div></details>\n'
|
||||||
return editProfileForm
|
return editProfileForm
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1790,30 +1789,32 @@ def _htmlEditProfileMain(displayNickname: str, bioStr: str,
|
||||||
imageFormats = getImageFormats()
|
imageFormats = getImageFormats()
|
||||||
|
|
||||||
editProfileForm = ' <div class="container">\n'
|
editProfileForm = ' <div class="container">\n'
|
||||||
editProfileForm += ' <label class="labels">' + \
|
|
||||||
translate['Nickname'] + '</label>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
' <label class="labels">' + \
|
||||||
|
translate['Nickname'] + '</label>\n' + \
|
||||||
' <input type="text" name="displayNickname" value="' + \
|
' <input type="text" name="displayNickname" value="' + \
|
||||||
displayNickname + '"><br>\n'
|
displayNickname + '"><br>\n'
|
||||||
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <label class="labels">' + translate['Your bio'] + '</label>\n'
|
' <label class="labels">' + \
|
||||||
editProfileForm += \
|
translate['Your bio'] + '</label>\n' + \
|
||||||
' <textarea id="message" name="bio" style="height:200px" ' + \
|
' <textarea id="message" name="bio" style="height:200px" ' + \
|
||||||
'spellcheck="true">' + bioStr + '</textarea>\n'
|
'spellcheck="true">' + bioStr + '</textarea>\n'
|
||||||
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
' <label class="labels">' + translate['Avatar image'] + \
|
' <label class="labels">' + translate['Avatar image'] + \
|
||||||
'</label>\n'
|
'</label>\n' + \
|
||||||
editProfileForm += \
|
' <input type="file" id="avatar" name="avatar"' + \
|
||||||
' <input type="file" id="avatar" name="avatar"'
|
' accept="' + imageFormats + '">\n'
|
||||||
editProfileForm += ' accept="' + imageFormats + '">\n'
|
|
||||||
|
|
||||||
occupationName = ''
|
occupationName = ''
|
||||||
if actorJson.get('hasOccupation'):
|
if actorJson.get('hasOccupation'):
|
||||||
occupationName = getOccupationName(actorJson)
|
occupationName = getOccupationName(actorJson)
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">' + \
|
|
||||||
translate['Occupation'] + ':</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + \
|
||||||
|
translate['Occupation'] + ':</label><br>\n' + \
|
||||||
' <input type="text" ' + \
|
' <input type="text" ' + \
|
||||||
'name="occupationName" value="' + occupationName + '">\n'
|
'name="occupationName" value="' + occupationName + '">\n'
|
||||||
|
|
||||||
|
|
@ -1827,27 +1828,29 @@ def _htmlEditProfileMain(displayNickname: str, bioStr: str,
|
||||||
ctr += 1
|
ctr += 1
|
||||||
alsoKnownAsStr += altActor
|
alsoKnownAsStr += altActor
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">' + \
|
|
||||||
translate['Other accounts'] + ':</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + \
|
||||||
|
translate['Other accounts'] + ':</label><br>\n' + \
|
||||||
' <input type="text" placeholder="https://..." ' + \
|
' <input type="text" placeholder="https://..." ' + \
|
||||||
'name="alsoKnownAs" value="' + alsoKnownAsStr + '">\n'
|
'name="alsoKnownAs" value="' + alsoKnownAsStr + '">\n'
|
||||||
|
|
||||||
editProfileForm += '<label class="labels">' + \
|
|
||||||
translate['Moved to new account address'] + ':</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + \
|
||||||
|
translate['Moved to new account address'] + ':</label><br>\n' + \
|
||||||
' <input type="text" placeholder="https://..." ' + \
|
' <input type="text" placeholder="https://..." ' + \
|
||||||
'name="movedTo" value="' + movedTo + '">\n'
|
'name="movedTo" value="' + movedTo + '">\n'
|
||||||
editProfileForm += '<label class="labels">' + \
|
|
||||||
translate['Donations link'] + '</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">' + \
|
||||||
|
translate['Donations link'] + '</label><br>\n' + \
|
||||||
' <input type="text" placeholder="https://..." ' + \
|
' <input type="text" placeholder="https://..." ' + \
|
||||||
'name="donateUrl" value="' + donateUrl + '">\n'
|
'name="donateUrl" value="' + donateUrl + '">\n'
|
||||||
editProfileForm += '<label class="labels">Blog</label><br>\n'
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
'<label class="labels">Blog</label><br>\n' + \
|
||||||
' <input type="text" name="blogAddress" value="' + \
|
' <input type="text" name="blogAddress" value="' + \
|
||||||
blogAddress + '">\n'
|
blogAddress + '">\n' + \
|
||||||
editProfileForm += ' </div>\n'
|
' </div>\n'
|
||||||
return editProfileForm
|
return editProfileForm
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1858,8 +1861,8 @@ def _htmlEditProfileTopBanner(baseDir: str,
|
||||||
"""top banner on edit profile screen
|
"""top banner on edit profile screen
|
||||||
"""
|
"""
|
||||||
editProfileForm = \
|
editProfileForm = \
|
||||||
'<a href="/users/' + nickname + '/' + defaultTimeline + '">'
|
'<a href="/users/' + nickname + '/' + defaultTimeline + '">' + \
|
||||||
editProfileForm += '<img loading="lazy" class="timeline-banner" src="' + \
|
'<img loading="lazy" class="timeline-banner" src="' + \
|
||||||
'/users/' + nickname + '/' + bannerFile + '" alt="" /></a>\n'
|
'/users/' + nickname + '/' + bannerFile + '" alt="" /></a>\n'
|
||||||
|
|
||||||
editProfileForm += \
|
editProfileForm += \
|
||||||
|
|
@ -2157,7 +2160,7 @@ def _individualFollowAsHtml(translate: {},
|
||||||
'?options=' + followUrl + \
|
'?options=' + followUrl + \
|
||||||
';1;' + avatarUrl + '"><button class="buttonunfollow">' + \
|
';1;' + avatarUrl + '"><button class="buttonunfollow">' + \
|
||||||
translate['Block'] + '</button></a>\n'
|
translate['Block'] + '</button></a>\n'
|
||||||
if b == 'unfollow':
|
elif b == 'unfollow':
|
||||||
buttonsStr += \
|
buttonsStr += \
|
||||||
'<a href="/users/' + actorNickname + \
|
'<a href="/users/' + actorNickname + \
|
||||||
'?options=' + followUrl + \
|
'?options=' + followUrl + \
|
||||||
|
|
|
||||||
|
|
@ -338,8 +338,7 @@ def htmlSearch(cssCache: {}, translate: {},
|
||||||
if os.path.isfile(baseDir + '/search.css'):
|
if os.path.isfile(baseDir + '/search.css'):
|
||||||
cssFilename = baseDir + '/search.css'
|
cssFilename = baseDir + '/search.css'
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = getConfigParam(baseDir, 'instanceTitle')
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
|
||||||
followStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
followStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
|
|
||||||
# show a banner above the search box
|
# show a banner above the search box
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,10 @@ def htmlSuspended(cssCache: {}, baseDir: str) -> str:
|
||||||
instanceTitle = \
|
instanceTitle = \
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
getConfigParam(baseDir, 'instanceTitle')
|
||||||
suspendedForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
suspendedForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
suspendedForm += '<div><center>\n'
|
suspendedForm += \
|
||||||
suspendedForm += ' <p class="screentitle">Account Suspended</p>\n'
|
'<div><center>\n' + \
|
||||||
suspendedForm += ' <p>See <a href="/terms">Terms of Service</a></p>\n'
|
' <p class="screentitle">Account Suspended</p>\n' + \
|
||||||
suspendedForm += '</center></div>\n'
|
' <p>See <a href="/terms">Terms of Service</a></p>\n' + \
|
||||||
|
'</center></div>\n'
|
||||||
suspendedForm += htmlFooter()
|
suspendedForm += htmlFooter()
|
||||||
return suspendedForm
|
return suspendedForm
|
||||||
|
|
|
||||||
|
|
@ -600,14 +600,15 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
|
||||||
iconsAsButtons, accessKeys)
|
iconsAsButtons, accessKeys)
|
||||||
|
|
||||||
# start the timeline
|
# start the timeline
|
||||||
tlStr += '<table class="timeline">\n'
|
tlStr += \
|
||||||
tlStr += ' <colgroup>\n'
|
'<table class="timeline">\n' + \
|
||||||
tlStr += ' <col span="1" class="column-left">\n'
|
' <colgroup>\n' + \
|
||||||
tlStr += ' <col span="1" class="column-center">\n'
|
' <col span="1" class="column-left">\n' + \
|
||||||
tlStr += ' <col span="1" class="column-right">\n'
|
' <col span="1" class="column-center">\n' + \
|
||||||
tlStr += ' </colgroup>\n'
|
' <col span="1" class="column-right">\n' + \
|
||||||
tlStr += ' <tbody>\n'
|
' </colgroup>\n' + \
|
||||||
tlStr += ' <tr>\n'
|
' <tbody>\n' + \
|
||||||
|
' <tr>\n'
|
||||||
|
|
||||||
domainFull = getFullDomain(domain, port)
|
domainFull = getFullDomain(domain, port)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -452,17 +452,18 @@ def getRightImageFile(baseDir: str,
|
||||||
|
|
||||||
def htmlHeaderWithExternalStyle(cssFilename: str, instanceTitle: str,
|
def htmlHeaderWithExternalStyle(cssFilename: str, instanceTitle: str,
|
||||||
lang='en') -> str:
|
lang='en') -> str:
|
||||||
htmlStr = '<!DOCTYPE html>\n'
|
|
||||||
htmlStr += '<html lang="' + lang + '">\n'
|
|
||||||
htmlStr += ' <head>\n'
|
|
||||||
htmlStr += ' <meta charset="utf-8">\n'
|
|
||||||
cssFile = '/' + cssFilename.split('/')[-1]
|
cssFile = '/' + cssFilename.split('/')[-1]
|
||||||
htmlStr += ' <link rel="stylesheet" href="' + cssFile + '">\n'
|
htmlStr = \
|
||||||
htmlStr += ' <link rel="manifest" href="/manifest.json">\n'
|
'<!DOCTYPE html>\n' + \
|
||||||
htmlStr += ' <meta name="theme-color" content="grey">\n'
|
'<html lang="' + lang + '">\n' + \
|
||||||
htmlStr += ' <title>' + instanceTitle + '</title>\n'
|
' <head>\n' + \
|
||||||
htmlStr += ' </head>\n'
|
' <meta charset="utf-8">\n' + \
|
||||||
htmlStr += ' <body>\n'
|
' <link rel="stylesheet" href="' + cssFile + '">\n' + \
|
||||||
|
' <link rel="manifest" href="/manifest.json">\n' + \
|
||||||
|
' <meta name="theme-color" content="grey">\n' + \
|
||||||
|
' <title>' + instanceTitle + '</title>\n' + \
|
||||||
|
' </head>\n' + \
|
||||||
|
' <body>\n'
|
||||||
return htmlStr
|
return htmlStr
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -511,37 +512,32 @@ def htmlHeaderWithPersonMarkup(cssFilename: str, instanceTitle: str,
|
||||||
sk['occupationalCategory']['codeValue']
|
sk['occupationalCategory']['codeValue']
|
||||||
categoryUrl = \
|
categoryUrl = \
|
||||||
'https://www.onetonline.org/link/summary/' + category
|
'https://www.onetonline.org/link/summary/' + category
|
||||||
skillsMarkup += ' {\n'
|
|
||||||
skillsMarkup += ' "@type": "Role",\n'
|
|
||||||
skillsMarkup += ' "hasOccupation": {\n'
|
|
||||||
skillsMarkup += ' "@type": "Occupation",\n'
|
|
||||||
skillsMarkup += ' "name": "' + roleName + '",\n'
|
|
||||||
skillsMarkup += ' "description": ' + \
|
|
||||||
'"Fediverse instance role",\n'
|
|
||||||
skillsMarkup += ' "occupationLocation": {\n'
|
|
||||||
skillsMarkup += \
|
|
||||||
' "@type": "City",\n'
|
|
||||||
skillsMarkup += \
|
|
||||||
' "name": "' + city + '"\n'
|
|
||||||
skillsMarkup += ' },\n'
|
|
||||||
skillsMarkup += ' "occupationalCategory": {\n'
|
|
||||||
skillsMarkup += ' "@type": "CategoryCode",\n'
|
|
||||||
skillsMarkup += ' "inCodeSet": {\n'
|
|
||||||
skillsMarkup += \
|
|
||||||
' "@type": "CategoryCodeSet",\n'
|
|
||||||
skillsMarkup += ' "name": "O*Net-SOC",\n'
|
|
||||||
skillsMarkup += ' "dateModified": "2019",\n'
|
|
||||||
skillsMarkup += \
|
skillsMarkup += \
|
||||||
|
' {\n' + \
|
||||||
|
' "@type": "Role",\n' + \
|
||||||
|
' "hasOccupation": {\n' + \
|
||||||
|
' "@type": "Occupation",\n' + \
|
||||||
|
' "name": "' + roleName + '",\n' + \
|
||||||
|
' "description": ' + \
|
||||||
|
'"Fediverse instance role",\n' + \
|
||||||
|
' "occupationLocation": {\n' + \
|
||||||
|
' "@type": "City",\n' + \
|
||||||
|
' "name": "' + city + '"\n' + \
|
||||||
|
' },\n' + \
|
||||||
|
' "occupationalCategory": {\n' + \
|
||||||
|
' "@type": "CategoryCode",\n' + \
|
||||||
|
' "inCodeSet": {\n' + \
|
||||||
|
' "@type": "CategoryCodeSet",\n' + \
|
||||||
|
' "name": "O*Net-SOC",\n' + \
|
||||||
|
' "dateModified": "2019",\n' + \
|
||||||
' ' + \
|
' ' + \
|
||||||
'"url": "https://www.onetonline.org/"\n'
|
'"url": "https://www.onetonline.org/"\n' + \
|
||||||
skillsMarkup += ' },\n'
|
' },\n' + \
|
||||||
skillsMarkup += \
|
' "codeValue": "' + category + '",\n' + \
|
||||||
' "codeValue": "' + category + '",\n'
|
' "url": "' + categoryUrl + '"\n' + \
|
||||||
skillsMarkup += \
|
' }\n' + \
|
||||||
' "url": "' + categoryUrl + '"\n'
|
' }\n' + \
|
||||||
skillsMarkup += ' }\n'
|
' }'
|
||||||
skillsMarkup += ' }\n'
|
|
||||||
skillsMarkup += ' }'
|
|
||||||
elif skillDict['@type'] == 'Occupation':
|
elif skillDict['@type'] == 'Occupation':
|
||||||
if not firstEntry:
|
if not firstEntry:
|
||||||
skillsMarkup += ',\n'
|
skillsMarkup += ',\n'
|
||||||
|
|
@ -555,19 +551,18 @@ def htmlHeaderWithPersonMarkup(cssFilename: str, instanceTitle: str,
|
||||||
skillsListStr += ', '
|
skillsListStr += ', '
|
||||||
skillsListStr += '"' + skillStr + '"'
|
skillsListStr += '"' + skillStr + '"'
|
||||||
skillsListStr += ']'
|
skillsListStr += ']'
|
||||||
skillsMarkup += ' {\n'
|
|
||||||
skillsMarkup += ' "@type": "Occupation",\n'
|
|
||||||
skillsMarkup += ' "name": "' + ocName + '",\n'
|
|
||||||
skillsMarkup += ' "description": ' + \
|
|
||||||
'"Fediverse instance occupation",\n'
|
|
||||||
skillsMarkup += ' "occupationLocation": {\n'
|
|
||||||
skillsMarkup += ' "@type": "City",\n'
|
|
||||||
skillsMarkup += \
|
skillsMarkup += \
|
||||||
' "name": "' + city + '"\n'
|
' {\n' + \
|
||||||
skillsMarkup += ' },\n'
|
' "@type": "Occupation",\n' + \
|
||||||
skillsMarkup += \
|
' "name": "' + ocName + '",\n' + \
|
||||||
' "skills": ' + skillsListStr + '\n'
|
' "description": ' + \
|
||||||
skillsMarkup += ' }'
|
'"Fediverse instance occupation",\n' + \
|
||||||
|
' "occupationLocation": {\n' + \
|
||||||
|
' "@type": "City",\n' + \
|
||||||
|
' "name": "' + city + '"\n' + \
|
||||||
|
' },\n' + \
|
||||||
|
' "skills": ' + skillsListStr + '\n' + \
|
||||||
|
' }'
|
||||||
firstEntry = False
|
firstEntry = False
|
||||||
skillsMarkup += '\n ],\n'
|
skillsMarkup += '\n ],\n'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,19 +63,17 @@ def htmlWelcomeFinal(baseDir: str, nickname: str, domain: str,
|
||||||
|
|
||||||
finalForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
finalForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
|
||||||
|
|
||||||
finalForm += '<div class="container">' + finalText + '</div>\n'
|
|
||||||
finalForm += \
|
finalForm += \
|
||||||
|
'<div class="container">' + finalText + '</div>\n' + \
|
||||||
'<form enctype="multipart/form-data" method="POST" ' + \
|
'<form enctype="multipart/form-data" method="POST" ' + \
|
||||||
'accept-charset="UTF-8" ' + \
|
'accept-charset="UTF-8" ' + \
|
||||||
'action="/users/' + nickname + '/profiledata">\n'
|
'action="/users/' + nickname + '/profiledata">\n' + \
|
||||||
finalForm += '<div class="container next">\n'
|
'<div class="container next">\n' + \
|
||||||
finalForm += \
|
|
||||||
' <button type="submit" class="button" ' + \
|
' <button type="submit" class="button" ' + \
|
||||||
'name="previewAvatar">' + translate['Go Back'] + '</button>\n'
|
'name="previewAvatar">' + translate['Go Back'] + '</button>\n' + \
|
||||||
finalForm += \
|
|
||||||
' <button type="submit" class="button" ' + \
|
' <button type="submit" class="button" ' + \
|
||||||
'name="welcomeCompleteButton">' + translate['Next'] + '</button>\n'
|
'name="welcomeCompleteButton">' + translate['Next'] + '</button>\n' + \
|
||||||
finalForm += '</div>\n'
|
'</div>\n'
|
||||||
|
|
||||||
finalForm += '</form>\n'
|
finalForm += '</form>\n'
|
||||||
finalForm += htmlFooter()
|
finalForm += htmlFooter()
|
||||||
|
|
|
||||||
59
webfinger.py
59
webfinger.py
|
|
@ -174,18 +174,19 @@ def webfingerNodeInfo(httpPrefix: str, domainFull: str) -> {}:
|
||||||
def webfingerMeta(httpPrefix: str, domainFull: str) -> str:
|
def webfingerMeta(httpPrefix: str, domainFull: str) -> str:
|
||||||
"""Return /.well-known/host-meta
|
"""Return /.well-known/host-meta
|
||||||
"""
|
"""
|
||||||
metaStr = "<?xml version=’1.0' encoding=’UTF-8'?>"
|
metaStr = \
|
||||||
metaStr += "<XRD xmlns=’http://docs.oasis-open.org/ns/xri/xrd-1.0'"
|
"<?xml version=’1.0' encoding=’UTF-8'?>" + \
|
||||||
metaStr += " xmlns:hm=’http://host-meta.net/xrd/1.0'>"
|
"<XRD xmlns=’http://docs.oasis-open.org/ns/xri/xrd-1.0'" + \
|
||||||
metaStr += ""
|
" xmlns:hm=’http://host-meta.net/xrd/1.0'>" + \
|
||||||
metaStr += "<hm:Host>" + domainFull + "</hm:Host>"
|
"" + \
|
||||||
metaStr += ""
|
"<hm:Host>" + domainFull + "</hm:Host>" + \
|
||||||
metaStr += "<Link rel=’lrdd’"
|
"" + \
|
||||||
metaStr += " template=’" + httpPrefix + "://" + domainFull + \
|
"<Link rel=’lrdd’" + \
|
||||||
"/describe?uri={uri}'>"
|
" template=’" + httpPrefix + "://" + domainFull + \
|
||||||
metaStr += " <Title>Resource Descriptor</Title>"
|
"/describe?uri={uri}'>" + \
|
||||||
metaStr += " </Link>"
|
" <Title>Resource Descriptor</Title>" + \
|
||||||
metaStr += "</XRD>"
|
" </Link>" + \
|
||||||
|
"</XRD>"
|
||||||
return metaStr
|
return metaStr
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -264,18 +265,28 @@ def _webfingerUpdateFromProfile(wfJson: {}, actorJson: {}) -> bool:
|
||||||
"matrix": "matrix",
|
"matrix": "matrix",
|
||||||
"email": "mailto",
|
"email": "mailto",
|
||||||
"ssb": "ssb",
|
"ssb": "ssb",
|
||||||
|
"briar": "briar",
|
||||||
|
"cwtch": "cwtch",
|
||||||
|
"jami": "jami",
|
||||||
"tox": "toxId"
|
"tox": "toxId"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aliasesNotFound = []
|
||||||
|
for name, alias in webfingerPropertyName.items():
|
||||||
|
aliasesNotFound.append(alias)
|
||||||
|
|
||||||
for propertyValue in actorJson['attachment']:
|
for propertyValue in actorJson['attachment']:
|
||||||
if not propertyValue.get('name'):
|
if not propertyValue.get('name'):
|
||||||
continue
|
continue
|
||||||
propertyName = propertyValue['name'].lower()
|
propertyName = propertyValue['name'].lower()
|
||||||
if not (propertyName.startswith('ssb') or
|
found = False
|
||||||
propertyName.startswith('xmpp') or
|
for name, alias in webfingerPropertyName.items():
|
||||||
propertyName.startswith('matrix') or
|
if name == propertyName:
|
||||||
propertyName.startswith('email') or
|
if alias in aliasesNotFound:
|
||||||
propertyName.startswith('tox')):
|
aliasesNotFound.remove(alias)
|
||||||
|
found = True
|
||||||
|
break
|
||||||
|
if not found:
|
||||||
continue
|
continue
|
||||||
if not propertyValue.get('type'):
|
if not propertyValue.get('type'):
|
||||||
continue
|
continue
|
||||||
|
|
@ -285,6 +296,9 @@ def _webfingerUpdateFromProfile(wfJson: {}, actorJson: {}) -> bool:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
newValue = propertyValue['value'].strip()
|
newValue = propertyValue['value'].strip()
|
||||||
|
if '://' in newValue:
|
||||||
|
newValue = newValue.split('://')[1]
|
||||||
|
|
||||||
aliasIndex = 0
|
aliasIndex = 0
|
||||||
found = False
|
found = False
|
||||||
for alias in wfJson['aliases']:
|
for alias in wfJson['aliases']:
|
||||||
|
|
@ -300,6 +314,17 @@ def _webfingerUpdateFromProfile(wfJson: {}, actorJson: {}) -> bool:
|
||||||
else:
|
else:
|
||||||
wfJson['aliases'].append(newAlias)
|
wfJson['aliases'].append(newAlias)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
# remove any aliases which are no longer in the actor profile
|
||||||
|
removeAlias = []
|
||||||
|
for alias in aliasesNotFound:
|
||||||
|
for fullAlias in wfJson['aliases']:
|
||||||
|
if fullAlias.startswith(alias + ':'):
|
||||||
|
removeAlias.append(fullAlias)
|
||||||
|
for fullAlias in removeAlias:
|
||||||
|
wfJson['aliases'].remove(fullAlias)
|
||||||
|
changed = True
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue