diff --git a/announce.py b/announce.py
index 1660827e6..f39732979 100644
--- a/announce.py
+++ b/announce.py
@@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
__status__ = "Production"
__module_group__ = "ActivityPub"
+from domainhandler import removeDomainPort
from utils import hasObjectDict
from utils import removeIdEnding
from utils import hasUsersPath
@@ -128,8 +129,7 @@ def createAnnounce(session, baseDir: str, federationList: [],
if not urlPermitted(objectUrl, federationList):
return None
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
fullDomain = getFullDomain(domain, port)
statusNumber, published = getStatusNumber()
@@ -399,8 +399,7 @@ def outboxUndoAnnounce(recentPostsCache: {},
print('DEBUG: c2s undo announce request arrived in outbox')
messageId = removeIdEnding(messageJson['object']['object'])
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename:
if debug:
diff --git a/blocking.py b/blocking.py
index af139a8c3..0c81fcd8a 100644
--- a/blocking.py
+++ b/blocking.py
@@ -5,12 +5,13 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
-__module_group__ = "ActivityPub"
+__module_group__ = "Core"
import os
import json
import time
from datetime import datetime
+from domainhandler import removeDomainPort
from utils import hasObjectDict
from utils import isAccountDir
from utils import getCachedPostFilename
@@ -58,8 +59,7 @@ def addBlock(baseDir: str, nickname: str, domain: str,
blockNickname: str, blockDomain: str) -> bool:
"""Block the given account
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
blockingFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/blocking.txt'
blockHandle = blockNickname + '@' + blockDomain
@@ -111,8 +111,7 @@ def removeBlock(baseDir: str, nickname: str, domain: str,
unblockNickname: str, unblockDomain: str) -> bool:
"""Unblock the given account
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
unblockingFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/blocking.txt'
unblockHandle = unblockNickname + '@' + unblockDomain
@@ -338,8 +337,7 @@ def outboxBlock(baseDir: str, httpPrefix: str,
if debug:
print('DEBUG: c2s block object has no nickname')
return
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename:
if debug:
@@ -406,8 +404,7 @@ def outboxUndoBlock(baseDir: str, httpPrefix: str,
if debug:
print('DEBUG: c2s undo block object has no nickname')
return
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename:
if debug:
@@ -605,8 +602,7 @@ def outboxMute(baseDir: str, httpPrefix: str,
if debug:
print('DEBUG: c2s mute object has no nickname')
return
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename:
if debug:
@@ -663,8 +659,7 @@ def outboxUndoMute(baseDir: str, httpPrefix: str,
if debug:
print('DEBUG: c2s undo mute object has no nickname')
return
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename:
if debug:
diff --git a/blog.py b/blog.py
index 0822aa64a..cbb2574c8 100644
--- a/blog.py
+++ b/blog.py
@@ -16,6 +16,7 @@ from webapp_utils import htmlHeaderWithBlogMarkup
from webapp_utils import htmlFooter
from webapp_utils import getPostAttachmentsAsHtml
from webapp_media import addEmbeddedElements
+from utils import isAccountDir
from utils import removeHtml
from utils import getConfigParam
from utils import getFullDomain
@@ -643,11 +644,7 @@ def _noOfBlogAccounts(baseDir: str) -> int:
ctr = 0
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for acct in dirs:
- if '@' not in acct:
- continue
- if acct.startswith('inbox@'):
- continue
- elif acct.startswith('news@'):
+ if not isAccountDir(acct):
continue
accountDir = os.path.join(baseDir + '/accounts', acct)
blogsIndex = accountDir + '/tlblogs.index'
@@ -662,11 +659,7 @@ def _singleBlogAccountNickname(baseDir: str) -> str:
"""
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for acct in dirs:
- if '@' not in acct:
- continue
- if acct.startswith('inbox@'):
- continue
- elif acct.startswith('news@'):
+ if not isAccountDir(acct):
continue
accountDir = os.path.join(baseDir + '/accounts', acct)
blogsIndex = accountDir + '/tlblogs.index'
@@ -704,11 +697,7 @@ def htmlBlogView(authorized: bool,
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for acct in dirs:
- if '@' not in acct:
- continue
- if acct.startswith('inbox@'):
- continue
- elif acct.startswith('news@'):
+ if not isAccountDir(acct):
continue
accountDir = os.path.join(baseDir + '/accounts', acct)
blogsIndex = accountDir + '/tlblogs.index'
diff --git a/bookmarks.py b/bookmarks.py
index 2e4de3c19..414f748bd 100644
--- a/bookmarks.py
+++ b/bookmarks.py
@@ -11,6 +11,7 @@ import os
from pprint import pprint
from webfinger import webfingerHandle
from auth import createBasicAuthHeader
+from domainhandler import removeDomainPort
from utils import hasUsersPath
from utils import getFullDomain
from utils import removeIdEnding
@@ -560,8 +561,7 @@ def outboxBookmark(recentPostsCache: {},
print('DEBUG: c2s bookmark Add request arrived in outbox')
messageUrl = removeIdEnding(messageJson['object']['url'])
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
if not postFilename:
if debug:
@@ -625,8 +625,7 @@ def outboxUndoBookmark(recentPostsCache: {},
print('DEBUG: c2s unbookmark Remove request arrived in outbox')
messageUrl = removeIdEnding(messageJson['object']['url'])
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
if not postFilename:
if debug:
diff --git a/content.py b/content.py
index 79d8b4dd0..be1eec89d 100644
--- a/content.py
+++ b/content.py
@@ -5,11 +5,13 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
+__module_group__ = "Core"
import os
import email.parser
import urllib.parse
from shutil import copyfile
+from domainhandler import removeDomainPort
from utils import isValidLanguage
from utils import getImageExtensions
from utils import loadJson
@@ -772,8 +774,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
replaceEmoji = {}
emojiDict = {}
originalDomain = domain
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
followingFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/following.txt'
diff --git a/daemon.py b/daemon.py
index b530f9901..e180512bf 100644
--- a/daemon.py
+++ b/daemon.py
@@ -5,6 +5,7 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
+__module_group__ = "Core"
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer, HTTPServer
import sys
@@ -139,8 +140,8 @@ from blog import htmlBlogView
from blog import htmlBlogPage
from blog import htmlBlogPost
from blog import htmlEditBlog
-from webapp_utils import setMinimal
-from webapp_utils import isMinimal
+from webapp_minimalbutton import setMinimal
+from webapp_minimalbutton import isMinimal
from webapp_utils import getAvatarImageUrl
from webapp_utils import htmlHashtagBlocked
from webapp_utils import htmlFollowingList
diff --git a/delete.py b/delete.py
index 05ceb051d..b51d5c7a0 100644
--- a/delete.py
+++ b/delete.py
@@ -9,6 +9,7 @@ __module_group__ = "ActivityPub"
import os
from datetime import datetime
+from domainhandler import removeDomainPort
from utils import hasUsersPath
from utils import getFullDomain
from utils import removeIdEnding
@@ -154,8 +155,7 @@ def outboxDelete(baseDir: str, httpPrefix: str,
"wasn't created by you (nickname does not match)")
return
deleteDomain, deletePort = getDomainFromActor(messageId)
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
if deleteDomain != domain:
if debug:
print("DEBUG: you can't delete a post which " +
diff --git a/domainhandler.py b/domainhandler.py
new file mode 100644
index 000000000..b7875b32a
--- /dev/null
+++ b/domainhandler.py
@@ -0,0 +1,32 @@
+__filename__ = "domainhandler.py"
+__author__ = "Bob Mottram"
+__license__ = "AGPL3+"
+__version__ = "1.2.0"
+__maintainer__ = "Bob Mottram"
+__email__ = "bob@freedombone.net"
+__status__ = "Production"
+__module_group__ = "Core"
+
+
+def removeDomainPort(domain: str) -> str:
+ """If the domain has a port appended then remove it
+ eg. mydomain.com:80 becomes mydomain.com
+ """
+ if ':' in domain:
+ if domain.startswith('did:'):
+ return domain
+ domain = domain.split(':')[0]
+ return domain
+
+
+def getPortFromDomain(domain: str) -> int:
+ """If the domain has a port number appended then return it
+ eg. mydomain.com:80 returns 80
+ """
+ if ':' in domain:
+ if domain.startswith('did:'):
+ return None
+ portStr = domain.split(':')[1]
+ if portStr.isdigit():
+ return int(portStr)
+ return None
diff --git a/epicyon.py b/epicyon.py
index 34baebdff..6e4abafdb 100644
--- a/epicyon.py
+++ b/epicyon.py
@@ -61,6 +61,8 @@ from tests import testUpdateActor
from tests import runAllTests
from auth import storeBasicCredentials
from auth import createPassword
+from domainhandler import removeDomainPort
+from domainhandler import getPortFromDomain
from utils import hasUsersPath
from utils import getFullDomain
from utils import setConfigParam
@@ -1080,8 +1082,8 @@ if args.message:
toDomain = toDomain.replace('\n', '').replace('\r', '')
toPort = 443
if ':' in toDomain:
- toPort = toDomain.split(':')[1]
- toDomain = toDomain.split(':')[0]
+ toPort = getPortFromDomain(toDomain)
+ toDomain = removeDomainPort(toDomain)
else:
if args.sendto.endswith('followers'):
toNickname = None
diff --git a/follow.py b/follow.py
index a26b2372c..2745c8ec5 100644
--- a/follow.py
+++ b/follow.py
@@ -9,6 +9,7 @@ __module_group__ = "ActivityPub"
from pprint import pprint
import os
+from domainhandler import removeDomainPort
from utils import hasObjectDict
from utils import hasUsersPath
from utils import getFullDomain
@@ -153,8 +154,7 @@ def isFollowingActor(baseDir: str,
"""Is the given nickname following the given actor?
The actor can also be a handle: nickname@domain
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
handle = nickname + '@' + domain
if not os.path.isdir(baseDir + '/accounts/' + handle):
return False
@@ -205,8 +205,7 @@ def isFollowerOfPerson(baseDir: str, nickname: str, domain: str,
followerNickname: str, followerDomain: str) -> bool:
"""is the given nickname a follower of followerNickname?
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
followersFile = baseDir + '/accounts/' + \
nickname + '@' + domain + '/followers.txt'
if not os.path.isfile(followersFile):
@@ -243,8 +242,7 @@ def unfollowAccount(baseDir: str, nickname: str, domain: str,
debug: bool = False) -> bool:
"""Removes a person to the follow list
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
handle = nickname + '@' + domain
handleToUnfollow = followNickname + '@' + followDomain
if not os.path.isdir(baseDir + '/accounts'):
@@ -433,8 +431,7 @@ def getFollowingFeed(baseDir: str, domain: str, port: int, path: str,
}
handleDomain = domain
- if ':' in handleDomain:
- handleDomain = domain.split(':')[0]
+ handleDomain = removeDomainPort(handleDomain)
handle = nickname + '@' + handleDomain
filename = baseDir + '/accounts/' + handle + '/' + followFile + '.txt'
if not os.path.isfile(filename):
@@ -493,8 +490,7 @@ def _followApprovalRequired(baseDir: str, nicknameToFollow: str,
return False
manuallyApproveFollows = False
- if ':' in domainToFollow:
- domainToFollow = domainToFollow.split(':')[0]
+ domainToFollow = removeDomainPort(domainToFollow)
actorFilename = baseDir + '/accounts/' + \
nicknameToFollow + '@' + domainToFollow + '.json'
if os.path.isfile(actorFilename):
diff --git a/followingCalendar.py b/followingCalendar.py
index 650687e14..68bef2973 100644
--- a/followingCalendar.py
+++ b/followingCalendar.py
@@ -8,6 +8,7 @@ __status__ = "Production"
__module_group__ = "Calendar"
import os
+from domainhandler import removeDomainPort
def receivingCalendarEvents(baseDir: str, nickname: str, domain: str,
@@ -43,8 +44,7 @@ def _receiveCalendarEvents(baseDir: str, nickname: str, domain: str,
indicating whether to receive calendar events from that account
"""
# check that a following file exists
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
followingFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/following.txt'
if not os.path.isfile(followingFilename):
diff --git a/git.py b/git.py
index 00f2c9a23..2dcea4d31 100644
--- a/git.py
+++ b/git.py
@@ -5,7 +5,7 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
-__module_group__ = "ActivityPub"
+__module_group__ = "Core"
import os
import html
diff --git a/happening.py b/happening.py
index 28c9d6552..b5606e0e7 100644
--- a/happening.py
+++ b/happening.py
@@ -5,7 +5,7 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
-__module_group__ = "Calendar"
+__module_group__ = "Core"
import os
from uuid import UUID
diff --git a/inbox.py b/inbox.py
index 0b1035b12..1f5c86e18 100644
--- a/inbox.py
+++ b/inbox.py
@@ -13,6 +13,8 @@ import datetime
import time
import random
from linked_data_sig import verifyJsonSignature
+from domainhandler import removeDomainPort
+from domainhandler import getPortFromDomain
from utils import hasObjectDict
from utils import dmAllowedFromDomain
from utils import isRecentPost
@@ -186,8 +188,7 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
def validInbox(baseDir: str, nickname: str, domain: str) -> bool:
"""Checks whether files were correctly saved to the inbox
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
inboxDir = baseDir + '/accounts/' + nickname + '@' + domain + '/inbox'
if not os.path.isdir(inboxDir):
return True
@@ -209,8 +210,7 @@ def validInboxFilenames(baseDir: str, nickname: str, domain: str,
"""Used by unit tests to check that the port number gets appended to
domain names within saved post filenames
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
inboxDir = baseDir + '/accounts/' + nickname + '@' + domain + '/inbox'
if not os.path.isdir(inboxDir):
return True
@@ -358,8 +358,7 @@ def savePostToInboxQueue(baseDir: str, httpPrefix: str,
str(len(messageBytes)) + ' bytes')
return None
originalDomain = domain
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
# block at the ealiest stage possible, which means the data
# isn't written to file
@@ -536,8 +535,7 @@ def _inboxPostRecipients(baseDir: str, postJsonObject: {},
print('WARNING: inbox post has no actor')
return recipientsDict, recipientsDictFollowers
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
domainBase = domain
domain = getFullDomain(domain, port)
domainMatch = '/' + domain + '/users/'
@@ -1124,8 +1122,7 @@ def _receiveBookmark(recentPostsCache: {},
print('DEBUG: c2s inbox bookmark Add request arrived in outbox')
messageUrl = removeIdEnding(messageJson['object']['url'])
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
if not postFilename:
if debug:
@@ -1200,8 +1197,7 @@ def _receiveUndoBookmark(recentPostsCache: {},
'request arrived in outbox')
messageUrl = removeIdEnding(messageJson['object']['url'])
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
if not postFilename:
if debug:
@@ -1521,11 +1517,15 @@ def jsonPostAllowsComments(postJsonObject: {}) -> bool:
"""
if 'commentsEnabled' in postJsonObject:
return postJsonObject['commentsEnabled']
+ if 'rejectReplies' in postJsonObject:
+ return not postJsonObject['rejectReplies']
if postJsonObject.get('object'):
if not hasObjectDict(postJsonObject):
return False
elif 'commentsEnabled' in postJsonObject['object']:
return postJsonObject['object']['commentsEnabled']
+ elif 'rejectReplies' in postJsonObject['object']:
+ return not postJsonObject['object']['rejectReplies']
return True
@@ -1580,24 +1580,6 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
print('DEBUG: post may have expired - ' + replyTo)
return False
-# TODO store replies collection
-# replyItem = {
-# "type": "Document",
-# "url": replyTo
-# }
-# if not messageJson['object'].get('replies'):
-# messageJson['object']['replies'] = {
-# "items": [replyItem]
-# }
-# else:
-# found = False
-# for item in messageJson['object']['replies']['items']:
-# if item['url'] == replyTo:
-# found = True
-# break
-# if not found:
-# messageJson['object']['replies']['items'].append(replyItem)
-#
if not _postAllowsComments(postFilename):
if debug:
print('DEBUG: post does not allow comments - ' + replyTo)
@@ -1975,8 +1957,7 @@ def _sendToGroupMembers(session, baseDir: str, handle: str, port: int,
# set subject
if not postJsonObject['object'].get('summary'):
postJsonObject['object']['summary'] = 'General Discussion'
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
with open(followersFile, 'r') as groupMembers:
for memberHandle in groupMembers:
if memberHandle != handle:
@@ -1984,10 +1965,8 @@ def _sendToGroupMembers(session, baseDir: str, handle: str, port: int,
memberDomain = memberHandle.split('@')[1]
memberPort = port
if ':' in memberDomain:
- memberPortStr = memberDomain.split(':')[1]
- if memberPortStr.isdigit():
- memberPort = int(memberPortStr)
- memberDomain = memberDomain.split(':')[0]
+ memberPort = getPortFromDomain(memberDomain)
+ memberDomain = removeDomainPort(memberDomain)
sendSignedJson(postJsonObject, session, baseDir,
nickname, domain, port,
memberNickname, memberDomain, memberPort, cc,
@@ -2078,8 +2057,7 @@ def _updateLastSeen(baseDir: str, handle: str, actor: str) -> None:
return
nickname = handle.split('@')[0]
domain = handle.split('@')[1]
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
accountPath = baseDir + '/accounts/' + nickname + '@' + domain
if not os.path.isdir(accountPath):
return
@@ -2130,10 +2108,8 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
senderDomain = sendingHandle.split('@')[1]
senderPort = port
if ':' in senderDomain:
- senderPortStr = senderDomain.split(':')[1]
- if senderPortStr.isdigit():
- senderPort = int(senderPortStr)
- senderDomain = senderDomain.split(':')[0]
+ senderPort = getPortFromDomain(senderDomain)
+ senderDomain = removeDomainPort(senderDomain)
cc = []
# create the bounce DM
diff --git a/like.py b/like.py
index 4c95ad7dd..ee42afead 100644
--- a/like.py
+++ b/like.py
@@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
__status__ = "Production"
__module_group__ = "ActivityPub"
+from domainhandler import removeDomainPort
from utils import hasObjectDict
from utils import hasUsersPath
from utils import getFullDomain
@@ -327,8 +328,7 @@ def outboxLike(recentPostsCache: {},
print('DEBUG: c2s like request arrived in outbox')
messageId = removeIdEnding(messageJson['object'])
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename:
if debug:
@@ -377,8 +377,7 @@ def outboxUndoLike(recentPostsCache: {},
print('DEBUG: c2s undo like request arrived in outbox')
messageId = removeIdEnding(messageJson['object']['object'])
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
postFilename = locatePost(baseDir, nickname, domain, messageId)
if not postFilename:
if debug:
diff --git a/manualapprove.py b/manualapprove.py
index dccc65320..91c78ffac 100644
--- a/manualapprove.py
+++ b/manualapprove.py
@@ -12,6 +12,8 @@ from follow import followedAccountAccepts
from follow import followedAccountRejects
from follow import removeFromFollowRequests
from utils import loadJson
+from domainhandler import removeDomainPort
+from domainhandler import getPortFromDomain
def manualDenyFollowRequest(session, baseDir: str,
@@ -49,8 +51,8 @@ def manualDenyFollowRequest(session, baseDir: str,
denyHandle.split('@')[1].replace('\n', '').replace('\r', '')
denyPort = port
if ':' in denyDomain:
- denyPort = denyDomain.split(':')[1]
- denyDomain = denyDomain.split(':')[0]
+ denyPort = getPortFromDomain(denyDomain)
+ denyDomain = removeDomainPort(denyDomain)
followedAccountRejects(session, baseDir, httpPrefix,
nickname, domain, port,
denyNickname, denyDomain, denyPort,
@@ -141,9 +143,7 @@ def manualApproveFollowRequest(session, baseDir: str,
handleOfFollowRequester.replace('\r', '')
port2 = port
if ':' in handleOfFollowRequester:
- port2Str = handleOfFollowRequester.split(':')[1]
- if port2Str.isdigit():
- port2 = int(port2Str)
+ port2 = getPortFromDomain(handleOfFollowRequester)
requestsDir = accountDir + '/requests'
followActivityfilename = \
requestsDir + '/' + handleOfFollowRequester + '.follow'
@@ -158,8 +158,8 @@ def manualApproveFollowRequest(session, baseDir: str,
approveDomain.replace('\r', '')
approvePort = port2
if ':' in approveDomain:
- approvePort = approveDomain.split(':')[1]
- approveDomain = approveDomain.split(':')[0]
+ approvePort = getPortFromDomain(approveDomain)
+ approveDomain = removeDomainPort(approveDomain)
print('Manual follow accept: Sending Accept for ' +
handle + ' follow request from ' +
approveNickname + '@' + approveDomain)
diff --git a/markdown.py b/markdown.py
new file mode 100644
index 000000000..67d99b426
--- /dev/null
+++ b/markdown.py
@@ -0,0 +1,168 @@
+__filename__ = "markdown.py"
+__author__ = "Bob Mottram"
+__license__ = "AGPL3+"
+__version__ = "1.2.0"
+__maintainer__ = "Bob Mottram"
+__email__ = "bob@freedombone.net"
+__status__ = "Production"
+__module_group__ = "Web Interface"
+
+
+def _markdownEmphasisHtml(markdown: str) -> str:
+ """Add italics and bold html markup to the given markdown
+ """
+ replacements = {
+ ' **': ' ',
+ '** ': ' ',
+ '**.': '.',
+ '**:': ':',
+ '**;': ';',
+ '**,': ',',
+ '**\n': '\n',
+ ' *': ' ',
+ '* ': ' ',
+ '*.': '.',
+ '*:': ':',
+ '*;': ';',
+ '*,': ',',
+ '*\n': '\n',
+ ' _': '
',
+ '_.': '.',
+ '_:': ':',
+ '_;': ';',
+ '_,': ',',
+ '_\n': '\n'
+ }
+ for md, html in replacements.items():
+ markdown = markdown.replace(md, html)
+
+ if markdown.startswith('**'):
+ markdown = markdown[2:] + ''
+ elif markdown.startswith('*'):
+ markdown = markdown[1:] + ''
+ elif markdown.startswith('_'):
+ markdown = markdown[1:] + ''
+
+ if markdown.endswith('**'):
+ markdown = markdown[:len(markdown) - 2] + '
'
+ elif markdown.endswith('*'):
+ markdown = markdown[:len(markdown) - 1] + ''
+ elif markdown.endswith('_'):
+ markdown = markdown[:len(markdown) - 1] + ''
+ return markdown
+
+
+def _markdownReplaceQuotes(markdown: str) -> str:
+ """Replaces > quotes with html blockquote
+ """
+ if '> ' not in markdown:
+ return markdown
+ lines = markdown.split('\n')
+ result = ''
+ prevQuoteLine = None
+ for line in lines:
+ if '> ' not in line:
+ result += line + '\n'
+ prevQuoteLine = None
+ continue
+ lineStr = line.strip()
+ if not lineStr.startswith('> '):
+ result += line + '\n'
+ prevQuoteLine = None
+ continue
+ lineStr = lineStr.replace('> ', '', 1).strip()
+ if prevQuoteLine:
+ newPrevLine = prevQuoteLine.replace('\n', '')
+ result = result.replace(prevQuoteLine, newPrevLine) + ' '
+ lineStr += '\n'
+ else:
+ lineStr = '' + lineStr + '
\n'
+ result += lineStr
+ prevQuoteLine = lineStr
+
+ if '\n' in result:
+ result = result.replace('\n', '')
+
+ if result.endswith('\n') and \
+ not markdown.endswith('\n'):
+ result = result[:len(result) - 1]
+ return result
+
+
+def _markdownReplaceLinks(markdown: str, images: bool = False) -> str:
+ """Replaces markdown links with html
+ Optionally replace image links
+ """
+ replaceLinks = {}
+ text = markdown
+ startChars = '['
+ if images:
+ startChars = '!['
+ while startChars in text:
+ if ')' not in text:
+ break
+ text = text.split(startChars, 1)[1]
+ markdownLink = startChars + text.split(')')[0] + ')'
+ if ']' not in markdownLink or \
+ '(' not in markdownLink:
+ text = text.split(')', 1)[1]
+ continue
+ if not images:
+ replaceLinks[markdownLink] = \
+ '' + \
+ markdownLink.split(startChars)[1].split(']')[0] + \
+ ''
+ else:
+ replaceLinks[markdownLink] = \
+ '
'
+ text = text.split(')', 1)[1]
+ for mdLink, htmlLink in replaceLinks.items():
+ markdown = markdown.replace(mdLink, htmlLink)
+ return markdown
+
+
+def markdownToHtml(markdown: str) -> str:
+ """Converts markdown formatted text to html
+ """
+ markdown = _markdownReplaceQuotes(markdown)
+ markdown = _markdownEmphasisHtml(markdown)
+ markdown = _markdownReplaceLinks(markdown, True)
+ markdown = _markdownReplaceLinks(markdown)
+
+ # replace headers
+ linesList = markdown.split('\n')
+ htmlStr = ''
+ ctr = 0
+ for line in linesList:
+ if ctr > 0:
+ htmlStr += '
'
+ if line.startswith('#####'):
+ line = line.replace('#####', '').strip()
+ line = '' + line + '
'
+ ctr = -1
+ elif line.startswith('####'):
+ line = line.replace('####', '').strip()
+ line = '' + line + '
'
+ ctr = -1
+ elif line.startswith('###'):
+ line = line.replace('###', '').strip()
+ line = '' + line + '
'
+ ctr = -1
+ elif line.startswith('##'):
+ line = line.replace('##', '').strip()
+ line = '' + line + '
'
+ ctr = -1
+ elif line.startswith('#'):
+ line = line.replace('#', '').strip()
+ line = '' + line + '
'
+ ctr = -1
+ htmlStr += line
+ ctr += 1
+ return htmlStr
diff --git a/mastoapiv1.py b/mastoapiv1.py
index 0a0e48ac0..51d6da9cb 100644
--- a/mastoapiv1.py
+++ b/mastoapiv1.py
@@ -5,7 +5,7 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
-__module_group__ = "Metadata"
+__module_group__ = "Core"
import os
from utils import loadJson
diff --git a/migrate.py b/migrate.py
index 4cca4b0e8..b36002a41 100644
--- a/migrate.py
+++ b/migrate.py
@@ -8,6 +8,7 @@ __status__ = "Production"
__module_group__ = "Core"
import os
+from utils import isAccountDir
from utils import getNicknameFromActor
from utils import getDomainFromActor
from webfinger import webfingerHandle
@@ -186,11 +187,7 @@ def migrateAccounts(baseDir: str, session,
ctr = 0
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for handle in dirs:
- if '@' not in handle:
- continue
- if handle.startswith('inbox@'):
- continue
- if handle.startswith('news@'):
+ if not isAccountDir(handle):
continue
nickname = handle.split('@')[0]
domain = handle.split('@')[1]
diff --git a/person.py b/person.py
index 44468e4de..e148397e2 100644
--- a/person.py
+++ b/person.py
@@ -38,6 +38,7 @@ from roles import setRole
from roles import setRolesFromList
from roles import getActorRolesList
from media import processMetaData
+from domainhandler import removeDomainPort
from utils import getStatusNumber
from utils import getFullDomain
from utils import validNickname
@@ -48,10 +49,12 @@ from utils import getConfigParam
from utils import refreshNewswire
from utils import getProtocolPrefixes
from utils import hasUsersPath
+from utils import getImageExtensions
from session import createSession
from session import getJson
from webfinger import webfingerHandle
from pprint import pprint
+from cache import getPersonFromCache
def generateRSAKey() -> (str, str):
@@ -93,8 +96,7 @@ def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
if imageFilename.startswith('~/'):
imageFilename = imageFilename.replace('~/', str(Path.home()) + '/')
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
fullDomain = getFullDomain(domain, port)
handle = nickname + '@' + domain
@@ -147,8 +149,7 @@ def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
def _accountExists(baseDir: str, nickname: str, domain: str) -> bool:
"""Returns true if the given account exists
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
return os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain) or \
os.path.isdir(baseDir + '/deactivated/' + nickname + '@' + domain)
@@ -720,8 +721,7 @@ def personLookup(domain: str, path: str, baseDir: str) -> {}:
return None
if not isSharedInbox and not validNickname(domain, nickname):
return None
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
handle = nickname + '@' + domain
filename = baseDir + '/accounts/' + handle + '.json'
if not os.path.isfile(filename):
@@ -1349,3 +1349,31 @@ def getActorJson(hostDomain: str, handle: str, http: bool, gnunet: bool,
pprint(personJson)
return personJson, asHeader
return None, None
+
+
+def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {},
+ allowDownloads: bool) -> str:
+ """Returns the avatar url for the person
+ """
+ personJson = \
+ getPersonFromCache(baseDir, personUrl, personCache, allowDownloads)
+ if not personJson:
+ return None
+
+ # get from locally stored image
+ if not personJson.get('id'):
+ return None
+ actorStr = personJson['id'].replace('/', '-')
+ avatarImagePath = baseDir + '/cache/avatars/' + actorStr
+
+ imageExtension = getImageExtensions()
+ for ext in imageExtension:
+ if os.path.isfile(avatarImagePath + '.' + ext):
+ return '/avatars/' + actorStr + '.' + ext
+ elif os.path.isfile(avatarImagePath.lower() + '.' + ext):
+ return '/avatars/' + actorStr.lower() + '.' + ext
+
+ if personJson.get('icon'):
+ if personJson['icon'].get('url'):
+ return personJson['icon']['url']
+ return None
diff --git a/posts.py b/posts.py
index 38d57a7db..41713a7cc 100644
--- a/posts.py
+++ b/posts.py
@@ -32,6 +32,8 @@ from session import postImage
from webfinger import webfingerHandle
from httpsig import createSignedHeader
from siteactive import siteIsActive
+from domainhandler import removeDomainPort
+from domainhandler import getPortFromDomain
from utils import hasObjectDict
from utils import rejectPostId
from utils import removeInvalidChars
@@ -683,8 +685,7 @@ def savePostToBox(baseDir: str, httpPrefix: str, postId: str,
boxname != 'scheduled':
return None
originalDomain = domain
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
if not postId:
statusNumber, published = getStatusNumber()
@@ -1077,6 +1078,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
'atomUri': newPostId,
'inReplyToAtomUri': inReplyToAtomUri,
'commentsEnabled': commentsEnabled,
+ 'rejectReplies': not commentsEnabled,
'mediaType': 'text/html',
'content': content,
'contentMap': {
@@ -1128,6 +1130,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
'atomUri': newPostId,
'inReplyToAtomUri': inReplyToAtomUri,
'commentsEnabled': commentsEnabled,
+ 'rejectReplies': not commentsEnabled,
'mediaType': 'text/html',
'content': content,
'contentMap': {
@@ -1689,7 +1692,7 @@ def getMentionedPeople(baseDir: str, httpPrefix: str,
mentionedNickname = handle.split('@')[0]
mentionedDomain = handle.split('@')[1].strip('\n').strip('\r')
if ':' in mentionedDomain:
- mentionedDomain = mentionedDomain.split(':')[0]
+ mentionedDomain = removeDomainPort(mentionedDomain)
if not validNickname(mentionedDomain, mentionedNickname):
continue
actor = \
@@ -2665,8 +2668,8 @@ def sendToFollowers(session, baseDir: str,
index = 0
toDomain = followerHandles[index].split('@')[1]
if ':' in toDomain:
- toPort = toDomain.split(':')[1]
- toDomain = toDomain.split(':')[0]
+ toPort = getPortFromDomain(toDomain)
+ toDomain = removeDomainPort(toDomain)
cc = ''
diff --git a/pyjsonld.py b/pyjsonld.py
index 6bdfd78c5..042f199ac 100644
--- a/pyjsonld.py
+++ b/pyjsonld.py
@@ -15,6 +15,7 @@ JSON-LD.
__copyright__ = 'Copyright (c) 2011-2014 Digital Bazaar, Inc.'
__license__ = 'New BSD license'
__version__ = '0.6.8'
+__module_group__ = "ActivityPub"
__all__ = [
'compact', 'expand', 'flatten', 'frame', 'link', 'from_rdf', 'to_rdf',
diff --git a/roles.py b/roles.py
index a3d139971..121dcf7b8 100644
--- a/roles.py
+++ b/roles.py
@@ -10,6 +10,7 @@ import os
from utils import loadJson
from utils import saveJson
from utils import getStatusNumber
+from domainhandler import removeDomainPort
def _clearRoleStatus(baseDir: str, role: str) -> None:
@@ -75,8 +76,7 @@ def _addRole(baseDir: str, nickname: str, domain: str,
"""Adds a role nickname to the file.
This is a file containing the nicknames of accounts having this role
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
roleFile = baseDir + '/accounts/' + roleFilename
if os.path.isfile(roleFile):
# is this nickname already in the file?
diff --git a/shares.py b/shares.py
index c906a4a23..488a276fb 100644
--- a/shares.py
+++ b/shares.py
@@ -20,6 +20,7 @@ from utils import loadJson
from utils import saveJson
from utils import getImageExtensions
from utils import hasObjectDict
+from domainhandler import removeDomainPort
from media import processMetaData
@@ -187,9 +188,7 @@ def expireShares(baseDir: str) -> None:
def _expireSharesForAccount(baseDir: str, nickname: str, domain: str) -> None:
"""Removes expired items from shares for a particular account
"""
- handleDomain = domain
- if ':' in handleDomain:
- handleDomain = domain.split(':')[0]
+ handleDomain = removeDomainPort(domain)
handle = nickname + '@' + handleDomain
sharesFilename = baseDir + '/accounts/' + handle + '/shares.json'
if os.path.isfile(sharesFilename):
@@ -250,9 +249,7 @@ def getSharesFeedForPerson(baseDir: str,
domain = getFullDomain(domain, port)
- handleDomain = domain
- if ':' in handleDomain:
- handleDomain = domain.split(':')[0]
+ handleDomain = removeDomainPort(domain)
handle = nickname + '@' + handleDomain
sharesFilename = baseDir + '/accounts/' + handle + '/shares.json'
diff --git a/tests.py b/tests.py
index b5e8c9b01..40098610f 100644
--- a/tests.py
+++ b/tests.py
@@ -5,6 +5,7 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
+__module_group__ = "Testing"
import time
import os
@@ -115,8 +116,8 @@ from newswire import parseFeedDate
from mastoapiv1 import getMastoApiV1IdFromNickname
from mastoapiv1 import getNicknameFromMastoApiV1Id
from webapp_post import prepareHtmlPostNickname
-from webapp_utils import markdownToHtml
from speaker import speakerReplaceLinks
+from markdown import markdownToHtml
testServerAliceRunning = False
testServerBobRunning = False
@@ -2359,6 +2360,16 @@ def _testJsonPostAllowsComments():
"commentsEnabled": False
}
assert not jsonPostAllowsComments(postJsonObject)
+ postJsonObject = {
+ "id": "123",
+ "rejectReplies": False
+ }
+ assert jsonPostAllowsComments(postJsonObject)
+ postJsonObject = {
+ "id": "123",
+ "rejectReplies": True
+ }
+ assert not jsonPostAllowsComments(postJsonObject)
postJsonObject = {
"id": "123",
"commentsEnabled": True
diff --git a/theme.py b/theme.py
index def0348ce..4223bb121 100644
--- a/theme.py
+++ b/theme.py
@@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
__status__ = "Production"
import os
+from utils import isAccountDir
from utils import loadJson
from utils import saveJson
from utils import getImageExtensions
@@ -623,11 +624,7 @@ def _setThemeImages(baseDir: str, name: str) -> None:
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for acct in dirs:
- if '@' not in acct:
- continue
- if acct.startswith('inbox@'):
- continue
- elif acct.startswith('news@'):
+ if not isAccountDir(acct):
continue
accountDir = \
os.path.join(baseDir + '/accounts', acct)
diff --git a/utils.py b/utils.py
index 94234eecc..33454cf14 100644
--- a/utils.py
+++ b/utils.py
@@ -5,6 +5,7 @@ __version__ = "1.2.0"
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
+__module_group__ = "ActivityPu"
import os
import re
@@ -15,6 +16,8 @@ import json
import idna
import locale
from pprint import pprint
+from domainhandler import removeDomainPort
+from domainhandler import getPortFromDomain
from followingCalendar import addPersonToCalendar
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
@@ -417,8 +420,7 @@ def getFollowersOfPerson(baseDir: str,
Used by the shared inbox to know who to send incoming mail to
"""
followers = []
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
handle = nickname + '@' + domain
if not os.path.isdir(baseDir + '/accounts/' + handle):
return followers
@@ -645,8 +647,7 @@ def createInboxQueueDir(nickname: str, domain: str, baseDir: str) -> str:
def domainPermitted(domain: str, federationList: []):
if len(federationList) == 0:
return True
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
if domain in federationList:
return True
return False
@@ -742,83 +743,90 @@ def getDisplayName(baseDir: str, actor: str, personCache: {}) -> str:
return nameFound
+def _genderFromString(translate: {}, text: str) -> str:
+ """Given some text, does it contain a gender description?
+ """
+ gender = None
+ textOrig = text
+ text = text.lower()
+ if translate['He/Him'].lower() in text or \
+ translate['boy'].lower() in text:
+ gender = 'He/Him'
+ elif (translate['She/Her'].lower() in text or
+ translate['girl'].lower() in text):
+ gender = 'She/Her'
+ elif 'him' in text or 'male' in text:
+ gender = 'He/Him'
+ elif 'her' in text or 'she' in text or \
+ 'fem' in text or 'woman' in text:
+ gender = 'She/Her'
+ elif 'man' in text or 'He' in textOrig:
+ gender = 'He/Him'
+ return gender
+
+
def getGenderFromBio(baseDir: str, actor: str, personCache: {},
translate: {}) -> str:
"""Tries to ascertain gender from bio description
+ This is for use by text-to-speech for pitch setting
"""
+ defaultGender = 'They/Them'
if '/statuses/' in actor:
actor = actor.split('/statuses/')[0]
if not personCache.get(actor):
- return None
+ return defaultGender
bioFound = None
if translate:
pronounStr = translate['pronoun'].lower()
else:
pronounStr = 'pronoun'
+ actorJson = None
if personCache[actor].get('actor'):
- # is gender defined as a profile tag?
- if personCache[actor]['actor'].get('attachment'):
- tagsList = personCache[actor]['actor']['attachment']
- if isinstance(tagsList, list):
- for tag in tagsList:
- if not isinstance(tag, dict):
- continue
- if not tag.get('name') or not tag.get('value'):
- continue
- if tag['name'].lower() == \
- translate['gender'].lower():
- bioFound = tag['value']
- break
- elif tag['name'].lower().startswith(pronounStr):
- bioFound = tag['value']
- break
- # if not then use the bio
- if not bioFound and personCache[actor]['actor'].get('summary'):
- bioFound = personCache[actor]['actor']['summary']
+ actorJson = personCache[actor]['actor']
else:
# Try to obtain from the cached actors
cachedActorFilename = \
baseDir + '/cache/actors/' + (actor.replace('/', '#')) + '.json'
if os.path.isfile(cachedActorFilename):
actorJson = loadJson(cachedActorFilename, 1)
- if actorJson:
- # is gender defined as a profile tag?
- if actorJson.get('attachment'):
- tagsList = actorJson['attachment']
- if isinstance(tagsList, list):
- for tag in tagsList:
- if not isinstance(tag, dict):
- continue
- if not tag.get('name') or not tag.get('value'):
- continue
- if tag['name'].lower() == \
- translate['gender'].lower():
- bioFound = tag['value']
- break
- elif tag['name'].lower().startswith(pronounStr):
- bioFound = tag['value']
- break
- # if not then use the bio
- if not bioFound and actorJson.get('summary'):
- bioFound = actorJson['summary']
+ if not actorJson:
+ return defaultGender
+ # is gender defined as a profile tag?
+ if actorJson.get('attachment'):
+ tagsList = actorJson['attachment']
+ if isinstance(tagsList, list):
+ # look for a gender field name
+ for tag in tagsList:
+ if not isinstance(tag, dict):
+ continue
+ if not tag.get('name') or not tag.get('value'):
+ continue
+ if tag['name'].lower() == \
+ translate['gender'].lower():
+ bioFound = tag['value']
+ break
+ elif tag['name'].lower().startswith(pronounStr):
+ bioFound = tag['value']
+ break
+ # the field name could be anything,
+ # just look at the value
+ if not bioFound:
+ for tag in tagsList:
+ if not isinstance(tag, dict):
+ continue
+ if not tag.get('name') or not tag.get('value'):
+ continue
+ gender = _genderFromString(translate, tag['value'])
+ if gender:
+ return gender
+ # if not then use the bio
+ if not bioFound and actorJson.get('summary'):
+ bioFound = actorJson['summary']
if not bioFound:
- return None
- gender = 'They/Them'
- bioFoundOrig = bioFound
- bioFound = bioFound.lower()
- if translate['He/Him'].lower() in bioFound or \
- translate['boy'].lower() in bioFound:
- gender = 'He/Him'
- elif (translate['She/Her'].lower() in bioFound or
- translate['girl'].lower() in bioFound):
- gender = 'She/Her'
- elif 'him' in bioFound or 'male' in bioFound:
- gender = 'He/Him'
- elif 'her' in bioFound or 'she' in bioFound or \
- 'fem' in bioFound or 'woman' in bioFound:
- gender = 'She/Her'
- elif 'man' in bioFound or 'He' in bioFoundOrig:
- gender = 'He/Him'
+ return defaultGender
+ gender = _genderFromString(translate, bioFound)
+ if not gender:
+ gender = defaultGender
return gender
@@ -827,56 +835,34 @@ def getNicknameFromActor(actor: str) -> str:
"""
if actor.startswith('@'):
actor = actor[1:]
- if '/users/' not in actor:
- if '/profile/' in actor:
- nickStr = actor.split('/profile/')[1].replace('@', '')
+ usersPaths = ('/users/', '/profile/', '/channel/', '/accounts/', '/u/')
+ for possiblePath in usersPaths:
+ if possiblePath in actor:
+ nickStr = actor.split(possiblePath)[1].replace('@', '')
if '/' not in nickStr:
return nickStr
else:
return nickStr.split('/')[0]
- elif '/channel/' in actor:
- nickStr = actor.split('/channel/')[1].replace('@', '')
- if '/' not in nickStr:
- return nickStr
- else:
- return nickStr.split('/')[0]
- elif '/accounts/' in actor:
- nickStr = actor.split('/accounts/')[1].replace('@', '')
- if '/' not in nickStr:
- return nickStr
- else:
- return nickStr.split('/')[0]
- elif '/u/' in actor:
- nickStr = actor.split('/u/')[1].replace('@', '')
- if '/' not in nickStr:
- return nickStr
- else:
- return nickStr.split('/')[0]
- elif '/@' in actor:
- # https://domain/@nick
- nickStr = actor.split('/@')[1]
- if '/' in nickStr:
- nickStr = nickStr.split('/')[0]
- return nickStr
- elif '@' in actor:
- nickStr = actor.split('@')[0]
- return nickStr
- elif '://' in actor:
- domain = actor.split('://')[1]
- if '/' in domain:
- domain = domain.split('/')[0]
- if '://' + domain + '/' not in actor:
- return None
- nickStr = actor.split('://' + domain + '/')[1]
- if '/' in nickStr or '.' in nickStr:
- return None
- return nickStr
- return None
- nickStr = actor.split('/users/')[1].replace('@', '')
- if '/' not in nickStr:
+ if '/@' in actor:
+ # https://domain/@nick
+ nickStr = actor.split('/@')[1]
+ if '/' in nickStr:
+ nickStr = nickStr.split('/')[0]
return nickStr
- else:
- return nickStr.split('/')[0]
+ elif '@' in actor:
+ nickStr = actor.split('@')[0]
+ return nickStr
+ elif '://' in actor:
+ domain = actor.split('://')[1]
+ if '/' in domain:
+ domain = domain.split('/')[0]
+ if '://' + domain + '/' not in actor:
+ return None
+ nickStr = actor.split('://' + domain + '/')[1]
+ if '/' in nickStr or '.' in nickStr:
+ return None
+ return nickStr
+ return None
def getDomainFromActor(actor: str) -> (str, int):
@@ -886,27 +872,14 @@ def getDomainFromActor(actor: str) -> (str, int):
actor = actor[1:]
port = None
prefixes = getProtocolPrefixes()
- if '/profile/' in actor:
- domain = actor.split('/profile/')[0]
- for prefix in prefixes:
- domain = domain.replace(prefix, '')
- elif '/accounts/' in actor:
- domain = actor.split('/accounts/')[0]
- for prefix in prefixes:
- domain = domain.replace(prefix, '')
- elif '/channel/' in actor:
- domain = actor.split('/channel/')[0]
- for prefix in prefixes:
- domain = domain.replace(prefix, '')
- elif '/users/' in actor:
- domain = actor.split('/users/')[0]
- for prefix in prefixes:
- domain = domain.replace(prefix, '')
- elif '/u/' in actor:
- domain = actor.split('/u/')[0]
- for prefix in prefixes:
- domain = domain.replace(prefix, '')
- elif '/@' in actor:
+ usersPaths = ('/users/', '/profile/', '/accounts/', '/channel/', '/u/')
+ for possiblePath in usersPaths:
+ if possiblePath in actor:
+ domain = actor.split(possiblePath)[0]
+ for prefix in prefixes:
+ domain = domain.replace(prefix, '')
+ break
+ if '/@' in actor:
domain = actor.split('/@')[0]
for prefix in prefixes:
domain = domain.replace(prefix, '')
@@ -919,11 +892,8 @@ def getDomainFromActor(actor: str) -> (str, int):
if '/' in actor:
domain = domain.split('/')[0]
if ':' in domain:
- portStr = domain.split(':')[1]
- if not portStr.isdigit():
- return None, None
- port = int(portStr)
- domain = domain.split(':')[0]
+ port = getPortFromDomain(domain)
+ domain = removeDomainPort(domain)
return domain, port
@@ -932,8 +902,7 @@ def _setDefaultPetName(baseDir: str, nickname: str, domain: str,
"""Sets a default petname
This helps especially when using onion or i2p address
"""
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domain)
userPath = baseDir + '/accounts/' + nickname + '@' + domain
petnamesFilename = userPath + '/petnames.txt'
@@ -975,7 +944,8 @@ def followPerson(baseDir: str, nickname: str, domain: str,
print('DEBUG: follow of domain ' + followDomain)
if ':' in domain:
- handle = nickname + '@' + domain.split(':')[0]
+ domainOnly = removeDomainPort(domain)
+ handle = nickname + '@' + domainOnly
else:
handle = nickname + '@' + domain
@@ -984,7 +954,8 @@ def followPerson(baseDir: str, nickname: str, domain: str,
return False
if ':' in followDomain:
- handleToFollow = followNickname + '@' + followDomain.split(':')[0]
+ followDomainOnly = removeDomainPort(followDomain)
+ handleToFollow = followNickname + '@' + followDomainOnly
else:
handleToFollow = followNickname + '@' + followDomain
@@ -1189,10 +1160,6 @@ def _removeAttachment(baseDir: str, httpPrefix: str, domain: str,
return
if not postJson['attachment'][0].get('url'):
return
-# if port:
-# if port != 80 and port != 443:
-# if ':' not in domain:
-# domain = domain + ':' + str(port)
attachmentUrl = postJson['attachment'][0]['url']
if not attachmentUrl:
return
@@ -1487,18 +1454,18 @@ def noOfActiveAccountsMonthly(baseDir: str, months: int) -> bool:
monthSeconds = int(60*60*24*30*months)
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for account in dirs:
- if '@' in account:
- if not account.startswith('inbox@') and \
- not account.startswith('news@'):
- lastUsedFilename = \
- baseDir + '/accounts/' + account + '/.lastUsed'
- if os.path.isfile(lastUsedFilename):
- with open(lastUsedFilename, 'r') as lastUsedFile:
- lastUsed = lastUsedFile.read()
- if lastUsed.isdigit():
- timeDiff = (currTime - int(lastUsed))
- if timeDiff < monthSeconds:
- accountCtr += 1
+ if not isAccountDir(account):
+ continue
+ lastUsedFilename = \
+ baseDir + '/accounts/' + account + '/.lastUsed'
+ if not os.path.isfile(lastUsedFilename):
+ continue
+ with open(lastUsedFilename, 'r') as lastUsedFile:
+ lastUsed = lastUsedFile.read()
+ if lastUsed.isdigit():
+ timeDiff = (currTime - int(lastUsed))
+ if timeDiff < monthSeconds:
+ accountCtr += 1
break
return accountCtr
@@ -1824,13 +1791,6 @@ def getFileCaseInsensitive(path: str) -> str:
if path != path.lower():
if os.path.isfile(path.lower()):
return path.lower()
- # directory, filename = os.path.split(path)
- # directory, filename = (directory or '.'), filename.lower()
- # for f in os.listdir(directory):
- # if f.lower() == filename:
- # newpath = os.path.join(directory, f)
- # if os.path.isfile(newpath):
- # return newpath
return None
diff --git a/webapp_about.py b/webapp_about.py
index 233d052f7..607e08a6d 100644
--- a/webapp_about.py
+++ b/webapp_about.py
@@ -12,7 +12,7 @@ from shutil import copyfile
from utils import getConfigParam
from webapp_utils import htmlHeaderWithWebsiteMarkup
from webapp_utils import htmlFooter
-from webapp_utils import markdownToHtml
+from markdown import markdownToHtml
def htmlAbout(cssCache: {}, baseDir: str, httpPrefix: str,
diff --git a/webapp_calendar.py b/webapp_calendar.py
index 486f8c061..740cf514c 100644
--- a/webapp_calendar.py
+++ b/webapp_calendar.py
@@ -18,6 +18,7 @@ from utils import getDomainFromActor
from utils import locatePost
from utils import loadJson
from utils import weekDayOfMonthStart
+from domainhandler import removeDomainPort
from happening import getTodaysEvents
from happening import getCalendarEvents
from webapp_utils import htmlHeaderWithExternalStyle
@@ -247,9 +248,7 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
textModeBanner: str, accessKeys: {}) -> str:
"""Show the calendar for a person
"""
- domain = domainFull
- if ':' in domainFull:
- domain = domainFull.split(':')[0]
+ domain = removeDomainPort(domainFull)
monthNumber = 0
dayNumber = None
@@ -460,7 +459,6 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
htmlHideFromScreenReader('←') + ' ' + translate['Previous month']
navLinks[prevMonthStr] = calActor + '/calendar?year=' + str(prevYear) + \
'?month=' + str(prevMonthNumber)
- # TODO
navAccessKeys = {
}
screenReaderCal = \
diff --git a/webapp_column_left.py b/webapp_column_left.py
index 5428650f0..6a63126db 100644
--- a/webapp_column_left.py
+++ b/webapp_column_left.py
@@ -11,6 +11,7 @@ import os
from utils import getConfigParam
from utils import getNicknameFromActor
from utils import isEditor
+from domainhandler import removeDomainPort
from webapp_utils import sharesTimelineJson
from webapp_utils import htmlPostSeparator
from webapp_utils import getLeftImageFile
@@ -76,9 +77,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
htmlStr = ''
separatorStr = htmlPostSeparator(baseDir, 'left')
- domain = domainFull
- if ':' in domain:
- domain = domain.split(':')
+ domain = removeDomainPort(domainFull)
editImageClass = ''
if showHeaderImage:
@@ -298,9 +297,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
else:
editor = isEditor(baseDir, nickname)
- domain = domainFull
- if ':' in domain:
- domain = domain.split(':')[0]
+ domain = removeDomainPort(domainFull)
instanceTitle = \
getConfigParam(baseDir, 'instanceTitle')
diff --git a/webapp_column_right.py b/webapp_column_right.py
index 0d194c1b0..15c95c40a 100644
--- a/webapp_column_right.py
+++ b/webapp_column_right.py
@@ -17,6 +17,7 @@ from utils import votesOnNewswireItem
from utils import getNicknameFromActor
from utils import isEditor
from utils import getConfigParam
+from domainhandler import removeDomainPort
from posts import isModerator
from webapp_utils import getRightImageFile
from webapp_utils import htmlHeaderWithExternalStyle
@@ -58,9 +59,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
"""
htmlStr = ''
- domain = domainFull
- if ':' in domain:
- domain = domain.split(':')
+ domain = removeDomainPort(domainFull)
if authorized:
# only show the publish button if logged in, otherwise replace it with
diff --git a/webapp_minimalbutton.py b/webapp_minimalbutton.py
new file mode 100644
index 000000000..3b1815f36
--- /dev/null
+++ b/webapp_minimalbutton.py
@@ -0,0 +1,40 @@
+__filename__ = "webapp_minimalbutton.py"
+__author__ = "Bob Mottram"
+__license__ = "AGPL3+"
+__version__ = "1.2.0"
+__maintainer__ = "Bob Mottram"
+__email__ = "bob@freedombone.net"
+__status__ = "Production"
+__module_group__ = "Web Interface"
+
+import os
+
+
+def isMinimal(baseDir: str, domain: str, nickname: str) -> bool:
+ """Returns true if minimal buttons should be shown
+ for the given account
+ """
+ accountDir = baseDir + '/accounts/' + \
+ nickname + '@' + domain
+ if not os.path.isdir(accountDir):
+ return True
+ minimalFilename = accountDir + '/.notminimal'
+ if os.path.isfile(minimalFilename):
+ return False
+ return True
+
+
+def setMinimal(baseDir: str, domain: str, nickname: str,
+ minimal: bool) -> None:
+ """Sets whether an account should display minimal buttons
+ """
+ accountDir = baseDir + '/accounts/' + nickname + '@' + domain
+ if not os.path.isdir(accountDir):
+ return
+ minimalFilename = accountDir + '/.notminimal'
+ minimalFileExists = os.path.isfile(minimalFilename)
+ if minimal and minimalFileExists:
+ os.remove(minimalFilename)
+ elif not minimal and not minimalFileExists:
+ with open(minimalFilename, 'w+') as fp:
+ fp.write('\n')
diff --git a/webapp_moderation.py b/webapp_moderation.py
index 4e79f9f4d..01bddd2ad 100644
--- a/webapp_moderation.py
+++ b/webapp_moderation.py
@@ -8,6 +8,7 @@ __status__ = "Production"
__module_group__ = "Web Interface"
import os
+from utils import isAccountDir
from utils import getFullDomain
from utils import isEditor
from utils import loadJson
@@ -270,11 +271,7 @@ def htmlModerationInfo(cssCache: {}, translate: {},
accounts = []
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
for acct in dirs:
- if '@' not in acct:
- continue
- if acct.startswith('inbox@'):
- continue
- elif acct.startswith('news@'):
+ if not isAccountDir(acct):
continue
accounts.append(acct)
break
diff --git a/webapp_post.py b/webapp_post.py
index b4bf0a33e..fa1317344 100644
--- a/webapp_post.py
+++ b/webapp_post.py
@@ -52,9 +52,9 @@ from content import removeLongWords
from content import getMentionsFromHtml
from content import switchWords
from person import isPersonSnoozed
+from person import getPersonAvatarUrl
from announce import announcedByPerson
from webapp_utils import getAvatarImageUrl
-from webapp_utils import getPersonAvatarUrl
from webapp_utils import updateAvatarImageCache
from webapp_utils import loadIndividualPostAsHtmlFromCache
from webapp_utils import addEmojiToDisplayName
@@ -1401,6 +1401,9 @@ def individualPostAsHtml(allowDownloads: bool,
if 'commentsEnabled' in postJsonObject['object']:
if postJsonObject['object']['commentsEnabled'] is False:
commentsEnabled = False
+ elif 'rejectReplies' in postJsonObject['object']:
+ if postJsonObject['object']['rejectReplies']:
+ commentsEnabled = False
replyStr = _getReplyIconHtml(nickname, isPublicRepeat,
showIcons, commentsEnabled,
diff --git a/webapp_profile.py b/webapp_profile.py
index fcaff60c8..4b47bbe36 100644
--- a/webapp_profile.py
+++ b/webapp_profile.py
@@ -26,6 +26,7 @@ from skills import getSkills
from theme import getThemesList
from person import personBoxJson
from person import getActorJson
+from person import getPersonAvatarUrl
from webfinger import webfingerHandle
from posts import parseUserFeed
from posts import getPersonBox
@@ -45,7 +46,6 @@ from webapp_frontscreen import htmlFrontScreen
from webapp_utils import htmlKeyboardNavigation
from webapp_utils import htmlHideFromScreenReader
from webapp_utils import scheduledPostsExist
-from webapp_utils import getPersonAvatarUrl
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlHeaderWithPersonMarkup
from webapp_utils import htmlFooter
diff --git a/webapp_search.py b/webapp_search.py
index e6beb6c18..22221ea1c 100644
--- a/webapp_search.py
+++ b/webapp_search.py
@@ -11,6 +11,7 @@ import os
from shutil import copyfile
import urllib.parse
from datetime import datetime
+from utils import isAccountDir
from utils import getConfigParam
from utils import getFullDomain
from utils import isEditor
@@ -407,11 +408,7 @@ def htmlSkillsSearch(actor: str,
for f in files:
if not f.endswith('.json'):
continue
- if '@' not in f:
- continue
- if f.startswith('inbox@'):
- continue
- elif f.startswith('news@'):
+ if not isAccountDir(f):
continue
actorFilename = os.path.join(subdir, f)
actorJson = loadJson(actorFilename)
@@ -446,11 +443,7 @@ def htmlSkillsSearch(actor: str,
for f in files:
if not f.endswith('.json'):
continue
- if '@' not in f:
- continue
- if f.startswith('inbox@'):
- continue
- elif f.startswith('news@'):
+ if not isAccountDir(f):
continue
actorFilename = os.path.join(subdir, f)
cachedActorJson = loadJson(actorFilename)
diff --git a/webapp_timeline.py b/webapp_timeline.py
index 8f4cb9d8e..471c1ede6 100644
--- a/webapp_timeline.py
+++ b/webapp_timeline.py
@@ -17,7 +17,7 @@ from utils import isEditor
from utils import removeIdEnding
from follow import followerApprovalActive
from person import isPersonSnoozed
-from webapp_utils import markdownToHtml
+from markdown import markdownToHtml
from webapp_utils import htmlKeyboardNavigation
from webapp_utils import htmlHideFromScreenReader
from webapp_utils import htmlPostSeparator
diff --git a/webapp_tos.py b/webapp_tos.py
index 3fe7c7f3d..119c853bf 100644
--- a/webapp_tos.py
+++ b/webapp_tos.py
@@ -12,7 +12,7 @@ from shutil import copyfile
from utils import getConfigParam
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter
-from webapp_utils import markdownToHtml
+from markdown import markdownToHtml
def htmlTermsOfService(cssCache: {}, baseDir: str,
diff --git a/webapp_utils.py b/webapp_utils.py
index 79163cf19..22d6fb787 100644
--- a/webapp_utils.py
+++ b/webapp_utils.py
@@ -16,170 +16,10 @@ from utils import getProtocolPrefixes
from utils import loadJson
from utils import getCachedPostFilename
from utils import getConfigParam
-from cache import getPersonFromCache
from cache import storePersonInCache
from content import addHtmlTags
from content import replaceEmojiFromTags
-
-
-def _markdownEmphasisHtml(markdown: str) -> str:
- """Add italics and bold html markup to the given markdown
- """
- replacements = {
- ' **': ' ',
- '** ': ' ',
- '**.': '.',
- '**:': ':',
- '**;': ';',
- '**,': ',',
- '**\n': '\n',
- ' *': ' ',
- '* ': ' ',
- '*.': '.',
- '*:': ':',
- '*;': ';',
- '*,': ',',
- '*\n': '\n',
- ' _': ' ',
- '_.': '.',
- '_:': ':',
- '_;': ';',
- '_,': ',',
- '_\n': '\n'
- }
- for md, html in replacements.items():
- markdown = markdown.replace(md, html)
-
- if markdown.startswith('**'):
- markdown = markdown[2:] + ''
- elif markdown.startswith('*'):
- markdown = markdown[1:] + ''
- elif markdown.startswith('_'):
- markdown = markdown[1:] + ''
-
- if markdown.endswith('**'):
- markdown = markdown[:len(markdown) - 2] + '
'
- elif markdown.endswith('*'):
- markdown = markdown[:len(markdown) - 1] + ''
- elif markdown.endswith('_'):
- markdown = markdown[:len(markdown) - 1] + ''
- return markdown
-
-
-def _markdownReplaceQuotes(markdown: str) -> str:
- """Replaces > quotes with html blockquote
- """
- if '> ' not in markdown:
- return markdown
- lines = markdown.split('\n')
- result = ''
- prevQuoteLine = None
- for line in lines:
- if '> ' not in line:
- result += line + '\n'
- prevQuoteLine = None
- continue
- lineStr = line.strip()
- if not lineStr.startswith('> '):
- result += line + '\n'
- prevQuoteLine = None
- continue
- lineStr = lineStr.replace('> ', '', 1).strip()
- if prevQuoteLine:
- newPrevLine = prevQuoteLine.replace('\n', '')
- result = result.replace(prevQuoteLine, newPrevLine) + ' '
- lineStr += '\n'
- else:
- lineStr = '' + lineStr + '
\n'
- result += lineStr
- prevQuoteLine = lineStr
-
- if '\n' in result:
- result = result.replace('\n', '')
-
- if result.endswith('\n') and \
- not markdown.endswith('\n'):
- result = result[:len(result) - 1]
- return result
-
-
-def _markdownReplaceLinks(markdown: str, images: bool = False) -> str:
- """Replaces markdown links with html
- Optionally replace image links
- """
- replaceLinks = {}
- text = markdown
- startChars = '['
- if images:
- startChars = '!['
- while startChars in text:
- if ')' not in text:
- break
- text = text.split(startChars, 1)[1]
- markdownLink = startChars + text.split(')')[0] + ')'
- if ']' not in markdownLink or \
- '(' not in markdownLink:
- text = text.split(')', 1)[1]
- continue
- if not images:
- replaceLinks[markdownLink] = \
- '' + \
- markdownLink.split(startChars)[1].split(']')[0] + \
- ''
- else:
- replaceLinks[markdownLink] = \
- '
'
- text = text.split(')', 1)[1]
- for mdLink, htmlLink in replaceLinks.items():
- markdown = markdown.replace(mdLink, htmlLink)
- return markdown
-
-
-def markdownToHtml(markdown: str) -> str:
- """Converts markdown formatted text to html
- """
- markdown = _markdownReplaceQuotes(markdown)
- markdown = _markdownEmphasisHtml(markdown)
- markdown = _markdownReplaceLinks(markdown, True)
- markdown = _markdownReplaceLinks(markdown)
-
- # replace headers
- linesList = markdown.split('\n')
- htmlStr = ''
- ctr = 0
- for line in linesList:
- if ctr > 0:
- htmlStr += '
'
- if line.startswith('#####'):
- line = line.replace('#####', '').strip()
- line = '' + line + '
'
- ctr = -1
- elif line.startswith('####'):
- line = line.replace('####', '').strip()
- line = '' + line + '
'
- ctr = -1
- elif line.startswith('###'):
- line = line.replace('###', '').strip()
- line = '' + line + '
'
- ctr = -1
- elif line.startswith('##'):
- line = line.replace('##', '').strip()
- line = '' + line + '
'
- ctr = -1
- elif line.startswith('#'):
- line = line.replace('#', '').strip()
- line = '' + line + '
'
- ctr = -1
- htmlStr += line
- ctr += 1
- return htmlStr
+from person import getPersonAvatarUrl
def getBrokenLinkSubstitute() -> str:
@@ -533,34 +373,6 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
return avatarImageFilename.replace(baseDir + '/cache', '')
-def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {},
- allowDownloads: bool) -> str:
- """Returns the avatar url for the person
- """
- personJson = \
- getPersonFromCache(baseDir, personUrl, personCache, allowDownloads)
- if not personJson:
- return None
-
- # get from locally stored image
- if not personJson.get('id'):
- return None
- actorStr = personJson['id'].replace('/', '-')
- avatarImagePath = baseDir + '/cache/avatars/' + actorStr
-
- imageExtension = getImageExtensions()
- for ext in imageExtension:
- if os.path.isfile(avatarImagePath + '.' + ext):
- return '/avatars/' + actorStr + '.' + ext
- elif os.path.isfile(avatarImagePath.lower() + '.' + ext):
- return '/avatars/' + actorStr.lower() + '.' + ext
-
- if personJson.get('icon'):
- if personJson['icon'].get('url'):
- return personJson['icon']['url']
- return None
-
-
def scheduledPostsExist(baseDir: str, nickname: str, domain: str) -> bool:
"""Returns true if there are posts scheduled to be delivered
"""
@@ -1359,33 +1171,3 @@ def htmlKeyboardNavigation(banner: str, links: {}, accessKeys: {},
str(title) + '\n'
htmlStr += '\n'
return htmlStr
-
-
-def isMinimal(baseDir: str, domain: str, nickname: str) -> bool:
- """Returns true if minimal buttons should be shown
- for the given account
- """
- accountDir = baseDir + '/accounts/' + \
- nickname + '@' + domain
- if not os.path.isdir(accountDir):
- return True
- minimalFilename = accountDir + '/.notminimal'
- if os.path.isfile(minimalFilename):
- return False
- return True
-
-
-def setMinimal(baseDir: str, domain: str, nickname: str,
- minimal: bool) -> None:
- """Sets whether an account should display minimal buttons
- """
- accountDir = baseDir + '/accounts/' + nickname + '@' + domain
- if not os.path.isdir(accountDir):
- return
- minimalFilename = accountDir + '/.notminimal'
- minimalFileExists = os.path.isfile(minimalFilename)
- if minimal and minimalFileExists:
- os.remove(minimalFilename)
- elif not minimal and not minimalFileExists:
- with open(minimalFilename, 'w+') as fp:
- fp.write('\n')
diff --git a/webapp_welcome.py b/webapp_welcome.py
index 7fd59b7ae..c1e804a82 100644
--- a/webapp_welcome.py
+++ b/webapp_welcome.py
@@ -13,7 +13,7 @@ from utils import getConfigParam
from utils import removeHtml
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter
-from webapp_utils import markdownToHtml
+from markdown import markdownToHtml
def isWelcomeScreenComplete(baseDir: str, nickname: str, domain: str) -> bool:
diff --git a/webapp_welcome_final.py b/webapp_welcome_final.py
index e3586aa72..01349aa28 100644
--- a/webapp_welcome_final.py
+++ b/webapp_welcome_final.py
@@ -13,7 +13,7 @@ from utils import removeHtml
from utils import getConfigParam
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter
-from webapp_utils import markdownToHtml
+from markdown import markdownToHtml
def htmlWelcomeFinal(baseDir: str, nickname: str, domain: str,
diff --git a/webapp_welcome_profile.py b/webapp_welcome_profile.py
index d734587c8..990c88fe2 100644
--- a/webapp_welcome_profile.py
+++ b/webapp_welcome_profile.py
@@ -16,7 +16,7 @@ from utils import getImageExtensions
from utils import getImageFormats
from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter
-from webapp_utils import markdownToHtml
+from markdown import markdownToHtml
def htmlWelcomeProfile(baseDir: str, nickname: str, domain: str,
diff --git a/webfinger.py b/webfinger.py
index 6235eb429..c774a0c85 100644
--- a/webfinger.py
+++ b/webfinger.py
@@ -17,6 +17,7 @@ from utils import loadJson
from utils import loadJsonOnionify
from utils import saveJson
from utils import getProtocolPrefixes
+from domainhandler import removeDomainPort
def _parseHandle(handle: str) -> (str, str):
@@ -53,13 +54,8 @@ def webfingerHandle(session, handle: str, httpPrefix: str,
nickname, domain = _parseHandle(handle)
if not nickname:
return None
- wfDomain = domain
- if ':' in wfDomain:
- # wfPortStr=wfDomain.split(':')[1]
- # if wfPortStr.isdigit():
- # wfPort=int(wfPortStr)
- # if wfPort==80 or wfPort==443:
- wfDomain = wfDomain.split(':')[0]
+ wfDomain = removeDomainPort(domain)
+
wf = getWebfingerFromCache(nickname + '@' + wfDomain,
cachedWebfingers)
if wf: