mirror of https://gitlab.com/bashrc2/epicyon
Merge branch 'main' of ssh://code.freedombone.net:2222/bashrc/epicyon
commit
40e766f029
|
|
@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
__module_group__ = "ActivityPub"
|
__module_group__ = "ActivityPub"
|
||||||
|
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import hasObjectDict
|
from utils import hasObjectDict
|
||||||
from utils import removeIdEnding
|
from utils import removeIdEnding
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
|
|
@ -128,8 +129,7 @@ def createAnnounce(session, baseDir: str, federationList: [],
|
||||||
if not urlPermitted(objectUrl, federationList):
|
if not urlPermitted(objectUrl, federationList):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
fullDomain = getFullDomain(domain, port)
|
fullDomain = getFullDomain(domain, port)
|
||||||
|
|
||||||
statusNumber, published = getStatusNumber()
|
statusNumber, published = getStatusNumber()
|
||||||
|
|
@ -399,8 +399,7 @@ def outboxUndoAnnounce(recentPostsCache: {},
|
||||||
print('DEBUG: c2s undo announce request arrived in outbox')
|
print('DEBUG: c2s undo announce request arrived in outbox')
|
||||||
|
|
||||||
messageId = removeIdEnding(messageJson['object']['object'])
|
messageId = removeIdEnding(messageJson['object']['object'])
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
|
||||||
21
blocking.py
21
blocking.py
|
|
@ -5,12 +5,13 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
__module_group__ = "ActivityPub"
|
__module_group__ = "Core"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import hasObjectDict
|
from utils import hasObjectDict
|
||||||
from utils import isAccountDir
|
from utils import isAccountDir
|
||||||
from utils import getCachedPostFilename
|
from utils import getCachedPostFilename
|
||||||
|
|
@ -58,8 +59,7 @@ def addBlock(baseDir: str, nickname: str, domain: str,
|
||||||
blockNickname: str, blockDomain: str) -> bool:
|
blockNickname: str, blockDomain: str) -> bool:
|
||||||
"""Block the given account
|
"""Block the given account
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
blockingFilename = baseDir + '/accounts/' + \
|
blockingFilename = baseDir + '/accounts/' + \
|
||||||
nickname + '@' + domain + '/blocking.txt'
|
nickname + '@' + domain + '/blocking.txt'
|
||||||
blockHandle = blockNickname + '@' + blockDomain
|
blockHandle = blockNickname + '@' + blockDomain
|
||||||
|
|
@ -111,8 +111,7 @@ def removeBlock(baseDir: str, nickname: str, domain: str,
|
||||||
unblockNickname: str, unblockDomain: str) -> bool:
|
unblockNickname: str, unblockDomain: str) -> bool:
|
||||||
"""Unblock the given account
|
"""Unblock the given account
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
unblockingFilename = baseDir + '/accounts/' + \
|
unblockingFilename = baseDir + '/accounts/' + \
|
||||||
nickname + '@' + domain + '/blocking.txt'
|
nickname + '@' + domain + '/blocking.txt'
|
||||||
unblockHandle = unblockNickname + '@' + unblockDomain
|
unblockHandle = unblockNickname + '@' + unblockDomain
|
||||||
|
|
@ -338,8 +337,7 @@ def outboxBlock(baseDir: str, httpPrefix: str,
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: c2s block object has no nickname')
|
print('DEBUG: c2s block object has no nickname')
|
||||||
return
|
return
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -406,8 +404,7 @@ def outboxUndoBlock(baseDir: str, httpPrefix: str,
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: c2s undo block object has no nickname')
|
print('DEBUG: c2s undo block object has no nickname')
|
||||||
return
|
return
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -605,8 +602,7 @@ def outboxMute(baseDir: str, httpPrefix: str,
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: c2s mute object has no nickname')
|
print('DEBUG: c2s mute object has no nickname')
|
||||||
return
|
return
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -663,8 +659,7 @@ def outboxUndoMute(baseDir: str, httpPrefix: str,
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: c2s undo mute object has no nickname')
|
print('DEBUG: c2s undo mute object has no nickname')
|
||||||
return
|
return
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
|
||||||
19
blog.py
19
blog.py
|
|
@ -16,6 +16,7 @@ from webapp_utils import htmlHeaderWithBlogMarkup
|
||||||
from webapp_utils import htmlFooter
|
from webapp_utils import htmlFooter
|
||||||
from webapp_utils import getPostAttachmentsAsHtml
|
from webapp_utils import getPostAttachmentsAsHtml
|
||||||
from webapp_media import addEmbeddedElements
|
from webapp_media import addEmbeddedElements
|
||||||
|
from utils import isAccountDir
|
||||||
from utils import removeHtml
|
from utils import removeHtml
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
|
|
@ -643,11 +644,7 @@ def _noOfBlogAccounts(baseDir: str) -> int:
|
||||||
ctr = 0
|
ctr = 0
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if not isAccountDir(acct):
|
||||||
continue
|
|
||||||
if acct.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
elif acct.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
accountDir = os.path.join(baseDir + '/accounts', acct)
|
accountDir = os.path.join(baseDir + '/accounts', acct)
|
||||||
blogsIndex = accountDir + '/tlblogs.index'
|
blogsIndex = accountDir + '/tlblogs.index'
|
||||||
|
|
@ -662,11 +659,7 @@ def _singleBlogAccountNickname(baseDir: str) -> str:
|
||||||
"""
|
"""
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if not isAccountDir(acct):
|
||||||
continue
|
|
||||||
if acct.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
elif acct.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
accountDir = os.path.join(baseDir + '/accounts', acct)
|
accountDir = os.path.join(baseDir + '/accounts', acct)
|
||||||
blogsIndex = accountDir + '/tlblogs.index'
|
blogsIndex = accountDir + '/tlblogs.index'
|
||||||
|
|
@ -704,11 +697,7 @@ def htmlBlogView(authorized: bool,
|
||||||
|
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if not isAccountDir(acct):
|
||||||
continue
|
|
||||||
if acct.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
elif acct.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
accountDir = os.path.join(baseDir + '/accounts', acct)
|
accountDir = os.path.join(baseDir + '/accounts', acct)
|
||||||
blogsIndex = accountDir + '/tlblogs.index'
|
blogsIndex = accountDir + '/tlblogs.index'
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import os
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from auth import createBasicAuthHeader
|
from auth import createBasicAuthHeader
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
from utils import removeIdEnding
|
from utils import removeIdEnding
|
||||||
|
|
@ -560,8 +561,7 @@ def outboxBookmark(recentPostsCache: {},
|
||||||
print('DEBUG: c2s bookmark Add request arrived in outbox')
|
print('DEBUG: c2s bookmark Add request arrived in outbox')
|
||||||
|
|
||||||
messageUrl = removeIdEnding(messageJson['object']['url'])
|
messageUrl = removeIdEnding(messageJson['object']['url'])
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -625,8 +625,7 @@ def outboxUndoBookmark(recentPostsCache: {},
|
||||||
print('DEBUG: c2s unbookmark Remove request arrived in outbox')
|
print('DEBUG: c2s unbookmark Remove request arrived in outbox')
|
||||||
|
|
||||||
messageUrl = removeIdEnding(messageJson['object']['url'])
|
messageUrl = removeIdEnding(messageJson['object']['url'])
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,13 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
|
__module_group__ = "Core"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import email.parser
|
import email.parser
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import isValidLanguage
|
from utils import isValidLanguage
|
||||||
from utils import getImageExtensions
|
from utils import getImageExtensions
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
|
|
@ -772,8 +774,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
|
||||||
replaceEmoji = {}
|
replaceEmoji = {}
|
||||||
emojiDict = {}
|
emojiDict = {}
|
||||||
originalDomain = domain
|
originalDomain = domain
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
followingFilename = baseDir + '/accounts/' + \
|
followingFilename = baseDir + '/accounts/' + \
|
||||||
nickname + '@' + domain + '/following.txt'
|
nickname + '@' + domain + '/following.txt'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
|
__module_group__ = "Core"
|
||||||
|
|
||||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer, HTTPServer
|
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer, HTTPServer
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -139,8 +140,8 @@ from blog import htmlBlogView
|
||||||
from blog import htmlBlogPage
|
from blog import htmlBlogPage
|
||||||
from blog import htmlBlogPost
|
from blog import htmlBlogPost
|
||||||
from blog import htmlEditBlog
|
from blog import htmlEditBlog
|
||||||
from webapp_utils import setMinimal
|
from webapp_minimalbutton import setMinimal
|
||||||
from webapp_utils import isMinimal
|
from webapp_minimalbutton import isMinimal
|
||||||
from webapp_utils import getAvatarImageUrl
|
from webapp_utils import getAvatarImageUrl
|
||||||
from webapp_utils import htmlHashtagBlocked
|
from webapp_utils import htmlHashtagBlocked
|
||||||
from webapp_utils import htmlFollowingList
|
from webapp_utils import htmlFollowingList
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ __module_group__ = "ActivityPub"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
from utils import removeIdEnding
|
from utils import removeIdEnding
|
||||||
|
|
@ -154,8 +155,7 @@ def outboxDelete(baseDir: str, httpPrefix: str,
|
||||||
"wasn't created by you (nickname does not match)")
|
"wasn't created by you (nickname does not match)")
|
||||||
return
|
return
|
||||||
deleteDomain, deletePort = getDomainFromActor(messageId)
|
deleteDomain, deletePort = getDomainFromActor(messageId)
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
if deleteDomain != domain:
|
if deleteDomain != domain:
|
||||||
if debug:
|
if debug:
|
||||||
print("DEBUG: you can't delete a post which " +
|
print("DEBUG: you can't delete a post which " +
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -61,6 +61,8 @@ from tests import testUpdateActor
|
||||||
from tests import runAllTests
|
from tests import runAllTests
|
||||||
from auth import storeBasicCredentials
|
from auth import storeBasicCredentials
|
||||||
from auth import createPassword
|
from auth import createPassword
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
from domainhandler import getPortFromDomain
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
from utils import setConfigParam
|
from utils import setConfigParam
|
||||||
|
|
@ -1080,8 +1082,8 @@ if args.message:
|
||||||
toDomain = toDomain.replace('\n', '').replace('\r', '')
|
toDomain = toDomain.replace('\n', '').replace('\r', '')
|
||||||
toPort = 443
|
toPort = 443
|
||||||
if ':' in toDomain:
|
if ':' in toDomain:
|
||||||
toPort = toDomain.split(':')[1]
|
toPort = getPortFromDomain(toDomain)
|
||||||
toDomain = toDomain.split(':')[0]
|
toDomain = removeDomainPort(toDomain)
|
||||||
else:
|
else:
|
||||||
if args.sendto.endswith('followers'):
|
if args.sendto.endswith('followers'):
|
||||||
toNickname = None
|
toNickname = None
|
||||||
|
|
|
||||||
16
follow.py
16
follow.py
|
|
@ -9,6 +9,7 @@ __module_group__ = "ActivityPub"
|
||||||
|
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
import os
|
import os
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import hasObjectDict
|
from utils import hasObjectDict
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
|
|
@ -153,8 +154,7 @@ def isFollowingActor(baseDir: str,
|
||||||
"""Is the given nickname following the given actor?
|
"""Is the given nickname following the given actor?
|
||||||
The actor can also be a handle: nickname@domain
|
The actor can also be a handle: nickname@domain
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
handle = nickname + '@' + domain
|
handle = nickname + '@' + domain
|
||||||
if not os.path.isdir(baseDir + '/accounts/' + handle):
|
if not os.path.isdir(baseDir + '/accounts/' + handle):
|
||||||
return False
|
return False
|
||||||
|
|
@ -205,8 +205,7 @@ def isFollowerOfPerson(baseDir: str, nickname: str, domain: str,
|
||||||
followerNickname: str, followerDomain: str) -> bool:
|
followerNickname: str, followerDomain: str) -> bool:
|
||||||
"""is the given nickname a follower of followerNickname?
|
"""is the given nickname a follower of followerNickname?
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
followersFile = baseDir + '/accounts/' + \
|
followersFile = baseDir + '/accounts/' + \
|
||||||
nickname + '@' + domain + '/followers.txt'
|
nickname + '@' + domain + '/followers.txt'
|
||||||
if not os.path.isfile(followersFile):
|
if not os.path.isfile(followersFile):
|
||||||
|
|
@ -243,8 +242,7 @@ def unfollowAccount(baseDir: str, nickname: str, domain: str,
|
||||||
debug: bool = False) -> bool:
|
debug: bool = False) -> bool:
|
||||||
"""Removes a person to the follow list
|
"""Removes a person to the follow list
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
handle = nickname + '@' + domain
|
handle = nickname + '@' + domain
|
||||||
handleToUnfollow = followNickname + '@' + followDomain
|
handleToUnfollow = followNickname + '@' + followDomain
|
||||||
if not os.path.isdir(baseDir + '/accounts'):
|
if not os.path.isdir(baseDir + '/accounts'):
|
||||||
|
|
@ -433,8 +431,7 @@ def getFollowingFeed(baseDir: str, domain: str, port: int, path: str,
|
||||||
}
|
}
|
||||||
|
|
||||||
handleDomain = domain
|
handleDomain = domain
|
||||||
if ':' in handleDomain:
|
handleDomain = removeDomainPort(handleDomain)
|
||||||
handleDomain = domain.split(':')[0]
|
|
||||||
handle = nickname + '@' + handleDomain
|
handle = nickname + '@' + handleDomain
|
||||||
filename = baseDir + '/accounts/' + handle + '/' + followFile + '.txt'
|
filename = baseDir + '/accounts/' + handle + '/' + followFile + '.txt'
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
|
|
@ -493,8 +490,7 @@ def _followApprovalRequired(baseDir: str, nicknameToFollow: str,
|
||||||
return False
|
return False
|
||||||
|
|
||||||
manuallyApproveFollows = False
|
manuallyApproveFollows = False
|
||||||
if ':' in domainToFollow:
|
domainToFollow = removeDomainPort(domainToFollow)
|
||||||
domainToFollow = domainToFollow.split(':')[0]
|
|
||||||
actorFilename = baseDir + '/accounts/' + \
|
actorFilename = baseDir + '/accounts/' + \
|
||||||
nicknameToFollow + '@' + domainToFollow + '.json'
|
nicknameToFollow + '@' + domainToFollow + '.json'
|
||||||
if os.path.isfile(actorFilename):
|
if os.path.isfile(actorFilename):
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
||||||
__module_group__ = "Calendar"
|
__module_group__ = "Calendar"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
|
||||||
|
|
||||||
def receivingCalendarEvents(baseDir: str, nickname: str, domain: str,
|
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
|
indicating whether to receive calendar events from that account
|
||||||
"""
|
"""
|
||||||
# check that a following file exists
|
# check that a following file exists
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
followingFilename = baseDir + '/accounts/' + \
|
followingFilename = baseDir + '/accounts/' + \
|
||||||
nickname + '@' + domain + '/following.txt'
|
nickname + '@' + domain + '/following.txt'
|
||||||
if not os.path.isfile(followingFilename):
|
if not os.path.isfile(followingFilename):
|
||||||
|
|
|
||||||
2
git.py
2
git.py
|
|
@ -5,7 +5,7 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
__module_group__ = "ActivityPub"
|
__module_group__ = "Core"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import html
|
import html
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
__module_group__ = "Calendar"
|
__module_group__ = "Core"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
|
||||||
60
inbox.py
60
inbox.py
|
|
@ -13,6 +13,8 @@ import datetime
|
||||||
import time
|
import time
|
||||||
import random
|
import random
|
||||||
from linked_data_sig import verifyJsonSignature
|
from linked_data_sig import verifyJsonSignature
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
from domainhandler import getPortFromDomain
|
||||||
from utils import hasObjectDict
|
from utils import hasObjectDict
|
||||||
from utils import dmAllowedFromDomain
|
from utils import dmAllowedFromDomain
|
||||||
from utils import isRecentPost
|
from utils import isRecentPost
|
||||||
|
|
@ -186,8 +188,7 @@ def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
|
||||||
def validInbox(baseDir: str, nickname: str, domain: str) -> bool:
|
def validInbox(baseDir: str, nickname: str, domain: str) -> bool:
|
||||||
"""Checks whether files were correctly saved to the inbox
|
"""Checks whether files were correctly saved to the inbox
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
inboxDir = baseDir + '/accounts/' + nickname + '@' + domain + '/inbox'
|
inboxDir = baseDir + '/accounts/' + nickname + '@' + domain + '/inbox'
|
||||||
if not os.path.isdir(inboxDir):
|
if not os.path.isdir(inboxDir):
|
||||||
return True
|
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
|
"""Used by unit tests to check that the port number gets appended to
|
||||||
domain names within saved post filenames
|
domain names within saved post filenames
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
inboxDir = baseDir + '/accounts/' + nickname + '@' + domain + '/inbox'
|
inboxDir = baseDir + '/accounts/' + nickname + '@' + domain + '/inbox'
|
||||||
if not os.path.isdir(inboxDir):
|
if not os.path.isdir(inboxDir):
|
||||||
return True
|
return True
|
||||||
|
|
@ -358,8 +358,7 @@ def savePostToInboxQueue(baseDir: str, httpPrefix: str,
|
||||||
str(len(messageBytes)) + ' bytes')
|
str(len(messageBytes)) + ' bytes')
|
||||||
return None
|
return None
|
||||||
originalDomain = domain
|
originalDomain = domain
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
|
|
||||||
# block at the ealiest stage possible, which means the data
|
# block at the ealiest stage possible, which means the data
|
||||||
# isn't written to file
|
# isn't written to file
|
||||||
|
|
@ -536,8 +535,7 @@ def _inboxPostRecipients(baseDir: str, postJsonObject: {},
|
||||||
print('WARNING: inbox post has no actor')
|
print('WARNING: inbox post has no actor')
|
||||||
return recipientsDict, recipientsDictFollowers
|
return recipientsDict, recipientsDictFollowers
|
||||||
|
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
domainBase = domain
|
domainBase = domain
|
||||||
domain = getFullDomain(domain, port)
|
domain = getFullDomain(domain, port)
|
||||||
domainMatch = '/' + domain + '/users/'
|
domainMatch = '/' + domain + '/users/'
|
||||||
|
|
@ -1124,8 +1122,7 @@ def _receiveBookmark(recentPostsCache: {},
|
||||||
print('DEBUG: c2s inbox bookmark Add request arrived in outbox')
|
print('DEBUG: c2s inbox bookmark Add request arrived in outbox')
|
||||||
|
|
||||||
messageUrl = removeIdEnding(messageJson['object']['url'])
|
messageUrl = removeIdEnding(messageJson['object']['url'])
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -1200,8 +1197,7 @@ def _receiveUndoBookmark(recentPostsCache: {},
|
||||||
'request arrived in outbox')
|
'request arrived in outbox')
|
||||||
|
|
||||||
messageUrl = removeIdEnding(messageJson['object']['url'])
|
messageUrl = removeIdEnding(messageJson['object']['url'])
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
postFilename = locatePost(baseDir, nickname, domain, messageUrl)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -1521,11 +1517,15 @@ def jsonPostAllowsComments(postJsonObject: {}) -> bool:
|
||||||
"""
|
"""
|
||||||
if 'commentsEnabled' in postJsonObject:
|
if 'commentsEnabled' in postJsonObject:
|
||||||
return postJsonObject['commentsEnabled']
|
return postJsonObject['commentsEnabled']
|
||||||
|
if 'rejectReplies' in postJsonObject:
|
||||||
|
return not postJsonObject['rejectReplies']
|
||||||
if postJsonObject.get('object'):
|
if postJsonObject.get('object'):
|
||||||
if not hasObjectDict(postJsonObject):
|
if not hasObjectDict(postJsonObject):
|
||||||
return False
|
return False
|
||||||
elif 'commentsEnabled' in postJsonObject['object']:
|
elif 'commentsEnabled' in postJsonObject['object']:
|
||||||
return postJsonObject['object']['commentsEnabled']
|
return postJsonObject['object']['commentsEnabled']
|
||||||
|
elif 'rejectReplies' in postJsonObject['object']:
|
||||||
|
return not postJsonObject['object']['rejectReplies']
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1580,24 +1580,6 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
|
||||||
print('DEBUG: post may have expired - ' + replyTo)
|
print('DEBUG: post may have expired - ' + replyTo)
|
||||||
return False
|
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 not _postAllowsComments(postFilename):
|
||||||
if debug:
|
if debug:
|
||||||
print('DEBUG: post does not allow comments - ' + replyTo)
|
print('DEBUG: post does not allow comments - ' + replyTo)
|
||||||
|
|
@ -1975,8 +1957,7 @@ def _sendToGroupMembers(session, baseDir: str, handle: str, port: int,
|
||||||
# set subject
|
# set subject
|
||||||
if not postJsonObject['object'].get('summary'):
|
if not postJsonObject['object'].get('summary'):
|
||||||
postJsonObject['object']['summary'] = 'General Discussion'
|
postJsonObject['object']['summary'] = 'General Discussion'
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
with open(followersFile, 'r') as groupMembers:
|
with open(followersFile, 'r') as groupMembers:
|
||||||
for memberHandle in groupMembers:
|
for memberHandle in groupMembers:
|
||||||
if memberHandle != handle:
|
if memberHandle != handle:
|
||||||
|
|
@ -1984,10 +1965,8 @@ def _sendToGroupMembers(session, baseDir: str, handle: str, port: int,
|
||||||
memberDomain = memberHandle.split('@')[1]
|
memberDomain = memberHandle.split('@')[1]
|
||||||
memberPort = port
|
memberPort = port
|
||||||
if ':' in memberDomain:
|
if ':' in memberDomain:
|
||||||
memberPortStr = memberDomain.split(':')[1]
|
memberPort = getPortFromDomain(memberDomain)
|
||||||
if memberPortStr.isdigit():
|
memberDomain = removeDomainPort(memberDomain)
|
||||||
memberPort = int(memberPortStr)
|
|
||||||
memberDomain = memberDomain.split(':')[0]
|
|
||||||
sendSignedJson(postJsonObject, session, baseDir,
|
sendSignedJson(postJsonObject, session, baseDir,
|
||||||
nickname, domain, port,
|
nickname, domain, port,
|
||||||
memberNickname, memberDomain, memberPort, cc,
|
memberNickname, memberDomain, memberPort, cc,
|
||||||
|
|
@ -2078,8 +2057,7 @@ def _updateLastSeen(baseDir: str, handle: str, actor: str) -> None:
|
||||||
return
|
return
|
||||||
nickname = handle.split('@')[0]
|
nickname = handle.split('@')[0]
|
||||||
domain = handle.split('@')[1]
|
domain = handle.split('@')[1]
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
accountPath = baseDir + '/accounts/' + nickname + '@' + domain
|
accountPath = baseDir + '/accounts/' + nickname + '@' + domain
|
||||||
if not os.path.isdir(accountPath):
|
if not os.path.isdir(accountPath):
|
||||||
return
|
return
|
||||||
|
|
@ -2130,10 +2108,8 @@ def _bounceDM(senderPostId: str, session, httpPrefix: str,
|
||||||
senderDomain = sendingHandle.split('@')[1]
|
senderDomain = sendingHandle.split('@')[1]
|
||||||
senderPort = port
|
senderPort = port
|
||||||
if ':' in senderDomain:
|
if ':' in senderDomain:
|
||||||
senderPortStr = senderDomain.split(':')[1]
|
senderPort = getPortFromDomain(senderDomain)
|
||||||
if senderPortStr.isdigit():
|
senderDomain = removeDomainPort(senderDomain)
|
||||||
senderPort = int(senderPortStr)
|
|
||||||
senderDomain = senderDomain.split(':')[0]
|
|
||||||
cc = []
|
cc = []
|
||||||
|
|
||||||
# create the bounce DM
|
# create the bounce DM
|
||||||
|
|
|
||||||
7
like.py
7
like.py
|
|
@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
__module_group__ = "ActivityPub"
|
__module_group__ = "ActivityPub"
|
||||||
|
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import hasObjectDict
|
from utils import hasObjectDict
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
|
|
@ -327,8 +328,7 @@ def outboxLike(recentPostsCache: {},
|
||||||
print('DEBUG: c2s like request arrived in outbox')
|
print('DEBUG: c2s like request arrived in outbox')
|
||||||
|
|
||||||
messageId = removeIdEnding(messageJson['object'])
|
messageId = removeIdEnding(messageJson['object'])
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
@ -377,8 +377,7 @@ def outboxUndoLike(recentPostsCache: {},
|
||||||
print('DEBUG: c2s undo like request arrived in outbox')
|
print('DEBUG: c2s undo like request arrived in outbox')
|
||||||
|
|
||||||
messageId = removeIdEnding(messageJson['object']['object'])
|
messageId = removeIdEnding(messageJson['object']['object'])
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
postFilename = locatePost(baseDir, nickname, domain, messageId)
|
||||||
if not postFilename:
|
if not postFilename:
|
||||||
if debug:
|
if debug:
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,8 @@ from follow import followedAccountAccepts
|
||||||
from follow import followedAccountRejects
|
from follow import followedAccountRejects
|
||||||
from follow import removeFromFollowRequests
|
from follow import removeFromFollowRequests
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
from domainhandler import getPortFromDomain
|
||||||
|
|
||||||
|
|
||||||
def manualDenyFollowRequest(session, baseDir: str,
|
def manualDenyFollowRequest(session, baseDir: str,
|
||||||
|
|
@ -49,8 +51,8 @@ def manualDenyFollowRequest(session, baseDir: str,
|
||||||
denyHandle.split('@')[1].replace('\n', '').replace('\r', '')
|
denyHandle.split('@')[1].replace('\n', '').replace('\r', '')
|
||||||
denyPort = port
|
denyPort = port
|
||||||
if ':' in denyDomain:
|
if ':' in denyDomain:
|
||||||
denyPort = denyDomain.split(':')[1]
|
denyPort = getPortFromDomain(denyDomain)
|
||||||
denyDomain = denyDomain.split(':')[0]
|
denyDomain = removeDomainPort(denyDomain)
|
||||||
followedAccountRejects(session, baseDir, httpPrefix,
|
followedAccountRejects(session, baseDir, httpPrefix,
|
||||||
nickname, domain, port,
|
nickname, domain, port,
|
||||||
denyNickname, denyDomain, denyPort,
|
denyNickname, denyDomain, denyPort,
|
||||||
|
|
@ -141,9 +143,7 @@ def manualApproveFollowRequest(session, baseDir: str,
|
||||||
handleOfFollowRequester.replace('\r', '')
|
handleOfFollowRequester.replace('\r', '')
|
||||||
port2 = port
|
port2 = port
|
||||||
if ':' in handleOfFollowRequester:
|
if ':' in handleOfFollowRequester:
|
||||||
port2Str = handleOfFollowRequester.split(':')[1]
|
port2 = getPortFromDomain(handleOfFollowRequester)
|
||||||
if port2Str.isdigit():
|
|
||||||
port2 = int(port2Str)
|
|
||||||
requestsDir = accountDir + '/requests'
|
requestsDir = accountDir + '/requests'
|
||||||
followActivityfilename = \
|
followActivityfilename = \
|
||||||
requestsDir + '/' + handleOfFollowRequester + '.follow'
|
requestsDir + '/' + handleOfFollowRequester + '.follow'
|
||||||
|
|
@ -158,8 +158,8 @@ def manualApproveFollowRequest(session, baseDir: str,
|
||||||
approveDomain.replace('\r', '')
|
approveDomain.replace('\r', '')
|
||||||
approvePort = port2
|
approvePort = port2
|
||||||
if ':' in approveDomain:
|
if ':' in approveDomain:
|
||||||
approvePort = approveDomain.split(':')[1]
|
approvePort = getPortFromDomain(approveDomain)
|
||||||
approveDomain = approveDomain.split(':')[0]
|
approveDomain = removeDomainPort(approveDomain)
|
||||||
print('Manual follow accept: Sending Accept for ' +
|
print('Manual follow accept: Sending Accept for ' +
|
||||||
handle + ' follow request from ' +
|
handle + ' follow request from ' +
|
||||||
approveNickname + '@' + approveDomain)
|
approveNickname + '@' + approveDomain)
|
||||||
|
|
|
||||||
|
|
@ -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 = {
|
||||||
|
' **': ' <b>',
|
||||||
|
'** ': '</b> ',
|
||||||
|
'**.': '</b>.',
|
||||||
|
'**:': '</b>:',
|
||||||
|
'**;': '</b>;',
|
||||||
|
'**,': '</b>,',
|
||||||
|
'**\n': '</b>\n',
|
||||||
|
' *': ' <i>',
|
||||||
|
'* ': '</i> ',
|
||||||
|
'*.': '</i>.',
|
||||||
|
'*:': '</i>:',
|
||||||
|
'*;': '</i>;',
|
||||||
|
'*,': '</i>,',
|
||||||
|
'*\n': '</i>\n',
|
||||||
|
' _': ' <ul>',
|
||||||
|
'_ ': '</ul> ',
|
||||||
|
'_.': '</ul>.',
|
||||||
|
'_:': '</ul>:',
|
||||||
|
'_;': '</ul>;',
|
||||||
|
'_,': '</ul>,',
|
||||||
|
'_\n': '</ul>\n'
|
||||||
|
}
|
||||||
|
for md, html in replacements.items():
|
||||||
|
markdown = markdown.replace(md, html)
|
||||||
|
|
||||||
|
if markdown.startswith('**'):
|
||||||
|
markdown = markdown[2:] + '<b>'
|
||||||
|
elif markdown.startswith('*'):
|
||||||
|
markdown = markdown[1:] + '<i>'
|
||||||
|
elif markdown.startswith('_'):
|
||||||
|
markdown = markdown[1:] + '<ul>'
|
||||||
|
|
||||||
|
if markdown.endswith('**'):
|
||||||
|
markdown = markdown[:len(markdown) - 2] + '</b>'
|
||||||
|
elif markdown.endswith('*'):
|
||||||
|
markdown = markdown[:len(markdown) - 1] + '</i>'
|
||||||
|
elif markdown.endswith('_'):
|
||||||
|
markdown = markdown[:len(markdown) - 1] + '</ul>'
|
||||||
|
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('</i></blockquote>\n', '')
|
||||||
|
result = result.replace(prevQuoteLine, newPrevLine) + ' '
|
||||||
|
lineStr += '</i></blockquote>\n'
|
||||||
|
else:
|
||||||
|
lineStr = '<blockquote><i>' + lineStr + '</i></blockquote>\n'
|
||||||
|
result += lineStr
|
||||||
|
prevQuoteLine = lineStr
|
||||||
|
|
||||||
|
if '</blockquote>\n' in result:
|
||||||
|
result = result.replace('</blockquote>\n', '</blockquote>')
|
||||||
|
|
||||||
|
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] = \
|
||||||
|
'<a href="' + \
|
||||||
|
markdownLink.split('(')[1].split(')')[0] + \
|
||||||
|
'" target="_blank" rel="nofollow noopener noreferrer">' + \
|
||||||
|
markdownLink.split(startChars)[1].split(']')[0] + \
|
||||||
|
'</a>'
|
||||||
|
else:
|
||||||
|
replaceLinks[markdownLink] = \
|
||||||
|
'<img class="markdownImage" src="' + \
|
||||||
|
markdownLink.split('(')[1].split(')')[0] + \
|
||||||
|
'" alt="' + \
|
||||||
|
markdownLink.split(startChars)[1].split(']')[0] + \
|
||||||
|
'" />'
|
||||||
|
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 += '<br>'
|
||||||
|
if line.startswith('#####'):
|
||||||
|
line = line.replace('#####', '').strip()
|
||||||
|
line = '<h5>' + line + '</h5>'
|
||||||
|
ctr = -1
|
||||||
|
elif line.startswith('####'):
|
||||||
|
line = line.replace('####', '').strip()
|
||||||
|
line = '<h4>' + line + '</h4>'
|
||||||
|
ctr = -1
|
||||||
|
elif line.startswith('###'):
|
||||||
|
line = line.replace('###', '').strip()
|
||||||
|
line = '<h3>' + line + '</h3>'
|
||||||
|
ctr = -1
|
||||||
|
elif line.startswith('##'):
|
||||||
|
line = line.replace('##', '').strip()
|
||||||
|
line = '<h2>' + line + '</h2>'
|
||||||
|
ctr = -1
|
||||||
|
elif line.startswith('#'):
|
||||||
|
line = line.replace('#', '').strip()
|
||||||
|
line = '<h1>' + line + '</h1>'
|
||||||
|
ctr = -1
|
||||||
|
htmlStr += line
|
||||||
|
ctr += 1
|
||||||
|
return htmlStr
|
||||||
|
|
@ -5,7 +5,7 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
__module_group__ = "Metadata"
|
__module_group__ = "Core"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
||||||
__module_group__ = "Core"
|
__module_group__ = "Core"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from utils import isAccountDir
|
||||||
from utils import getNicknameFromActor
|
from utils import getNicknameFromActor
|
||||||
from utils import getDomainFromActor
|
from utils import getDomainFromActor
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
|
|
@ -186,11 +187,7 @@ def migrateAccounts(baseDir: str, session,
|
||||||
ctr = 0
|
ctr = 0
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for handle in dirs:
|
for handle in dirs:
|
||||||
if '@' not in handle:
|
if not isAccountDir(handle):
|
||||||
continue
|
|
||||||
if handle.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
if handle.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
nickname = handle.split('@')[0]
|
nickname = handle.split('@')[0]
|
||||||
domain = handle.split('@')[1]
|
domain = handle.split('@')[1]
|
||||||
|
|
|
||||||
40
person.py
40
person.py
|
|
@ -38,6 +38,7 @@ from roles import setRole
|
||||||
from roles import setRolesFromList
|
from roles import setRolesFromList
|
||||||
from roles import getActorRolesList
|
from roles import getActorRolesList
|
||||||
from media import processMetaData
|
from media import processMetaData
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from utils import getStatusNumber
|
from utils import getStatusNumber
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
from utils import validNickname
|
from utils import validNickname
|
||||||
|
|
@ -48,10 +49,12 @@ from utils import getConfigParam
|
||||||
from utils import refreshNewswire
|
from utils import refreshNewswire
|
||||||
from utils import getProtocolPrefixes
|
from utils import getProtocolPrefixes
|
||||||
from utils import hasUsersPath
|
from utils import hasUsersPath
|
||||||
|
from utils import getImageExtensions
|
||||||
from session import createSession
|
from session import createSession
|
||||||
from session import getJson
|
from session import getJson
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
from cache import getPersonFromCache
|
||||||
|
|
||||||
|
|
||||||
def generateRSAKey() -> (str, str):
|
def generateRSAKey() -> (str, str):
|
||||||
|
|
@ -93,8 +96,7 @@ def setProfileImage(baseDir: str, httpPrefix: str, nickname: str, domain: str,
|
||||||
if imageFilename.startswith('~/'):
|
if imageFilename.startswith('~/'):
|
||||||
imageFilename = imageFilename.replace('~/', str(Path.home()) + '/')
|
imageFilename = imageFilename.replace('~/', str(Path.home()) + '/')
|
||||||
|
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
fullDomain = getFullDomain(domain, port)
|
fullDomain = getFullDomain(domain, port)
|
||||||
|
|
||||||
handle = nickname + '@' + domain
|
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:
|
def _accountExists(baseDir: str, nickname: str, domain: str) -> bool:
|
||||||
"""Returns true if the given account exists
|
"""Returns true if the given account exists
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
return os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain) or \
|
return os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain) or \
|
||||||
os.path.isdir(baseDir + '/deactivated/' + nickname + '@' + domain)
|
os.path.isdir(baseDir + '/deactivated/' + nickname + '@' + domain)
|
||||||
|
|
||||||
|
|
@ -720,8 +721,7 @@ def personLookup(domain: str, path: str, baseDir: str) -> {}:
|
||||||
return None
|
return None
|
||||||
if not isSharedInbox and not validNickname(domain, nickname):
|
if not isSharedInbox and not validNickname(domain, nickname):
|
||||||
return None
|
return None
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
handle = nickname + '@' + domain
|
handle = nickname + '@' + domain
|
||||||
filename = baseDir + '/accounts/' + handle + '.json'
|
filename = baseDir + '/accounts/' + handle + '.json'
|
||||||
if not os.path.isfile(filename):
|
if not os.path.isfile(filename):
|
||||||
|
|
@ -1349,3 +1349,31 @@ def getActorJson(hostDomain: str, handle: str, http: bool, gnunet: bool,
|
||||||
pprint(personJson)
|
pprint(personJson)
|
||||||
return personJson, asHeader
|
return personJson, asHeader
|
||||||
return None, None
|
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
|
||||||
|
|
|
||||||
13
posts.py
13
posts.py
|
|
@ -32,6 +32,8 @@ from session import postImage
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from httpsig import createSignedHeader
|
from httpsig import createSignedHeader
|
||||||
from siteactive import siteIsActive
|
from siteactive import siteIsActive
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
from domainhandler import getPortFromDomain
|
||||||
from utils import hasObjectDict
|
from utils import hasObjectDict
|
||||||
from utils import rejectPostId
|
from utils import rejectPostId
|
||||||
from utils import removeInvalidChars
|
from utils import removeInvalidChars
|
||||||
|
|
@ -683,8 +685,7 @@ def savePostToBox(baseDir: str, httpPrefix: str, postId: str,
|
||||||
boxname != 'scheduled':
|
boxname != 'scheduled':
|
||||||
return None
|
return None
|
||||||
originalDomain = domain
|
originalDomain = domain
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
|
|
||||||
if not postId:
|
if not postId:
|
||||||
statusNumber, published = getStatusNumber()
|
statusNumber, published = getStatusNumber()
|
||||||
|
|
@ -1077,6 +1078,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
|
||||||
'atomUri': newPostId,
|
'atomUri': newPostId,
|
||||||
'inReplyToAtomUri': inReplyToAtomUri,
|
'inReplyToAtomUri': inReplyToAtomUri,
|
||||||
'commentsEnabled': commentsEnabled,
|
'commentsEnabled': commentsEnabled,
|
||||||
|
'rejectReplies': not commentsEnabled,
|
||||||
'mediaType': 'text/html',
|
'mediaType': 'text/html',
|
||||||
'content': content,
|
'content': content,
|
||||||
'contentMap': {
|
'contentMap': {
|
||||||
|
|
@ -1128,6 +1130,7 @@ def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
|
||||||
'atomUri': newPostId,
|
'atomUri': newPostId,
|
||||||
'inReplyToAtomUri': inReplyToAtomUri,
|
'inReplyToAtomUri': inReplyToAtomUri,
|
||||||
'commentsEnabled': commentsEnabled,
|
'commentsEnabled': commentsEnabled,
|
||||||
|
'rejectReplies': not commentsEnabled,
|
||||||
'mediaType': 'text/html',
|
'mediaType': 'text/html',
|
||||||
'content': content,
|
'content': content,
|
||||||
'contentMap': {
|
'contentMap': {
|
||||||
|
|
@ -1689,7 +1692,7 @@ def getMentionedPeople(baseDir: str, httpPrefix: str,
|
||||||
mentionedNickname = handle.split('@')[0]
|
mentionedNickname = handle.split('@')[0]
|
||||||
mentionedDomain = handle.split('@')[1].strip('\n').strip('\r')
|
mentionedDomain = handle.split('@')[1].strip('\n').strip('\r')
|
||||||
if ':' in mentionedDomain:
|
if ':' in mentionedDomain:
|
||||||
mentionedDomain = mentionedDomain.split(':')[0]
|
mentionedDomain = removeDomainPort(mentionedDomain)
|
||||||
if not validNickname(mentionedDomain, mentionedNickname):
|
if not validNickname(mentionedDomain, mentionedNickname):
|
||||||
continue
|
continue
|
||||||
actor = \
|
actor = \
|
||||||
|
|
@ -2665,8 +2668,8 @@ def sendToFollowers(session, baseDir: str,
|
||||||
index = 0
|
index = 0
|
||||||
toDomain = followerHandles[index].split('@')[1]
|
toDomain = followerHandles[index].split('@')[1]
|
||||||
if ':' in toDomain:
|
if ':' in toDomain:
|
||||||
toPort = toDomain.split(':')[1]
|
toPort = getPortFromDomain(toDomain)
|
||||||
toDomain = toDomain.split(':')[0]
|
toDomain = removeDomainPort(toDomain)
|
||||||
|
|
||||||
cc = ''
|
cc = ''
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ JSON-LD.
|
||||||
__copyright__ = 'Copyright (c) 2011-2014 Digital Bazaar, Inc.'
|
__copyright__ = 'Copyright (c) 2011-2014 Digital Bazaar, Inc.'
|
||||||
__license__ = 'New BSD license'
|
__license__ = 'New BSD license'
|
||||||
__version__ = '0.6.8'
|
__version__ = '0.6.8'
|
||||||
|
__module_group__ = "ActivityPub"
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
'compact', 'expand', 'flatten', 'frame', 'link', 'from_rdf', 'to_rdf',
|
'compact', 'expand', 'flatten', 'frame', 'link', 'from_rdf', 'to_rdf',
|
||||||
|
|
|
||||||
4
roles.py
4
roles.py
|
|
@ -10,6 +10,7 @@ import os
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
from utils import saveJson
|
from utils import saveJson
|
||||||
from utils import getStatusNumber
|
from utils import getStatusNumber
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
|
||||||
|
|
||||||
def _clearRoleStatus(baseDir: str, role: str) -> None:
|
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.
|
"""Adds a role nickname to the file.
|
||||||
This is a file containing the nicknames of accounts having this role
|
This is a file containing the nicknames of accounts having this role
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
roleFile = baseDir + '/accounts/' + roleFilename
|
roleFile = baseDir + '/accounts/' + roleFilename
|
||||||
if os.path.isfile(roleFile):
|
if os.path.isfile(roleFile):
|
||||||
# is this nickname already in the file?
|
# is this nickname already in the file?
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ from utils import loadJson
|
||||||
from utils import saveJson
|
from utils import saveJson
|
||||||
from utils import getImageExtensions
|
from utils import getImageExtensions
|
||||||
from utils import hasObjectDict
|
from utils import hasObjectDict
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from media import processMetaData
|
from media import processMetaData
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -187,9 +188,7 @@ def expireShares(baseDir: str) -> None:
|
||||||
def _expireSharesForAccount(baseDir: str, nickname: str, domain: str) -> None:
|
def _expireSharesForAccount(baseDir: str, nickname: str, domain: str) -> None:
|
||||||
"""Removes expired items from shares for a particular account
|
"""Removes expired items from shares for a particular account
|
||||||
"""
|
"""
|
||||||
handleDomain = domain
|
handleDomain = removeDomainPort(domain)
|
||||||
if ':' in handleDomain:
|
|
||||||
handleDomain = domain.split(':')[0]
|
|
||||||
handle = nickname + '@' + handleDomain
|
handle = nickname + '@' + handleDomain
|
||||||
sharesFilename = baseDir + '/accounts/' + handle + '/shares.json'
|
sharesFilename = baseDir + '/accounts/' + handle + '/shares.json'
|
||||||
if os.path.isfile(sharesFilename):
|
if os.path.isfile(sharesFilename):
|
||||||
|
|
@ -250,9 +249,7 @@ def getSharesFeedForPerson(baseDir: str,
|
||||||
|
|
||||||
domain = getFullDomain(domain, port)
|
domain = getFullDomain(domain, port)
|
||||||
|
|
||||||
handleDomain = domain
|
handleDomain = removeDomainPort(domain)
|
||||||
if ':' in handleDomain:
|
|
||||||
handleDomain = domain.split(':')[0]
|
|
||||||
handle = nickname + '@' + handleDomain
|
handle = nickname + '@' + handleDomain
|
||||||
sharesFilename = baseDir + '/accounts/' + handle + '/shares.json'
|
sharesFilename = baseDir + '/accounts/' + handle + '/shares.json'
|
||||||
|
|
||||||
|
|
|
||||||
13
tests.py
13
tests.py
|
|
@ -5,6 +5,7 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
|
__module_group__ = "Testing"
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
|
|
@ -115,8 +116,8 @@ from newswire import parseFeedDate
|
||||||
from mastoapiv1 import getMastoApiV1IdFromNickname
|
from mastoapiv1 import getMastoApiV1IdFromNickname
|
||||||
from mastoapiv1 import getNicknameFromMastoApiV1Id
|
from mastoapiv1 import getNicknameFromMastoApiV1Id
|
||||||
from webapp_post import prepareHtmlPostNickname
|
from webapp_post import prepareHtmlPostNickname
|
||||||
from webapp_utils import markdownToHtml
|
|
||||||
from speaker import speakerReplaceLinks
|
from speaker import speakerReplaceLinks
|
||||||
|
from markdown import markdownToHtml
|
||||||
|
|
||||||
testServerAliceRunning = False
|
testServerAliceRunning = False
|
||||||
testServerBobRunning = False
|
testServerBobRunning = False
|
||||||
|
|
@ -2359,6 +2360,16 @@ def _testJsonPostAllowsComments():
|
||||||
"commentsEnabled": False
|
"commentsEnabled": False
|
||||||
}
|
}
|
||||||
assert not jsonPostAllowsComments(postJsonObject)
|
assert not jsonPostAllowsComments(postJsonObject)
|
||||||
|
postJsonObject = {
|
||||||
|
"id": "123",
|
||||||
|
"rejectReplies": False
|
||||||
|
}
|
||||||
|
assert jsonPostAllowsComments(postJsonObject)
|
||||||
|
postJsonObject = {
|
||||||
|
"id": "123",
|
||||||
|
"rejectReplies": True
|
||||||
|
}
|
||||||
|
assert not jsonPostAllowsComments(postJsonObject)
|
||||||
postJsonObject = {
|
postJsonObject = {
|
||||||
"id": "123",
|
"id": "123",
|
||||||
"commentsEnabled": True
|
"commentsEnabled": True
|
||||||
|
|
|
||||||
7
theme.py
7
theme.py
|
|
@ -7,6 +7,7 @@ __email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from utils import isAccountDir
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
from utils import saveJson
|
from utils import saveJson
|
||||||
from utils import getImageExtensions
|
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 subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if not isAccountDir(acct):
|
||||||
continue
|
|
||||||
if acct.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
elif acct.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
accountDir = \
|
accountDir = \
|
||||||
os.path.join(baseDir + '/accounts', acct)
|
os.path.join(baseDir + '/accounts', acct)
|
||||||
|
|
|
||||||
184
utils.py
184
utils.py
|
|
@ -5,6 +5,7 @@ __version__ = "1.2.0"
|
||||||
__maintainer__ = "Bob Mottram"
|
__maintainer__ = "Bob Mottram"
|
||||||
__email__ = "bob@freedombone.net"
|
__email__ = "bob@freedombone.net"
|
||||||
__status__ = "Production"
|
__status__ = "Production"
|
||||||
|
__module_group__ = "ActivityPu"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
@ -15,6 +16,8 @@ import json
|
||||||
import idna
|
import idna
|
||||||
import locale
|
import locale
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
from domainhandler import getPortFromDomain
|
||||||
from followingCalendar import addPersonToCalendar
|
from followingCalendar import addPersonToCalendar
|
||||||
from cryptography.hazmat.backends import default_backend
|
from cryptography.hazmat.backends import default_backend
|
||||||
from cryptography.hazmat.primitives import hashes
|
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
|
Used by the shared inbox to know who to send incoming mail to
|
||||||
"""
|
"""
|
||||||
followers = []
|
followers = []
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
handle = nickname + '@' + domain
|
handle = nickname + '@' + domain
|
||||||
if not os.path.isdir(baseDir + '/accounts/' + handle):
|
if not os.path.isdir(baseDir + '/accounts/' + handle):
|
||||||
return followers
|
return followers
|
||||||
|
|
@ -645,8 +647,7 @@ def createInboxQueueDir(nickname: str, domain: str, baseDir: str) -> str:
|
||||||
def domainPermitted(domain: str, federationList: []):
|
def domainPermitted(domain: str, federationList: []):
|
||||||
if len(federationList) == 0:
|
if len(federationList) == 0:
|
||||||
return True
|
return True
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
if domain in federationList:
|
if domain in federationList:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
@ -742,50 +743,59 @@ def getDisplayName(baseDir: str, actor: str, personCache: {}) -> str:
|
||||||
return nameFound
|
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: {},
|
def getGenderFromBio(baseDir: str, actor: str, personCache: {},
|
||||||
translate: {}) -> str:
|
translate: {}) -> str:
|
||||||
"""Tries to ascertain gender from bio description
|
"""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:
|
if '/statuses/' in actor:
|
||||||
actor = actor.split('/statuses/')[0]
|
actor = actor.split('/statuses/')[0]
|
||||||
if not personCache.get(actor):
|
if not personCache.get(actor):
|
||||||
return None
|
return defaultGender
|
||||||
bioFound = None
|
bioFound = None
|
||||||
if translate:
|
if translate:
|
||||||
pronounStr = translate['pronoun'].lower()
|
pronounStr = translate['pronoun'].lower()
|
||||||
else:
|
else:
|
||||||
pronounStr = 'pronoun'
|
pronounStr = 'pronoun'
|
||||||
|
actorJson = None
|
||||||
if personCache[actor].get('actor'):
|
if personCache[actor].get('actor'):
|
||||||
# is gender defined as a profile tag?
|
actorJson = personCache[actor]['actor']
|
||||||
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']
|
|
||||||
else:
|
else:
|
||||||
# Try to obtain from the cached actors
|
# Try to obtain from the cached actors
|
||||||
cachedActorFilename = \
|
cachedActorFilename = \
|
||||||
baseDir + '/cache/actors/' + (actor.replace('/', '#')) + '.json'
|
baseDir + '/cache/actors/' + (actor.replace('/', '#')) + '.json'
|
||||||
if os.path.isfile(cachedActorFilename):
|
if os.path.isfile(cachedActorFilename):
|
||||||
actorJson = loadJson(cachedActorFilename, 1)
|
actorJson = loadJson(cachedActorFilename, 1)
|
||||||
if actorJson:
|
if not actorJson:
|
||||||
|
return defaultGender
|
||||||
# is gender defined as a profile tag?
|
# is gender defined as a profile tag?
|
||||||
if actorJson.get('attachment'):
|
if actorJson.get('attachment'):
|
||||||
tagsList = actorJson['attachment']
|
tagsList = actorJson['attachment']
|
||||||
if isinstance(tagsList, list):
|
if isinstance(tagsList, list):
|
||||||
|
# look for a gender field name
|
||||||
for tag in tagsList:
|
for tag in tagsList:
|
||||||
if not isinstance(tag, dict):
|
if not isinstance(tag, dict):
|
||||||
continue
|
continue
|
||||||
|
|
@ -798,27 +808,25 @@ def getGenderFromBio(baseDir: str, actor: str, personCache: {},
|
||||||
elif tag['name'].lower().startswith(pronounStr):
|
elif tag['name'].lower().startswith(pronounStr):
|
||||||
bioFound = tag['value']
|
bioFound = tag['value']
|
||||||
break
|
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 then use the bio
|
||||||
if not bioFound and actorJson.get('summary'):
|
if not bioFound and actorJson.get('summary'):
|
||||||
bioFound = actorJson['summary']
|
bioFound = actorJson['summary']
|
||||||
if not bioFound:
|
if not bioFound:
|
||||||
return None
|
return defaultGender
|
||||||
gender = 'They/Them'
|
gender = _genderFromString(translate, bioFound)
|
||||||
bioFoundOrig = bioFound
|
if not gender:
|
||||||
bioFound = bioFound.lower()
|
gender = defaultGender
|
||||||
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 gender
|
return gender
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -827,32 +835,15 @@ def getNicknameFromActor(actor: str) -> str:
|
||||||
"""
|
"""
|
||||||
if actor.startswith('@'):
|
if actor.startswith('@'):
|
||||||
actor = actor[1:]
|
actor = actor[1:]
|
||||||
if '/users/' not in actor:
|
usersPaths = ('/users/', '/profile/', '/channel/', '/accounts/', '/u/')
|
||||||
if '/profile/' in actor:
|
for possiblePath in usersPaths:
|
||||||
nickStr = actor.split('/profile/')[1].replace('@', '')
|
if possiblePath in actor:
|
||||||
|
nickStr = actor.split(possiblePath)[1].replace('@', '')
|
||||||
if '/' not in nickStr:
|
if '/' not in nickStr:
|
||||||
return nickStr
|
return nickStr
|
||||||
else:
|
else:
|
||||||
return nickStr.split('/')[0]
|
return nickStr.split('/')[0]
|
||||||
elif '/channel/' in actor:
|
if '/@' 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
|
# https://domain/@nick
|
||||||
nickStr = actor.split('/@')[1]
|
nickStr = actor.split('/@')[1]
|
||||||
if '/' in nickStr:
|
if '/' in nickStr:
|
||||||
|
|
@ -872,11 +863,6 @@ def getNicknameFromActor(actor: str) -> str:
|
||||||
return None
|
return None
|
||||||
return nickStr
|
return nickStr
|
||||||
return None
|
return None
|
||||||
nickStr = actor.split('/users/')[1].replace('@', '')
|
|
||||||
if '/' not in nickStr:
|
|
||||||
return nickStr
|
|
||||||
else:
|
|
||||||
return nickStr.split('/')[0]
|
|
||||||
|
|
||||||
|
|
||||||
def getDomainFromActor(actor: str) -> (str, int):
|
def getDomainFromActor(actor: str) -> (str, int):
|
||||||
|
|
@ -886,27 +872,14 @@ def getDomainFromActor(actor: str) -> (str, int):
|
||||||
actor = actor[1:]
|
actor = actor[1:]
|
||||||
port = None
|
port = None
|
||||||
prefixes = getProtocolPrefixes()
|
prefixes = getProtocolPrefixes()
|
||||||
if '/profile/' in actor:
|
usersPaths = ('/users/', '/profile/', '/accounts/', '/channel/', '/u/')
|
||||||
domain = actor.split('/profile/')[0]
|
for possiblePath in usersPaths:
|
||||||
|
if possiblePath in actor:
|
||||||
|
domain = actor.split(possiblePath)[0]
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
domain = domain.replace(prefix, '')
|
domain = domain.replace(prefix, '')
|
||||||
elif '/accounts/' in actor:
|
break
|
||||||
domain = actor.split('/accounts/')[0]
|
if '/@' in actor:
|
||||||
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:
|
|
||||||
domain = actor.split('/@')[0]
|
domain = actor.split('/@')[0]
|
||||||
for prefix in prefixes:
|
for prefix in prefixes:
|
||||||
domain = domain.replace(prefix, '')
|
domain = domain.replace(prefix, '')
|
||||||
|
|
@ -919,11 +892,8 @@ def getDomainFromActor(actor: str) -> (str, int):
|
||||||
if '/' in actor:
|
if '/' in actor:
|
||||||
domain = domain.split('/')[0]
|
domain = domain.split('/')[0]
|
||||||
if ':' in domain:
|
if ':' in domain:
|
||||||
portStr = domain.split(':')[1]
|
port = getPortFromDomain(domain)
|
||||||
if not portStr.isdigit():
|
domain = removeDomainPort(domain)
|
||||||
return None, None
|
|
||||||
port = int(portStr)
|
|
||||||
domain = domain.split(':')[0]
|
|
||||||
return domain, port
|
return domain, port
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -932,8 +902,7 @@ def _setDefaultPetName(baseDir: str, nickname: str, domain: str,
|
||||||
"""Sets a default petname
|
"""Sets a default petname
|
||||||
This helps especially when using onion or i2p address
|
This helps especially when using onion or i2p address
|
||||||
"""
|
"""
|
||||||
if ':' in domain:
|
domain = removeDomainPort(domain)
|
||||||
domain = domain.split(':')[0]
|
|
||||||
userPath = baseDir + '/accounts/' + nickname + '@' + domain
|
userPath = baseDir + '/accounts/' + nickname + '@' + domain
|
||||||
petnamesFilename = userPath + '/petnames.txt'
|
petnamesFilename = userPath + '/petnames.txt'
|
||||||
|
|
||||||
|
|
@ -975,7 +944,8 @@ def followPerson(baseDir: str, nickname: str, domain: str,
|
||||||
print('DEBUG: follow of domain ' + followDomain)
|
print('DEBUG: follow of domain ' + followDomain)
|
||||||
|
|
||||||
if ':' in domain:
|
if ':' in domain:
|
||||||
handle = nickname + '@' + domain.split(':')[0]
|
domainOnly = removeDomainPort(domain)
|
||||||
|
handle = nickname + '@' + domainOnly
|
||||||
else:
|
else:
|
||||||
handle = nickname + '@' + domain
|
handle = nickname + '@' + domain
|
||||||
|
|
||||||
|
|
@ -984,7 +954,8 @@ def followPerson(baseDir: str, nickname: str, domain: str,
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if ':' in followDomain:
|
if ':' in followDomain:
|
||||||
handleToFollow = followNickname + '@' + followDomain.split(':')[0]
|
followDomainOnly = removeDomainPort(followDomain)
|
||||||
|
handleToFollow = followNickname + '@' + followDomainOnly
|
||||||
else:
|
else:
|
||||||
handleToFollow = followNickname + '@' + followDomain
|
handleToFollow = followNickname + '@' + followDomain
|
||||||
|
|
||||||
|
|
@ -1189,10 +1160,6 @@ def _removeAttachment(baseDir: str, httpPrefix: str, domain: str,
|
||||||
return
|
return
|
||||||
if not postJson['attachment'][0].get('url'):
|
if not postJson['attachment'][0].get('url'):
|
||||||
return
|
return
|
||||||
# if port:
|
|
||||||
# if port != 80 and port != 443:
|
|
||||||
# if ':' not in domain:
|
|
||||||
# domain = domain + ':' + str(port)
|
|
||||||
attachmentUrl = postJson['attachment'][0]['url']
|
attachmentUrl = postJson['attachment'][0]['url']
|
||||||
if not attachmentUrl:
|
if not attachmentUrl:
|
||||||
return
|
return
|
||||||
|
|
@ -1487,12 +1454,12 @@ def noOfActiveAccountsMonthly(baseDir: str, months: int) -> bool:
|
||||||
monthSeconds = int(60*60*24*30*months)
|
monthSeconds = int(60*60*24*30*months)
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for account in dirs:
|
for account in dirs:
|
||||||
if '@' in account:
|
if not isAccountDir(account):
|
||||||
if not account.startswith('inbox@') and \
|
continue
|
||||||
not account.startswith('news@'):
|
|
||||||
lastUsedFilename = \
|
lastUsedFilename = \
|
||||||
baseDir + '/accounts/' + account + '/.lastUsed'
|
baseDir + '/accounts/' + account + '/.lastUsed'
|
||||||
if os.path.isfile(lastUsedFilename):
|
if not os.path.isfile(lastUsedFilename):
|
||||||
|
continue
|
||||||
with open(lastUsedFilename, 'r') as lastUsedFile:
|
with open(lastUsedFilename, 'r') as lastUsedFile:
|
||||||
lastUsed = lastUsedFile.read()
|
lastUsed = lastUsedFile.read()
|
||||||
if lastUsed.isdigit():
|
if lastUsed.isdigit():
|
||||||
|
|
@ -1824,13 +1791,6 @@ def getFileCaseInsensitive(path: str) -> str:
|
||||||
if path != path.lower():
|
if path != path.lower():
|
||||||
if os.path.isfile(path.lower()):
|
if os.path.isfile(path.lower()):
|
||||||
return 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
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from shutil import copyfile
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from webapp_utils import htmlHeaderWithWebsiteMarkup
|
from webapp_utils import htmlHeaderWithWebsiteMarkup
|
||||||
from webapp_utils import htmlFooter
|
from webapp_utils import htmlFooter
|
||||||
from webapp_utils import markdownToHtml
|
from markdown import markdownToHtml
|
||||||
|
|
||||||
|
|
||||||
def htmlAbout(cssCache: {}, baseDir: str, httpPrefix: str,
|
def htmlAbout(cssCache: {}, baseDir: str, httpPrefix: str,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ from utils import getDomainFromActor
|
||||||
from utils import locatePost
|
from utils import locatePost
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
from utils import weekDayOfMonthStart
|
from utils import weekDayOfMonthStart
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from happening import getTodaysEvents
|
from happening import getTodaysEvents
|
||||||
from happening import getCalendarEvents
|
from happening import getCalendarEvents
|
||||||
from webapp_utils import htmlHeaderWithExternalStyle
|
from webapp_utils import htmlHeaderWithExternalStyle
|
||||||
|
|
@ -247,9 +248,7 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
|
||||||
textModeBanner: str, accessKeys: {}) -> str:
|
textModeBanner: str, accessKeys: {}) -> str:
|
||||||
"""Show the calendar for a person
|
"""Show the calendar for a person
|
||||||
"""
|
"""
|
||||||
domain = domainFull
|
domain = removeDomainPort(domainFull)
|
||||||
if ':' in domainFull:
|
|
||||||
domain = domainFull.split(':')[0]
|
|
||||||
|
|
||||||
monthNumber = 0
|
monthNumber = 0
|
||||||
dayNumber = None
|
dayNumber = None
|
||||||
|
|
@ -460,7 +459,6 @@ def htmlCalendar(personCache: {}, cssCache: {}, translate: {},
|
||||||
htmlHideFromScreenReader('←') + ' ' + translate['Previous month']
|
htmlHideFromScreenReader('←') + ' ' + translate['Previous month']
|
||||||
navLinks[prevMonthStr] = calActor + '/calendar?year=' + str(prevYear) + \
|
navLinks[prevMonthStr] = calActor + '/calendar?year=' + str(prevYear) + \
|
||||||
'?month=' + str(prevMonthNumber)
|
'?month=' + str(prevMonthNumber)
|
||||||
# TODO
|
|
||||||
navAccessKeys = {
|
navAccessKeys = {
|
||||||
}
|
}
|
||||||
screenReaderCal = \
|
screenReaderCal = \
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import os
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from utils import getNicknameFromActor
|
from utils import getNicknameFromActor
|
||||||
from utils import isEditor
|
from utils import isEditor
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from webapp_utils import sharesTimelineJson
|
from webapp_utils import sharesTimelineJson
|
||||||
from webapp_utils import htmlPostSeparator
|
from webapp_utils import htmlPostSeparator
|
||||||
from webapp_utils import getLeftImageFile
|
from webapp_utils import getLeftImageFile
|
||||||
|
|
@ -76,9 +77,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
htmlStr = ''
|
htmlStr = ''
|
||||||
|
|
||||||
separatorStr = htmlPostSeparator(baseDir, 'left')
|
separatorStr = htmlPostSeparator(baseDir, 'left')
|
||||||
domain = domainFull
|
domain = removeDomainPort(domainFull)
|
||||||
if ':' in domain:
|
|
||||||
domain = domain.split(':')
|
|
||||||
|
|
||||||
editImageClass = ''
|
editImageClass = ''
|
||||||
if showHeaderImage:
|
if showHeaderImage:
|
||||||
|
|
@ -298,9 +297,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
|
||||||
else:
|
else:
|
||||||
editor = isEditor(baseDir, nickname)
|
editor = isEditor(baseDir, nickname)
|
||||||
|
|
||||||
domain = domainFull
|
domain = removeDomainPort(domainFull)
|
||||||
if ':' in domain:
|
|
||||||
domain = domain.split(':')[0]
|
|
||||||
|
|
||||||
instanceTitle = \
|
instanceTitle = \
|
||||||
getConfigParam(baseDir, 'instanceTitle')
|
getConfigParam(baseDir, 'instanceTitle')
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ from utils import votesOnNewswireItem
|
||||||
from utils import getNicknameFromActor
|
from utils import getNicknameFromActor
|
||||||
from utils import isEditor
|
from utils import isEditor
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
from posts import isModerator
|
from posts import isModerator
|
||||||
from webapp_utils import getRightImageFile
|
from webapp_utils import getRightImageFile
|
||||||
from webapp_utils import htmlHeaderWithExternalStyle
|
from webapp_utils import htmlHeaderWithExternalStyle
|
||||||
|
|
@ -58,9 +59,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
|
||||||
"""
|
"""
|
||||||
htmlStr = ''
|
htmlStr = ''
|
||||||
|
|
||||||
domain = domainFull
|
domain = removeDomainPort(domainFull)
|
||||||
if ':' in domain:
|
|
||||||
domain = domain.split(':')
|
|
||||||
|
|
||||||
if authorized:
|
if authorized:
|
||||||
# only show the publish button if logged in, otherwise replace it with
|
# only show the publish button if logged in, otherwise replace it with
|
||||||
|
|
|
||||||
|
|
@ -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')
|
||||||
|
|
@ -8,6 +8,7 @@ __status__ = "Production"
|
||||||
__module_group__ = "Web Interface"
|
__module_group__ = "Web Interface"
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
from utils import isAccountDir
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
from utils import isEditor
|
from utils import isEditor
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
|
|
@ -270,11 +271,7 @@ def htmlModerationInfo(cssCache: {}, translate: {},
|
||||||
accounts = []
|
accounts = []
|
||||||
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
for subdir, dirs, files in os.walk(baseDir + '/accounts'):
|
||||||
for acct in dirs:
|
for acct in dirs:
|
||||||
if '@' not in acct:
|
if not isAccountDir(acct):
|
||||||
continue
|
|
||||||
if acct.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
elif acct.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
accounts.append(acct)
|
accounts.append(acct)
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,9 @@ from content import removeLongWords
|
||||||
from content import getMentionsFromHtml
|
from content import getMentionsFromHtml
|
||||||
from content import switchWords
|
from content import switchWords
|
||||||
from person import isPersonSnoozed
|
from person import isPersonSnoozed
|
||||||
|
from person import getPersonAvatarUrl
|
||||||
from announce import announcedByPerson
|
from announce import announcedByPerson
|
||||||
from webapp_utils import getAvatarImageUrl
|
from webapp_utils import getAvatarImageUrl
|
||||||
from webapp_utils import getPersonAvatarUrl
|
|
||||||
from webapp_utils import updateAvatarImageCache
|
from webapp_utils import updateAvatarImageCache
|
||||||
from webapp_utils import loadIndividualPostAsHtmlFromCache
|
from webapp_utils import loadIndividualPostAsHtmlFromCache
|
||||||
from webapp_utils import addEmojiToDisplayName
|
from webapp_utils import addEmojiToDisplayName
|
||||||
|
|
@ -1401,6 +1401,9 @@ def individualPostAsHtml(allowDownloads: bool,
|
||||||
if 'commentsEnabled' in postJsonObject['object']:
|
if 'commentsEnabled' in postJsonObject['object']:
|
||||||
if postJsonObject['object']['commentsEnabled'] is False:
|
if postJsonObject['object']['commentsEnabled'] is False:
|
||||||
commentsEnabled = False
|
commentsEnabled = False
|
||||||
|
elif 'rejectReplies' in postJsonObject['object']:
|
||||||
|
if postJsonObject['object']['rejectReplies']:
|
||||||
|
commentsEnabled = False
|
||||||
|
|
||||||
replyStr = _getReplyIconHtml(nickname, isPublicRepeat,
|
replyStr = _getReplyIconHtml(nickname, isPublicRepeat,
|
||||||
showIcons, commentsEnabled,
|
showIcons, commentsEnabled,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from skills import getSkills
|
||||||
from theme import getThemesList
|
from theme import getThemesList
|
||||||
from person import personBoxJson
|
from person import personBoxJson
|
||||||
from person import getActorJson
|
from person import getActorJson
|
||||||
|
from person import getPersonAvatarUrl
|
||||||
from webfinger import webfingerHandle
|
from webfinger import webfingerHandle
|
||||||
from posts import parseUserFeed
|
from posts import parseUserFeed
|
||||||
from posts import getPersonBox
|
from posts import getPersonBox
|
||||||
|
|
@ -45,7 +46,6 @@ from webapp_frontscreen import htmlFrontScreen
|
||||||
from webapp_utils import htmlKeyboardNavigation
|
from webapp_utils import htmlKeyboardNavigation
|
||||||
from webapp_utils import htmlHideFromScreenReader
|
from webapp_utils import htmlHideFromScreenReader
|
||||||
from webapp_utils import scheduledPostsExist
|
from webapp_utils import scheduledPostsExist
|
||||||
from webapp_utils import getPersonAvatarUrl
|
|
||||||
from webapp_utils import htmlHeaderWithExternalStyle
|
from webapp_utils import htmlHeaderWithExternalStyle
|
||||||
from webapp_utils import htmlHeaderWithPersonMarkup
|
from webapp_utils import htmlHeaderWithPersonMarkup
|
||||||
from webapp_utils import htmlFooter
|
from webapp_utils import htmlFooter
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import os
|
||||||
from shutil import copyfile
|
from shutil import copyfile
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from utils import isAccountDir
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from utils import getFullDomain
|
from utils import getFullDomain
|
||||||
from utils import isEditor
|
from utils import isEditor
|
||||||
|
|
@ -407,11 +408,7 @@ def htmlSkillsSearch(actor: str,
|
||||||
for f in files:
|
for f in files:
|
||||||
if not f.endswith('.json'):
|
if not f.endswith('.json'):
|
||||||
continue
|
continue
|
||||||
if '@' not in f:
|
if not isAccountDir(f):
|
||||||
continue
|
|
||||||
if f.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
elif f.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
actorFilename = os.path.join(subdir, f)
|
actorFilename = os.path.join(subdir, f)
|
||||||
actorJson = loadJson(actorFilename)
|
actorJson = loadJson(actorFilename)
|
||||||
|
|
@ -446,11 +443,7 @@ def htmlSkillsSearch(actor: str,
|
||||||
for f in files:
|
for f in files:
|
||||||
if not f.endswith('.json'):
|
if not f.endswith('.json'):
|
||||||
continue
|
continue
|
||||||
if '@' not in f:
|
if not isAccountDir(f):
|
||||||
continue
|
|
||||||
if f.startswith('inbox@'):
|
|
||||||
continue
|
|
||||||
elif f.startswith('news@'):
|
|
||||||
continue
|
continue
|
||||||
actorFilename = os.path.join(subdir, f)
|
actorFilename = os.path.join(subdir, f)
|
||||||
cachedActorJson = loadJson(actorFilename)
|
cachedActorJson = loadJson(actorFilename)
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ from utils import isEditor
|
||||||
from utils import removeIdEnding
|
from utils import removeIdEnding
|
||||||
from follow import followerApprovalActive
|
from follow import followerApprovalActive
|
||||||
from person import isPersonSnoozed
|
from person import isPersonSnoozed
|
||||||
from webapp_utils import markdownToHtml
|
from markdown import markdownToHtml
|
||||||
from webapp_utils import htmlKeyboardNavigation
|
from webapp_utils import htmlKeyboardNavigation
|
||||||
from webapp_utils import htmlHideFromScreenReader
|
from webapp_utils import htmlHideFromScreenReader
|
||||||
from webapp_utils import htmlPostSeparator
|
from webapp_utils import htmlPostSeparator
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from shutil import copyfile
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from webapp_utils import htmlHeaderWithExternalStyle
|
from webapp_utils import htmlHeaderWithExternalStyle
|
||||||
from webapp_utils import htmlFooter
|
from webapp_utils import htmlFooter
|
||||||
from webapp_utils import markdownToHtml
|
from markdown import markdownToHtml
|
||||||
|
|
||||||
|
|
||||||
def htmlTermsOfService(cssCache: {}, baseDir: str,
|
def htmlTermsOfService(cssCache: {}, baseDir: str,
|
||||||
|
|
|
||||||
220
webapp_utils.py
220
webapp_utils.py
|
|
@ -16,170 +16,10 @@ from utils import getProtocolPrefixes
|
||||||
from utils import loadJson
|
from utils import loadJson
|
||||||
from utils import getCachedPostFilename
|
from utils import getCachedPostFilename
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from cache import getPersonFromCache
|
|
||||||
from cache import storePersonInCache
|
from cache import storePersonInCache
|
||||||
from content import addHtmlTags
|
from content import addHtmlTags
|
||||||
from content import replaceEmojiFromTags
|
from content import replaceEmojiFromTags
|
||||||
|
from person import getPersonAvatarUrl
|
||||||
|
|
||||||
def _markdownEmphasisHtml(markdown: str) -> str:
|
|
||||||
"""Add italics and bold html markup to the given markdown
|
|
||||||
"""
|
|
||||||
replacements = {
|
|
||||||
' **': ' <b>',
|
|
||||||
'** ': '</b> ',
|
|
||||||
'**.': '</b>.',
|
|
||||||
'**:': '</b>:',
|
|
||||||
'**;': '</b>;',
|
|
||||||
'**,': '</b>,',
|
|
||||||
'**\n': '</b>\n',
|
|
||||||
' *': ' <i>',
|
|
||||||
'* ': '</i> ',
|
|
||||||
'*.': '</i>.',
|
|
||||||
'*:': '</i>:',
|
|
||||||
'*;': '</i>;',
|
|
||||||
'*,': '</i>,',
|
|
||||||
'*\n': '</i>\n',
|
|
||||||
' _': ' <ul>',
|
|
||||||
'_ ': '</ul> ',
|
|
||||||
'_.': '</ul>.',
|
|
||||||
'_:': '</ul>:',
|
|
||||||
'_;': '</ul>;',
|
|
||||||
'_,': '</ul>,',
|
|
||||||
'_\n': '</ul>\n'
|
|
||||||
}
|
|
||||||
for md, html in replacements.items():
|
|
||||||
markdown = markdown.replace(md, html)
|
|
||||||
|
|
||||||
if markdown.startswith('**'):
|
|
||||||
markdown = markdown[2:] + '<b>'
|
|
||||||
elif markdown.startswith('*'):
|
|
||||||
markdown = markdown[1:] + '<i>'
|
|
||||||
elif markdown.startswith('_'):
|
|
||||||
markdown = markdown[1:] + '<ul>'
|
|
||||||
|
|
||||||
if markdown.endswith('**'):
|
|
||||||
markdown = markdown[:len(markdown) - 2] + '</b>'
|
|
||||||
elif markdown.endswith('*'):
|
|
||||||
markdown = markdown[:len(markdown) - 1] + '</i>'
|
|
||||||
elif markdown.endswith('_'):
|
|
||||||
markdown = markdown[:len(markdown) - 1] + '</ul>'
|
|
||||||
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('</i></blockquote>\n', '')
|
|
||||||
result = result.replace(prevQuoteLine, newPrevLine) + ' '
|
|
||||||
lineStr += '</i></blockquote>\n'
|
|
||||||
else:
|
|
||||||
lineStr = '<blockquote><i>' + lineStr + '</i></blockquote>\n'
|
|
||||||
result += lineStr
|
|
||||||
prevQuoteLine = lineStr
|
|
||||||
|
|
||||||
if '</blockquote>\n' in result:
|
|
||||||
result = result.replace('</blockquote>\n', '</blockquote>')
|
|
||||||
|
|
||||||
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] = \
|
|
||||||
'<a href="' + \
|
|
||||||
markdownLink.split('(')[1].split(')')[0] + \
|
|
||||||
'" target="_blank" rel="nofollow noopener noreferrer">' + \
|
|
||||||
markdownLink.split(startChars)[1].split(']')[0] + \
|
|
||||||
'</a>'
|
|
||||||
else:
|
|
||||||
replaceLinks[markdownLink] = \
|
|
||||||
'<img class="markdownImage" src="' + \
|
|
||||||
markdownLink.split('(')[1].split(')')[0] + \
|
|
||||||
'" alt="' + \
|
|
||||||
markdownLink.split(startChars)[1].split(']')[0] + \
|
|
||||||
'" />'
|
|
||||||
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 += '<br>'
|
|
||||||
if line.startswith('#####'):
|
|
||||||
line = line.replace('#####', '').strip()
|
|
||||||
line = '<h5>' + line + '</h5>'
|
|
||||||
ctr = -1
|
|
||||||
elif line.startswith('####'):
|
|
||||||
line = line.replace('####', '').strip()
|
|
||||||
line = '<h4>' + line + '</h4>'
|
|
||||||
ctr = -1
|
|
||||||
elif line.startswith('###'):
|
|
||||||
line = line.replace('###', '').strip()
|
|
||||||
line = '<h3>' + line + '</h3>'
|
|
||||||
ctr = -1
|
|
||||||
elif line.startswith('##'):
|
|
||||||
line = line.replace('##', '').strip()
|
|
||||||
line = '<h2>' + line + '</h2>'
|
|
||||||
ctr = -1
|
|
||||||
elif line.startswith('#'):
|
|
||||||
line = line.replace('#', '').strip()
|
|
||||||
line = '<h1>' + line + '</h1>'
|
|
||||||
ctr = -1
|
|
||||||
htmlStr += line
|
|
||||||
ctr += 1
|
|
||||||
return htmlStr
|
|
||||||
|
|
||||||
|
|
||||||
def getBrokenLinkSubstitute() -> str:
|
def getBrokenLinkSubstitute() -> str:
|
||||||
|
|
@ -533,34 +373,6 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
|
||||||
return avatarImageFilename.replace(baseDir + '/cache', '')
|
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:
|
def scheduledPostsExist(baseDir: str, nickname: str, domain: str) -> bool:
|
||||||
"""Returns true if there are posts scheduled to be delivered
|
"""Returns true if there are posts scheduled to be delivered
|
||||||
"""
|
"""
|
||||||
|
|
@ -1359,33 +1171,3 @@ def htmlKeyboardNavigation(banner: str, links: {}, accessKeys: {},
|
||||||
str(title) + '</a></label></li>\n'
|
str(title) + '</a></label></li>\n'
|
||||||
htmlStr += '</ul></div>\n'
|
htmlStr += '</ul></div>\n'
|
||||||
return htmlStr
|
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')
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ from utils import getConfigParam
|
||||||
from utils import removeHtml
|
from utils import removeHtml
|
||||||
from webapp_utils import htmlHeaderWithExternalStyle
|
from webapp_utils import htmlHeaderWithExternalStyle
|
||||||
from webapp_utils import htmlFooter
|
from webapp_utils import htmlFooter
|
||||||
from webapp_utils import markdownToHtml
|
from markdown import markdownToHtml
|
||||||
|
|
||||||
|
|
||||||
def isWelcomeScreenComplete(baseDir: str, nickname: str, domain: str) -> bool:
|
def isWelcomeScreenComplete(baseDir: str, nickname: str, domain: str) -> bool:
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ from utils import removeHtml
|
||||||
from utils import getConfigParam
|
from utils import getConfigParam
|
||||||
from webapp_utils import htmlHeaderWithExternalStyle
|
from webapp_utils import htmlHeaderWithExternalStyle
|
||||||
from webapp_utils import htmlFooter
|
from webapp_utils import htmlFooter
|
||||||
from webapp_utils import markdownToHtml
|
from markdown import markdownToHtml
|
||||||
|
|
||||||
|
|
||||||
def htmlWelcomeFinal(baseDir: str, nickname: str, domain: str,
|
def htmlWelcomeFinal(baseDir: str, nickname: str, domain: str,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ from utils import getImageExtensions
|
||||||
from utils import getImageFormats
|
from utils import getImageFormats
|
||||||
from webapp_utils import htmlHeaderWithExternalStyle
|
from webapp_utils import htmlHeaderWithExternalStyle
|
||||||
from webapp_utils import htmlFooter
|
from webapp_utils import htmlFooter
|
||||||
from webapp_utils import markdownToHtml
|
from markdown import markdownToHtml
|
||||||
|
|
||||||
|
|
||||||
def htmlWelcomeProfile(baseDir: str, nickname: str, domain: str,
|
def htmlWelcomeProfile(baseDir: str, nickname: str, domain: str,
|
||||||
|
|
|
||||||
10
webfinger.py
10
webfinger.py
|
|
@ -17,6 +17,7 @@ from utils import loadJson
|
||||||
from utils import loadJsonOnionify
|
from utils import loadJsonOnionify
|
||||||
from utils import saveJson
|
from utils import saveJson
|
||||||
from utils import getProtocolPrefixes
|
from utils import getProtocolPrefixes
|
||||||
|
from domainhandler import removeDomainPort
|
||||||
|
|
||||||
|
|
||||||
def _parseHandle(handle: str) -> (str, str):
|
def _parseHandle(handle: str) -> (str, str):
|
||||||
|
|
@ -53,13 +54,8 @@ def webfingerHandle(session, handle: str, httpPrefix: str,
|
||||||
nickname, domain = _parseHandle(handle)
|
nickname, domain = _parseHandle(handle)
|
||||||
if not nickname:
|
if not nickname:
|
||||||
return None
|
return None
|
||||||
wfDomain = domain
|
wfDomain = removeDomainPort(domain)
|
||||||
if ':' in wfDomain:
|
|
||||||
# wfPortStr=wfDomain.split(':')[1]
|
|
||||||
# if wfPortStr.isdigit():
|
|
||||||
# wfPort=int(wfPortStr)
|
|
||||||
# if wfPort==80 or wfPort==443:
|
|
||||||
wfDomain = wfDomain.split(':')[0]
|
|
||||||
wf = getWebfingerFromCache(nickname + '@' + wfDomain,
|
wf = getWebfingerFromCache(nickname + '@' + wfDomain,
|
||||||
cachedWebfingers)
|
cachedWebfingers)
|
||||||
if wf:
|
if wf:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue