Enforce convention of underscore before local function names

alt-html-css
Bob Mottram 2020-12-22 18:06:23 +00:00
parent 0cf0841402
commit 5cd9aa8d66
42 changed files with 1805 additions and 1786 deletions

View File

@ -15,7 +15,7 @@ from utils import domainPermitted
from utils import followPerson from utils import followPerson
def createAcceptReject(baseDir: str, federationList: [], def _createAcceptReject(baseDir: str, federationList: [],
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
toUrl: str, ccUrl: str, httpPrefix: str, toUrl: str, ccUrl: str, httpPrefix: str,
objectJson: {}, acceptType: str) -> {}: objectJson: {}, acceptType: str) -> {}:
@ -51,7 +51,7 @@ def createAccept(baseDir: str, federationList: [],
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
toUrl: str, ccUrl: str, httpPrefix: str, toUrl: str, ccUrl: str, httpPrefix: str,
objectJson: {}) -> {}: objectJson: {}) -> {}:
return createAcceptReject(baseDir, federationList, return _createAcceptReject(baseDir, federationList,
nickname, domain, port, nickname, domain, port,
toUrl, ccUrl, httpPrefix, toUrl, ccUrl, httpPrefix,
objectJson, 'Accept') objectJson, 'Accept')
@ -61,13 +61,13 @@ def createReject(baseDir: str, federationList: [],
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
toUrl: str, ccUrl: str, httpPrefix: str, toUrl: str, ccUrl: str, httpPrefix: str,
objectJson: {}) -> {}: objectJson: {}) -> {}:
return createAcceptReject(baseDir, federationList, return _createAcceptReject(baseDir, federationList,
nickname, domain, port, nickname, domain, port,
toUrl, ccUrl, toUrl, ccUrl,
httpPrefix, objectJson, 'Reject') httpPrefix, objectJson, 'Reject')
def acceptFollow(baseDir: str, domain: str, messageJson: {}, def _acceptFollow(baseDir: str, domain: str, messageJson: {},
federationList: [], debug: bool) -> None: federationList: [], debug: bool) -> None:
"""Receiving a follow Accept activity """Receiving a follow Accept activity
""" """
@ -204,7 +204,7 @@ def receiveAcceptReject(session, baseDir: str,
' does not contain a nickname. ' + ' does not contain a nickname. ' +
'Assuming single user instance.') 'Assuming single user instance.')
# receive follow accept # receive follow accept
acceptFollow(baseDir, domain, messageJson, federationList, debug) _acceptFollow(baseDir, domain, messageJson, federationList, debug)
if debug: if debug:
print('DEBUG: Uh, ' + messageJson['type'] + ', I guess') print('DEBUG: Uh, ' + messageJson['type'] + ', I guess')
return True return True

12
auth.py
View File

@ -14,7 +14,7 @@ import secrets
from utils import isSystemAccount from utils import isSystemAccount
def hashPassword(password: str) -> str: def _hashPassword(password: str) -> str:
"""Hash a password for storing """Hash a password for storing
""" """
salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii') salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii')
@ -25,7 +25,7 @@ def hashPassword(password: str) -> str:
return (salt + pwdhash).decode('ascii') return (salt + pwdhash).decode('ascii')
def getPasswordHash(salt: str, providedPassword: str) -> str: def _getPasswordHash(salt: str, providedPassword: str) -> str:
"""Returns the hash of a password """Returns the hash of a password
""" """
pwdhash = hashlib.pbkdf2_hmac('sha512', pwdhash = hashlib.pbkdf2_hmac('sha512',
@ -57,7 +57,7 @@ def constantTimeStringCheck(string1: str, string2: str) -> bool:
return matched return matched
def verifyPassword(storedPassword: str, providedPassword: str) -> bool: def _verifyPassword(storedPassword: str, providedPassword: str) -> bool:
"""Verify a stored password against one provided by user """Verify a stored password against one provided by user
""" """
if not storedPassword: if not storedPassword:
@ -66,7 +66,7 @@ def verifyPassword(storedPassword: str, providedPassword: str) -> bool:
return False return False
salt = storedPassword[:64] salt = storedPassword[:64]
storedPassword = storedPassword[64:] storedPassword = storedPassword[64:]
pwHash = getPasswordHash(salt, providedPassword) pwHash = _getPasswordHash(salt, providedPassword)
return constantTimeStringCheck(pwHash, storedPassword) return constantTimeStringCheck(pwHash, storedPassword)
@ -137,7 +137,7 @@ def authorizeBasic(baseDir: str, path: str, authHeader: str,
if line.startswith(nickname+':'): if line.startswith(nickname+':'):
storedPassword = \ storedPassword = \
line.split(':')[1].replace('\n', '').replace('\r', '') line.split(':')[1].replace('\n', '').replace('\r', '')
success = verifyPassword(storedPassword, providedPassword) success = _verifyPassword(storedPassword, providedPassword)
if not success: if not success:
if debug: if debug:
print('DEBUG: Password check failed for ' + nickname) print('DEBUG: Password check failed for ' + nickname)
@ -159,7 +159,7 @@ def storeBasicCredentials(baseDir: str, nickname: str, password: str) -> bool:
os.mkdir(baseDir + '/accounts') os.mkdir(baseDir + '/accounts')
passwordFile = baseDir + '/accounts/passwords' passwordFile = baseDir + '/accounts/passwords'
storeStr = nickname + ':' + hashPassword(password) storeStr = nickname + ':' + _hashPassword(password)
if os.path.isfile(passwordFile): if os.path.isfile(passwordFile):
if nickname + ':' in open(passwordFile).read(): if nickname + ':' in open(passwordFile).read():
with open(passwordFile, "r") as fin: with open(passwordFile, "r") as fin:

43
blog.py
View File

@ -26,7 +26,7 @@ from newswire import rss2Header
from newswire import rss2Footer from newswire import rss2Footer
def noOfBlogReplies(baseDir: str, httpPrefix: str, translate: {}, def _noOfBlogReplies(baseDir: str, httpPrefix: str, translate: {},
nickname: str, domain: str, domainFull: str, nickname: str, domain: str, domainFull: str,
postId: str, depth=0) -> int: postId: str, depth=0) -> int:
"""Returns the number of replies on the post """Returns the number of replies on the post
@ -66,7 +66,8 @@ def noOfBlogReplies(baseDir: str, httpPrefix: str, translate: {},
replyPostId = replyPostId.replace('.json', '') replyPostId = replyPostId.replace('.json', '')
if locatePost(baseDir, nickname, domain, replyPostId): if locatePost(baseDir, nickname, domain, replyPostId):
replyPostId = replyPostId.replace('.replies', '') replyPostId = replyPostId.replace('.replies', '')
replies += 1 + noOfBlogReplies(baseDir, httpPrefix, translate, replies += \
1 + _noOfBlogReplies(baseDir, httpPrefix, translate,
nickname, domain, domainFull, nickname, domain, domainFull,
replyPostId, depth+1) replyPostId, depth+1)
else: else:
@ -86,7 +87,7 @@ def noOfBlogReplies(baseDir: str, httpPrefix: str, translate: {},
return replies return replies
def getBlogReplies(baseDir: str, httpPrefix: str, translate: {}, def _getBlogReplies(baseDir: str, httpPrefix: str, translate: {},
nickname: str, domain: str, domainFull: str, nickname: str, domain: str, domainFull: str,
postId: str, depth=0) -> str: postId: str, depth=0) -> str:
"""Returns a string containing html blog posts """Returns a string containing html blog posts
@ -136,7 +137,7 @@ def getBlogReplies(baseDir: str, httpPrefix: str, translate: {},
continue continue
with open(postFilename, "r") as postFile: with open(postFilename, "r") as postFile:
repliesStr += postFile.read() + '\n' repliesStr += postFile.read() + '\n'
rply = getBlogReplies(baseDir, httpPrefix, translate, rply = _getBlogReplies(baseDir, httpPrefix, translate,
nickname, domain, domainFull, nickname, domain, domainFull,
replyPostId, depth+1) replyPostId, depth+1)
if rply not in repliesStr: if rply not in repliesStr:
@ -152,7 +153,7 @@ def getBlogReplies(baseDir: str, httpPrefix: str, translate: {},
return '' return ''
def htmlBlogPostContent(authorized: bool, def _htmlBlogPostContent(authorized: bool,
baseDir: str, httpPrefix: str, translate: {}, baseDir: str, httpPrefix: str, translate: {},
nickname: str, domain: str, domainFull: str, nickname: str, domain: str, domainFull: str,
postJsonObject: {}, postJsonObject: {},
@ -269,7 +270,7 @@ def htmlBlogPostContent(authorized: bool,
'/users/' + nickname + '">' + translate['About the author'] + \ '/users/' + nickname + '">' + translate['About the author'] + \
'</a></p>\n' '</a></p>\n'
replies = noOfBlogReplies(baseDir, httpPrefix, translate, replies = _noOfBlogReplies(baseDir, httpPrefix, translate,
nickname, domain, domainFull, nickname, domain, domainFull,
postJsonObject['object']['id']) postJsonObject['object']['id'])
@ -288,11 +289,11 @@ def htmlBlogPostContent(authorized: bool,
else: else:
blogStr += blogSeparator + '<h1>' + translate['Replies'] + '</h1>\n' blogStr += blogSeparator + '<h1>' + translate['Replies'] + '</h1>\n'
if not titleStr: if not titleStr:
blogStr += getBlogReplies(baseDir, httpPrefix, translate, blogStr += _getBlogReplies(baseDir, httpPrefix, translate,
nickname, domain, domainFull, nickname, domain, domainFull,
postJsonObject['object']['id']) postJsonObject['object']['id'])
else: else:
blogRepliesStr = getBlogReplies(baseDir, httpPrefix, translate, blogRepliesStr = _getBlogReplies(baseDir, httpPrefix, translate,
nickname, domain, domainFull, nickname, domain, domainFull,
postJsonObject['object']['id']) postJsonObject['object']['id'])
blogStr += blogRepliesStr.replace('>' + titleStr + '<', '') blogStr += blogRepliesStr.replace('>' + titleStr + '<', '')
@ -300,7 +301,7 @@ def htmlBlogPostContent(authorized: bool,
return blogStr return blogStr
def htmlBlogPostRSS2(authorized: bool, def _htmlBlogPostRSS2(authorized: bool,
baseDir: str, httpPrefix: str, translate: {}, baseDir: str, httpPrefix: str, translate: {},
nickname: str, domain: str, domainFull: str, nickname: str, domain: str, domainFull: str,
postJsonObject: {}, postJsonObject: {},
@ -331,7 +332,7 @@ def htmlBlogPostRSS2(authorized: bool,
return rssStr return rssStr
def htmlBlogPostRSS3(authorized: bool, def _htmlBlogPostRSS3(authorized: bool,
baseDir: str, httpPrefix: str, translate: {}, baseDir: str, httpPrefix: str, translate: {},
nickname: str, domain: str, domainFull: str, nickname: str, domain: str, domainFull: str,
postJsonObject: {}, postJsonObject: {},
@ -359,7 +360,7 @@ def htmlBlogPostRSS3(authorized: bool,
return rssStr return rssStr
def htmlBlogRemoveCwButton(blogStr: str, translate: {}) -> str: def _htmlBlogRemoveCwButton(blogStr: str, translate: {}) -> str:
"""Removes the CW button from blog posts, where the """Removes the CW button from blog posts, where the
summary field is instead used as the blog title summary field is instead used as the blog title
""" """
@ -383,9 +384,9 @@ def htmlBlogPost(authorized: bool,
if os.path.isfile(baseDir + '/blog.css'): if os.path.isfile(baseDir + '/blog.css'):
cssFilename = baseDir + '/blog.css' cssFilename = baseDir + '/blog.css'
blogStr = htmlHeaderWithExternalStyle(cssFilename) blogStr = htmlHeaderWithExternalStyle(cssFilename)
htmlBlogRemoveCwButton(blogStr, translate) _htmlBlogRemoveCwButton(blogStr, translate)
blogStr += htmlBlogPostContent(authorized, baseDir, blogStr += _htmlBlogPostContent(authorized, baseDir,
httpPrefix, translate, httpPrefix, translate,
nickname, domain, nickname, domain,
domainFull, postJsonObject, domainFull, postJsonObject,
@ -428,7 +429,7 @@ def htmlBlogPage(authorized: bool, session,
if os.path.isfile(baseDir + '/epicyon.css'): if os.path.isfile(baseDir + '/epicyon.css'):
cssFilename = baseDir + '/epicyon.css' cssFilename = baseDir + '/epicyon.css'
blogStr = htmlHeaderWithExternalStyle(cssFilename) blogStr = htmlHeaderWithExternalStyle(cssFilename)
htmlBlogRemoveCwButton(blogStr, translate) _htmlBlogRemoveCwButton(blogStr, translate)
blogsIndex = baseDir + '/accounts/' + \ blogsIndex = baseDir + '/accounts/' + \
nickname + '@' + domain + '/tlblogs.index' nickname + '@' + domain + '/tlblogs.index'
@ -472,7 +473,7 @@ def htmlBlogPage(authorized: bool, session,
if item['type'] != 'Create': if item['type'] != 'Create':
continue continue
blogStr += htmlBlogPostContent(authorized, baseDir, blogStr += _htmlBlogPostContent(authorized, baseDir,
httpPrefix, translate, httpPrefix, translate,
nickname, domain, nickname, domain,
domainFull, item, domainFull, item,
@ -544,7 +545,7 @@ def htmlBlogPageRSS2(authorized: bool, session,
continue continue
blogRSS2 += \ blogRSS2 += \
htmlBlogPostRSS2(authorized, baseDir, _htmlBlogPostRSS2(authorized, baseDir,
httpPrefix, translate, httpPrefix, translate,
nickname, domain, nickname, domain,
domainFull, item, domainFull, item,
@ -590,7 +591,7 @@ def htmlBlogPageRSS3(authorized: bool, session,
continue continue
blogRSS3 += \ blogRSS3 += \
htmlBlogPostRSS3(authorized, baseDir, _htmlBlogPostRSS3(authorized, baseDir,
httpPrefix, translate, httpPrefix, translate,
nickname, domain, nickname, domain,
domainFull, item, domainFull, item,
@ -599,7 +600,7 @@ def htmlBlogPageRSS3(authorized: bool, session,
return blogRSS3 return blogRSS3
def noOfBlogAccounts(baseDir: str) -> int: def _noOfBlogAccounts(baseDir: str) -> int:
"""Returns the number of blog accounts """Returns the number of blog accounts
""" """
ctr = 0 ctr = 0
@ -617,7 +618,7 @@ def noOfBlogAccounts(baseDir: str) -> int:
return ctr return ctr
def singleBlogAccountNickname(baseDir: str) -> str: def _singleBlogAccountNickname(baseDir: str) -> str:
"""Returns the nickname of a single blog account """Returns the nickname of a single blog account
""" """
for subdir, dirs, files in os.walk(baseDir + '/accounts'): for subdir, dirs, files in os.walk(baseDir + '/accounts'):
@ -647,8 +648,8 @@ def htmlBlogView(authorized: bool,
cssFilename = baseDir + '/epicyon.css' cssFilename = baseDir + '/epicyon.css'
blogStr = htmlHeaderWithExternalStyle(cssFilename) blogStr = htmlHeaderWithExternalStyle(cssFilename)
if noOfBlogAccounts(baseDir) <= 1: if _noOfBlogAccounts(baseDir) <= 1:
nickname = singleBlogAccountNickname(baseDir) nickname = _singleBlogAccountNickname(baseDir)
if nickname: if nickname:
return htmlBlogPage(authorized, session, return htmlBlogPage(authorized, session,
baseDir, httpPrefix, translate, baseDir, httpPrefix, translate,

View File

@ -39,7 +39,7 @@ alphabet = \
alphabet_values = dict(zip(alphabet, range(len(alphabet)))) alphabet_values = dict(zip(alphabet, range(len(alphabet))))
def base83_encode(value, length): def _base83_encode(value, length):
""" """
Decodes an integer to a base83 string, as used in blurhash. Decodes an integer to a base83 string, as used in blurhash.
@ -57,7 +57,7 @@ def base83_encode(value, length):
return result return result
def srgb_to_linear(value): def _srgb_to_linear(value):
""" """
srgb 0-255 integer to linear 0.0-1.0 floating point conversion. srgb 0-255 integer to linear 0.0-1.0 floating point conversion.
""" """
@ -67,14 +67,14 @@ def srgb_to_linear(value):
return math.pow((value + 0.055) / 1.055, 2.4) return math.pow((value + 0.055) / 1.055, 2.4)
def sign_pow(value, exp): def _sign_pow(value, exp):
""" """
Sign-preserving exponentiation. Sign-preserving exponentiation.
""" """
return math.copysign(math.pow(abs(value), exp), value) return math.copysign(math.pow(abs(value), exp), value)
def linear_to_srgb(value): def _linear_to_srgb(value):
""" """
linear 0.0-1.0 floating point to srgb 0-255 integer conversion. linear 0.0-1.0 floating point to srgb 0-255 integer conversion.
""" """
@ -113,9 +113,9 @@ def blurhash_encode(image, components_x=4, components_y=4, linear=False):
image_linear_line = [] image_linear_line = []
for x in range(int(width)): for x in range(int(width)):
image_linear_line.append([ image_linear_line.append([
srgb_to_linear(image[y][x][0]), _srgb_to_linear(image[y][x][0]),
srgb_to_linear(image[y][x][1]), _srgb_to_linear(image[y][x][1]),
srgb_to_linear(image[y][x][2]) _srgb_to_linear(image[y][x][2])
]) ])
image_linear.append(image_linear_line) image_linear.append(image_linear_line)
else: else:
@ -149,9 +149,9 @@ def blurhash_encode(image, components_x=4, components_y=4, linear=False):
abs(component[1]), abs(component[2])) abs(component[1]), abs(component[2]))
# Encode components # Encode components
dc_value = (linear_to_srgb(components[0][0]) << 16) + \ dc_value = (_linear_to_srgb(components[0][0]) << 16) + \
(linear_to_srgb(components[0][1]) << 8) + \ (_linear_to_srgb(components[0][1]) << 8) + \
linear_to_srgb(components[0][2]) _linear_to_srgb(components[0][2])
quant_max_ac_component = int(max(0, min(82, quant_max_ac_component = int(max(0, min(82,
math.floor(max_ac_component * math.floor(max_ac_component *
@ -163,9 +163,9 @@ def blurhash_encode(image, components_x=4, components_y=4, linear=False):
r2 = r / ac_component_norm_factor r2 = r / ac_component_norm_factor
g2 = g / ac_component_norm_factor g2 = g / ac_component_norm_factor
b2 = b / ac_component_norm_factor b2 = b / ac_component_norm_factor
r3 = math.floor(sign_pow(r2, 0.5) * 9.0 + 9.5) r3 = math.floor(_sign_pow(r2, 0.5) * 9.0 + 9.5)
g3 = math.floor(sign_pow(g2, 0.5) * 9.0 + 9.5) g3 = math.floor(_sign_pow(g2, 0.5) * 9.0 + 9.5)
b3 = math.floor(sign_pow(b2, 0.5) * 9.0 + 9.5) b3 = math.floor(_sign_pow(b2, 0.5) * 9.0 + 9.5)
ac_values.append( ac_values.append(
int(max(0.0, min(18.0, r3))) * 19 * 19 + int(max(0.0, min(18.0, r3))) * 19 * 19 +
int(max(0.0, min(18.0, g3))) * 19 + int(max(0.0, min(18.0, g3))) * 19 +
@ -174,10 +174,10 @@ def blurhash_encode(image, components_x=4, components_y=4, linear=False):
# Build final blurhash # Build final blurhash
blurhash = "" blurhash = ""
blurhash += base83_encode((components_x - 1) + (components_y - 1) * 9, 1) blurhash += _base83_encode((components_x - 1) + (components_y - 1) * 9, 1)
blurhash += base83_encode(quant_max_ac_component, 1) blurhash += _base83_encode(quant_max_ac_component, 1)
blurhash += base83_encode(dc_value, 4) blurhash += _base83_encode(dc_value, 4)
for ac_value in ac_values: for ac_value in ac_values:
blurhash += base83_encode(ac_value, 2) blurhash += _base83_encode(ac_value, 2)
return blurhash return blurhash

View File

@ -107,7 +107,7 @@ def undoBookmarksCollectionEntry(recentPostsCache: {},
def bookmarkedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool: def bookmarkedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool:
"""Returns True if the given post is bookmarked by the given person """Returns True if the given post is bookmarked by the given person
""" """
if noOfBookmarks(postJsonObject) == 0: if _noOfBookmarks(postJsonObject) == 0:
return False return False
actorMatch = domain + '/users/' + nickname actorMatch = domain + '/users/' + nickname
for item in postJsonObject['object']['bookmarks']['items']: for item in postJsonObject['object']['bookmarks']['items']:
@ -116,7 +116,7 @@ def bookmarkedByPerson(postJsonObject: {}, nickname: str, domain: str) -> bool:
return False return False
def noOfBookmarks(postJsonObject: {}) -> int: def _noOfBookmarks(postJsonObject: {}) -> int:
"""Returns the number of bookmarks ona given post """Returns the number of bookmarks ona given post
""" """
if not postJsonObject.get('object'): if not postJsonObject.get('object'):

View File

@ -33,7 +33,7 @@ def removeHtmlTag(htmlStr: str, tag: str) -> str:
return htmlStr return htmlStr
def removeQuotesWithinQuotes(content: str) -> str: def _removeQuotesWithinQuotes(content: str) -> str:
"""Removes any blockquote inside blockquote """Removes any blockquote inside blockquote
""" """
if '<blockquote>' not in content: if '<blockquote>' not in content:
@ -96,7 +96,7 @@ def htmlReplaceEmailQuote(content: str) -> str:
else: else:
lineStr = lineStr.replace('&gt;', '<br>') lineStr = lineStr.replace('&gt;', '<br>')
newContent += '<p>' + lineStr + '</blockquote></p>' newContent += '<p>' + lineStr + '</blockquote></p>'
return removeQuotesWithinQuotes(newContent) return _removeQuotesWithinQuotes(newContent)
def htmlReplaceQuoteMarks(content: str) -> str: def htmlReplaceQuoteMarks(content: str) -> str:
@ -314,7 +314,7 @@ def replaceEmojiFromTags(content: str, tag: [], messageType: str) -> str:
return content return content
def addMusicTag(content: str, tag: str) -> str: def _addMusicTag(content: str, tag: str) -> str:
"""If a music link is found then ensure that the post is """If a music link is found then ensure that the post is
tagged appropriately tagged appropriately
""" """
@ -416,7 +416,7 @@ def validHashTag(hashtag: str) -> bool:
return False return False
def addHashTags(wordStr: str, httpPrefix: str, domain: str, def _addHashTags(wordStr: str, httpPrefix: str, domain: str,
replaceHashTags: {}, postHashtags: {}) -> bool: replaceHashTags: {}, postHashtags: {}) -> bool:
"""Detects hashtags and adds them to the replacements dict """Detects hashtags and adds them to the replacements dict
Also updates the hashtags list to be added to the post Also updates the hashtags list to be added to the post
@ -438,7 +438,7 @@ def addHashTags(wordStr: str, httpPrefix: str, domain: str,
return True return True
def addEmoji(baseDir: str, wordStr: str, def _addEmoji(baseDir: str, wordStr: str,
httpPrefix: str, domain: str, httpPrefix: str, domain: str,
replaceEmoji: {}, postTags: {}, replaceEmoji: {}, postTags: {},
emojiDict: {}) -> bool: emojiDict: {}) -> bool:
@ -489,7 +489,7 @@ def tagExists(tagType: str, tagName: str, tags: {}) -> bool:
return False return False
def addMention(wordStr: str, httpPrefix: str, following: str, def _addMention(wordStr: str, httpPrefix: str, following: str,
replaceMentions: {}, recipients: [], tags: {}) -> bool: replaceMentions: {}, recipients: [], tags: {}) -> bool:
"""Detects mentions and adds them to the replacements dict and """Detects mentions and adds them to the replacements dict and
recipients list recipients list
@ -672,7 +672,7 @@ def removeLongWords(content: str, maxWordLength: int,
return content return content
def loadAutoTags(baseDir: str, nickname: str, domain: str) -> []: def _loadAutoTags(baseDir: str, nickname: str, domain: str) -> []:
"""Loads automatic tags file and returns a list containing """Loads automatic tags file and returns a list containing
the lines of the file the lines of the file
""" """
@ -685,7 +685,7 @@ def loadAutoTags(baseDir: str, nickname: str, domain: str) -> []:
return [] return []
def autoTag(baseDir: str, nickname: str, domain: str, def _autoTag(baseDir: str, nickname: str, domain: str,
wordStr: str, autoTagList: [], wordStr: str, autoTagList: [],
appendTags: []): appendTags: []):
"""Generates a list of tags to be automatically appended to the content """Generates a list of tags to be automatically appended to the content
@ -719,7 +719,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
maxWordLength = 40 maxWordLength = 40
content = content.replace('\r', '') content = content.replace('\r', '')
content = content.replace('\n', ' --linebreak-- ') content = content.replace('\n', ' --linebreak-- ')
content = addMusicTag(content, 'nowplaying') content = _addMusicTag(content, 'nowplaying')
contentSimplified = \ contentSimplified = \
content.replace(',', ' ').replace(';', ' ').replace('- ', ' ') content.replace(',', ' ').replace(';', ' ').replace('- ', ' ')
contentSimplified = contentSimplified.replace('. ', ' ').strip() contentSimplified = contentSimplified.replace('. ', ' ').strip()
@ -760,7 +760,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
# extract mentions and tags from words # extract mentions and tags from words
longWordsList = [] longWordsList = []
prevWordStr = '' prevWordStr = ''
autoTagsList = loadAutoTags(baseDir, nickname, domain) autoTagsList = _loadAutoTags(baseDir, nickname, domain)
appendTags = [] appendTags = []
for wordStr in words: for wordStr in words:
wordLen = len(wordStr) wordLen = len(wordStr)
@ -769,12 +769,12 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
longWordsList.append(wordStr) longWordsList.append(wordStr)
firstChar = wordStr[0] firstChar = wordStr[0]
if firstChar == '@': if firstChar == '@':
if addMention(wordStr, httpPrefix, following, if _addMention(wordStr, httpPrefix, following,
replaceMentions, recipients, hashtags): replaceMentions, recipients, hashtags):
prevWordStr = '' prevWordStr = ''
continue continue
elif firstChar == '#': elif firstChar == '#':
if addHashTags(wordStr, httpPrefix, originalDomain, if _addHashTags(wordStr, httpPrefix, originalDomain,
replaceHashTags, hashtags): replaceHashTags, hashtags):
prevWordStr = '' prevWordStr = ''
continue continue
@ -791,16 +791,16 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
emojiDict = loadJson(baseDir + '/emoji/emoji.json') emojiDict = loadJson(baseDir + '/emoji/emoji.json')
# print('TAG: looking up emoji for :'+wordStr2+':') # print('TAG: looking up emoji for :'+wordStr2+':')
addEmoji(baseDir, ':' + wordStr2 + ':', httpPrefix, _addEmoji(baseDir, ':' + wordStr2 + ':', httpPrefix,
originalDomain, replaceEmoji, hashtags, originalDomain, replaceEmoji, hashtags,
emojiDict) emojiDict)
else: else:
if autoTag(baseDir, nickname, domain, wordStr, if _autoTag(baseDir, nickname, domain, wordStr,
autoTagsList, appendTags): autoTagsList, appendTags):
prevWordStr = '' prevWordStr = ''
continue continue
if prevWordStr: if prevWordStr:
if autoTag(baseDir, nickname, domain, if _autoTag(baseDir, nickname, domain,
prevWordStr + ' ' + wordStr, prevWordStr + ' ' + wordStr,
autoTagsList, appendTags): autoTagsList, appendTags):
prevWordStr = '' prevWordStr = ''
@ -810,7 +810,7 @@ def addHtmlTags(baseDir: str, httpPrefix: str,
# add any auto generated tags # add any auto generated tags
for appended in appendTags: for appended in appendTags:
content = content + ' ' + appended content = content + ' ' + appended
addHashTags(appended, httpPrefix, originalDomain, _addHashTags(appended, httpPrefix, originalDomain,
replaceHashTags, hashtags) replaceHashTags, hashtags)
# replace words with their html versions # replace words with their html versions

View File

@ -7,7 +7,7 @@ __email__ = "bob@freedombone.net"
__status__ = "Production" __status__ = "Production"
def getDonationTypes() -> str: def _getDonationTypes() -> str:
return ('patreon', 'paypal', 'gofundme', 'liberapay', return ('patreon', 'paypal', 'gofundme', 'liberapay',
'kickstarter', 'indiegogo', 'crowdsupply', 'kickstarter', 'indiegogo', 'crowdsupply',
'subscribestar') 'subscribestar')
@ -18,7 +18,7 @@ def getDonationUrl(actorJson: {}) -> str:
""" """
if not actorJson.get('attachment'): if not actorJson.get('attachment'):
return '' return ''
donationType = getDonationTypes() donationType = _getDonationTypes()
for propertyValue in actorJson['attachment']: for propertyValue in actorJson['attachment']:
if not propertyValue.get('name'): if not propertyValue.get('name'):
continue continue
@ -54,7 +54,7 @@ def setDonationUrl(actorJson: {}, donateUrl: str) -> None:
if not actorJson.get('attachment'): if not actorJson.get('attachment'):
actorJson['attachment'] = [] actorJson['attachment'] = []
donationType = getDonationTypes() donationType = _getDonationTypes()
donateName = None donateName = None
for paymentService in donationType: for paymentService in donationType:
if paymentService in donateUrl: if paymentService in donateUrl:

View File

@ -79,7 +79,7 @@ def removeGlobalFilter(baseDir: str, words: str) -> bool:
return False return False
def isTwitterPost(content: str) -> bool: def _isTwitterPost(content: str) -> bool:
"""Returns true if the given post content is a retweet or twitter crosspost """Returns true if the given post content is a retweet or twitter crosspost
""" """
if '/twitter.' in content or '@twitter.' in content: if '/twitter.' in content or '@twitter.' in content:
@ -89,7 +89,7 @@ def isTwitterPost(content: str) -> bool:
return False return False
def isFilteredBase(filename: str, content: str) -> bool: def _isFilteredBase(filename: str, content: str) -> bool:
"""Uses the given file containing filtered words to check """Uses the given file containing filtered words to check
the given content the given content
""" """
@ -122,7 +122,7 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool:
words must be present although not necessarily adjacent words must be present although not necessarily adjacent
""" """
globalFiltersFilename = baseDir + '/accounts/filters.txt' globalFiltersFilename = baseDir + '/accounts/filters.txt'
if isFilteredBase(globalFiltersFilename, content): if _isFilteredBase(globalFiltersFilename, content):
return True return True
if not nickname or not domain: if not nickname or not domain:
@ -132,9 +132,9 @@ def isFiltered(baseDir: str, nickname: str, domain: str, content: str) -> bool:
removeTwitter = baseDir + '/accounts/' + \ removeTwitter = baseDir + '/accounts/' + \
nickname + '@' + domain + '/.removeTwitter' nickname + '@' + domain + '/.removeTwitter'
if os.path.isfile(removeTwitter): if os.path.isfile(removeTwitter):
if isTwitterPost(content): if _isTwitterPost(content):
return True return True
accountFiltersFilename = baseDir + '/accounts/' + \ accountFiltersFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/filters.txt' nickname + '@' + domain + '/filters.txt'
return isFilteredBase(accountFiltersFilename, content) return _isFilteredBase(accountFiltersFilename, content)

View File

@ -65,7 +65,7 @@ def createInitialLastSeen(baseDir: str, httpPrefix: str) -> None:
break break
def preApprovedFollower(baseDir: str, def _preApprovedFollower(baseDir: str,
nickname: str, domain: str, nickname: str, domain: str,
approveHandle: str, approveHandle: str,
allowNewsFollowers: bool) -> bool: allowNewsFollowers: bool) -> bool:
@ -84,7 +84,7 @@ def preApprovedFollower(baseDir: str,
return False return False
def removeFromFollowBase(baseDir: str, def _removeFromFollowBase(baseDir: str,
nickname: str, domain: str, nickname: str, domain: str,
acceptOrDenyHandle: str, followFile: str, acceptOrDenyHandle: str, followFile: str,
debug: bool) -> None: debug: bool) -> None:
@ -114,16 +114,16 @@ def removeFromFollowRequests(baseDir: str,
denyHandle: str, debug: bool) -> None: denyHandle: str, debug: bool) -> None:
"""Removes a handle from follow requests """Removes a handle from follow requests
""" """
removeFromFollowBase(baseDir, nickname, domain, _removeFromFollowBase(baseDir, nickname, domain,
denyHandle, 'followrequests', debug) denyHandle, 'followrequests', debug)
def removeFromFollowRejects(baseDir: str, def _removeFromFollowRejects(baseDir: str,
nickname: str, domain: str, nickname: str, domain: str,
acceptHandle: str, debug: bool) -> None: acceptHandle: str, debug: bool) -> None:
"""Removes a handle from follow rejects """Removes a handle from follow rejects
""" """
removeFromFollowBase(baseDir, nickname, domain, _removeFromFollowBase(baseDir, nickname, domain,
acceptHandle, 'followrejects', debug) acceptHandle, 'followrejects', debug)
@ -179,7 +179,7 @@ def followerOfPerson(baseDir: str, nickname: str, domain: str,
federationList, debug, 'followers.txt') federationList, debug, 'followers.txt')
def isFollowerOfPerson(baseDir: str, nickname: str, domain: str, 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?
""" """
@ -291,7 +291,7 @@ def clearFollowers(baseDir: str, nickname: str, domain: str) -> None:
clearFollows(baseDir, nickname, domain, 'followers.txt') clearFollows(baseDir, nickname, domain, 'followers.txt')
def getNoOfFollows(baseDir: str, nickname: str, domain: str, def _getNoOfFollows(baseDir: str, nickname: str, domain: str,
authenticated: bool, authenticated: bool,
followFile='following.txt') -> int: followFile='following.txt') -> int:
"""Returns the number of follows or followers """Returns the number of follows or followers
@ -324,11 +324,11 @@ def getNoOfFollows(baseDir: str, nickname: str, domain: str,
return ctr return ctr
def getNoOfFollowers(baseDir: str, def _getNoOfFollowers(baseDir: str,
nickname: str, domain: str, authenticated: bool) -> int: nickname: str, domain: str, authenticated: bool) -> int:
"""Returns the number of followers of the given person """Returns the number of followers of the given person
""" """
return getNoOfFollows(baseDir, nickname, domain, return _getNoOfFollows(baseDir, nickname, domain,
authenticated, 'followers.txt') authenticated, 'followers.txt')
@ -382,7 +382,7 @@ def getFollowingFeed(baseDir: str, domain: str, port: int, path: str,
httpPrefix + '://' + domain + '/users/' + \ httpPrefix + '://' + domain + '/users/' + \
nickname + '/' + followFile nickname + '/' + followFile
totalStr = \ totalStr = \
getNoOfFollows(baseDir, nickname, domain, authenticated) _getNoOfFollows(baseDir, nickname, domain, authenticated)
following = { following = {
'@context': 'https://www.w3.org/ns/activitystreams', '@context': 'https://www.w3.org/ns/activitystreams',
'first': firstStr, 'first': firstStr,
@ -463,14 +463,14 @@ def getFollowingFeed(baseDir: str, domain: str, port: int, path: str,
return following return following
def followApprovalRequired(baseDir: str, nicknameToFollow: str, def _followApprovalRequired(baseDir: str, nicknameToFollow: str,
domainToFollow: str, debug: bool, domainToFollow: str, debug: bool,
followRequestHandle: str, followRequestHandle: str,
allowNewsFollowers: bool) -> bool: allowNewsFollowers: bool) -> bool:
""" Returns the policy for follower approvals """ Returns the policy for follower approvals
""" """
# has this handle already been manually approved? # has this handle already been manually approved?
if preApprovedFollower(baseDir, nicknameToFollow, domainToFollow, if _preApprovedFollower(baseDir, nicknameToFollow, domainToFollow,
followRequestHandle, allowNewsFollowers): followRequestHandle, allowNewsFollowers):
return False return False
@ -494,7 +494,7 @@ def followApprovalRequired(baseDir: str, nicknameToFollow: str,
return manuallyApproveFollows return manuallyApproveFollows
def noOfFollowRequests(baseDir: str, def _noOfFollowRequests(baseDir: str,
nicknameToFollow: str, domainToFollow: str, nicknameToFollow: str, domainToFollow: str,
nickname: str, domain: str, fromPort: int, nickname: str, domain: str, fromPort: int,
followType: str) -> int: followType: str) -> int:
@ -521,7 +521,7 @@ def noOfFollowRequests(baseDir: str,
return ctr return ctr
def storeFollowRequest(baseDir: str, def _storeFollowRequest(baseDir: str,
nicknameToFollow: str, domainToFollow: str, port: int, nicknameToFollow: str, domainToFollow: str, port: int,
nickname: str, domain: str, fromPort: int, nickname: str, domain: str, fromPort: int,
followJson: {}, followJson: {},
@ -668,7 +668,7 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
nicknameToFollow) nicknameToFollow)
return True return True
if maxFollowers > 0: if maxFollowers > 0:
if getNoOfFollowers(baseDir, if _getNoOfFollowers(baseDir,
nicknameToFollow, domainToFollow, nicknameToFollow, domainToFollow,
True) > maxFollowers: True) > maxFollowers:
print('WARN: ' + nicknameToFollow + print('WARN: ' + nicknameToFollow +
@ -682,7 +682,7 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
baseDir + '/accounts/' + handleToFollow) baseDir + '/accounts/' + handleToFollow)
return True return True
if isFollowerOfPerson(baseDir, if _isFollowerOfPerson(baseDir,
nicknameToFollow, domainToFollowFull, nicknameToFollow, domainToFollowFull,
nickname, domainFull): nickname, domainFull):
if debug: if debug:
@ -693,26 +693,26 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
# what is the followers policy? # what is the followers policy?
approveHandle = nickname + '@' + domainFull approveHandle = nickname + '@' + domainFull
if followApprovalRequired(baseDir, nicknameToFollow, if _followApprovalRequired(baseDir, nicknameToFollow,
domainToFollow, debug, approveHandle, domainToFollow, debug, approveHandle,
allowNewsFollowers): allowNewsFollowers):
print('Follow approval is required') print('Follow approval is required')
if domain.endswith('.onion'): if domain.endswith('.onion'):
if noOfFollowRequests(baseDir, if _noOfFollowRequests(baseDir,
nicknameToFollow, domainToFollow, nicknameToFollow, domainToFollow,
nickname, domain, fromPort, nickname, domain, fromPort,
'onion') > 5: 'onion') > 5:
print('Too many follow requests from onion addresses') print('Too many follow requests from onion addresses')
return False return False
elif domain.endswith('.i2p'): elif domain.endswith('.i2p'):
if noOfFollowRequests(baseDir, if _noOfFollowRequests(baseDir,
nicknameToFollow, domainToFollow, nicknameToFollow, domainToFollow,
nickname, domain, fromPort, nickname, domain, fromPort,
'i2p') > 5: 'i2p') > 5:
print('Too many follow requests from i2p addresses') print('Too many follow requests from i2p addresses')
return False return False
else: else:
if noOfFollowRequests(baseDir, if _noOfFollowRequests(baseDir,
nicknameToFollow, domainToFollow, nicknameToFollow, domainToFollow,
nickname, domain, fromPort, nickname, domain, fromPort,
'') > 10: '') > 10:
@ -720,7 +720,7 @@ def receiveFollowRequest(session, baseDir: str, httpPrefix: str,
return False return False
print('Storing follow request for approval') print('Storing follow request for approval')
return storeFollowRequest(baseDir, return _storeFollowRequest(baseDir,
nicknameToFollow, domainToFollow, port, nicknameToFollow, domainToFollow, port,
nickname, domain, fromPort, nickname, domain, fromPort,
messageJson, debug, messageJson['actor']) messageJson, debug, messageJson['actor'])
@ -920,13 +920,13 @@ def sendFollowRequest(session, baseDir: str,
'object': followedId 'object': followedId
} }
if followApprovalRequired(baseDir, nickname, domain, debug, if _followApprovalRequired(baseDir, nickname, domain, debug,
followHandle, allowNewsFollowers): followHandle, allowNewsFollowers):
# Remove any follow requests rejected for the account being followed. # Remove any follow requests rejected for the account being followed.
# It's assumed that if you are following someone then you are # It's assumed that if you are following someone then you are
# ok with them following back. If this isn't the case then a rejected # ok with them following back. If this isn't the case then a rejected
# follow request will block them again. # follow request will block them again.
removeFromFollowRejects(baseDir, _removeFromFollowRejects(baseDir,
nickname, domain, nickname, domain,
followHandle, debug) followHandle, debug)

View File

@ -34,7 +34,7 @@ def receivingCalendarEvents(baseDir: str, nickname: str, domain: str,
return handle + '\n' in open(calendarFilename).read() return handle + '\n' in open(calendarFilename).read()
def receiveCalendarEvents(baseDir: str, nickname: str, domain: str, def _receiveCalendarEvents(baseDir: str, nickname: str, domain: str,
followingNickname: str, followingNickname: str,
followingDomain: str, followingDomain: str,
add: bool) -> None: add: bool) -> None:
@ -100,12 +100,12 @@ def receiveCalendarEvents(baseDir: str, nickname: str, domain: str,
def addPersonToCalendar(baseDir: str, nickname: str, domain: str, def addPersonToCalendar(baseDir: str, nickname: str, domain: str,
followingNickname: str, followingNickname: str,
followingDomain: str) -> None: followingDomain: str) -> None:
receiveCalendarEvents(baseDir, nickname, domain, _receiveCalendarEvents(baseDir, nickname, domain,
followingNickname, followingDomain, True) followingNickname, followingDomain, True)
def removePersonFromCalendar(baseDir: str, nickname: str, domain: str, def removePersonFromCalendar(baseDir: str, nickname: str, domain: str,
followingNickname: str, followingNickname: str,
followingDomain: str) -> None: followingDomain: str) -> None:
receiveCalendarEvents(baseDir, nickname, domain, _receiveCalendarEvents(baseDir, nickname, domain,
followingNickname, followingDomain, False) followingNickname, followingDomain, False)

24
git.py
View File

@ -10,7 +10,7 @@ import os
import html import html
def gitFormatContent(content: str) -> str: def _gitFormatContent(content: str) -> str:
""" replace html formatting, so that it's more """ replace html formatting, so that it's more
like the original patch file like the original patch file
""" """
@ -22,7 +22,7 @@ def gitFormatContent(content: str) -> str:
return patchStr return patchStr
def getGitProjectName(baseDir: str, nickname: str, domain: str, def _getGitProjectName(baseDir: str, nickname: str, domain: str,
subject: str) -> str: subject: str) -> str:
"""Returns the project name for a git patch """Returns the project name for a git patch
The project name should be contained within the subject line The project name should be contained within the subject line
@ -71,13 +71,13 @@ def isGitPatch(baseDir: str, nickname: str, domain: str,
return False return False
if checkProjectName: if checkProjectName:
projectName = \ projectName = \
getGitProjectName(baseDir, nickname, domain, subject) _getGitProjectName(baseDir, nickname, domain, subject)
if not projectName: if not projectName:
return False return False
return True return True
def getGitHash(patchStr: str) -> str: def _getGitHash(patchStr: str) -> str:
"""Returns the commit hash from a given patch """Returns the commit hash from a given patch
""" """
patchLines = patchStr.split('\n') patchLines = patchStr.split('\n')
@ -91,7 +91,7 @@ def getGitHash(patchStr: str) -> str:
return None return None
def getPatchDescription(patchStr: str) -> str: def _getPatchDescription(patchStr: str) -> str:
"""Returns the description from a given patch """Returns the description from a given patch
""" """
patchLines = patchStr.split('\n') patchLines = patchStr.split('\n')
@ -134,8 +134,8 @@ def convertPostToPatch(baseDir: str, nickname: str, domain: str,
postJsonObject['object']['content'], postJsonObject['object']['content'],
False): False):
return False return False
patchStr = gitFormatContent(postJsonObject['object']['content']) patchStr = _gitFormatContent(postJsonObject['object']['content'])
commitHash = getGitHash(patchStr) commitHash = _getGitHash(patchStr)
if not commitHash: if not commitHash:
return False return False
postJsonObject['object']['type'] = 'Patch' postJsonObject['object']['type'] = 'Patch'
@ -146,7 +146,7 @@ def convertPostToPatch(baseDir: str, nickname: str, domain: str,
postJsonObject['object']['hash'] = commitHash postJsonObject['object']['hash'] = commitHash
postJsonObject['object']['description'] = { postJsonObject['object']['description'] = {
"mediaType": "text/plain", "mediaType": "text/plain",
"content": getPatchDescription(patchStr) "content": _getPatchDescription(patchStr)
} }
# remove content map # remove content map
if postJsonObject['object'].get('contentMap'): if postJsonObject['object'].get('contentMap'):
@ -155,7 +155,7 @@ def convertPostToPatch(baseDir: str, nickname: str, domain: str,
return True return True
def gitAddFromHandle(patchStr: str, handle: str) -> str: def _gitAddFromHandle(patchStr: str, handle: str) -> str:
"""Adds the activitypub handle of the sender to the patch """Adds the activitypub handle of the sender to the patch
""" """
fromStr = 'AP-signed-off-by: ' fromStr = 'AP-signed-off-by: '
@ -181,7 +181,7 @@ def receiveGitPatch(baseDir: str, nickname: str, domain: str,
messageType, subject, content): messageType, subject, content):
return False return False
patchStr = gitFormatContent(content) patchStr = _gitFormatContent(content)
patchLines = patchStr.split('\n') patchLines = patchStr.split('\n')
patchFilename = None patchFilename = None
@ -197,7 +197,7 @@ def receiveGitPatch(baseDir: str, nickname: str, domain: str,
patchSubject = patchSubject.replace('[PATCH]', '').strip() patchSubject = patchSubject.replace('[PATCH]', '').strip()
patchSubject = patchSubject.replace(' ', '_') patchSubject = patchSubject.replace(' ', '_')
projectName = \ projectName = \
getGitProjectName(baseDir, nickname, domain, subject) _getGitProjectName(baseDir, nickname, domain, subject)
if not os.path.isdir(patchesDir): if not os.path.isdir(patchesDir):
os.mkdir(patchesDir) os.mkdir(patchesDir)
projectDir = patchesDir + '/' + projectName projectDir = patchesDir + '/' + projectName
@ -209,7 +209,7 @@ def receiveGitPatch(baseDir: str, nickname: str, domain: str,
if not patchFilename: if not patchFilename:
return False return False
patchStr = \ patchStr = \
gitAddFromHandle(patchStr, '@' + fromNickname + '@' + fromDomain) _gitAddFromHandle(patchStr, '@' + fromNickname + '@' + fromDomain)
with open(patchFilename, 'w+') as patchFile: with open(patchFilename, 'w+') as patchFile:
patchFile.write(patchStr) patchFile.write(patchStr)
patchNotifyFilename = \ patchNotifyFilename = \

View File

@ -17,7 +17,7 @@ from utils import daysInMonth
from utils import mergeDicts from utils import mergeDicts
def validUuid(testUuid: str, version=4): def _validUuid(testUuid: str, version=4):
"""Check if uuid_to_test is a valid UUID """Check if uuid_to_test is a valid UUID
""" """
try: try:
@ -28,7 +28,7 @@ def validUuid(testUuid: str, version=4):
return str(uuid_obj) == testUuid return str(uuid_obj) == testUuid
def removeEventFromTimeline(eventId: str, tlEventsFilename: str) -> None: def _removeEventFromTimeline(eventId: str, tlEventsFilename: str) -> None:
"""Removes the given event Id from the timeline """Removes the given event Id from the timeline
""" """
if eventId + '\n' not in open(tlEventsFilename).read(): if eventId + '\n' not in open(tlEventsFilename).read():
@ -71,7 +71,7 @@ def saveEventPost(baseDir: str, handle: str, postId: str,
if eventJson.get('name') and eventJson.get('actor') and \ if eventJson.get('name') and eventJson.get('actor') and \
eventJson.get('uuid') and eventJson.get('content'): eventJson.get('uuid') and eventJson.get('content'):
if not validUuid(eventJson['uuid']): if not _validUuid(eventJson['uuid']):
return False return False
print('Mobilizon type event') print('Mobilizon type event')
# if this is a full description of an event then save it # if this is a full description of an event then save it
@ -92,7 +92,7 @@ def saveEventPost(baseDir: str, handle: str, postId: str,
tlEventsFilename = baseDir + '/accounts/' + handle + '/events.txt' tlEventsFilename = baseDir + '/accounts/' + handle + '/events.txt'
if os.path.isfile(tlEventsFilename): if os.path.isfile(tlEventsFilename):
removeEventFromTimeline(eventId, tlEventsFilename) _removeEventFromTimeline(eventId, tlEventsFilename)
try: try:
with open(tlEventsFilename, 'r+') as tlEventsFile: with open(tlEventsFilename, 'r+') as tlEventsFile:
content = tlEventsFile.read() content = tlEventsFile.read()
@ -146,7 +146,7 @@ def saveEventPost(baseDir: str, handle: str, postId: str,
return True return True
def isHappeningEvent(tag: {}) -> bool: def _isHappeningEvent(tag: {}) -> bool:
"""Is this tag an Event or Place ActivityStreams type? """Is this tag an Event or Place ActivityStreams type?
""" """
if not tag.get('type'): if not tag.get('type'):
@ -156,7 +156,7 @@ def isHappeningEvent(tag: {}) -> bool:
return True return True
def isHappeningPost(postJsonObject: {}) -> bool: def _isHappeningPost(postJsonObject: {}) -> bool:
"""Is this a post with tags? """Is this a post with tags?
""" """
if not postJsonObject: if not postJsonObject:
@ -208,13 +208,13 @@ def getTodaysEvents(baseDir: str, nickname: str, domain: str,
continue continue
postJsonObject = loadJson(postFilename) postJsonObject = loadJson(postFilename)
if not isHappeningPost(postJsonObject): if not _isHappeningPost(postJsonObject):
continue continue
postEvent = [] postEvent = []
dayOfMonth = None dayOfMonth = None
for tag in postJsonObject['object']['tag']: for tag in postJsonObject['object']['tag']:
if not isHappeningEvent(tag): if not _isHappeningEvent(tag):
continue continue
# this tag is an event or a place # this tag is an event or a place
if tag['type'] == 'Event': if tag['type'] == 'Event':
@ -275,11 +275,11 @@ def todaysEventsCheck(baseDir: str, nickname: str, domain: str) -> bool:
continue continue
postJsonObject = loadJson(postFilename) postJsonObject = loadJson(postFilename)
if not isHappeningPost(postJsonObject): if not _isHappeningPost(postJsonObject):
continue continue
for tag in postJsonObject['object']['tag']: for tag in postJsonObject['object']['tag']:
if not isHappeningEvent(tag): if not _isHappeningEvent(tag):
continue continue
# this tag is an event or a place # this tag is an event or a place
if tag['type'] != 'Event': if tag['type'] != 'Event':
@ -322,11 +322,11 @@ def thisWeeksEventsCheck(baseDir: str, nickname: str, domain: str) -> bool:
continue continue
postJsonObject = loadJson(postFilename) postJsonObject = loadJson(postFilename)
if not isHappeningPost(postJsonObject): if not _isHappeningPost(postJsonObject):
continue continue
for tag in postJsonObject['object']['tag']: for tag in postJsonObject['object']['tag']:
if not isHappeningEvent(tag): if not _isHappeningEvent(tag):
continue continue
# this tag is an event or a place # this tag is an event or a place
if tag['type'] != 'Event': if tag['type'] != 'Event':
@ -377,14 +377,14 @@ def getThisWeeksEvents(baseDir: str, nickname: str, domain: str) -> {}:
continue continue
postJsonObject = loadJson(postFilename) postJsonObject = loadJson(postFilename)
if not isHappeningPost(postJsonObject): if not _isHappeningPost(postJsonObject):
continue continue
postEvent = [] postEvent = []
dayOfMonth = None dayOfMonth = None
weekDayIndex = None weekDayIndex = None
for tag in postJsonObject['object']['tag']: for tag in postJsonObject['object']['tag']:
if not isHappeningEvent(tag): if not _isHappeningEvent(tag):
continue continue
# this tag is an event or a place # this tag is an event or a place
if tag['type'] == 'Event': if tag['type'] == 'Event':
@ -462,13 +462,13 @@ def getCalendarEvents(baseDir: str, nickname: str, domain: str,
continue continue
postJsonObject = loadJson(postFilename) postJsonObject = loadJson(postFilename)
if not isHappeningPost(postJsonObject): if not _isHappeningPost(postJsonObject):
continue continue
postEvent = [] postEvent = []
dayOfMonth = None dayOfMonth = None
for tag in postJsonObject['object']['tag']: for tag in postJsonObject['object']['tag']:
if not isHappeningEvent(tag): if not _isHappeningEvent(tag):
continue continue
# this tag is an event or a place # this tag is an event or a place
if tag['type'] == 'Event': if tag['type'] == 'Event':

View File

@ -135,7 +135,7 @@ def createSignedHeader(privateKeyPem: str, nickname: str,
return headers return headers
def verifyRecentSignature(signedDateStr: str) -> bool: def _verifyRecentSignature(signedDateStr: str) -> bool:
"""Checks whether the given time taken from the header is within """Checks whether the given time taken from the header is within
12 hours of the current time 12 hours of the current time
""" """
@ -219,7 +219,7 @@ def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
else: else:
if headers.get(signedHeader): if headers.get(signedHeader):
if signedHeader == 'date': if signedHeader == 'date':
if not verifyRecentSignature(headers[signedHeader]): if not _verifyRecentSignature(headers[signedHeader]):
if debug: if debug:
print('DEBUG: ' + print('DEBUG: ' +
'verifyPostHeaders date is not recent ' + 'verifyPostHeaders date is not recent ' +
@ -230,7 +230,7 @@ def verifyPostHeaders(httpPrefix: str, publicKeyPem: str, headers: dict,
else: else:
signedHeaderCap = signedHeader.capitalize() signedHeaderCap = signedHeader.capitalize()
if signedHeaderCap == 'Date': if signedHeaderCap == 'Date':
if not verifyRecentSignature(headers[signedHeaderCap]): if not _verifyRecentSignature(headers[signedHeaderCap]):
if debug: if debug:
print('DEBUG: ' + print('DEBUG: ' +
'verifyPostHeaders date is not recent ' + 'verifyPostHeaders date is not recent ' +

158
inbox.py
View File

@ -138,7 +138,7 @@ def storeHashTags(baseDir: str, nickname: str, postJsonObject: {}) -> None:
setHashtagCategory(baseDir, tagName, categoryStr) setHashtagCategory(baseDir, tagName, categoryStr)
def inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int, def _inboxStorePostToHtmlCache(recentPostsCache: {}, maxRecentPosts: int,
translate: {}, translate: {},
baseDir: str, httpPrefix: str, baseDir: str, httpPrefix: str,
session, cachedWebfingers: {}, personCache: {}, session, cachedWebfingers: {}, personCache: {},
@ -451,7 +451,7 @@ def savePostToInboxQueue(baseDir: str, httpPrefix: str,
return filename return filename
def inboxPostRecipientsAdd(baseDir: str, httpPrefix: str, toList: [], def _inboxPostRecipientsAdd(baseDir: str, httpPrefix: str, toList: [],
recipientsDict: {}, recipientsDict: {},
domainMatch: str, domain: str, domainMatch: str, domain: str,
actor: str, debug: bool) -> bool: actor: str, debug: bool) -> bool:
@ -485,7 +485,7 @@ def inboxPostRecipientsAdd(baseDir: str, httpPrefix: str, toList: [],
return followerRecipients, recipientsDict return followerRecipients, recipientsDict
def inboxPostRecipients(baseDir: str, postJsonObject: {}, def _inboxPostRecipients(baseDir: str, postJsonObject: {},
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
debug: bool) -> ([], []): debug: bool) -> ([], []):
"""Returns dictionaries containing the recipients of the given post """Returns dictionaries containing the recipients of the given post
@ -520,7 +520,7 @@ def inboxPostRecipients(baseDir: str, postJsonObject: {},
if debug: if debug:
print('DEBUG: resolving "to"') print('DEBUG: resolving "to"')
includesFollowers, recipientsDict = \ includesFollowers, recipientsDict = \
inboxPostRecipientsAdd(baseDir, httpPrefix, _inboxPostRecipientsAdd(baseDir, httpPrefix,
recipientsList, recipientsList,
recipientsDict, recipientsDict,
domainMatch, domainBase, domainMatch, domainBase,
@ -537,7 +537,7 @@ def inboxPostRecipients(baseDir: str, postJsonObject: {},
else: else:
recipientsList = [postJsonObject['object']['cc']] recipientsList = [postJsonObject['object']['cc']]
includesFollowers, recipientsDict = \ includesFollowers, recipientsDict = \
inboxPostRecipientsAdd(baseDir, httpPrefix, _inboxPostRecipientsAdd(baseDir, httpPrefix,
recipientsList, recipientsList,
recipientsDict, recipientsDict,
domainMatch, domainBase, domainMatch, domainBase,
@ -562,7 +562,7 @@ def inboxPostRecipients(baseDir: str, postJsonObject: {},
else: else:
recipientsList = [postJsonObject['to']] recipientsList = [postJsonObject['to']]
includesFollowers, recipientsDict = \ includesFollowers, recipientsDict = \
inboxPostRecipientsAdd(baseDir, httpPrefix, _inboxPostRecipientsAdd(baseDir, httpPrefix,
recipientsList, recipientsList,
recipientsDict, recipientsDict,
domainMatch, domainBase, domainMatch, domainBase,
@ -576,7 +576,7 @@ def inboxPostRecipients(baseDir: str, postJsonObject: {},
else: else:
recipientsList = [postJsonObject['cc']] recipientsList = [postJsonObject['cc']]
includesFollowers, recipientsDict = \ includesFollowers, recipientsDict = \
inboxPostRecipientsAdd(baseDir, httpPrefix, _inboxPostRecipientsAdd(baseDir, httpPrefix,
recipientsList, recipientsList,
recipientsDict, recipientsDict,
domainMatch, domainBase, domainMatch, domainBase,
@ -596,7 +596,7 @@ def inboxPostRecipients(baseDir: str, postJsonObject: {},
return recipientsDict, recipientsDictFollowers return recipientsDict, recipientsDictFollowers
def receiveUndoFollow(session, baseDir: str, httpPrefix: str, def _receiveUndoFollow(session, baseDir: str, httpPrefix: str,
port: int, messageJson: {}, port: int, messageJson: {},
federationList: [], federationList: [],
debug: bool) -> bool: debug: bool) -> bool:
@ -653,7 +653,7 @@ def receiveUndoFollow(session, baseDir: str, httpPrefix: str,
return False return False
def receiveUndo(session, baseDir: str, httpPrefix: str, def _receiveUndo(session, baseDir: str, httpPrefix: str,
port: int, sendThreads: [], postLog: [], port: int, sendThreads: [], postLog: [],
cachedWebfingers: {}, personCache: {}, cachedWebfingers: {}, personCache: {},
messageJson: {}, federationList: [], messageJson: {}, federationList: [],
@ -698,13 +698,13 @@ def receiveUndo(session, baseDir: str, httpPrefix: str,
' object within object is not a string') ' object within object is not a string')
return False return False
if messageJson['object']['type'] == 'Follow': if messageJson['object']['type'] == 'Follow':
return receiveUndoFollow(session, baseDir, httpPrefix, return _receiveUndoFollow(session, baseDir, httpPrefix,
port, messageJson, port, messageJson,
federationList, debug) federationList, debug)
return False return False
def receiveEventPost(recentPostsCache: {}, session, baseDir: str, def _receiveEventPost(recentPostsCache: {}, session, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
personCache: {}, messageJson: {}, federationList: [], personCache: {}, messageJson: {}, federationList: [],
@ -723,11 +723,12 @@ def receiveEventPost(recentPostsCache: {}, session, baseDir: str,
saveEventPost(baseDir, handle, postId, messageJson['object']) saveEventPost(baseDir, handle, postId, messageJson['object'])
def personReceiveUpdate(baseDir: str, def _personReceiveUpdate(baseDir: str,
domain: str, port: int, domain: str, port: int,
updateNickname: str, updateDomain: str, updateNickname: str, updateDomain: str,
updatePort: int, updatePort: int,
personJson: {}, personCache: {}, debug: bool) -> bool: personJson: {}, personCache: {},
debug: bool) -> bool:
"""Changes an actor. eg: avatar or display name change """Changes an actor. eg: avatar or display name change
""" """
print('Receiving actor update for ' + personJson['url'] + print('Receiving actor update for ' + personJson['url'] +
@ -795,8 +796,9 @@ def personReceiveUpdate(baseDir: str,
return True return True
def receiveUpdateToQuestion(recentPostsCache: {}, messageJson: {}, def _receiveUpdateToQuestion(recentPostsCache: {}, messageJson: {},
baseDir: str, nickname: str, domain: str) -> None: baseDir: str,
nickname: str, domain: str) -> None:
"""Updating a question as new votes arrive """Updating a question as new votes arrive
""" """
# message url of the question # message url of the question
@ -832,7 +834,7 @@ def receiveUpdateToQuestion(recentPostsCache: {}, messageJson: {},
removePostFromCache(messageJson, recentPostsCache) removePostFromCache(messageJson, recentPostsCache)
def receiveUpdate(recentPostsCache: {}, session, baseDir: str, def _receiveUpdate(recentPostsCache: {}, session, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
personCache: {}, messageJson: {}, federationList: [], personCache: {}, messageJson: {}, federationList: [],
@ -867,7 +869,7 @@ def receiveUpdate(recentPostsCache: {}, session, baseDir: str,
return False return False
if messageJson['object']['type'] == 'Question': if messageJson['object']['type'] == 'Question':
receiveUpdateToQuestion(recentPostsCache, messageJson, _receiveUpdateToQuestion(recentPostsCache, messageJson,
baseDir, nickname, domain) baseDir, nickname, domain)
if debug: if debug:
print('DEBUG: Question update was received') print('DEBUG: Question update was received')
@ -880,7 +882,7 @@ def receiveUpdate(recentPostsCache: {}, session, baseDir: str,
if updateNickname: if updateNickname:
updateDomain, updatePort = \ updateDomain, updatePort = \
getDomainFromActor(messageJson['id']) getDomainFromActor(messageJson['id'])
if personReceiveUpdate(baseDir, domain, port, if _personReceiveUpdate(baseDir, domain, port,
updateNickname, updateDomain, updateNickname, updateDomain,
updatePort, messageJson, updatePort, messageJson,
personCache, debug): personCache, debug):
@ -901,7 +903,7 @@ def receiveUpdate(recentPostsCache: {}, session, baseDir: str,
if updateNickname: if updateNickname:
updateDomain, updatePort = \ updateDomain, updatePort = \
getDomainFromActor(messageJson['actor']) getDomainFromActor(messageJson['actor'])
if personReceiveUpdate(baseDir, if _personReceiveUpdate(baseDir,
domain, port, domain, port,
updateNickname, updateDomain, updateNickname, updateDomain,
updatePort, updatePort,
@ -914,7 +916,7 @@ def receiveUpdate(recentPostsCache: {}, session, baseDir: str,
return False return False
def receiveLike(recentPostsCache: {}, def _receiveLike(recentPostsCache: {},
session, handle: str, isGroup: bool, baseDir: str, session, handle: str, isGroup: bool, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
onionDomain: str, onionDomain: str,
@ -968,7 +970,7 @@ def receiveLike(recentPostsCache: {},
if debug: if debug:
print('DEBUG: liked post found in inbox') print('DEBUG: liked post found in inbox')
if not alreadyLiked(baseDir, if not _alreadyLiked(baseDir,
handle.split('@')[0], handle.split('@')[0],
handle.split('@')[1], handle.split('@')[1],
messageJson['object'], messageJson['object'],
@ -976,12 +978,12 @@ def receiveLike(recentPostsCache: {},
updateLikesCollection(recentPostsCache, baseDir, postFilename, updateLikesCollection(recentPostsCache, baseDir, postFilename,
messageJson['object'], messageJson['object'],
messageJson['actor'], domain, debug) messageJson['actor'], domain, debug)
likeNotify(baseDir, domain, onionDomain, handle, _likeNotify(baseDir, domain, onionDomain, handle,
messageJson['actor'], messageJson['object']) messageJson['actor'], messageJson['object'])
return True return True
def receiveUndoLike(recentPostsCache: {}, def _receiveUndoLike(recentPostsCache: {},
session, handle: str, isGroup: bool, baseDir: str, session, handle: str, isGroup: bool, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
@ -1042,7 +1044,7 @@ def receiveUndoLike(recentPostsCache: {},
return True return True
def receiveBookmark(recentPostsCache: {}, def _receiveBookmark(recentPostsCache: {},
session, handle: str, isGroup: bool, baseDir: str, session, handle: str, isGroup: bool, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
@ -1108,7 +1110,7 @@ def receiveBookmark(recentPostsCache: {},
return True return True
def receiveUndoBookmark(recentPostsCache: {}, def _receiveUndoBookmark(recentPostsCache: {},
session, handle: str, isGroup: bool, baseDir: str, session, handle: str, isGroup: bool, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
@ -1177,7 +1179,7 @@ def receiveUndoBookmark(recentPostsCache: {},
return True return True
def receiveDelete(session, handle: str, isGroup: bool, baseDir: str, def _receiveDelete(session, handle: str, isGroup: bool, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
personCache: {}, messageJson: {}, federationList: [], personCache: {}, messageJson: {}, federationList: [],
@ -1263,9 +1265,10 @@ def receiveDelete(session, handle: str, isGroup: bool, baseDir: str,
return True return True
def receiveAnnounce(recentPostsCache: {}, def _receiveAnnounce(recentPostsCache: {},
session, handle: str, isGroup: bool, baseDir: str, session, handle: str, isGroup: bool, baseDir: str,
httpPrefix: str, domain: str, onionDomain: str, port: int, httpPrefix: str,
domain: str, onionDomain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
personCache: {}, messageJson: {}, federationList: [], personCache: {}, messageJson: {}, federationList: [],
debug: bool, translate: {}, debug: bool, translate: {},
@ -1410,7 +1413,7 @@ def receiveAnnounce(recentPostsCache: {},
return True return True
def receiveUndoAnnounce(recentPostsCache: {}, def _receiveUndoAnnounce(recentPostsCache: {},
session, handle: str, isGroup: bool, baseDir: str, session, handle: str, isGroup: bool, baseDir: str,
httpPrefix: str, domain: str, port: int, httpPrefix: str, domain: str, port: int,
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
@ -1482,7 +1485,7 @@ def jsonPostAllowsComments(postJsonObject: {}) -> bool:
return True return True
def postAllowsComments(postFilename: str) -> bool: def _postAllowsComments(postFilename: str) -> bool:
"""Returns true if the given post allows comments/replies """Returns true if the given post allows comments/replies
""" """
postJsonObject = loadJson(postFilename) postJsonObject = loadJson(postFilename)
@ -1533,7 +1536,7 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
if debug: if debug:
print('DEBUG: post may have expired - ' + replyTo) print('DEBUG: post may have expired - ' + replyTo)
return False return False
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)
return False return False
@ -1555,19 +1558,19 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
return True return True
def estimateNumberOfMentions(content: str) -> int: def _estimateNumberOfMentions(content: str) -> int:
"""Returns a rough estimate of the number of mentions """Returns a rough estimate of the number of mentions
""" """
return int(content.count('@') / 2) return int(content.count('@') / 2)
def estimateNumberOfEmoji(content: str) -> int: def _estimateNumberOfEmoji(content: str) -> int:
"""Returns a rough estimate of the number of emoji """Returns a rough estimate of the number of emoji
""" """
return int(content.count(':') / 2) return int(content.count(':') / 2)
def validPostContent(baseDir: str, nickname: str, domain: str, def _validPostContent(baseDir: str, nickname: str, domain: str,
messageJson: {}, maxMentions: int, maxEmoji: int, messageJson: {}, maxMentions: int, maxEmoji: int,
allowLocalNetworkAccess: bool) -> bool: allowLocalNetworkAccess: bool) -> bool:
"""Is the content of a received post valid? """Is the content of a received post valid?
@ -1615,14 +1618,14 @@ def validPostContent(baseDir: str, nickname: str, domain: str,
return False return False
# check (rough) number of mentions # check (rough) number of mentions
mentionsEst = estimateNumberOfMentions(messageJson['object']['content']) mentionsEst = _estimateNumberOfMentions(messageJson['object']['content'])
if mentionsEst > maxMentions: if mentionsEst > maxMentions:
if messageJson['object'].get('id'): if messageJson['object'].get('id'):
print('REJECT HELLTHREAD: ' + messageJson['object']['id']) print('REJECT HELLTHREAD: ' + messageJson['object']['id'])
print('REJECT HELLTHREAD: Too many mentions in post - ' + print('REJECT HELLTHREAD: Too many mentions in post - ' +
messageJson['object']['content']) messageJson['object']['content'])
return False return False
if estimateNumberOfEmoji(messageJson['object']['content']) > maxEmoji: if _estimateNumberOfEmoji(messageJson['object']['content']) > maxEmoji:
if messageJson['object'].get('id'): if messageJson['object'].get('id'):
print('REJECT EMOJI OVERLOAD: ' + messageJson['object']['id']) print('REJECT EMOJI OVERLOAD: ' + messageJson['object']['id'])
print('REJECT EMOJI OVERLOAD: Too many emoji in post - ' + print('REJECT EMOJI OVERLOAD: Too many emoji in post - ' +
@ -1650,7 +1653,7 @@ def validPostContent(baseDir: str, nickname: str, domain: str,
postPostFilename = locatePost(baseDir, nickname, domain, postPostFilename = locatePost(baseDir, nickname, domain,
originalPostId) originalPostId)
if postPostFilename: if postPostFilename:
if not postAllowsComments(postPostFilename): if not _postAllowsComments(postPostFilename):
print('REJECT: reply to post which does not ' + print('REJECT: reply to post which does not ' +
'allow comments: ' + originalPostId) 'allow comments: ' + originalPostId)
return False return False
@ -1658,7 +1661,7 @@ def validPostContent(baseDir: str, nickname: str, domain: str,
return True return True
def obtainAvatarForReplyPost(session, baseDir: str, httpPrefix: str, def _obtainAvatarForReplyPost(session, baseDir: str, httpPrefix: str,
domain: str, onionDomain: str, personCache: {}, domain: str, onionDomain: str, personCache: {},
postJsonObject: {}, debug: bool) -> None: postJsonObject: {}, debug: bool) -> None:
"""Tries to obtain the actor for the person being replied to """Tries to obtain the actor for the person being replied to
@ -1708,7 +1711,7 @@ def obtainAvatarForReplyPost(session, baseDir: str, httpPrefix: str,
time.sleep(5) time.sleep(5)
def dmNotify(baseDir: str, handle: str, url: str) -> None: def _dmNotify(baseDir: str, handle: str, url: str) -> None:
"""Creates a notification that a new DM has arrived """Creates a notification that a new DM has arrived
""" """
accountDir = baseDir + '/accounts/' + handle accountDir = baseDir + '/accounts/' + handle
@ -1720,7 +1723,7 @@ def dmNotify(baseDir: str, handle: str, url: str) -> None:
fp.write(url) fp.write(url)
def alreadyLiked(baseDir: str, nickname: str, domain: str, def _alreadyLiked(baseDir: str, nickname: str, domain: str,
postUrl: str, likerActor: str) -> bool: postUrl: str, likerActor: str) -> bool:
"""Is the given post already liked by the given handle? """Is the given post already liked by the given handle?
""" """
@ -1751,7 +1754,7 @@ def alreadyLiked(baseDir: str, nickname: str, domain: str,
return False return False
def likeNotify(baseDir: str, domain: str, onionDomain: str, def _likeNotify(baseDir: str, domain: str, onionDomain: str,
handle: str, actor: str, url: str) -> None: handle: str, actor: str, url: str) -> None:
"""Creates a notification that a like has arrived """Creates a notification that a like has arrived
""" """
@ -1784,7 +1787,7 @@ def likeNotify(baseDir: str, domain: str, onionDomain: str,
if likerNickname and likerDomain: if likerNickname and likerDomain:
likerHandle = likerNickname + '@' + likerDomain likerHandle = likerNickname + '@' + likerDomain
else: else:
print('likeNotify likerHandle: ' + print('_likeNotify likerHandle: ' +
str(likerNickname) + '@' + str(likerDomain)) str(likerNickname) + '@' + str(likerDomain))
likerHandle = actor likerHandle = actor
if likerHandle != handle: if likerHandle != handle:
@ -1813,7 +1816,7 @@ def likeNotify(baseDir: str, domain: str, onionDomain: str,
pass pass
def replyNotify(baseDir: str, handle: str, url: str) -> None: def _replyNotify(baseDir: str, handle: str, url: str) -> None:
"""Creates a notification that a new reply has arrived """Creates a notification that a new reply has arrived
""" """
accountDir = baseDir + '/accounts/' + handle accountDir = baseDir + '/accounts/' + handle
@ -1825,7 +1828,7 @@ def replyNotify(baseDir: str, handle: str, url: str) -> None:
fp.write(url) fp.write(url)
def gitPatchNotify(baseDir: str, handle: str, def _gitPatchNotify(baseDir: str, handle: str,
subject: str, content: str, subject: str, content: str,
fromNickname: str, fromDomain: str) -> None: fromNickname: str, fromDomain: str) -> None:
"""Creates a notification that a new git patch has arrived """Creates a notification that a new git patch has arrived
@ -1840,7 +1843,7 @@ def gitPatchNotify(baseDir: str, handle: str,
fp.write('git ' + handle + ' ' + subject) fp.write('git ' + handle + ' ' + subject)
def groupHandle(baseDir: str, handle: str) -> bool: def _groupHandle(baseDir: str, handle: str) -> bool:
"""Is the given account handle a group? """Is the given account handle a group?
""" """
actorFile = baseDir + '/accounts/' + handle + '.json' actorFile = baseDir + '/accounts/' + handle + '.json'
@ -1852,7 +1855,7 @@ def groupHandle(baseDir: str, handle: str) -> bool:
return actorJson['type'] == 'Group' return actorJson['type'] == 'Group'
def getGroupName(baseDir: str, handle: str) -> str: def _getGroupName(baseDir: str, handle: str) -> str:
"""Returns the preferred name of a group """Returns the preferred name of a group
""" """
actorFile = baseDir + '/accounts/' + handle + '.json' actorFile = baseDir + '/accounts/' + handle + '.json'
@ -1864,7 +1867,7 @@ def getGroupName(baseDir: str, handle: str) -> str:
return actorJson['name'] return actorJson['name']
def sendToGroupMembers(session, baseDir: str, handle: str, port: int, def _sendToGroupMembers(session, baseDir: str, handle: str, port: int,
postJsonObject: {}, postJsonObject: {},
httpPrefix: str, federationList: [], httpPrefix: str, federationList: [],
sendThreads: [], postLog: [], cachedWebfingers: {}, sendThreads: [], postLog: [], cachedWebfingers: {},
@ -1877,7 +1880,7 @@ def sendToGroupMembers(session, baseDir: str, handle: str, port: int,
if not postJsonObject.get('object'): if not postJsonObject.get('object'):
return return
nickname = handle.split('@')[0] nickname = handle.split('@')[0]
# groupname = getGroupName(baseDir, handle) # groupname = _getGroupName(baseDir, handle)
domain = handle.split('@')[1] domain = handle.split('@')[1]
domainFull = getFullDomain(domain, port) domainFull = getFullDomain(domain, port)
# set sender # set sender
@ -1941,7 +1944,8 @@ def sendToGroupMembers(session, baseDir: str, handle: str, port: int,
personCache, debug, __version__) personCache, debug, __version__)
def inboxUpdateCalendar(baseDir: str, handle: str, postJsonObject: {}) -> None: def _inboxUpdateCalendar(baseDir: str, handle: str,
postJsonObject: {}) -> None:
"""Detects whether the tag list on a post contains calendar events """Detects whether the tag list on a post contains calendar events
and if so saves the post id to a file in the calendar directory and if so saves the post id to a file in the calendar directory
for the account for the account
@ -2017,7 +2021,7 @@ def inboxUpdateIndex(boxname: str, baseDir: str, handle: str,
return False return False
def updateLastSeen(baseDir: str, handle: str, actor: str) -> None: def _updateLastSeen(baseDir: str, handle: str, actor: str) -> None:
"""Updates the time when the given handle last saw the given actor """Updates the time when the given handle last saw the given actor
This can later be used to indicate if accounts are dormant/abandoned/moved This can later be used to indicate if accounts are dormant/abandoned/moved
""" """
@ -2049,7 +2053,7 @@ def updateLastSeen(baseDir: str, handle: str, actor: str) -> None:
lastSeenFile.write(str(daysSinceEpoch)) lastSeenFile.write(str(daysSinceEpoch))
def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int, def _inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
session, keyId: str, handle: str, messageJson: {}, session, keyId: str, handle: str, messageJson: {},
baseDir: str, httpPrefix: str, sendThreads: [], baseDir: str, httpPrefix: str, sendThreads: [],
postLog: [], cachedWebfingers: {}, personCache: {}, postLog: [], cachedWebfingers: {}, personCache: {},
@ -2069,11 +2073,11 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
if '#' in actor: if '#' in actor:
actor = keyId.split('#')[0] actor = keyId.split('#')[0]
updateLastSeen(baseDir, handle, actor) _updateLastSeen(baseDir, handle, actor)
isGroup = groupHandle(baseDir, handle) isGroup = _groupHandle(baseDir, handle)
if receiveLike(recentPostsCache, if _receiveLike(recentPostsCache,
session, handle, isGroup, session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
@ -2088,7 +2092,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
print('DEBUG: Like accepted from ' + actor) print('DEBUG: Like accepted from ' + actor)
return False return False
if receiveUndoLike(recentPostsCache, if _receiveUndoLike(recentPostsCache,
session, handle, isGroup, session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
@ -2102,7 +2106,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
print('DEBUG: Undo like accepted from ' + actor) print('DEBUG: Undo like accepted from ' + actor)
return False return False
if receiveBookmark(recentPostsCache, if _receiveBookmark(recentPostsCache,
session, handle, isGroup, session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
@ -2116,7 +2120,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
print('DEBUG: Bookmark accepted from ' + actor) print('DEBUG: Bookmark accepted from ' + actor)
return False return False
if receiveUndoBookmark(recentPostsCache, if _receiveUndoBookmark(recentPostsCache,
session, handle, isGroup, session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
@ -2130,9 +2134,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
print('DEBUG: Undo bookmark accepted from ' + actor) print('DEBUG: Undo bookmark accepted from ' + actor)
return False return False
# labelAccusatoryPost(messageJson, translate) if _receiveAnnounce(recentPostsCache,
if receiveAnnounce(recentPostsCache,
session, handle, isGroup, session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, onionDomain, port, domain, onionDomain, port,
@ -2146,7 +2148,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
if debug: if debug:
print('DEBUG: Announce accepted from ' + actor) print('DEBUG: Announce accepted from ' + actor)
if receiveUndoAnnounce(recentPostsCache, if _receiveUndoAnnounce(recentPostsCache,
session, handle, isGroup, session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
@ -2160,7 +2162,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
print('DEBUG: Undo announce accepted from ' + actor) print('DEBUG: Undo announce accepted from ' + actor)
return False return False
if receiveDelete(session, handle, isGroup, if _receiveDelete(session, handle, isGroup,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
sendThreads, postLog, sendThreads, postLog,
@ -2188,7 +2190,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject = messageJson postJsonObject = messageJson
nickname = handle.split('@')[0] nickname = handle.split('@')[0]
if validPostContent(baseDir, nickname, domain, if _validPostContent(baseDir, nickname, domain,
postJsonObject, maxMentions, maxEmoji, postJsonObject, maxMentions, maxEmoji,
allowLocalNetworkAccess): allowLocalNetworkAccess):
@ -2213,7 +2215,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
jsonObj['summary'], jsonObj['summary'],
jsonObj['content'], jsonObj['content'],
fromNickname, fromDomain): fromNickname, fromDomain):
gitPatchNotify(baseDir, handle, _gitPatchNotify(baseDir, handle,
jsonObj['summary'], jsonObj['summary'],
jsonObj['content'], jsonObj['content'],
fromNickname, fromDomain) fromNickname, fromDomain)
@ -2293,7 +2295,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
return False return False
# dm index will be updated # dm index will be updated
updateIndexList.append('dm') updateIndexList.append('dm')
dmNotify(baseDir, handle, _dmNotify(baseDir, handle,
httpPrefix + '://' + domain + '/users/' + httpPrefix + '://' + domain + '/users/' +
nickname + '/dm') nickname + '/dm')
@ -2313,7 +2315,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
if isinstance(inReplyTo, str): if isinstance(inReplyTo, str):
if not isMuted(baseDir, nickname, domain, if not isMuted(baseDir, nickname, domain,
inReplyTo): inReplyTo):
replyNotify(baseDir, handle, _replyNotify(baseDir, handle,
httpPrefix + '://' + domain + httpPrefix + '://' + domain +
'/users/' + nickname + '/users/' + nickname +
'/tlreplies') '/tlreplies')
@ -2333,7 +2335,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
updateIndexList.append('tlevents') updateIndexList.append('tlevents')
# get the avatar for a reply/announce # get the avatar for a reply/announce
obtainAvatarForReplyPost(session, baseDir, _obtainAvatarForReplyPost(session, baseDir,
httpPrefix, domain, onionDomain, httpPrefix, domain, onionDomain,
personCache, postJsonObject, debug) personCache, postJsonObject, debug)
@ -2359,7 +2361,7 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
print('Saving inbox post as html to cache') print('Saving inbox post as html to cache')
htmlCacheStartTime = time.time() htmlCacheStartTime = time.time()
inboxStorePostToHtmlCache(recentPostsCache, _inboxStorePostToHtmlCache(recentPostsCache,
maxRecentPosts, maxRecentPosts,
translate, baseDir, translate, baseDir,
httpPrefix, httpPrefix,
@ -2379,13 +2381,13 @@ def inboxAfterInitial(recentPostsCache: {}, maxRecentPosts: int,
' post as html to cache in ' + ' post as html to cache in ' +
timeDiff + ' mS') timeDiff + ' mS')
inboxUpdateCalendar(baseDir, handle, postJsonObject) _inboxUpdateCalendar(baseDir, handle, postJsonObject)
storeHashTags(baseDir, handle.split('@')[0], postJsonObject) storeHashTags(baseDir, handle.split('@')[0], postJsonObject)
# send the post out to group members # send the post out to group members
if isGroup: if isGroup:
sendToGroupMembers(session, baseDir, handle, port, _sendToGroupMembers(session, baseDir, handle, port,
postJsonObject, postJsonObject,
httpPrefix, federationList, sendThreads, httpPrefix, federationList, sendThreads,
postLog, cachedWebfingers, personCache, postLog, cachedWebfingers, personCache,
@ -2420,7 +2422,7 @@ def clearQueueItems(baseDir: str, queue: []) -> None:
print('Removed ' + str(ctr) + ' inbox queue items') print('Removed ' + str(ctr) + ' inbox queue items')
def restoreQueueItems(baseDir: str, queue: []) -> None: def _restoreQueueItems(baseDir: str, queue: []) -> None:
"""Checks the queue for each account and appends filenames """Checks the queue for each account and appends filenames
""" """
queue.clear() queue.clear()
@ -2483,7 +2485,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
# if queue processing was interrupted (eg server crash) # if queue processing was interrupted (eg server crash)
# then this loads any outstanding items back into the queue # then this loads any outstanding items back into the queue
restoreQueueItems(baseDir, queue) _restoreQueueItems(baseDir, queue)
# keep track of numbers of incoming posts per day # keep track of numbers of incoming posts per day
quotasLastUpdateDaily = int(time.time()) quotasLastUpdateDaily = int(time.time())
@ -2515,7 +2517,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
queueRestoreCtr += 1 queueRestoreCtr += 1
if queueRestoreCtr >= 30: if queueRestoreCtr >= 30:
queueRestoreCtr = 0 queueRestoreCtr = 0
restoreQueueItems(baseDir, queue) _restoreQueueItems(baseDir, queue)
continue continue
currTime = int(time.time()) currTime = int(time.time())
@ -2731,7 +2733,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
# if queueJson['post'].get('id'): # if queueJson['post'].get('id'):
# queueJson['post']['id']=queueJson['id'] # queueJson['post']['id']=queueJson['id']
if receiveUndo(session, if _receiveUndo(session,
baseDir, httpPrefix, port, baseDir, httpPrefix, port,
sendThreads, postLog, sendThreads, postLog,
cachedWebfingers, cachedWebfingers,
@ -2782,7 +2784,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
queue.pop(0) queue.pop(0)
continue continue
if receiveEventPost(recentPostsCache, session, if _receiveEventPost(recentPostsCache, session,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
sendThreads, postLog, sendThreads, postLog,
@ -2799,7 +2801,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
queue.pop(0) queue.pop(0)
continue continue
if receiveUpdate(recentPostsCache, session, if _receiveUpdate(recentPostsCache, session,
baseDir, httpPrefix, baseDir, httpPrefix,
domain, port, domain, port,
sendThreads, postLog, sendThreads, postLog,
@ -2818,7 +2820,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
# get recipients list # get recipients list
recipientsDict, recipientsDictFollowers = \ recipientsDict, recipientsDictFollowers = \
inboxPostRecipients(baseDir, queueJson['post'], _inboxPostRecipients(baseDir, queueJson['post'],
httpPrefix, domain, port, debug) httpPrefix, domain, port, debug)
if len(recipientsDict.items()) == 0 and \ if len(recipientsDict.items()) == 0 and \
len(recipientsDictFollowers.items()) == 0: len(recipientsDictFollowers.items()) == 0:
@ -2866,7 +2868,7 @@ def runInboxQueue(recentPostsCache: {}, maxRecentPosts: int,
for handle, capsId in recipientsDict.items(): for handle, capsId in recipientsDict.items():
destination = \ destination = \
queueJson['destination'].replace(inboxHandle, handle) queueJson['destination'].replace(inboxHandle, handle)
inboxAfterInitial(recentPostsCache, _inboxAfterInitial(recentPostsCache,
maxRecentPosts, maxRecentPosts,
session, keyId, handle, session, keyId, handle,
queueJson['post'], queueJson['post'],

View File

@ -28,21 +28,21 @@ import base64
import json import json
def b64safeEncode(payload: {}) -> str: def _b64safeEncode(payload: {}) -> str:
""" """
b64 url safe encoding with the padding removed. b64 url safe encoding with the padding removed.
""" """
return base64.urlsafe_b64encode(payload).rstrip(b'=') return base64.urlsafe_b64encode(payload).rstrip(b'=')
def b64safeDecode(payload: {}) -> str: def _b64safeDecode(payload: {}) -> str:
""" """
b64 url safe decoding with the padding added. b64 url safe decoding with the padding added.
""" """
return base64.urlsafe_b64decode(payload + b'=' * (4 - len(payload) % 4)) return base64.urlsafe_b64decode(payload + b'=' * (4 - len(payload) % 4))
def normalizeJson(payload: {}) -> str: def _normalizeJson(payload: {}) -> str:
""" """
Normalize with URDNA2015 Normalize with URDNA2015
""" """
@ -50,7 +50,7 @@ def normalizeJson(payload: {}) -> str:
sort_keys=True).encode('utf-8') sort_keys=True).encode('utf-8')
def signRs256(payload: {}, privateKeyPem: str) -> str: def _signRs256(payload: {}, privateKeyPem: str) -> str:
""" """
Produce a RS256 signature of the payload Produce a RS256 signature of the payload
""" """
@ -60,7 +60,7 @@ def signRs256(payload: {}, privateKeyPem: str) -> str:
return signature return signature
def verifyRs256(payload: {}, signature: str, publicKeyPem: str) -> bool: def _verifyRs256(payload: {}, signature: str, publicKeyPem: str) -> bool:
""" """
Verifies a RS256 signature Verifies a RS256 signature
""" """
@ -69,7 +69,7 @@ def verifyRs256(payload: {}, signature: str, publicKeyPem: str) -> bool:
return verifier.verify(SHA256.new(payload), signature) return verifier.verify(SHA256.new(payload), signature)
def signJws(payload: {}, privateKeyPem: str) -> str: def _signJws(payload: {}, privateKeyPem: str) -> str:
""" """
Prepare payload to sign Prepare payload to sign
""" """
@ -78,28 +78,28 @@ def signJws(payload: {}, privateKeyPem: str) -> str:
'b64': False, 'b64': False,
'crit': ['b64'] 'crit': ['b64']
} }
normalizedJson = normalizeJson(header) normalizedJson = _normalizeJson(header)
encodedHeader = b64safeEncode(normalizedJson) encodedHeader = _b64safeEncode(normalizedJson)
preparedPayload = b'.'.join([encodedHeader, payload]) preparedPayload = b'.'.join([encodedHeader, payload])
signature = signRs256(preparedPayload, privateKeyPem) signature = _signRs256(preparedPayload, privateKeyPem)
encodedSignature = b64safeEncode(signature) encodedSignature = _b64safeEncode(signature)
jwsSignature = b'..'.join([encodedHeader, encodedSignature]) jwsSignature = b'..'.join([encodedHeader, encodedSignature])
return jwsSignature return jwsSignature
def verifyJws(payload: {}, jwsSignature: str, publicKeyPem: str) -> bool: def _verifyJws(payload: {}, jwsSignature: str, publicKeyPem: str) -> bool:
""" """
Verifies a signature using the given public key Verifies a signature using the given public key
""" """
encodedHeader, encodedSignature = jwsSignature.split(b'..') encodedHeader, encodedSignature = jwsSignature.split(b'..')
signature = b64safeDecode(encodedSignature) signature = _b64safeDecode(encodedSignature)
payload = b'.'.join([encodedHeader, payload]) payload = b'.'.join([encodedHeader, payload])
return verifyRs256(payload, signature, publicKeyPem) return _verifyRs256(payload, signature, publicKeyPem)
def jsonldNormalize(jldDocument: str): def _jsonldNormalize(jldDocument: str):
""" """
Normalize and hash the json-ld document Normalize and hash the json-ld document
""" """
@ -117,8 +117,8 @@ def jsonldSign(jldDocument: {}, privateKeyPem: str) -> {}:
Produces a signed JSON-LD document with a Json Web Signature Produces a signed JSON-LD document with a Json Web Signature
""" """
jldDocument = deepcopy(jldDocument) jldDocument = deepcopy(jldDocument)
normalizedJldHash = jsonldNormalize(jldDocument) normalizedJldHash = _jsonldNormalize(jldDocument)
jwsSignature = signJws(normalizedJldHash, privateKeyPem) jwsSignature = _signJws(normalizedJldHash, privateKeyPem)
# construct the signature document and add it to jsonld # construct the signature document and add it to jsonld
signature = { signature = {
@ -138,9 +138,9 @@ def jsonldVerify(signedJldDocument: {}, publicKeyPem: str) -> bool:
signedJldDocument = deepcopy(signedJldDocument) signedJldDocument = deepcopy(signedJldDocument)
signature = signedJldDocument.pop('signature') signature = signedJldDocument.pop('signature')
jwsSignature = signature['signatureValue'].encode('utf-8') jwsSignature = signature['signatureValue'].encode('utf-8')
normalizedJldHash = jsonldNormalize(signedJldDocument) normalizedJldHash = _jsonldNormalize(signedJldDocument)
return verifyJws(normalizedJldHash, jwsSignature, publicKeyPem) return _verifyJws(normalizedJldHash, jwsSignature, publicKeyPem)
def testSignJsonld(jldDocument: {}, privateKeyPem: str) -> {}: def testSignJsonld(jldDocument: {}, privateKeyPem: str) -> {}:

View File

@ -50,7 +50,7 @@ def noOfLikes(postJsonObject: {}) -> int:
return len(postJsonObject['object']['likes']['items']) return len(postJsonObject['object']['likes']['items'])
def like(recentPostsCache: {}, def _like(recentPostsCache: {},
session, baseDir: str, federationList: [], session, baseDir: str, federationList: [],
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
ccList: [], httpPrefix: str, ccList: [], httpPrefix: str,
@ -134,7 +134,7 @@ def likePost(recentPostsCache: {},
actorLiked = httpPrefix + '://' + likeDomain + '/users/' + likeNickname actorLiked = httpPrefix + '://' + likeDomain + '/users/' + likeNickname
objectUrl = actorLiked + '/statuses/' + str(likeStatusNumber) objectUrl = actorLiked + '/statuses/' + str(likeStatusNumber)
return like(recentPostsCache, return _like(recentPostsCache,
session, baseDir, federationList, nickname, domain, port, session, baseDir, federationList, nickname, domain, port,
ccList, httpPrefix, objectUrl, actorLiked, clientToServer, ccList, httpPrefix, objectUrl, actorLiked, clientToServer,
sendThreads, postLog, personCache, cachedWebfingers, sendThreads, postLog, personCache, cachedWebfingers,

View File

@ -62,7 +62,7 @@ def manualDenyFollowRequest(session, baseDir: str,
print('Follow request from ' + denyHandle + ' was denied.') print('Follow request from ' + denyHandle + ' was denied.')
def approveFollowerHandle(accountDir: str, approveHandle: str) -> None: def _approveFollowerHandle(accountDir: str, approveHandle: str) -> None:
""" Record manually approved handles so that if they unfollow and then """ Record manually approved handles so that if they unfollow and then
re-follow later then they don't need to be manually approved again re-follow later then they don't need to be manually approved again
""" """
@ -203,7 +203,7 @@ def manualApproveFollowRequest(session, baseDir: str,
# in followers.txt # in followers.txt
if approveHandleFull in open(followersFilename).read(): if approveHandleFull in open(followersFilename).read():
# mark this handle as approved for following # mark this handle as approved for following
approveFollowerHandle(accountDir, approveHandle) _approveFollowerHandle(accountDir, approveHandle)
# update the follow requests with the handles not yet approved # update the follow requests with the handles not yet approved
os.rename(approveFollowsFilename + '.new', approveFollowsFilename) os.rename(approveFollowsFilename + '.new', approveFollowsFilename)
# remove the .follow file # remove the .follow file

View File

@ -56,12 +56,12 @@ def removeMetaData(imageFilename: str, outputFilename: str) -> None:
os.system('/usr/bin/mogrify -strip ' + outputFilename) # nosec os.system('/usr/bin/mogrify -strip ' + outputFilename) # nosec
def getImageHash(imageFilename: str) -> str: def _getImageHash(imageFilename: str) -> str:
value = numpy.array(Image.open(imageFilename).convert("RGB")) value = numpy.array(Image.open(imageFilename).convert("RGB"))
return blurhash_encode(value) return blurhash_encode(value)
def isMedia(imageFilename: str) -> bool: def _isMedia(imageFilename: str) -> bool:
permittedMedia = getMediaExtensions() permittedMedia = getMediaExtensions()
for m in permittedMedia: for m in permittedMedia:
if imageFilename.endswith('.' + m): if imageFilename.endswith('.' + m):
@ -103,7 +103,7 @@ def getAttachmentMediaType(filename: str) -> str:
return mediaType return mediaType
def updateEtag(mediaFilename: str) -> None: def _updateEtag(mediaFilename: str) -> None:
""" calculate the etag, which is a sha1 of the data """ calculate the etag, which is a sha1 of the data
""" """
# only create etags for media # only create etags for media
@ -143,7 +143,7 @@ def attachMedia(baseDir: str, httpPrefix: str, domain: str, port: int,
Blurhash is optional, since low power systems may take a long Blurhash is optional, since low power systems may take a long
time to calculate it time to calculate it
""" """
if not isMedia(imageFilename): if not _isMedia(imageFilename):
return postJson return postJson
fileExtension = None fileExtension = None
@ -182,7 +182,7 @@ def attachMedia(baseDir: str, httpPrefix: str, domain: str, port: int,
if mediaType.startswith('image/'): if mediaType.startswith('image/'):
attachmentJson['focialPoint'] = [0.0, 0.0] attachmentJson['focialPoint'] = [0.0, 0.0]
if useBlurhash: if useBlurhash:
attachmentJson['blurhash'] = getImageHash(imageFilename) attachmentJson['blurhash'] = _getImageHash(imageFilename)
postJson['attachment'] = [attachmentJson] postJson['attachment'] = [attachmentJson]
if baseDir: if baseDir:
@ -190,7 +190,7 @@ def attachMedia(baseDir: str, httpPrefix: str, domain: str, port: int,
removeMetaData(imageFilename, mediaFilename) removeMetaData(imageFilename, mediaFilename)
else: else:
copyfile(imageFilename, mediaFilename) copyfile(imageFilename, mediaFilename)
updateEtag(mediaFilename) _updateEtag(mediaFilename)
return postJson return postJson

View File

@ -9,7 +9,7 @@ __status__ = "Production"
import os import os
def migrateFollows(followFilename: str, oldHandle: str, def _migrateFollows(followFilename: str, oldHandle: str,
newHandle: str) -> None: newHandle: str) -> None:
"""Changes a handle within following or followers list """Changes a handle within following or followers list
""" """
@ -48,7 +48,7 @@ def migrateAccount(baseDir: str, oldHandle: str, newHandle: str) -> None:
if '@' in handle: if '@' in handle:
accountDir = baseDir + '/accounts/' + handle accountDir = baseDir + '/accounts/' + handle
followFilename = accountDir + '/following.txt' followFilename = accountDir + '/following.txt'
migrateFollows(followFilename, oldHandle, newHandle) _migrateFollows(followFilename, oldHandle, newHandle)
followFilename = accountDir + '/followers.txt' followFilename = accountDir + '/followers.txt'
migrateFollows(followFilename, oldHandle, newHandle) _migrateFollows(followFilename, oldHandle, newHandle)
break break

View File

@ -35,7 +35,7 @@ from inbox import storeHashTags
from session import createSession from session import createSession
def updateFeedsOutboxIndex(baseDir: str, domain: str, postId: str) -> None: def _updateFeedsOutboxIndex(baseDir: str, domain: str, postId: str) -> None:
"""Updates the index used for imported RSS feeds """Updates the index used for imported RSS feeds
""" """
basePath = baseDir + '/accounts/news@' + domain basePath = baseDir + '/accounts/news@' + domain
@ -59,7 +59,7 @@ def updateFeedsOutboxIndex(baseDir: str, domain: str, postId: str) -> None:
feedsFile.close() feedsFile.close()
def saveArrivedTime(baseDir: str, postFilename: str, arrived: str) -> None: def _saveArrivedTime(baseDir: str, postFilename: str, arrived: str) -> None:
"""Saves the time when an rss post arrived to a file """Saves the time when an rss post arrived to a file
""" """
arrivedFile = open(postFilename + '.arrived', 'w+') arrivedFile = open(postFilename + '.arrived', 'w+')
@ -68,7 +68,7 @@ def saveArrivedTime(baseDir: str, postFilename: str, arrived: str) -> None:
arrivedFile.close() arrivedFile.close()
def removeControlCharacters(content: str) -> str: def _removeControlCharacters(content: str) -> str:
"""Remove escaped html """Remove escaped html
""" """
if '&' in content: if '&' in content:
@ -227,7 +227,7 @@ def hashtagRuleTree(operators: [],
return tree return tree
def newswireHashtagProcessing(session, baseDir: str, postJsonObject: {}, def _newswireHashtagProcessing(session, baseDir: str, postJsonObject: {},
hashtags: [], httpPrefix: str, hashtags: [], httpPrefix: str,
domain: str, port: int, domain: str, port: int,
personCache: {}, personCache: {},
@ -356,7 +356,7 @@ def newswireHashtagProcessing(session, baseDir: str, postJsonObject: {},
return True return True
def createNewsMirror(baseDir: str, domain: str, def _createNewsMirror(baseDir: str, domain: str,
postIdNumber: str, url: str, postIdNumber: str, url: str,
maxMirroredArticles: int) -> bool: maxMirroredArticles: int) -> bool:
"""Creates a local mirror of a news article """Creates a local mirror of a news article
@ -446,7 +446,7 @@ def createNewsMirror(baseDir: str, domain: str,
return True return True
def convertRSStoActivityPub(baseDir: str, httpPrefix: str, def _convertRSStoActivityPub(baseDir: str, httpPrefix: str,
domain: str, port: int, domain: str, port: int,
newswire: {}, newswire: {},
translate: {}, translate: {},
@ -497,7 +497,7 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
newswire[originalDateStr][3] = filename newswire[originalDateStr][3] = filename
continue continue
rssTitle = removeControlCharacters(item[0]) rssTitle = _removeControlCharacters(item[0])
url = item[1] url = item[1]
if dangerousMarkup(url, allowLocalNetworkAccess) or \ if dangerousMarkup(url, allowLocalNetworkAccess) or \
dangerousMarkup(rssTitle, allowLocalNetworkAccess): dangerousMarkup(rssTitle, allowLocalNetworkAccess):
@ -505,7 +505,7 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
rssDescription = '' rssDescription = ''
# get the rss description if it exists # get the rss description if it exists
rssDescription = removeControlCharacters(item[4]) rssDescription = _removeControlCharacters(item[4])
if rssDescription.startswith('<![CDATA['): if rssDescription.startswith('<![CDATA['):
rssDescription = rssDescription.replace('<![CDATA[', '') rssDescription = rssDescription.replace('<![CDATA[', '')
rssDescription = rssDescription.replace(']]>', '') rssDescription = rssDescription.replace(']]>', '')
@ -555,7 +555,7 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
continue continue
if mirrored: if mirrored:
if not createNewsMirror(baseDir, domain, statusNumber, if not _createNewsMirror(baseDir, domain, statusNumber,
url, maxMirroredArticles): url, maxMirroredArticles):
continue continue
@ -590,7 +590,7 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
moderated = item[5] moderated = item[5]
savePost = newswireHashtagProcessing(session, baseDir, blog, hashtags, savePost = _newswireHashtagProcessing(session, baseDir, blog, hashtags,
httpPrefix, domain, port, httpPrefix, domain, port,
personCache, cachedWebfingers, personCache, cachedWebfingers,
federationList, federationList,
@ -628,7 +628,7 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
blog['object']['content'] = content blog['object']['content'] = content
# update the newswire tags if new ones have been found by # update the newswire tags if new ones have been found by
# newswireHashtagProcessing # _newswireHashtagProcessing
for tag in hashtags: for tag in hashtags:
if tag not in newswire[originalDateStr][6]: if tag not in newswire[originalDateStr][6]:
newswire[originalDateStr][6].append(tag) newswire[originalDateStr][6].append(tag)
@ -637,13 +637,13 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
clearFromPostCaches(baseDir, recentPostsCache, postId) clearFromPostCaches(baseDir, recentPostsCache, postId)
if saveJson(blog, filename): if saveJson(blog, filename):
updateFeedsOutboxIndex(baseDir, domain, postId + '.json') _updateFeedsOutboxIndex(baseDir, domain, postId + '.json')
# Save a file containing the time when the post arrived # Save a file containing the time when the post arrived
# this can then later be used to construct the news timeline # this can then later be used to construct the news timeline
# excluding items during the voting period # excluding items during the voting period
if moderated: if moderated:
saveArrivedTime(baseDir, filename, _saveArrivedTime(baseDir, filename,
blog['object']['arrived']) blog['object']['arrived'])
else: else:
if os.path.isfile(filename + '.arrived'): if os.path.isfile(filename + '.arrived'):
@ -658,7 +658,7 @@ def convertRSStoActivityPub(baseDir: str, httpPrefix: str,
newswire[originalDateStr][3] = filename newswire[originalDateStr][3] = filename
def mergeWithPreviousNewswire(oldNewswire: {}, newNewswire: {}) -> None: def _mergeWithPreviousNewswire(oldNewswire: {}, newNewswire: {}) -> None:
"""Preserve any votes or generated activitypub post filename """Preserve any votes or generated activitypub post filename
as rss feeds are updated as rss feeds are updated
""" """
@ -707,14 +707,14 @@ def runNewswireDaemon(baseDir: str, httpd,
if os.path.isfile(newswireStateFilename): if os.path.isfile(newswireStateFilename):
httpd.newswire = loadJson(newswireStateFilename) httpd.newswire = loadJson(newswireStateFilename)
mergeWithPreviousNewswire(httpd.newswire, newNewswire) _mergeWithPreviousNewswire(httpd.newswire, newNewswire)
httpd.newswire = newNewswire httpd.newswire = newNewswire
if newNewswire: if newNewswire:
saveJson(httpd.newswire, newswireStateFilename) saveJson(httpd.newswire, newswireStateFilename)
print('Newswire updated') print('Newswire updated')
convertRSStoActivityPub(baseDir, _convertRSStoActivityPub(baseDir,
httpPrefix, domain, port, httpPrefix, domain, port,
newNewswire, translate, newNewswire, translate,
httpd.recentPostsCache, httpd.recentPostsCache,

View File

@ -29,7 +29,7 @@ from blocking import isBlockedHashtag
from filters import isFiltered from filters import isFiltered
def removeCDATA(text: str) -> str: def _removeCDATA(text: str) -> str:
"""Removes any CDATA from the given text """Removes any CDATA from the given text
""" """
if 'CDATA[' in text: if 'CDATA[' in text:
@ -95,7 +95,7 @@ def getNewswireTags(text: str, maxTags: int) -> []:
return tags return tags
def addNewswireDictEntry(baseDir: str, domain: str, def _addNewswireDictEntry(baseDir: str, domain: str,
newswire: {}, dateStr: str, newswire: {}, dateStr: str,
title: str, link: str, title: str, link: str,
votesStatus: str, postFilename: str, votesStatus: str, postFilename: str,
@ -143,7 +143,7 @@ def addNewswireDictEntry(baseDir: str, domain: str,
] ]
def validFeedDate(pubDate: str) -> bool: def _validFeedDate(pubDate: str) -> bool:
# convert from YY-MM-DD HH:MM:SS+00:00 to # convert from YY-MM-DD HH:MM:SS+00:00 to
# YY-MM-DDTHH:MM:SSZ # YY-MM-DDTHH:MM:SSZ
postDate = pubDate.replace(' ', 'T').replace('+00:00', 'Z') postDate = pubDate.replace(' ', 'T').replace('+00:00', 'Z')
@ -219,10 +219,10 @@ def loadHashtagCategories(baseDir: str, language: str) -> None:
with open(hashtagCategoriesFilename, 'r') as fp: with open(hashtagCategoriesFilename, 'r') as fp:
xmlStr = fp.read() xmlStr = fp.read()
xml2StrToHashtagCategories(baseDir, xmlStr, 1024, True) _xml2StrToHashtagCategories(baseDir, xmlStr, 1024, True)
def xml2StrToHashtagCategories(baseDir: str, xmlStr: str, def _xml2StrToHashtagCategories(baseDir: str, xmlStr: str,
maxCategoriesFeedItemSizeKb: int, maxCategoriesFeedItemSizeKb: int,
force=False) -> None: force=False) -> None:
"""Updates hashtag categories based upon an rss feed """Updates hashtag categories based upon an rss feed
@ -261,7 +261,7 @@ def xml2StrToHashtagCategories(baseDir: str, xmlStr: str,
setHashtagCategory(baseDir, hashtag, categoryStr, force) setHashtagCategory(baseDir, hashtag, categoryStr, force)
def xml2StrToDict(baseDir: str, domain: str, xmlStr: str, def _xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
moderated: bool, mirrored: bool, moderated: bool, mirrored: bool,
maxPostsPerSource: int, maxPostsPerSource: int,
maxFeedItemSizeKb: int, maxFeedItemSizeKb: int,
@ -274,7 +274,7 @@ def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
# is this an rss feed containing hashtag categories? # is this an rss feed containing hashtag categories?
if '<title>#categories</title>' in xmlStr: if '<title>#categories</title>' in xmlStr:
xml2StrToHashtagCategories(baseDir, xmlStr, _xml2StrToHashtagCategories(baseDir, xmlStr,
maxCategoriesFeedItemSizeKb) maxCategoriesFeedItemSizeKb)
return {} return {}
@ -300,17 +300,17 @@ def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
if '</pubDate>' not in rssItem: if '</pubDate>' not in rssItem:
continue continue
title = rssItem.split('<title>')[1] title = rssItem.split('<title>')[1]
title = removeCDATA(title.split('</title>')[0]) title = _removeCDATA(title.split('</title>')[0])
description = '' description = ''
if '<description>' in rssItem and '</description>' in rssItem: if '<description>' in rssItem and '</description>' in rssItem:
description = rssItem.split('<description>')[1] description = rssItem.split('<description>')[1]
description = removeCDATA(description.split('</description>')[0]) description = _removeCDATA(description.split('</description>')[0])
else: else:
if '<media:description>' in rssItem and \ if '<media:description>' in rssItem and \
'</media:description>' in rssItem: '</media:description>' in rssItem:
description = rssItem.split('<media:description>')[1] description = rssItem.split('<media:description>')[1]
description = description.split('</media:description>')[0] description = description.split('</media:description>')[0]
description = removeCDATA(description) description = _removeCDATA(description)
link = rssItem.split('<link>')[1] link = rssItem.split('<link>')[1]
link = link.split('</link>')[0] link = link.split('</link>')[0]
if '://' not in link: if '://' not in link:
@ -325,10 +325,10 @@ def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
pubDateStr = parseFeedDate(pubDate) pubDateStr = parseFeedDate(pubDate)
if pubDateStr: if pubDateStr:
if validFeedDate(pubDateStr): if _validFeedDate(pubDateStr):
postFilename = '' postFilename = ''
votesStatus = [] votesStatus = []
addNewswireDictEntry(baseDir, domain, _addNewswireDictEntry(baseDir, domain,
result, pubDateStr, result, pubDateStr,
title, link, title, link,
votesStatus, postFilename, votesStatus, postFilename,
@ -341,7 +341,7 @@ def xml2StrToDict(baseDir: str, domain: str, xmlStr: str,
return result return result
def xml1StrToDict(baseDir: str, domain: str, xmlStr: str, def _xml1StrToDict(baseDir: str, domain: str, xmlStr: str,
moderated: bool, mirrored: bool, moderated: bool, mirrored: bool,
maxPostsPerSource: int, maxPostsPerSource: int,
maxFeedItemSizeKb: int, maxFeedItemSizeKb: int,
@ -356,7 +356,7 @@ def xml1StrToDict(baseDir: str, domain: str, xmlStr: str,
# is this an rss feed containing hashtag categories? # is this an rss feed containing hashtag categories?
if '<title>#categories</title>' in xmlStr: if '<title>#categories</title>' in xmlStr:
xml2StrToHashtagCategories(baseDir, xmlStr, _xml2StrToHashtagCategories(baseDir, xmlStr,
maxCategoriesFeedItemSizeKb) maxCategoriesFeedItemSizeKb)
return {} return {}
@ -384,17 +384,17 @@ def xml1StrToDict(baseDir: str, domain: str, xmlStr: str,
if '</dc:date>' not in rssItem: if '</dc:date>' not in rssItem:
continue continue
title = rssItem.split('<title>')[1] title = rssItem.split('<title>')[1]
title = removeCDATA(title.split('</title>')[0]) title = _removeCDATA(title.split('</title>')[0])
description = '' description = ''
if '<description>' in rssItem and '</description>' in rssItem: if '<description>' in rssItem and '</description>' in rssItem:
description = rssItem.split('<description>')[1] description = rssItem.split('<description>')[1]
description = removeCDATA(description.split('</description>')[0]) description = _removeCDATA(description.split('</description>')[0])
else: else:
if '<media:description>' in rssItem and \ if '<media:description>' in rssItem and \
'</media:description>' in rssItem: '</media:description>' in rssItem:
description = rssItem.split('<media:description>')[1] description = rssItem.split('<media:description>')[1]
description = description.split('</media:description>')[0] description = description.split('</media:description>')[0]
description = removeCDATA(description) description = _removeCDATA(description)
link = rssItem.split('<link>')[1] link = rssItem.split('<link>')[1]
link = link.split('</link>')[0] link = link.split('</link>')[0]
if '://' not in link: if '://' not in link:
@ -409,10 +409,10 @@ def xml1StrToDict(baseDir: str, domain: str, xmlStr: str,
pubDateStr = parseFeedDate(pubDate) pubDateStr = parseFeedDate(pubDate)
if pubDateStr: if pubDateStr:
if validFeedDate(pubDateStr): if _validFeedDate(pubDateStr):
postFilename = '' postFilename = ''
votesStatus = [] votesStatus = []
addNewswireDictEntry(baseDir, domain, _addNewswireDictEntry(baseDir, domain,
result, pubDateStr, result, pubDateStr,
title, link, title, link,
votesStatus, postFilename, votesStatus, postFilename,
@ -425,7 +425,7 @@ def xml1StrToDict(baseDir: str, domain: str, xmlStr: str,
return result return result
def atomFeedToDict(baseDir: str, domain: str, xmlStr: str, def _atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
moderated: bool, mirrored: bool, moderated: bool, mirrored: bool,
maxPostsPerSource: int, maxPostsPerSource: int,
maxFeedItemSizeKb: int) -> {}: maxFeedItemSizeKb: int) -> {}:
@ -456,17 +456,17 @@ def atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
if '</updated>' not in atomItem: if '</updated>' not in atomItem:
continue continue
title = atomItem.split('<title>')[1] title = atomItem.split('<title>')[1]
title = removeCDATA(title.split('</title>')[0]) title = _removeCDATA(title.split('</title>')[0])
description = '' description = ''
if '<summary>' in atomItem and '</summary>' in atomItem: if '<summary>' in atomItem and '</summary>' in atomItem:
description = atomItem.split('<summary>')[1] description = atomItem.split('<summary>')[1]
description = removeCDATA(description.split('</summary>')[0]) description = _removeCDATA(description.split('</summary>')[0])
else: else:
if '<media:description>' in atomItem and \ if '<media:description>' in atomItem and \
'</media:description>' in atomItem: '</media:description>' in atomItem:
description = atomItem.split('<media:description>')[1] description = atomItem.split('<media:description>')[1]
description = description.split('</media:description>')[0] description = description.split('</media:description>')[0]
description = removeCDATA(description) description = _removeCDATA(description)
link = atomItem.split('<link>')[1] link = atomItem.split('<link>')[1]
link = link.split('</link>')[0] link = link.split('</link>')[0]
if '://' not in link: if '://' not in link:
@ -481,10 +481,10 @@ def atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
pubDateStr = parseFeedDate(pubDate) pubDateStr = parseFeedDate(pubDate)
if pubDateStr: if pubDateStr:
if validFeedDate(pubDateStr): if _validFeedDate(pubDateStr):
postFilename = '' postFilename = ''
votesStatus = [] votesStatus = []
addNewswireDictEntry(baseDir, domain, _addNewswireDictEntry(baseDir, domain,
result, pubDateStr, result, pubDateStr,
title, link, title, link,
votesStatus, postFilename, votesStatus, postFilename,
@ -497,7 +497,7 @@ def atomFeedToDict(baseDir: str, domain: str, xmlStr: str,
return result return result
def atomFeedYTToDict(baseDir: str, domain: str, xmlStr: str, def _atomFeedYTToDict(baseDir: str, domain: str, xmlStr: str,
moderated: bool, mirrored: bool, moderated: bool, mirrored: bool,
maxPostsPerSource: int, maxPostsPerSource: int,
maxFeedItemSizeKb: int) -> {}: maxFeedItemSizeKb: int) -> {}:
@ -532,17 +532,17 @@ def atomFeedYTToDict(baseDir: str, domain: str, xmlStr: str,
if '</yt:videoId>' not in atomItem: if '</yt:videoId>' not in atomItem:
continue continue
title = atomItem.split('<title>')[1] title = atomItem.split('<title>')[1]
title = removeCDATA(title.split('</title>')[0]) title = _removeCDATA(title.split('</title>')[0])
description = '' description = ''
if '<media:description>' in atomItem and \ if '<media:description>' in atomItem and \
'</media:description>' in atomItem: '</media:description>' in atomItem:
description = atomItem.split('<media:description>')[1] description = atomItem.split('<media:description>')[1]
description = description.split('</media:description>')[0] description = description.split('</media:description>')[0]
description = removeCDATA(description) description = _removeCDATA(description)
elif '<summary>' in atomItem and '</summary>' in atomItem: elif '<summary>' in atomItem and '</summary>' in atomItem:
description = atomItem.split('<summary>')[1] description = atomItem.split('<summary>')[1]
description = description.split('</summary>')[0] description = description.split('</summary>')[0]
description = removeCDATA(description) description = _removeCDATA(description)
link = atomItem.split('<yt:videoId>')[1] link = atomItem.split('<yt:videoId>')[1]
link = link.split('</yt:videoId>')[0] link = link.split('</yt:videoId>')[0]
link = 'https://www.youtube.com/watch?v=' + link.strip() link = 'https://www.youtube.com/watch?v=' + link.strip()
@ -551,10 +551,10 @@ def atomFeedYTToDict(baseDir: str, domain: str, xmlStr: str,
pubDateStr = parseFeedDate(pubDate) pubDateStr = parseFeedDate(pubDate)
if pubDateStr: if pubDateStr:
if validFeedDate(pubDateStr): if _validFeedDate(pubDateStr):
postFilename = '' postFilename = ''
votesStatus = [] votesStatus = []
addNewswireDictEntry(baseDir, domain, _addNewswireDictEntry(baseDir, domain,
result, pubDateStr, result, pubDateStr,
title, link, title, link,
votesStatus, postFilename, votesStatus, postFilename,
@ -567,7 +567,7 @@ def atomFeedYTToDict(baseDir: str, domain: str, xmlStr: str,
return result return result
def xmlStrToDict(baseDir: str, domain: str, xmlStr: str, def _xmlStrToDict(baseDir: str, domain: str, xmlStr: str,
moderated: bool, mirrored: bool, moderated: bool, mirrored: bool,
maxPostsPerSource: int, maxPostsPerSource: int,
maxFeedItemSizeKb: int, maxFeedItemSizeKb: int,
@ -576,27 +576,27 @@ def xmlStrToDict(baseDir: str, domain: str, xmlStr: str,
""" """
if '<yt:videoId>' in xmlStr and '<yt:channelId>' in xmlStr: if '<yt:videoId>' in xmlStr and '<yt:channelId>' in xmlStr:
print('YouTube feed: reading') print('YouTube feed: reading')
return atomFeedYTToDict(baseDir, domain, return _atomFeedYTToDict(baseDir, domain,
xmlStr, moderated, mirrored, xmlStr, moderated, mirrored,
maxPostsPerSource, maxFeedItemSizeKb) maxPostsPerSource, maxFeedItemSizeKb)
elif 'rss version="2.0"' in xmlStr: elif 'rss version="2.0"' in xmlStr:
return xml2StrToDict(baseDir, domain, return _xml2StrToDict(baseDir, domain,
xmlStr, moderated, mirrored, xmlStr, moderated, mirrored,
maxPostsPerSource, maxFeedItemSizeKb, maxPostsPerSource, maxFeedItemSizeKb,
maxCategoriesFeedItemSizeKb) maxCategoriesFeedItemSizeKb)
elif '<?xml version="1.0"' in xmlStr: elif '<?xml version="1.0"' in xmlStr:
return xml1StrToDict(baseDir, domain, return _xml1StrToDict(baseDir, domain,
xmlStr, moderated, mirrored, xmlStr, moderated, mirrored,
maxPostsPerSource, maxFeedItemSizeKb, maxPostsPerSource, maxFeedItemSizeKb,
maxCategoriesFeedItemSizeKb) maxCategoriesFeedItemSizeKb)
elif 'xmlns="http://www.w3.org/2005/Atom"' in xmlStr: elif 'xmlns="http://www.w3.org/2005/Atom"' in xmlStr:
return atomFeedToDict(baseDir, domain, return _atomFeedToDict(baseDir, domain,
xmlStr, moderated, mirrored, xmlStr, moderated, mirrored,
maxPostsPerSource, maxFeedItemSizeKb) maxPostsPerSource, maxFeedItemSizeKb)
return {} return {}
def YTchannelToAtomFeed(url: str) -> str: def _YTchannelToAtomFeed(url: str) -> str:
"""Converts a YouTube channel url into an atom feed url """Converts a YouTube channel url into an atom feed url
""" """
if 'youtube.com/channel/' not in url: if 'youtube.com/channel/' not in url:
@ -633,13 +633,13 @@ def getRSS(baseDir: str, domain: str, session, url: str,
'Mozilla/5.0 (X11; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0' 'Mozilla/5.0 (X11; Linux x86_64; rv:81.0) Gecko/20100101 Firefox/81.0'
if not session: if not session:
print('WARN: no session specified for getRSS') print('WARN: no session specified for getRSS')
url = YTchannelToAtomFeed(url) url = _YTchannelToAtomFeed(url)
try: try:
result = session.get(url, headers=sessionHeaders, params=sessionParams) result = session.get(url, headers=sessionHeaders, params=sessionParams)
if result: if result:
if int(len(result.text) / 1024) < maxFeedSizeKb and \ if int(len(result.text) / 1024) < maxFeedSizeKb and \
not containsInvalidChars(result.text): not containsInvalidChars(result.text):
return xmlStrToDict(baseDir, domain, result.text, return _xmlStrToDict(baseDir, domain, result.text,
moderated, mirrored, moderated, mirrored,
maxPostsPerSource, maxPostsPerSource,
maxFeedItemSizeKb, maxFeedItemSizeKb,
@ -692,7 +692,7 @@ def getRSSfromDict(baseDir: str, newswire: {},
continue continue
rssStr += '<item>\n' rssStr += '<item>\n'
rssStr += ' <title>' + fields[0] + '</title>\n' rssStr += ' <title>' + fields[0] + '</title>\n'
description = removeCDATA(firstParagraphFromString(fields[4])) description = _removeCDATA(firstParagraphFromString(fields[4]))
rssStr += ' <description>' + description + '</description>\n' rssStr += ' <description>' + description + '</description>\n'
url = fields[1] url = fields[1]
if '://' not in url: if '://' not in url:
@ -707,7 +707,7 @@ def getRSSfromDict(baseDir: str, newswire: {},
return rssStr return rssStr
def isNewswireBlogPost(postJsonObject: {}) -> bool: def _isNewswireBlogPost(postJsonObject: {}) -> bool:
"""Is the given object a blog post? """Is the given object a blog post?
There isn't any difference between a blog post and a newswire blog post There isn't any difference between a blog post and a newswire blog post
but we may here need to check for different properties than but we may here need to check for different properties than
@ -727,7 +727,7 @@ def isNewswireBlogPost(postJsonObject: {}) -> bool:
return False return False
def getHashtagsFromPost(postJsonObject: {}) -> []: def _getHashtagsFromPost(postJsonObject: {}) -> []:
"""Returns a list of any hashtags within a post """Returns a list of any hashtags within a post
""" """
if not postJsonObject.get('object'): if not postJsonObject.get('object'):
@ -753,7 +753,7 @@ def getHashtagsFromPost(postJsonObject: {}) -> []:
return tags return tags
def addAccountBlogsToNewswire(baseDir: str, nickname: str, domain: str, def _addAccountBlogsToNewswire(baseDir: str, nickname: str, domain: str,
newswire: {}, newswire: {},
maxBlogsPerAccount: int, maxBlogsPerAccount: int,
indexFilename: str, indexFilename: str,
@ -803,7 +803,7 @@ def addAccountBlogsToNewswire(baseDir: str, nickname: str, domain: str,
postJsonObject = None postJsonObject = None
if fullPostFilename: if fullPostFilename:
postJsonObject = loadJson(fullPostFilename) postJsonObject = loadJson(fullPostFilename)
if isNewswireBlogPost(postJsonObject): if _isNewswireBlogPost(postJsonObject):
published = postJsonObject['object']['published'] published = postJsonObject['object']['published']
published = published.replace('T', ' ') published = published.replace('T', ' ')
published = published.replace('Z', '+00:00') published = published.replace('Z', '+00:00')
@ -812,14 +812,14 @@ def addAccountBlogsToNewswire(baseDir: str, nickname: str, domain: str,
votes = loadJson(fullPostFilename + '.votes') votes = loadJson(fullPostFilename + '.votes')
content = postJsonObject['object']['content'] content = postJsonObject['object']['content']
description = firstParagraphFromString(content) description = firstParagraphFromString(content)
description = removeCDATA(description) description = _removeCDATA(description)
addNewswireDictEntry(baseDir, domain, _addNewswireDictEntry(baseDir, domain,
newswire, published, newswire, published,
postJsonObject['object']['summary'], postJsonObject['object']['summary'],
postJsonObject['object']['url'], postJsonObject['object']['url'],
votes, fullPostFilename, votes, fullPostFilename,
description, moderated, False, description, moderated, False,
getHashtagsFromPost(postJsonObject), _getHashtagsFromPost(postJsonObject),
maxTags) maxTags)
ctr += 1 ctr += 1
@ -827,7 +827,7 @@ def addAccountBlogsToNewswire(baseDir: str, nickname: str, domain: str,
break break
def addBlogsToNewswire(baseDir: str, domain: str, newswire: {}, def _addBlogsToNewswire(baseDir: str, domain: str, newswire: {},
maxBlogsPerAccount: int, maxBlogsPerAccount: int,
maxTags: int) -> None: maxTags: int) -> None:
"""Adds blogs from each user account into the newswire """Adds blogs from each user account into the newswire
@ -857,7 +857,7 @@ def addBlogsToNewswire(baseDir: str, domain: str, newswire: {},
blogsIndex = accountDir + '/tlblogs.index' blogsIndex = accountDir + '/tlblogs.index'
if os.path.isfile(blogsIndex): if os.path.isfile(blogsIndex):
domain = handle.split('@')[1] domain = handle.split('@')[1]
addAccountBlogsToNewswire(baseDir, nickname, domain, _addAccountBlogsToNewswire(baseDir, nickname, domain,
newswire, maxBlogsPerAccount, newswire, maxBlogsPerAccount,
blogsIndex, maxTags) blogsIndex, maxTags)
break break
@ -926,7 +926,7 @@ def getDictFromNewswire(session, baseDir: str, domain: str,
result[dateStr] = item result[dateStr] = item
# add blogs from each user account # add blogs from each user account
addBlogsToNewswire(baseDir, domain, result, _addBlogsToNewswire(baseDir, domain, result,
maxPostsPerSource, maxTags) maxPostsPerSource, maxTags)
# sort into chronological order, latest first # sort into chronological order, latest first

View File

@ -134,7 +134,7 @@ def setOrganizationScheme(baseDir: str, nickname: str, domain: str,
return True return True
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: if ':' in domain:
@ -201,7 +201,7 @@ def getDefaultPersonContext() -> str:
} }
def createPersonBase(baseDir: str, nickname: str, domain: str, port: int, def _createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
httpPrefix: str, saveToFile: bool, httpPrefix: str, saveToFile: bool,
manualFollowerApproval: bool, manualFollowerApproval: bool,
password=None) -> (str, str, {}, {}): password=None) -> (str, str, {}, {}):
@ -377,7 +377,7 @@ def registerAccount(baseDir: str, httpPrefix: str, domain: str, port: int,
manualFollowerApproval: bool) -> bool: manualFollowerApproval: bool) -> bool:
"""Registers a new account from the web interface """Registers a new account from the web interface
""" """
if accountExists(baseDir, nickname, domain): if _accountExists(baseDir, nickname, domain):
return False return False
if not validNickname(domain, nickname): if not validNickname(domain, nickname):
print('REGISTER: Nickname ' + nickname + ' is invalid') print('REGISTER: Nickname ' + nickname + ' is invalid')
@ -449,7 +449,7 @@ def createPerson(baseDir: str, nickname: str, domain: str, port: int,
return None, None, None, None return None, None, None, None
(privateKeyPem, publicKeyPem, (privateKeyPem, publicKeyPem,
newPerson, webfingerEndpoint) = createPersonBase(baseDir, nickname, newPerson, webfingerEndpoint) = _createPersonBase(baseDir, nickname,
domain, port, domain, port,
httpPrefix, httpPrefix,
saveToFile, saveToFile,
@ -525,7 +525,7 @@ def createSharedInbox(baseDir: str, nickname: str, domain: str, port: int,
httpPrefix: str) -> (str, str, {}, {}): httpPrefix: str) -> (str, str, {}, {}):
"""Generates the shared inbox """Generates the shared inbox
""" """
return createPersonBase(baseDir, nickname, domain, port, httpPrefix, return _createPersonBase(baseDir, nickname, domain, port, httpPrefix,
True, True, None) True, True, None)
@ -845,7 +845,7 @@ def canRemovePost(baseDir: str, nickname: str,
return True return True
def removeTagsForNickname(baseDir: str, nickname: str, def _removeTagsForNickname(baseDir: str, nickname: str,
domain: str, port: int) -> None: domain: str, port: int) -> None:
"""Removes tags for a nickname """Removes tags for a nickname
""" """
@ -900,7 +900,7 @@ def removeAccount(baseDir: str, nickname: str,
unsuspendAccount(baseDir, nickname) unsuspendAccount(baseDir, nickname)
handle = nickname + '@' + domain handle = nickname + '@' + domain
removePassword(baseDir, nickname) removePassword(baseDir, nickname)
removeTagsForNickname(baseDir, nickname, domain, port) _removeTagsForNickname(baseDir, nickname, domain, port)
if os.path.isdir(baseDir + '/deactivated/' + handle): if os.path.isdir(baseDir + '/deactivated/' + handle):
shutil.rmtree(baseDir + '/deactivated/' + handle) shutil.rmtree(baseDir + '/deactivated/' + handle)
if os.path.isdir(baseDir + '/accounts/' + handle): if os.path.isdir(baseDir + '/accounts/' + handle):

View File

@ -77,7 +77,7 @@ def getPetName(baseDir: str, nickname: str, domain: str,
return '' return ''
def getPetNameHandle(baseDir: str, nickname: str, domain: str, def _getPetNameHandle(baseDir: str, nickname: str, domain: str,
petname: str) -> str: petname: str) -> str:
"""Given a petname returns the handle """Given a petname returns the handle
""" """
@ -113,7 +113,7 @@ def resolvePetnames(baseDir: str, nickname: str, domain: str,
if not wrd.startswith('@'): if not wrd.startswith('@'):
break break
# does a petname handle exist for this? # does a petname handle exist for this?
handle = getPetNameHandle(baseDir, nickname, domain, wrd) handle = _getPetNameHandle(baseDir, nickname, domain, wrd)
if not handle: if not handle:
continue continue
# replace the petname with the handle # replace the petname with the handle

147
posts.py
View File

@ -116,7 +116,7 @@ def noOfFollowersOnDomain(baseDir: str, handle: str,
return ctr return ctr
def getPersonKey(nickname: str, domain: str, baseDir: str, keyType='public', def _getPersonKey(nickname: str, domain: str, baseDir: str, keyType='public',
debug=False): debug=False):
"""Returns the public or private key of a person """Returns the public or private key of a person
""" """
@ -136,7 +136,7 @@ def getPersonKey(nickname: str, domain: str, baseDir: str, keyType='public',
return keyPem return keyPem
def cleanHtml(rawHtml: str) -> str: def _cleanHtml(rawHtml: str) -> str:
# text=BeautifulSoup(rawHtml, 'html.parser').get_text() # text=BeautifulSoup(rawHtml, 'html.parser').get_text()
text = rawHtml text = rawHtml
return html.unescape(text) return html.unescape(text)
@ -288,7 +288,7 @@ def getPersonBox(baseDir: str, session, wfRequest: {},
avatarUrl, displayName avatarUrl, displayName
def getPosts(session, outboxUrl: str, maxPosts: int, def _getPosts(session, outboxUrl: str, maxPosts: int,
maxMentions: int, maxMentions: int,
maxEmoji: int, maxAttachments: int, maxEmoji: int, maxAttachments: int,
federationList: [], federationList: [],
@ -445,7 +445,7 @@ def getPosts(session, outboxUrl: str, maxPosts: int,
sensitive = item['object']['sensitive'] sensitive = item['object']['sensitive']
if simple: if simple:
print(cleanHtml(content) + '\n') print(_cleanHtml(content) + '\n')
else: else:
pprint(item) pprint(item)
personPosts[item['id']] = { personPosts[item['id']] = {
@ -453,7 +453,7 @@ def getPosts(session, outboxUrl: str, maxPosts: int,
"inreplyto": inReplyTo, "inreplyto": inReplyTo,
"summary": summary, "summary": summary,
"html": content, "html": content,
"plaintext": cleanHtml(content), "plaintext": _cleanHtml(content),
"attachment": attachment, "attachment": attachment,
"mentions": mentions, "mentions": mentions,
"emoji": emoji, "emoji": emoji,
@ -519,7 +519,7 @@ def getPostDomains(session, outboxUrl: str, maxPosts: int,
return postDomains return postDomains
def getPostsForBlockedDomains(baseDir: str, def _getPostsForBlockedDomains(baseDir: str,
session, outboxUrl: str, maxPosts: int, session, outboxUrl: str, maxPosts: int,
maxMentions: int, maxMentions: int,
maxEmoji: int, maxAttachments: int, maxEmoji: int, maxAttachments: int,
@ -643,7 +643,7 @@ def savePostToBox(baseDir: str, httpPrefix: str, postId: str,
return filename return filename
def updateHashtagsIndex(baseDir: str, tag: {}, newPostId: str) -> None: def _updateHashtagsIndex(baseDir: str, tag: {}, newPostId: str) -> None:
"""Writes the post url for hashtags to a file """Writes the post url for hashtags to a file
This allows posts for a hashtag to be quickly looked up This allows posts for a hashtag to be quickly looked up
""" """
@ -677,7 +677,7 @@ def updateHashtagsIndex(baseDir: str, tag: {}, newPostId: str) -> None:
tagsFilename + ' ' + str(e)) tagsFilename + ' ' + str(e))
def addSchedulePost(baseDir: str, nickname: str, domain: str, def _addSchedulePost(baseDir: str, nickname: str, domain: str,
eventDateStr: str, postId: str) -> None: eventDateStr: str, postId: str) -> None:
"""Adds a scheduled post to the index """Adds a scheduled post to the index
""" """
@ -703,7 +703,7 @@ def addSchedulePost(baseDir: str, nickname: str, domain: str,
scheduleFile.close() scheduleFile.close()
def appendEventFields(newPost: {}, def _appendEventFields(newPost: {},
eventUUID: str, eventStatus: str, eventUUID: str, eventStatus: str,
anonymousParticipationEnabled: bool, anonymousParticipationEnabled: bool,
repliesModerationOption: str, repliesModerationOption: str,
@ -758,7 +758,7 @@ def validContentWarning(cw: str) -> str:
return cw return cw
def loadAutoCW(baseDir: str, nickname: str, domain: str) -> []: def _loadAutoCW(baseDir: str, nickname: str, domain: str) -> []:
"""Loads automatic CWs file and returns a list containing """Loads automatic CWs file and returns a list containing
the lines of the file the lines of the file
""" """
@ -771,13 +771,13 @@ def loadAutoCW(baseDir: str, nickname: str, domain: str) -> []:
return [] return []
def addAutoCW(baseDir: str, nickname: str, domain: str, def _addAutoCW(baseDir: str, nickname: str, domain: str,
subject: str, content: str) -> str: subject: str, content: str) -> str:
"""Appends any automatic CW to the subject line """Appends any automatic CW to the subject line
and returns the new subject line and returns the new subject line
""" """
newSubject = subject newSubject = subject
autoCWList = loadAutoCW(baseDir, nickname, domain) autoCWList = _loadAutoCW(baseDir, nickname, domain)
for cwRule in autoCWList: for cwRule in autoCWList:
if '->' not in cwRule: if '->' not in cwRule:
continue continue
@ -793,10 +793,10 @@ def addAutoCW(baseDir: str, nickname: str, domain: str,
return newSubject return newSubject
def createPostBase(baseDir: str, nickname: str, domain: str, port: int, def _createPostBase(baseDir: str, nickname: str, domain: str, port: int,
toUrl: str, ccUrl: str, httpPrefix: str, content: str, toUrl: str, ccUrl: str, httpPrefix: str, content: str,
followersOnly: bool, saveToFile: bool, clientToServer: bool, followersOnly: bool, saveToFile: bool,
commentsEnabled: bool, clientToServer: bool, commentsEnabled: bool,
attachImageFilename: str, attachImageFilename: str,
mediaType: str, imageDescription: str, mediaType: str, imageDescription: str,
useBlurhash: bool, isModerationReport: bool, useBlurhash: bool, isModerationReport: bool,
@ -812,7 +812,7 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int,
eventStatus=None, ticketUrl=None) -> {}: eventStatus=None, ticketUrl=None) -> {}:
"""Creates a message """Creates a message
""" """
subject = addAutoCW(baseDir, nickname, domain, subject, content) subject = _addAutoCW(baseDir, nickname, domain, subject, content)
if nickname != 'news': if nickname != 'news':
mentionedRecipients = \ mentionedRecipients = \
@ -885,7 +885,7 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int,
if not tagExists(tag['type'], tag['name'], tags): if not tagExists(tag['type'], tag['name'], tags):
tags.append(tag) tags.append(tag)
if isPublic: if isPublic:
updateHashtagsIndex(baseDir, tag, newPostId) _updateHashtagsIndex(baseDir, tag, newPostId)
print('Content tags: ' + str(tags)) print('Content tags: ' + str(tags))
if inReplyTo and not sensitive: if inReplyTo and not sensitive:
@ -1031,7 +1031,7 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int,
attachMedia(baseDir, httpPrefix, domain, port, attachMedia(baseDir, httpPrefix, domain, port,
newPost['object'], attachImageFilename, newPost['object'], attachImageFilename,
mediaType, imageDescription, useBlurhash) mediaType, imageDescription, useBlurhash)
appendEventFields(newPost['object'], eventUUID, eventStatus, _appendEventFields(newPost['object'], eventUUID, eventStatus,
anonymousParticipationEnabled, anonymousParticipationEnabled,
repliesModerationOption, repliesModerationOption,
category, joinMode, category, joinMode,
@ -1079,7 +1079,7 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int,
attachMedia(baseDir, httpPrefix, domain, port, attachMedia(baseDir, httpPrefix, domain, port,
newPost, attachImageFilename, newPost, attachImageFilename,
mediaType, imageDescription, useBlurhash) mediaType, imageDescription, useBlurhash)
appendEventFields(newPost, eventUUID, eventStatus, _appendEventFields(newPost, eventUUID, eventStatus,
anonymousParticipationEnabled, anonymousParticipationEnabled,
repliesModerationOption, repliesModerationOption,
category, joinMode, category, joinMode,
@ -1123,7 +1123,8 @@ def createPostBase(baseDir: str, nickname: str, domain: str, port: int,
if schedulePost: if schedulePost:
if eventDate and eventTime: if eventDate and eventTime:
# add an item to the scheduled post index file # add an item to the scheduled post index file
addSchedulePost(baseDir, nickname, domain, eventDateStr, newPostId) _addSchedulePost(baseDir, nickname, domain,
eventDateStr, newPostId)
savePostToBox(baseDir, httpPrefix, newPostId, savePostToBox(baseDir, httpPrefix, newPostId,
nickname, domain, newPost, 'scheduled') nickname, domain, newPost, 'scheduled')
else: else:
@ -1179,7 +1180,7 @@ def outboxMessageCreateWrap(httpPrefix: str,
return newPost return newPost
def postIsAddressedToFollowers(baseDir: str, def _postIsAddressedToFollowers(baseDir: str,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
httpPrefix: str, httpPrefix: str,
postJsonObject: {}) -> bool: postJsonObject: {}) -> bool:
@ -1227,7 +1228,7 @@ def createPublicPost(baseDir: str,
"""Public post """Public post
""" """
domainFull = getFullDomain(domain, port) domainFull = getFullDomain(domain, port)
return createPostBase(baseDir, nickname, domain, port, return _createPostBase(baseDir, nickname, domain, port,
'https://www.w3.org/ns/activitystreams#Public', 'https://www.w3.org/ns/activitystreams#Public',
httpPrefix + '://' + domainFull + '/users/' + httpPrefix + '://' + domainFull + '/users/' +
nickname + '/followers', nickname + '/followers',
@ -1328,7 +1329,7 @@ def createQuestionPost(baseDir: str,
""" """
domainFull = getFullDomain(domain, port) domainFull = getFullDomain(domain, port)
messageJson = \ messageJson = \
createPostBase(baseDir, nickname, domain, port, _createPostBase(baseDir, nickname, domain, port,
'https://www.w3.org/ns/activitystreams#Public', 'https://www.w3.org/ns/activitystreams#Public',
httpPrefix + '://' + domainFull + '/users/' + httpPrefix + '://' + domainFull + '/users/' +
nickname + '/followers', nickname + '/followers',
@ -1373,7 +1374,7 @@ def createUnlistedPost(baseDir: str,
"""Unlisted post. This has the #Public and followers links inverted. """Unlisted post. This has the #Public and followers links inverted.
""" """
domainFull = getFullDomain(domain, port) domainFull = getFullDomain(domain, port)
return createPostBase(baseDir, nickname, domain, port, return _createPostBase(baseDir, nickname, domain, port,
httpPrefix + '://' + domainFull + '/users/' + httpPrefix + '://' + domainFull + '/users/' +
nickname + '/followers', nickname + '/followers',
'https://www.w3.org/ns/activitystreams#Public', 'https://www.w3.org/ns/activitystreams#Public',
@ -1402,7 +1403,7 @@ def createFollowersOnlyPost(baseDir: str,
"""Followers only post """Followers only post
""" """
domainFull = getFullDomain(domain, port) domainFull = getFullDomain(domain, port)
return createPostBase(baseDir, nickname, domain, port, return _createPostBase(baseDir, nickname, domain, port,
httpPrefix + '://' + domainFull + '/users/' + httpPrefix + '://' + domainFull + '/users/' +
nickname + '/followers', nickname + '/followers',
None, None,
@ -1451,7 +1452,7 @@ def createEventPost(baseDir: str,
if followersOnly: if followersOnly:
toStr1 = toStr2 toStr1 = toStr2
toStr2 = None toStr2 = None
return createPostBase(baseDir, nickname, domain, port, return _createPostBase(baseDir, nickname, domain, port,
toStr1, toStr2, toStr1, toStr2,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
@ -1526,7 +1527,7 @@ def createDirectMessagePost(baseDir: str,
postTo = None postTo = None
postCc = None postCc = None
messageJson = \ messageJson = \
createPostBase(baseDir, nickname, domain, port, _createPostBase(baseDir, nickname, domain, port,
postTo, postCc, postTo, postCc,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
@ -1616,7 +1617,7 @@ def createReportPost(baseDir: str,
handle = toNickname + '@' + domain handle = toNickname + '@' + domain
postJsonObject = \ postJsonObject = \
createPostBase(baseDir, nickname, domain, port, _createPostBase(baseDir, nickname, domain, port,
toUrl, postCc, toUrl, postCc,
httpPrefix, content, followersOnly, saveToFile, httpPrefix, content, followersOnly, saveToFile,
clientToServer, commentsEnabled, clientToServer, commentsEnabled,
@ -1766,7 +1767,7 @@ def sendPost(projectVersion: str,
# sharedInbox is optional # sharedInbox is optional
postJsonObject = \ postJsonObject = \
createPostBase(baseDir, nickname, domain, port, _createPostBase(baseDir, nickname, domain, port,
toPersonId, cc, httpPrefix, content, toPersonId, cc, httpPrefix, content,
followersOnly, saveToFile, clientToServer, followersOnly, saveToFile, clientToServer,
commentsEnabled, commentsEnabled,
@ -1779,7 +1780,7 @@ def sendPost(projectVersion: str,
None, None, None, None, None) None, None, None, None, None)
# get the senders private key # get the senders private key
privateKeyPem = getPersonKey(nickname, domain, baseDir, 'private') privateKeyPem = _getPersonKey(nickname, domain, baseDir, 'private')
if len(privateKeyPem) == 0: if len(privateKeyPem) == 0:
return 6 return 6
@ -1902,7 +1903,7 @@ def sendPostViaServer(projectVersion: str,
'/users/' + toNickname '/users/' + toNickname
postJsonObject = \ postJsonObject = \
createPostBase(baseDir, _createPostBase(baseDir,
fromNickname, fromDomain, fromPort, fromNickname, fromDomain, fromPort,
toPersonId, cc, httpPrefix, content, toPersonId, cc, httpPrefix, content,
followersOnly, saveToFile, clientToServer, followersOnly, saveToFile, clientToServer,
@ -1969,7 +1970,7 @@ def groupFollowersByDomain(baseDir: str, nickname: str, domain: str) -> {}:
return grouped return grouped
def addFollowersToPublicPost(postJsonObject: {}) -> None: def _addFollowersToPublicPost(postJsonObject: {}) -> None:
"""Adds followers entry to cc if it doesn't exist """Adds followers entry to cc if it doesn't exist
""" """
if not postJsonObject.get('actor'): if not postJsonObject.get('actor'):
@ -2099,7 +2100,7 @@ def sendSignedJson(postJsonObject: {}, session, baseDir: str,
# sharedInbox is optional # sharedInbox is optional
# get the senders private key # get the senders private key
privateKeyPem = getPersonKey(nickname, domain, baseDir, 'private', debug) privateKeyPem = _getPersonKey(nickname, domain, baseDir, 'private', debug)
if len(privateKeyPem) == 0: if len(privateKeyPem) == 0:
if debug: if debug:
print('DEBUG: Private key not found for ' + print('DEBUG: Private key not found for ' +
@ -2112,7 +2113,7 @@ def sendSignedJson(postJsonObject: {}, session, baseDir: str,
return 7 return 7
postPath = inboxUrl.split(toDomain, 1)[1] postPath = inboxUrl.split(toDomain, 1)[1]
addFollowersToPublicPost(postJsonObject) _addFollowersToPublicPost(postJsonObject)
if not postJsonObject.get('signature'): if not postJsonObject.get('signature'):
try: try:
@ -2332,7 +2333,7 @@ def sendToNamedAddresses(session, baseDir: str,
personCache, debug, projectVersion) personCache, debug, projectVersion)
def hasSharedInbox(session, httpPrefix: str, domain: str) -> bool: def _hasSharedInbox(session, httpPrefix: str, domain: str) -> bool:
"""Returns true if the given domain has a shared inbox """Returns true if the given domain has a shared inbox
This tries the new and the old way of webfingering the shared inbox This tries the new and the old way of webfingering the shared inbox
""" """
@ -2351,7 +2352,7 @@ def hasSharedInbox(session, httpPrefix: str, domain: str) -> bool:
return False return False
def sendingProfileUpdate(postJsonObject: {}) -> bool: def _sendingProfileUpdate(postJsonObject: {}) -> bool:
"""Returns true if the given json is a profile update """Returns true if the given json is a profile update
""" """
if postJsonObject['type'] != 'Update': if postJsonObject['type'] != 'Update':
@ -2386,7 +2387,7 @@ def sendToFollowers(session, baseDir: str,
if not session: if not session:
print('WARN: No session for sendToFollowers') print('WARN: No session for sendToFollowers')
return return
if not postIsAddressedToFollowers(baseDir, nickname, domain, if not _postIsAddressedToFollowers(baseDir, nickname, domain,
port, httpPrefix, port, httpPrefix,
postJsonObject): postJsonObject):
if debug: if debug:
@ -2428,7 +2429,7 @@ def sendToFollowers(session, baseDir: str,
print('Sending post to followers domain is active: ' + print('Sending post to followers domain is active: ' +
followerDomainUrl) followerDomainUrl)
withSharedInbox = hasSharedInbox(session, httpPrefix, followerDomain) withSharedInbox = _hasSharedInbox(session, httpPrefix, followerDomain)
if debug: if debug:
if withSharedInbox: if withSharedInbox:
print(followerDomain + ' has shared inbox') print(followerDomain + ' has shared inbox')
@ -2467,7 +2468,7 @@ def sendToFollowers(session, baseDir: str,
toNickname = 'inbox' toNickname = 'inbox'
if toNickname != 'inbox' and postJsonObject.get('type'): if toNickname != 'inbox' and postJsonObject.get('type'):
if sendingProfileUpdate(postJsonObject): if _sendingProfileUpdate(postJsonObject):
print('Sending post to followers ' + print('Sending post to followers ' +
'shared inbox of ' + toDomain) 'shared inbox of ' + toDomain)
toNickname = 'inbox' toNickname = 'inbox'
@ -2554,7 +2555,7 @@ def createInbox(recentPostsCache: {},
session, baseDir: str, nickname: str, domain: str, port: int, session, baseDir: str, nickname: str, domain: str, port: int,
httpPrefix: str, itemsPerPage: int, headerOnly: bool, httpPrefix: str, itemsPerPage: int, headerOnly: bool,
pageNumber=None) -> {}: pageNumber=None) -> {}:
return createBoxIndexed(recentPostsCache, return _createBoxIndexed(recentPostsCache,
session, baseDir, 'inbox', session, baseDir, 'inbox',
nickname, domain, port, httpPrefix, nickname, domain, port, httpPrefix,
itemsPerPage, headerOnly, True, itemsPerPage, headerOnly, True,
@ -2564,7 +2565,7 @@ def createInbox(recentPostsCache: {},
def createBookmarksTimeline(session, baseDir: str, nickname: str, domain: str, def createBookmarksTimeline(session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, itemsPerPage: int, port: int, httpPrefix: str, itemsPerPage: int,
headerOnly: bool, pageNumber=None) -> {}: headerOnly: bool, pageNumber=None) -> {}:
return createBoxIndexed({}, session, baseDir, 'tlbookmarks', return _createBoxIndexed({}, session, baseDir, 'tlbookmarks',
nickname, domain, nickname, domain,
port, httpPrefix, itemsPerPage, headerOnly, port, httpPrefix, itemsPerPage, headerOnly,
True, 0, False, 0, pageNumber) True, 0, False, 0, pageNumber)
@ -2574,7 +2575,7 @@ def createEventsTimeline(recentPostsCache: {},
session, baseDir: str, nickname: str, domain: str, session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, itemsPerPage: int, port: int, httpPrefix: str, itemsPerPage: int,
headerOnly: bool, pageNumber=None) -> {}: headerOnly: bool, pageNumber=None) -> {}:
return createBoxIndexed(recentPostsCache, session, baseDir, 'tlevents', return _createBoxIndexed(recentPostsCache, session, baseDir, 'tlevents',
nickname, domain, nickname, domain,
port, httpPrefix, itemsPerPage, headerOnly, port, httpPrefix, itemsPerPage, headerOnly,
True, 0, False, 0, pageNumber) True, 0, False, 0, pageNumber)
@ -2584,7 +2585,7 @@ def createDMTimeline(recentPostsCache: {},
session, baseDir: str, nickname: str, domain: str, session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, itemsPerPage: int, port: int, httpPrefix: str, itemsPerPage: int,
headerOnly: bool, pageNumber=None) -> {}: headerOnly: bool, pageNumber=None) -> {}:
return createBoxIndexed(recentPostsCache, return _createBoxIndexed(recentPostsCache,
session, baseDir, 'dm', nickname, session, baseDir, 'dm', nickname,
domain, port, httpPrefix, itemsPerPage, domain, port, httpPrefix, itemsPerPage,
headerOnly, True, 0, False, 0, pageNumber) headerOnly, True, 0, False, 0, pageNumber)
@ -2594,7 +2595,7 @@ def createRepliesTimeline(recentPostsCache: {},
session, baseDir: str, nickname: str, domain: str, session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, itemsPerPage: int, port: int, httpPrefix: str, itemsPerPage: int,
headerOnly: bool, pageNumber=None) -> {}: headerOnly: bool, pageNumber=None) -> {}:
return createBoxIndexed(recentPostsCache, session, baseDir, 'tlreplies', return _createBoxIndexed(recentPostsCache, session, baseDir, 'tlreplies',
nickname, domain, port, httpPrefix, nickname, domain, port, httpPrefix,
itemsPerPage, headerOnly, True, itemsPerPage, headerOnly, True,
0, False, 0, pageNumber) 0, False, 0, pageNumber)
@ -2603,7 +2604,7 @@ def createRepliesTimeline(recentPostsCache: {},
def createBlogsTimeline(session, baseDir: str, nickname: str, domain: str, def createBlogsTimeline(session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, itemsPerPage: int, port: int, httpPrefix: str, itemsPerPage: int,
headerOnly: bool, pageNumber=None) -> {}: headerOnly: bool, pageNumber=None) -> {}:
return createBoxIndexed({}, session, baseDir, 'tlblogs', nickname, return _createBoxIndexed({}, session, baseDir, 'tlblogs', nickname,
domain, port, httpPrefix, domain, port, httpPrefix,
itemsPerPage, headerOnly, True, itemsPerPage, headerOnly, True,
0, False, 0, pageNumber) 0, False, 0, pageNumber)
@ -2612,7 +2613,7 @@ def createBlogsTimeline(session, baseDir: str, nickname: str, domain: str,
def createFeaturesTimeline(session, baseDir: str, nickname: str, domain: str, def createFeaturesTimeline(session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, itemsPerPage: int, port: int, httpPrefix: str, itemsPerPage: int,
headerOnly: bool, pageNumber=None) -> {}: headerOnly: bool, pageNumber=None) -> {}:
return createBoxIndexed({}, session, baseDir, 'tlfeatures', nickname, return _createBoxIndexed({}, session, baseDir, 'tlfeatures', nickname,
domain, port, httpPrefix, domain, port, httpPrefix,
itemsPerPage, headerOnly, True, itemsPerPage, headerOnly, True,
0, False, 0, pageNumber) 0, False, 0, pageNumber)
@ -2621,7 +2622,7 @@ def createFeaturesTimeline(session, baseDir: str, nickname: str, domain: str,
def createMediaTimeline(session, baseDir: str, nickname: str, domain: str, def createMediaTimeline(session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, itemsPerPage: int, port: int, httpPrefix: str, itemsPerPage: int,
headerOnly: bool, pageNumber=None) -> {}: headerOnly: bool, pageNumber=None) -> {}:
return createBoxIndexed({}, session, baseDir, 'tlmedia', nickname, return _createBoxIndexed({}, session, baseDir, 'tlmedia', nickname,
domain, port, httpPrefix, domain, port, httpPrefix,
itemsPerPage, headerOnly, True, itemsPerPage, headerOnly, True,
0, False, 0, pageNumber) 0, False, 0, pageNumber)
@ -2632,7 +2633,7 @@ def createNewsTimeline(session, baseDir: str, nickname: str, domain: str,
headerOnly: bool, newswireVotesThreshold: int, headerOnly: bool, newswireVotesThreshold: int,
positiveVoting: bool, votingTimeMins: int, positiveVoting: bool, votingTimeMins: int,
pageNumber=None) -> {}: pageNumber=None) -> {}:
return createBoxIndexed({}, session, baseDir, 'outbox', 'news', return _createBoxIndexed({}, session, baseDir, 'outbox', 'news',
domain, port, httpPrefix, domain, port, httpPrefix,
itemsPerPage, headerOnly, True, itemsPerPage, headerOnly, True,
newswireVotesThreshold, positiveVoting, newswireVotesThreshold, positiveVoting,
@ -2643,7 +2644,7 @@ def createOutbox(session, baseDir: str, nickname: str, domain: str,
port: int, httpPrefix: str, port: int, httpPrefix: str,
itemsPerPage: int, headerOnly: bool, authorized: bool, itemsPerPage: int, headerOnly: bool, authorized: bool,
pageNumber=None) -> {}: pageNumber=None) -> {}:
return createBoxIndexed({}, session, baseDir, 'outbox', return _createBoxIndexed({}, session, baseDir, 'outbox',
nickname, domain, port, httpPrefix, nickname, domain, port, httpPrefix,
itemsPerPage, headerOnly, authorized, itemsPerPage, headerOnly, authorized,
0, False, 0, pageNumber) 0, False, 0, pageNumber)
@ -2816,7 +2817,7 @@ def isReply(postJsonObject: {}, actor: str) -> bool:
return False return False
def addPostStringToTimeline(postStr: str, boxname: str, def _addPostStringToTimeline(postStr: str, boxname: str,
postsInBox: [], boxActor: str) -> bool: postsInBox: [], boxActor: str) -> bool:
""" is this a valid timeline post? """ is this a valid timeline post?
""" """
@ -2853,7 +2854,7 @@ def addPostStringToTimeline(postStr: str, boxname: str,
return False return False
def addPostToTimeline(filePath: str, boxname: str, def _addPostToTimeline(filePath: str, boxname: str,
postsInBox: [], boxActor: str) -> bool: postsInBox: [], boxActor: str) -> bool:
""" Reads a post from file and decides whether it is valid """ Reads a post from file and decides whether it is valid
""" """
@ -2866,11 +2867,11 @@ def addPostToTimeline(filePath: str, boxname: str,
# append a replies identifier, which will later be removed # append a replies identifier, which will later be removed
postStr += '<hasReplies>' postStr += '<hasReplies>'
return addPostStringToTimeline(postStr, boxname, postsInBox, boxActor) return _addPostStringToTimeline(postStr, boxname, postsInBox, boxActor)
return False return False
def createBoxIndexed(recentPostsCache: {}, def _createBoxIndexed(recentPostsCache: {},
session, baseDir: str, boxname: str, session, baseDir: str, boxname: str,
nickname: str, domain: str, port: int, httpPrefix: str, nickname: str, domain: str, port: int, httpPrefix: str,
itemsPerPage: int, headerOnly: bool, authorized: bool, itemsPerPage: int, headerOnly: bool, authorized: bool,
@ -3006,7 +3007,7 @@ def createBoxIndexed(recentPostsCache: {},
if postUrl in recentPostsCache['index']: if postUrl in recentPostsCache['index']:
if recentPostsCache['json'].get(postUrl): if recentPostsCache['json'].get(postUrl):
url = recentPostsCache['json'][postUrl] url = recentPostsCache['json'][postUrl]
addPostStringToTimeline(url, _addPostStringToTimeline(url,
boxname, postsInBox, boxname, postsInBox,
boxActor) boxActor)
postsCtr += 1 postsCtr += 1
@ -3017,7 +3018,7 @@ def createBoxIndexed(recentPostsCache: {},
locatePost(baseDir, nickname, locatePost(baseDir, nickname,
domain, postUrl, False) domain, postUrl, False)
if fullPostFilename: if fullPostFilename:
addPostToTimeline(fullPostFilename, boxname, _addPostToTimeline(fullPostFilename, boxname,
postsInBox, boxActor) postsInBox, boxActor)
else: else:
# if this is the features timeline # if this is the features timeline
@ -3026,7 +3027,7 @@ def createBoxIndexed(recentPostsCache: {},
locatePost(baseDir, timelineNickname, locatePost(baseDir, timelineNickname,
domain, postUrl, False) domain, postUrl, False)
if fullPostFilename: if fullPostFilename:
addPostToTimeline(fullPostFilename, boxname, _addPostToTimeline(fullPostFilename, boxname,
postsInBox, boxActor) postsInBox, boxActor)
else: else:
print('WARN: unable to locate post ' + postUrl) print('WARN: unable to locate post ' + postUrl)
@ -3314,7 +3315,7 @@ def getPublicPostsOfPerson(baseDir: str, nickname: str, domain: str,
maxMentions = 10 maxMentions = 10
maxEmoji = 10 maxEmoji = 10
maxAttachments = 5 maxAttachments = 5
getPosts(session, personUrl, 30, maxMentions, maxEmoji, _getPosts(session, personUrl, 30, maxMentions, maxEmoji,
maxAttachments, federationList, maxAttachments, federationList,
personCache, raw, simple, debug, personCache, raw, simple, debug,
projectVersion, httpPrefix, domain) projectVersion, httpPrefix, domain)
@ -3413,7 +3414,7 @@ def getPublicPostInfo(session, baseDir: str, nickname: str, domain: str,
domainsInfo[d] = [] domainsInfo[d] = []
blockedPosts = \ blockedPosts = \
getPostsForBlockedDomains(baseDir, session, personUrl, maxPosts, _getPostsForBlockedDomains(baseDir, session, personUrl, maxPosts,
maxMentions, maxMentions,
maxEmoji, maxAttachments, maxEmoji, maxAttachments,
federationList, federationList,
@ -3467,7 +3468,7 @@ def getPublicPostDomainsBlocked(session, baseDir: str,
return blockedDomains return blockedDomains
def getNonMutualsOfPerson(baseDir: str, def _getNonMutualsOfPerson(baseDir: str,
nickname: str, domain: str) -> []: nickname: str, domain: str) -> []:
"""Returns the followers who are not mutuals of a person """Returns the followers who are not mutuals of a person
i.e. accounts which follow you but you don't follow them i.e. accounts which follow you but you don't follow them
@ -3490,7 +3491,7 @@ def checkDomains(session, baseDir: str,
maxBlockedDomains: int, singleCheck: bool): maxBlockedDomains: int, singleCheck: bool):
"""Checks follower accounts for references to globally blocked domains """Checks follower accounts for references to globally blocked domains
""" """
nonMutuals = getNonMutualsOfPerson(baseDir, nickname, domain) nonMutuals = _getNonMutualsOfPerson(baseDir, nickname, domain)
if not nonMutuals: if not nonMutuals:
print('No non-mutual followers were found') print('No non-mutual followers were found')
return return
@ -3614,7 +3615,7 @@ def populateRepliesJson(baseDir: str, nickname: str, domain: str,
repliesJson['orderedItems'].append(pjo) repliesJson['orderedItems'].append(pjo)
def rejectAnnounce(announceFilename: str): def _rejectAnnounce(announceFilename: str):
"""Marks an announce as rejected """Marks an announce as rejected
""" """
if not os.path.isfile(announceFilename + '.reject'): if not os.path.isfile(announceFilename + '.reject'):
@ -3699,40 +3700,40 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
if not isinstance(announcedJson, dict): if not isinstance(announcedJson, dict):
print('WARN: announce json is not a dict - ' + print('WARN: announce json is not a dict - ' +
postJsonObject['object']) postJsonObject['object'])
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
if not announcedJson.get('id'): if not announcedJson.get('id'):
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
if '/statuses/' not in announcedJson['id']: if '/statuses/' not in announcedJson['id']:
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
if '/users/' not in announcedJson['id'] and \ if '/users/' not in announcedJson['id'] and \
'/accounts/' not in announcedJson['id'] and \ '/accounts/' not in announcedJson['id'] and \
'/channel/' not in announcedJson['id'] and \ '/channel/' not in announcedJson['id'] and \
'/profile/' not in announcedJson['id']: '/profile/' not in announcedJson['id']:
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
if not announcedJson.get('type'): if not announcedJson.get('type'):
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
# pprint(announcedJson) # pprint(announcedJson)
return None return None
if announcedJson['type'] != 'Note' and \ if announcedJson['type'] != 'Note' and \
announcedJson['type'] != 'Article': announcedJson['type'] != 'Article':
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
# pprint(announcedJson) # pprint(announcedJson)
return None return None
if not announcedJson.get('content'): if not announcedJson.get('content'):
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
if not announcedJson.get('published'): if not announcedJson.get('published'):
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
if not validPostDate(announcedJson['published']): if not validPostDate(announcedJson['published']):
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
if isFiltered(baseDir, nickname, domain, announcedJson['content']): if isFiltered(baseDir, nickname, domain, announcedJson['content']):
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
# remove any long words # remove any long words
announcedJson['content'] = \ announcedJson['content'] = \
@ -3748,7 +3749,7 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
actorNickname, actorDomain, actorPort, actorNickname, actorDomain, actorPort,
announcedJson) announcedJson)
if announcedJson['type'] != 'Create': if announcedJson['type'] != 'Create':
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
# pprint(announcedJson) # pprint(announcedJson)
return None return None
@ -3765,7 +3766,7 @@ def downloadAnnounce(session, baseDir: str, httpPrefix: str,
attributedDomain = getFullDomain(attributedDomain, attributedPort) attributedDomain = getFullDomain(attributedDomain, attributedPort)
if isBlocked(baseDir, nickname, domain, if isBlocked(baseDir, nickname, domain,
attributedNickname, attributedDomain): attributedNickname, attributedDomain):
rejectAnnounce(announceFilename) _rejectAnnounce(announceFilename)
return None return None
postJsonObject = announcedJson postJsonObject = announcedJson
replaceYouTube(postJsonObject, YTReplacementDomain) replaceYouTube(postJsonObject, YTReplacementDomain)

View File

@ -63,7 +63,7 @@ def clearEditorStatus(baseDir: str) -> None:
saveJson(actorJson, filename) saveJson(actorJson, filename)
def addModerator(baseDir: str, nickname: str, domain: str) -> None: def _addModerator(baseDir: str, nickname: str, domain: str) -> None:
"""Adds a moderator nickname to the file """Adds a moderator nickname to the file
""" """
if ':' in domain: if ':' in domain:
@ -92,7 +92,7 @@ def addModerator(baseDir: str, nickname: str, domain: str) -> None:
f.write(nickname + '\n') f.write(nickname + '\n')
def removeModerator(baseDir: str, nickname: str): def _removeModerator(baseDir: str, nickname: str):
"""Removes a moderator nickname from the file """Removes a moderator nickname from the file
""" """
moderatorsFile = baseDir + '/accounts/moderators.txt' moderatorsFile = baseDir + '/accounts/moderators.txt'
@ -125,7 +125,7 @@ def setRole(baseDir: str, nickname: str, domain: str,
if role: if role:
# add the role # add the role
if project == 'instance' and 'role' == 'moderator': if project == 'instance' and 'role' == 'moderator':
addModerator(baseDir, nickname, domain) _addModerator(baseDir, nickname, domain)
if actorJson['roles'].get(project): if actorJson['roles'].get(project):
if role not in actorJson['roles'][project]: if role not in actorJson['roles'][project]:
actorJson['roles'][project].append(role) actorJson['roles'][project].append(role)
@ -134,7 +134,7 @@ def setRole(baseDir: str, nickname: str, domain: str,
else: else:
# remove the role # remove the role
if project == 'instance': if project == 'instance':
removeModerator(baseDir, nickname) _removeModerator(baseDir, nickname)
if actorJson['roles'].get(project): if actorJson['roles'].get(project):
actorJson['roles'][project].remove(role) actorJson['roles'][project].remove(role)
# if the project contains no roles then remove it # if the project contains no roles then remove it
@ -144,7 +144,7 @@ def setRole(baseDir: str, nickname: str, domain: str,
return True return True
def getRoles(baseDir: str, nickname: str, domain: str, def _getRoles(baseDir: str, nickname: str, domain: str,
project: str) -> []: project: str) -> []:
"""Returns the roles for a given person on a given project """Returns the roles for a given person on a given project
""" """
@ -198,7 +198,7 @@ def outboxDelegate(baseDir: str, authenticatedNickname: str,
# instance delegators can delagate to other projects # instance delegators can delagate to other projects
# than their own # than their own
canDelegate = False canDelegate = False
delegatorRoles = getRoles(baseDir, delegatorNickname, delegatorRoles = _getRoles(baseDir, delegatorNickname,
domain, 'instance') domain, 'instance')
if delegatorRoles: if delegatorRoles:
if 'delegator' in delegatorRoles: if 'delegator' in delegatorRoles:
@ -207,7 +207,7 @@ def outboxDelegate(baseDir: str, authenticatedNickname: str,
if not canDelegate: if not canDelegate:
canDelegate = True canDelegate = True
# non-instance delegators can only delegate within their project # non-instance delegators can only delegate within their project
delegatorRoles = getRoles(baseDir, delegatorNickname, delegatorRoles = _getRoles(baseDir, delegatorNickname,
domain, project) domain, project)
if delegatorRoles: if delegatorRoles:
if 'delegator' not in delegatorRoles: if 'delegator' not in delegatorRoles:
@ -230,7 +230,7 @@ def outboxDelegate(baseDir: str, authenticatedNickname: str,
return True return True
# what roles is this person already assigned to? # what roles is this person already assigned to?
existingRoles = getRoles(baseDir, nickname, domain, project) existingRoles = _getRoles(baseDir, nickname, domain, project)
if existingRoles: if existingRoles:
if role in existingRoles: if role in existingRoles:
if debug: if debug:

View File

@ -14,7 +14,7 @@ from utils import loadJson
from outbox import postMessageToOutbox from outbox import postMessageToOutbox
def updatePostSchedule(baseDir: str, handle: str, httpd, def _updatePostSchedule(baseDir: str, handle: str, httpd,
maxScheduledPosts: int) -> None: maxScheduledPosts: int) -> None:
"""Checks if posts are due to be delivered and if so moves them to the outbox """Checks if posts are due to be delivered and if so moves them to the outbox
""" """
@ -145,7 +145,7 @@ def runPostSchedule(baseDir: str, httpd, maxScheduledPosts: int):
baseDir + '/accounts/' + account + '/schedule.index' baseDir + '/accounts/' + account + '/schedule.index'
if not os.path.isfile(scheduleIndexFilename): if not os.path.isfile(scheduleIndexFilename):
continue continue
updatePostSchedule(baseDir, account, httpd, maxScheduledPosts) _updatePostSchedule(baseDir, account, httpd, maxScheduledPosts)
break break

View File

@ -176,11 +176,11 @@ def expireShares(baseDir: str) -> None:
continue continue
nickname = account.split('@')[0] nickname = account.split('@')[0]
domain = account.split('@')[1] domain = account.split('@')[1]
expireSharesForAccount(baseDir, nickname, domain) _expireSharesForAccount(baseDir, nickname, domain)
break break
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 = domain

View File

@ -101,7 +101,7 @@ thrBob = None
thrEve = None thrEve = None
def testHttpsigBase(withDigest): def _testHttpsigBase(withDigest):
print('testHttpsig(' + str(withDigest) + ')') print('testHttpsig(' + str(withDigest) + ')')
baseDir = os.getcwd() baseDir = os.getcwd()
@ -206,8 +206,8 @@ def testHttpsigBase(withDigest):
def testHttpsig(): def testHttpsig():
testHttpsigBase(True) _testHttpsigBase(True)
testHttpsigBase(False) _testHttpsigBase(False)
def testCache(): def testCache():
@ -2617,6 +2617,11 @@ def testFunctions():
excludeImports = [ excludeImports = [
'link' 'link'
] ]
excludeLocal = [
'pyjsonld',
'daemon',
'tests'
]
# check that functions are called somewhere # check that functions are called somewhere
for name, properties in functionProperties.items(): for name, properties in functionProperties.items():
if name in exclusions: if name in exclusions:
@ -2626,6 +2631,16 @@ def testFunctions():
' in module ' + properties['module'] + ' in module ' + properties['module'] +
' is not called anywhere') ' is not called anywhere')
assert properties['calledInModule'] assert properties['calledInModule']
if len(properties['calledInModule']) == 1:
modName = properties['calledInModule'][0]
if modName not in excludeLocal and \
modName == properties['module']:
if not name.startswith('_'):
print('Local function ' + name +
' in ' + modName + ' does not begin with _')
assert False
if name not in excludeImports: if name not in excludeImports:
for modName in properties['calledInModule']: for modName in properties['calledInModule']:
if modName == properties['module']: if modName == properties['module']:
@ -2635,8 +2650,6 @@ def testFunctions():
print(importStr + ' not found in ' + modName + '.py') print(importStr + ' not found in ' + modName + '.py')
assert False assert False
print('Function: ' + name + '') print('Function: ' + name + '')
# print(str(function))
# print(str(functionProperties))
def runAllTests(): def runAllTests():

View File

@ -14,7 +14,7 @@ from shutil import copyfile
from content import dangerousCSS from content import dangerousCSS
def getThemeFiles() -> []: def _getThemeFiles() -> []:
return ('epicyon.css', 'login.css', 'follow.css', return ('epicyon.css', 'login.css', 'follow.css',
'suspended.css', 'calendar.css', 'blog.css', 'suspended.css', 'calendar.css', 'blog.css',
'options.css', 'search.css', 'links.css') 'options.css', 'search.css', 'links.css')
@ -38,7 +38,7 @@ def getThemesList(baseDir: str) -> []:
return themes return themes
def setThemeInConfig(baseDir: str, name: str) -> bool: def _setThemeInConfig(baseDir: str, name: str) -> bool:
configFilename = baseDir + '/config.json' configFilename = baseDir + '/config.json'
if not os.path.isfile(configFilename): if not os.path.isfile(configFilename):
return False return False
@ -49,7 +49,7 @@ def setThemeInConfig(baseDir: str, name: str) -> bool:
return saveJson(configJson, configFilename) return saveJson(configJson, configFilename)
def setNewswirePublishAsIcon(baseDir: str, useIcon: bool) -> bool: def _setNewswirePublishAsIcon(baseDir: str, useIcon: bool) -> bool:
"""Shows the newswire publish action as an icon or a button """Shows the newswire publish action as an icon or a button
""" """
configFilename = baseDir + '/config.json' configFilename = baseDir + '/config.json'
@ -62,7 +62,7 @@ def setNewswirePublishAsIcon(baseDir: str, useIcon: bool) -> bool:
return saveJson(configJson, configFilename) return saveJson(configJson, configFilename)
def setIconsAsButtons(baseDir: str, useButtons: bool) -> bool: def _setIconsAsButtons(baseDir: str, useButtons: bool) -> bool:
"""Whether to show icons in the header (inbox, outbox, etc) """Whether to show icons in the header (inbox, outbox, etc)
as buttons as buttons
""" """
@ -76,7 +76,7 @@ def setIconsAsButtons(baseDir: str, useButtons: bool) -> bool:
return saveJson(configJson, configFilename) return saveJson(configJson, configFilename)
def setRssIconAtTop(baseDir: str, atTop: bool) -> bool: def _setRssIconAtTop(baseDir: str, atTop: bool) -> bool:
"""Whether to show RSS icon at the top of the timeline """Whether to show RSS icon at the top of the timeline
""" """
configFilename = baseDir + '/config.json' configFilename = baseDir + '/config.json'
@ -89,7 +89,7 @@ def setRssIconAtTop(baseDir: str, atTop: bool) -> bool:
return saveJson(configJson, configFilename) return saveJson(configJson, configFilename)
def setPublishButtonAtTop(baseDir: str, atTop: bool) -> bool: def _setPublishButtonAtTop(baseDir: str, atTop: bool) -> bool:
"""Whether to show the publish button above the title image """Whether to show the publish button above the title image
in the newswire column in the newswire column
""" """
@ -103,7 +103,7 @@ def setPublishButtonAtTop(baseDir: str, atTop: bool) -> bool:
return saveJson(configJson, configFilename) return saveJson(configJson, configFilename)
def setFullWidthTimelineButtonHeader(baseDir: str, fullWidth: bool) -> bool: def _setFullWidthTimelineButtonHeader(baseDir: str, fullWidth: bool) -> bool:
"""Shows the timeline button header containing inbox, outbox, """Shows the timeline button header containing inbox, outbox,
calendar, etc as full width calendar, etc as full width
""" """
@ -127,8 +127,8 @@ def getTheme(baseDir: str) -> str:
return 'default' return 'default'
def removeTheme(baseDir: str): def _removeTheme(baseDir: str):
themeFiles = getThemeFiles() themeFiles = _getThemeFiles()
for filename in themeFiles: for filename in themeFiles:
if os.path.isfile(baseDir + '/' + filename): if os.path.isfile(baseDir + '/' + filename):
os.remove(baseDir + '/' + filename) os.remove(baseDir + '/' + filename)
@ -183,14 +183,14 @@ def setCSSparam(css: str, param: str, value: str) -> str:
return newcss.strip() return newcss.strip()
def setThemeFromDict(baseDir: str, name: str, def _setThemeFromDict(baseDir: str, name: str,
themeParams: {}, bgParams: {}, themeParams: {}, bgParams: {},
allowLocalNetworkAccess: bool) -> None: allowLocalNetworkAccess: bool) -> None:
"""Uses a dictionary to set a theme """Uses a dictionary to set a theme
""" """
if name: if name:
setThemeInConfig(baseDir, name) _setThemeInConfig(baseDir, name)
themeFiles = getThemeFiles() themeFiles = _getThemeFiles()
for filename in themeFiles: for filename in themeFiles:
# check for custom css within the theme directory # check for custom css within the theme directory
templateFilename = baseDir + '/theme/' + name + '/epicyon-' + filename templateFilename = baseDir + '/theme/' + name + '/epicyon-' + filename
@ -215,33 +215,33 @@ def setThemeFromDict(baseDir: str, name: str,
for paramName, paramValue in themeParams.items(): for paramName, paramValue in themeParams.items():
if paramName == 'newswire-publish-icon': if paramName == 'newswire-publish-icon':
if paramValue.lower() == 'true': if paramValue.lower() == 'true':
setNewswirePublishAsIcon(baseDir, True) _setNewswirePublishAsIcon(baseDir, True)
else: else:
setNewswirePublishAsIcon(baseDir, False) _setNewswirePublishAsIcon(baseDir, False)
continue continue
elif paramName == 'full-width-timeline-buttons': elif paramName == 'full-width-timeline-buttons':
if paramValue.lower() == 'true': if paramValue.lower() == 'true':
setFullWidthTimelineButtonHeader(baseDir, True) _setFullWidthTimelineButtonHeader(baseDir, True)
else: else:
setFullWidthTimelineButtonHeader(baseDir, False) _setFullWidthTimelineButtonHeader(baseDir, False)
continue continue
elif paramName == 'icons-as-buttons': elif paramName == 'icons-as-buttons':
if paramValue.lower() == 'true': if paramValue.lower() == 'true':
setIconsAsButtons(baseDir, True) _setIconsAsButtons(baseDir, True)
else: else:
setIconsAsButtons(baseDir, False) _setIconsAsButtons(baseDir, False)
continue continue
elif paramName == 'rss-icon-at-top': elif paramName == 'rss-icon-at-top':
if paramValue.lower() == 'true': if paramValue.lower() == 'true':
setRssIconAtTop(baseDir, True) _setRssIconAtTop(baseDir, True)
else: else:
setRssIconAtTop(baseDir, False) _setRssIconAtTop(baseDir, False)
continue continue
elif paramName == 'publish-button-at-top': elif paramName == 'publish-button-at-top':
if paramValue.lower() == 'true': if paramValue.lower() == 'true':
setPublishButtonAtTop(baseDir, True) _setPublishButtonAtTop(baseDir, True)
else: else:
setPublishButtonAtTop(baseDir, False) _setPublishButtonAtTop(baseDir, False)
continue continue
css = setCSSparam(css, paramName, paramValue) css = setCSSparam(css, paramName, paramValue)
filename = baseDir + '/' + filename filename = baseDir + '/' + filename
@ -249,16 +249,16 @@ def setThemeFromDict(baseDir: str, name: str,
cssfile.write(css) cssfile.write(css)
if bgParams.get('login'): if bgParams.get('login'):
setBackgroundFormat(baseDir, name, 'login', bgParams['login']) _setBackgroundFormat(baseDir, name, 'login', bgParams['login'])
if bgParams.get('follow'): if bgParams.get('follow'):
setBackgroundFormat(baseDir, name, 'follow', bgParams['follow']) _setBackgroundFormat(baseDir, name, 'follow', bgParams['follow'])
if bgParams.get('options'): if bgParams.get('options'):
setBackgroundFormat(baseDir, name, 'options', bgParams['options']) _setBackgroundFormat(baseDir, name, 'options', bgParams['options'])
if bgParams.get('search'): if bgParams.get('search'):
setBackgroundFormat(baseDir, name, 'search', bgParams['search']) _setBackgroundFormat(baseDir, name, 'search', bgParams['search'])
def setBackgroundFormat(baseDir: str, name: str, def _setBackgroundFormat(baseDir: str, name: str,
backgroundType: str, extension: str) -> None: backgroundType: str, extension: str) -> None:
"""Sets the background file extension """Sets the background file extension
""" """
@ -277,7 +277,7 @@ def setBackgroundFormat(baseDir: str, name: str,
def enableGrayscale(baseDir: str) -> None: def enableGrayscale(baseDir: str) -> None:
"""Enables grayscale for the current theme """Enables grayscale for the current theme
""" """
themeFiles = getThemeFiles() themeFiles = _getThemeFiles()
for filename in themeFiles: for filename in themeFiles:
templateFilename = baseDir + '/' + filename templateFilename = baseDir + '/' + filename
if not os.path.isfile(templateFilename): if not os.path.isfile(templateFilename):
@ -300,7 +300,7 @@ def enableGrayscale(baseDir: str) -> None:
def disableGrayscale(baseDir: str) -> None: def disableGrayscale(baseDir: str) -> None:
"""Disables grayscale for the current theme """Disables grayscale for the current theme
""" """
themeFiles = getThemeFiles() themeFiles = _getThemeFiles()
for filename in themeFiles: for filename in themeFiles:
templateFilename = baseDir + '/' + filename templateFilename = baseDir + '/' + filename
if not os.path.isfile(templateFilename): if not os.path.isfile(templateFilename):
@ -318,7 +318,7 @@ def disableGrayscale(baseDir: str) -> None:
os.remove(grayscaleFilename) os.remove(grayscaleFilename)
def setCustomFont(baseDir: str): def _setCustomFont(baseDir: str):
"""Uses a dictionary to set a theme """Uses a dictionary to set a theme
""" """
customFontExt = None customFontExt = None
@ -337,7 +337,7 @@ def setCustomFont(baseDir: str):
if not customFontExt: if not customFontExt:
return return
themeFiles = getThemeFiles() themeFiles = _getThemeFiles()
for filename in themeFiles: for filename in themeFiles:
templateFilename = baseDir + '/' + filename templateFilename = baseDir + '/' + filename
if not os.path.isfile(templateFilename): if not os.path.isfile(templateFilename):
@ -356,7 +356,7 @@ def setCustomFont(baseDir: str):
cssfile.write(css) cssfile.write(css)
def readVariablesFile(baseDir: str, themeName: str, def _readVariablesFile(baseDir: str, themeName: str,
variablesFile: str, variablesFile: str,
allowLocalNetworkAccess: bool) -> None: allowLocalNetworkAccess: bool) -> None:
"""Reads variables from a file in the theme directory """Reads variables from a file in the theme directory
@ -370,14 +370,14 @@ def readVariablesFile(baseDir: str, themeName: str,
"options": "jpg", "options": "jpg",
"search": "jpg" "search": "jpg"
} }
setThemeFromDict(baseDir, themeName, themeParams, bgParams, _setThemeFromDict(baseDir, themeName, themeParams, bgParams,
allowLocalNetworkAccess) allowLocalNetworkAccess)
def setThemeDefault(baseDir: str, allowLocalNetworkAccess: bool): def _setThemeDefault(baseDir: str, allowLocalNetworkAccess: bool):
name = 'default' name = 'default'
removeTheme(baseDir) _removeTheme(baseDir)
setThemeInConfig(baseDir, name) _setThemeInConfig(baseDir, name)
bgParams = { bgParams = {
"login": "jpg", "login": "jpg",
"follow": "jpg", "follow": "jpg",
@ -394,11 +394,11 @@ def setThemeDefault(baseDir: str, allowLocalNetworkAccess: bool):
"banner-height-mobile": "10vh", "banner-height-mobile": "10vh",
"search-banner-height-mobile": "15vh" "search-banner-height-mobile": "15vh"
} }
setThemeFromDict(baseDir, name, themeParams, bgParams, _setThemeFromDict(baseDir, name, themeParams, bgParams,
allowLocalNetworkAccess) allowLocalNetworkAccess)
def setThemeFonts(baseDir: str, themeName: str) -> None: def _setThemeFonts(baseDir: str, themeName: str) -> None:
"""Adds custom theme fonts """Adds custom theme fonts
""" """
themeNameLower = themeName.lower() themeNameLower = themeName.lower()
@ -422,7 +422,7 @@ def setThemeFonts(baseDir: str, themeName: str) -> None:
break break
def setThemeImages(baseDir: str, name: str) -> None: def _setThemeImages(baseDir: str, name: str) -> None:
"""Changes the profile background image """Changes the profile background image
and banner to the defaults and banner to the defaults
""" """
@ -557,7 +557,7 @@ def setTheme(baseDir: str, name: str, domain: str,
result = False result = False
prevThemeName = getTheme(baseDir) prevThemeName = getTheme(baseDir)
removeTheme(baseDir) _removeTheme(baseDir)
themes = getThemesList(baseDir) themes = getThemesList(baseDir)
for themeName in themes: for themeName in themes:
@ -573,21 +573,21 @@ def setTheme(baseDir: str, name: str, domain: str,
if prevThemeName.lower() != themeNameLower: if prevThemeName.lower() != themeNameLower:
# change the banner and profile image # change the banner and profile image
# to the default for the theme # to the default for the theme
setThemeImages(baseDir, name) _setThemeImages(baseDir, name)
setThemeFonts(baseDir, name) _setThemeFonts(baseDir, name)
result = True result = True
if not result: if not result:
# default # default
setThemeDefault(baseDir) _setThemeDefault(baseDir)
result = True result = True
variablesFile = baseDir + '/theme/' + name + '/theme.json' variablesFile = baseDir + '/theme/' + name + '/theme.json'
if os.path.isfile(variablesFile): if os.path.isfile(variablesFile):
readVariablesFile(baseDir, name, variablesFile, _readVariablesFile(baseDir, name, variablesFile,
allowLocalNetworkAccess) allowLocalNetworkAccess)
setCustomFont(baseDir) _setCustomFont(baseDir)
# set the news avatar # set the news avatar
newsAvatarThemeFilename = \ newsAvatarThemeFilename = \
@ -604,5 +604,5 @@ def setTheme(baseDir: str, name: str, domain: str,
else: else:
disableGrayscale(baseDir) disableGrayscale(baseDir)
setThemeInConfig(baseDir, name) _setThemeInConfig(baseDir, name)
return result return result

View File

@ -197,7 +197,7 @@ def isSystemAccount(nickname: str) -> bool:
return False return False
def createConfig(baseDir: str) -> None: def _createConfig(baseDir: str) -> None:
"""Creates a configuration file """Creates a configuration file
""" """
configFilename = baseDir + '/config.json' configFilename = baseDir + '/config.json'
@ -211,7 +211,7 @@ def createConfig(baseDir: str) -> None:
def setConfigParam(baseDir: str, variableName: str, variableValue) -> None: def setConfigParam(baseDir: str, variableName: str, variableValue) -> None:
"""Sets a configuration value """Sets a configuration value
""" """
createConfig(baseDir) _createConfig(baseDir)
configFilename = baseDir + '/config.json' configFilename = baseDir + '/config.json'
configJson = {} configJson = {}
if os.path.isfile(configFilename): if os.path.isfile(configFilename):
@ -223,7 +223,7 @@ def setConfigParam(baseDir: str, variableName: str, variableValue) -> None:
def getConfigParam(baseDir: str, variableName: str): def getConfigParam(baseDir: str, variableName: str):
"""Gets a configuration value """Gets a configuration value
""" """
createConfig(baseDir) _createConfig(baseDir)
configFilename = baseDir + '/config.json' configFilename = baseDir + '/config.json'
configJson = loadJson(configFilename) configJson = loadJson(configFilename)
if configJson: if configJson:
@ -610,7 +610,7 @@ def getDomainFromActor(actor: str) -> (str, int):
return domain, port return domain, port
def setDefaultPetName(baseDir: str, nickname: str, domain: str, def _setDefaultPetName(baseDir: str, nickname: str, domain: str,
followNickname: str, followDomain: str) -> None: followNickname: str, followDomain: str) -> None:
"""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
@ -723,7 +723,7 @@ def followPerson(baseDir: str, nickname: str, domain: str,
addPersonToCalendar(baseDir, nickname, domain, addPersonToCalendar(baseDir, nickname, domain,
followNickname, followDomain) followNickname, followDomain)
# add a default petname # add a default petname
setDefaultPetName(baseDir, nickname, domain, _setDefaultPetName(baseDir, nickname, domain,
followNickname, followDomain) followNickname, followDomain)
return True return True
@ -864,7 +864,8 @@ def locatePost(baseDir: str, nickname: str, domain: str,
return None return None
def removeAttachment(baseDir: str, httpPrefix: str, domain: str, postJson: {}): def _removeAttachment(baseDir: str, httpPrefix: str, domain: str,
postJson: {}):
if not postJson.get('attachment'): if not postJson.get('attachment'):
return return
if not postJson['attachment'][0].get('url'): if not postJson['attachment'][0].get('url'):
@ -907,7 +908,7 @@ def removeModerationPostFromIndex(baseDir: str, postUrl: str,
' from moderation index') ' from moderation index')
def isReplyToBlogPost(baseDir: str, nickname: str, domain: str, def _isReplyToBlogPost(baseDir: str, nickname: str, domain: str,
postJsonObject: str): postJsonObject: str):
"""Is the given post a reply to a blog post? """Is the given post a reply to a blog post?
""" """
@ -947,7 +948,7 @@ def deletePost(baseDir: str, httpPrefix: str,
return return
# don't remove replies to blog posts # don't remove replies to blog posts
if isReplyToBlogPost(baseDir, nickname, domain, if _isReplyToBlogPost(baseDir, nickname, domain,
postJsonObject): postJsonObject):
return return
@ -966,7 +967,7 @@ def deletePost(baseDir: str, httpPrefix: str,
del recentPostsCache['html'][postId] del recentPostsCache['html'][postId]
# remove any attachment # remove any attachment
removeAttachment(baseDir, httpPrefix, domain, postJsonObject) _removeAttachment(baseDir, httpPrefix, domain, postJsonObject)
extensions = ('votes', 'arrived', 'muted') extensions = ('votes', 'arrived', 'muted')
for ext in extensions: for ext in extensions:

View File

@ -89,7 +89,7 @@ def htmlCalendarDeleteConfirm(cssCache: {}, translate: {}, baseDir: str,
return deletePostStr return deletePostStr
def htmlCalendarDay(cssCache: {}, translate: {}, def _htmlCalendarDay(cssCache: {}, translate: {},
baseDir: str, path: str, baseDir: str, path: str,
year: int, monthNumber: int, dayNumber: int, year: int, monthNumber: int, dayNumber: int,
nickname: str, domain: str, dayEvents: [], nickname: str, domain: str, dayEvents: [],
@ -251,7 +251,7 @@ def htmlCalendar(cssCache: {}, translate: {},
if events: if events:
if events.get(str(dayNumber)): if events.get(str(dayNumber)):
dayEvents = events[str(dayNumber)] dayEvents = events[str(dayNumber)]
return htmlCalendarDay(cssCache, translate, baseDir, path, return _htmlCalendarDay(cssCache, translate, baseDir, path,
year, monthNumber, dayNumber, year, monthNumber, dayNumber,
nickname, domain, dayEvents, nickname, domain, dayEvents,
monthName, actor) monthName, actor)

View File

@ -19,14 +19,14 @@ from webapp_utils import htmlFooter
from webapp_utils import getBannerFile from webapp_utils import getBannerFile
def linksExist(baseDir: str) -> bool: def _linksExist(baseDir: str) -> bool:
"""Returns true if links have been created """Returns true if links have been created
""" """
linksFilename = baseDir + '/accounts/links.txt' linksFilename = baseDir + '/accounts/links.txt'
return os.path.isfile(linksFilename) return os.path.isfile(linksFilename)
def getLeftColumnShares(baseDir: str, def _getLeftColumnShares(baseDir: str,
httpPrefix: str, domainFull: str, httpPrefix: str, domainFull: str,
nickname: str, nickname: str,
maxSharesInLeftColumn: int, maxSharesInLeftColumn: int,
@ -164,7 +164,7 @@ def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str,
# show a number of shares # show a number of shares
maxSharesInLeftColumn = 3 maxSharesInLeftColumn = 3
sharesList = \ sharesList = \
getLeftColumnShares(baseDir, _getLeftColumnShares(baseDir,
httpPrefix, domainFull, nickname, httpPrefix, domainFull, nickname,
maxSharesInLeftColumn, translate) maxSharesInLeftColumn, translate)
if linksList and sharesList: if linksList and sharesList:
@ -271,7 +271,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
headerButtonsFrontScreen(translate, nickname, headerButtonsFrontScreen(translate, nickname,
'links', authorized, 'links', authorized,
iconsAsButtons) + '</center>' iconsAsButtons) + '</center>'
if linksExist(baseDir): if _linksExist(baseDir):
htmlStr += \ htmlStr += \
getLeftColumnContent(baseDir, nickname, domainFull, getLeftColumnContent(baseDir, nickname, domainFull,
httpPrefix, translate, httpPrefix, translate,

View File

@ -24,7 +24,7 @@ from webapp_utils import htmlPostSeparator
from webapp_utils import headerButtonsFrontScreen from webapp_utils import headerButtonsFrontScreen
def votesIndicator(totalVotes: int, positiveVoting: bool) -> str: def _votesIndicator(totalVotes: int, positiveVoting: bool) -> str:
"""Returns an indicator of the number of votes on a newswire item """Returns an indicator of the number of votes on a newswire item
""" """
if totalVotes <= 0: if totalVotes <= 0:
@ -177,7 +177,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
# show the newswire lines # show the newswire lines
newswireContentStr = \ newswireContentStr = \
htmlNewswire(baseDir, newswire, nickname, moderator, translate, _htmlNewswire(baseDir, newswire, nickname, moderator, translate,
positiveVoting) positiveVoting)
htmlStr += newswireContentStr htmlStr += newswireContentStr
@ -187,7 +187,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
return htmlStr return htmlStr
def htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool, def _htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
translate: {}, positiveVoting: bool) -> str: translate: {}, positiveVoting: bool) -> str:
"""Converts a newswire dict into html """Converts a newswire dict into html
""" """
@ -220,7 +220,7 @@ def htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
if moderator: if moderator:
totalVotes = votesOnNewswireItem(item[2]) totalVotes = votesOnNewswireItem(item[2])
totalVotesStr = \ totalVotesStr = \
votesIndicator(totalVotes, positiveVoting) _votesIndicator(totalVotes, positiveVoting)
title = removeLongWords(item[0], 16, []).replace('\n', '<br>') title = removeLongWords(item[0], 16, []).replace('\n', '<br>')
htmlStr += '<p class="newswireItemVotedOn">' + \ htmlStr += '<p class="newswireItemVotedOn">' + \
@ -247,7 +247,7 @@ def htmlNewswire(baseDir: str, newswire: {}, nickname: str, moderator: bool,
# show a number of ticks or crosses for how many # show a number of ticks or crosses for how many
# votes for or against # votes for or against
totalVotesStr = \ totalVotesStr = \
votesIndicator(totalVotes, positiveVoting) _votesIndicator(totalVotes, positiveVoting)
title = removeLongWords(item[0], 16, []).replace('\n', '<br>') title = removeLongWords(item[0], 16, []).replace('\n', '<br>')
if moderator and moderatedItem: if moderator and moderatedItem:

View File

@ -17,7 +17,7 @@ from webapp_utils import htmlHeaderWithExternalStyle
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
def htmlFollowingDataList(baseDir: str, nickname: str, def _htmlFollowingDataList(baseDir: str, nickname: str,
domain: str, domainFull: str) -> str: domain: str, domainFull: str) -> str:
"""Returns a datalist of handles being followed """Returns a datalist of handles being followed
""" """
@ -57,7 +57,7 @@ def htmlFollowingDataList(baseDir: str, nickname: str,
return listStr return listStr
def htmlNewPostDropDown(scopeIcon: str, scopeDescription: str, def _htmlNewPostDropDown(scopeIcon: str, scopeDescription: str,
replyStr: str, replyStr: str,
translate: {}, translate: {},
showPublicOnDropdown: bool, showPublicOnDropdown: bool,
@ -617,7 +617,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
dropDownContent = '' dropDownContent = ''
if not reportUrl and not shareDescription: if not reportUrl and not shareDescription:
dropDownContent = \ dropDownContent = \
htmlNewPostDropDown(scopeIcon, scopeDescription, _htmlNewPostDropDown(scopeIcon, scopeDescription,
replyStr, replyStr,
translate, translate,
showPublicOnDropdown, showPublicOnDropdown,
@ -717,7 +717,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
' <input type="text" name="mentions" ' + \ ' <input type="text" name="mentions" ' + \
'list="followingHandles" value="' + mentionsStr + '" selected>\n' 'list="followingHandles" value="' + mentionsStr + '" selected>\n'
newPostForm += \ newPostForm += \
htmlFollowingDataList(baseDir, nickname, domain, domainFull) _htmlFollowingDataList(baseDir, nickname, domain, domainFull)
newPostForm += '' newPostForm += ''
selectedStr = '' selectedStr = ''

View File

@ -20,7 +20,7 @@ from webapp_column_right import getRightColumnContent
from webapp_post import individualPostAsHtml from webapp_post import individualPostAsHtml
def htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int, def _htmlFrontScreenPosts(recentPostsCache: {}, maxRecentPosts: int,
translate: {}, translate: {},
baseDir: str, httpPrefix: str, baseDir: str, httpPrefix: str,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
@ -139,7 +139,7 @@ def htmlFrontScreen(rssIconAtTop: bool,
bannerFile, bannerFilename = \ bannerFile, bannerFilename = \
getBannerFile(baseDir, nickname, domain, theme) getBannerFile(baseDir, nickname, domain, theme)
profileStr += \ profileStr += \
htmlFrontScreenPosts(recentPostsCache, maxRecentPosts, _htmlFrontScreenPosts(recentPostsCache, maxRecentPosts,
translate, translate,
baseDir, httpPrefix, baseDir, httpPrefix,
nickname, domain, port, nickname, domain, port,

View File

@ -51,7 +51,7 @@ def getHashtagCategoriesFeed(baseDir: str,
return rssStr return rssStr
def getHashtagDomainMax(domainHistogram: {}) -> str: def _getHashtagDomainMax(domainHistogram: {}) -> str:
"""Returns the domain with the maximum number of hashtags """Returns the domain with the maximum number of hashtags
""" """
maxCount = 1 maxCount = 1
@ -63,7 +63,7 @@ def getHashtagDomainMax(domainHistogram: {}) -> str:
return maxDomain return maxDomain
def getHashtagDomainHistogram(domainHistogram: {}, translate: {}) -> str: def _getHashtagDomainHistogram(domainHistogram: {}, translate: {}) -> str:
"""Returns the html for a histogram of domains """Returns the html for a histogram of domains
from which hashtags are coming from which hashtags are coming
""" """
@ -88,7 +88,7 @@ def getHashtagDomainHistogram(domainHistogram: {}, translate: {}) -> str:
rightColStr = '' rightColStr = ''
for i in range(len(domainHistogram)): for i in range(len(domainHistogram)):
domain = getHashtagDomainMax(domainHistogram) domain = _getHashtagDomainMax(domainHistogram)
if not domain: if not domain:
break break
percent = int(domainHistogram[domain] * 100 / totalCount) percent = int(domainHistogram[domain] * 100 / totalCount)
@ -224,7 +224,7 @@ def htmlHashTagSwarm(baseDir: str, actor: str, translate: {}) -> str:
getContentWarningButton('alltags', translate, tagSwarmStr) getContentWarningButton('alltags', translate, tagSwarmStr)
tagSwarmHtml = categorySwarmStr + tagSwarmStr.strip() + '\n' tagSwarmHtml = categorySwarmStr + tagSwarmStr.strip() + '\n'
# tagSwarmHtml += getHashtagDomainHistogram(domainHistogram, translate) # tagSwarmHtml += _getHashtagDomainHistogram(domainHistogram, translate)
return tagSwarmHtml return tagSwarmHtml

View File

@ -7,7 +7,7 @@ __email__ = "bob@freedombone.net"
__status__ = "Production" __status__ = "Production"
def addEmbeddedVideoFromSites(translate: {}, content: str, def _addEmbeddedVideoFromSites(translate: {}, content: str,
width=400, height=300) -> str: width=400, height=300) -> str:
"""Adds embedded videos """Adds embedded videos
""" """
@ -122,7 +122,7 @@ def addEmbeddedVideoFromSites(translate: {}, content: str,
return content return content
def addEmbeddedAudio(translate: {}, content: str) -> str: def _addEmbeddedAudio(translate: {}, content: str) -> str:
"""Adds embedded audio for mp3/ogg """Adds embedded audio for mp3/ogg
""" """
if not ('.mp3' in content or '.ogg' in content): if not ('.mp3' in content or '.ogg' in content):
@ -167,7 +167,7 @@ def addEmbeddedAudio(translate: {}, content: str) -> str:
return content return content
def addEmbeddedVideo(translate: {}, content: str, def _addEmbeddedVideo(translate: {}, content: str,
width=400, height=300) -> str: width=400, height=300) -> str:
"""Adds embedded video for mp4/webm/ogv """Adds embedded video for mp4/webm/ogv
""" """
@ -219,6 +219,6 @@ def addEmbeddedVideo(translate: {}, content: str,
def addEmbeddedElements(translate: {}, content: str) -> str: def addEmbeddedElements(translate: {}, content: str) -> str:
"""Adds embedded elements for various media types """Adds embedded elements for various media types
""" """
content = addEmbeddedVideoFromSites(translate, content) content = _addEmbeddedVideoFromSites(translate, content)
content = addEmbeddedAudio(translate, content) content = _addEmbeddedAudio(translate, content)
return addEmbeddedVideo(translate, content) return _addEmbeddedVideo(translate, content)

View File

@ -63,7 +63,7 @@ from webapp_question import insertQuestion
from devices import E2EEdecryptMessageFromDevice from devices import E2EEdecryptMessageFromDevice
def logPostTiming(enableTimingLog: bool, postStartTime, debugId: str) -> None: def _logPostTiming(enableTimingLog: bool, postStartTime, debugId: str) -> None:
"""Create a log of timings for performance tuning """Create a log of timings for performance tuning
""" """
if not enableTimingLog: if not enableTimingLog:
@ -92,7 +92,7 @@ def preparePostFromHtmlCache(postHtml: str, boxName: str,
return withPageNumber return withPageNumber
def saveIndividualPostAsHtmlToCache(baseDir: str, def _saveIndividualPostAsHtmlToCache(baseDir: str,
nickname: str, domain: str, nickname: str, domain: str,
postJsonObject: {}, postJsonObject: {},
postHtml: str) -> bool: postHtml: str) -> bool:
@ -118,7 +118,7 @@ def saveIndividualPostAsHtmlToCache(baseDir: str,
return False return False
def getPostFromRecentCache(session, def _getPostFromRecentCache(session,
baseDir: str, baseDir: str,
httpPrefix: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
@ -157,13 +157,13 @@ def getPostFromRecentCache(session,
getPersonAvatarUrl(baseDir, postActor, personCache, getPersonAvatarUrl(baseDir, postActor, personCache,
allowDownloads) allowDownloads)
logPostTiming(enableTimingLog, postStartTime, '2.1') _logPostTiming(enableTimingLog, postStartTime, '2.1')
updateAvatarImageCache(session, baseDir, httpPrefix, updateAvatarImageCache(session, baseDir, httpPrefix,
postActor, avatarUrl, personCache, postActor, avatarUrl, personCache,
allowDownloads) allowDownloads)
logPostTiming(enableTimingLog, postStartTime, '2.2') _logPostTiming(enableTimingLog, postStartTime, '2.2')
postHtml = \ postHtml = \
loadIndividualPostAsHtmlFromCache(baseDir, nickname, domain, loadIndividualPostAsHtmlFromCache(baseDir, nickname, domain,
@ -174,11 +174,11 @@ def getPostFromRecentCache(session,
postHtml = preparePostFromHtmlCache(postHtml, boxName, pageNumber) postHtml = preparePostFromHtmlCache(postHtml, boxName, pageNumber)
updateRecentPostsCache(recentPostsCache, maxRecentPosts, updateRecentPostsCache(recentPostsCache, maxRecentPosts,
postJsonObject, postHtml) postJsonObject, postHtml)
logPostTiming(enableTimingLog, postStartTime, '3') _logPostTiming(enableTimingLog, postStartTime, '3')
return postHtml return postHtml
def getAvatarImageHtml(showAvatarOptions: bool, def _getAvatarImageHtml(showAvatarOptions: bool,
nickname: str, domainFull: str, nickname: str, domainFull: str,
avatarUrl: str, postActor: str, avatarUrl: str, postActor: str,
translate: {}, avatarPosition: str, translate: {}, avatarPosition: str,
@ -215,7 +215,7 @@ def getAvatarImageHtml(showAvatarOptions: bool,
return avatarLink.strip() return avatarLink.strip()
def getReplyIconHtml(nickname: str, isPublicRepeat: bool, def _getReplyIconHtml(nickname: str, isPublicRepeat: bool,
showIcons: bool, commentsEnabled: bool, showIcons: bool, commentsEnabled: bool,
postJsonObject: {}, pageNumberParam: str, postJsonObject: {}, pageNumberParam: str,
translate: {}) -> str: translate: {}) -> str:
@ -274,7 +274,7 @@ def getReplyIconHtml(nickname: str, isPublicRepeat: bool,
return replyStr return replyStr
def getEditIconHtml(baseDir: str, nickname: str, domainFull: str, def _getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
postJsonObject: {}, actorNickname: str, postJsonObject: {}, actorNickname: str,
translate: {}, isEvent: bool) -> str: translate: {}, isEvent: bool) -> str:
"""Returns html for the edit icon/button """Returns html for the edit icon/button
@ -330,7 +330,7 @@ def getEditIconHtml(baseDir: str, nickname: str, domainFull: str,
return editStr return editStr
def getAnnounceIconHtml(nickname: str, domainFull: str, def _getAnnounceIconHtml(nickname: str, domainFull: str,
postJsonObject: {}, postJsonObject: {},
isPublicRepeat: bool, isPublicRepeat: bool,
isModerationPost: bool, isModerationPost: bool,
@ -372,7 +372,7 @@ def getAnnounceIconHtml(nickname: str, domainFull: str,
return announceStr return announceStr
def getLikeIconHtml(nickname: str, domainFull: str, def _getLikeIconHtml(nickname: str, domainFull: str,
isModerationPost: bool, isModerationPost: bool,
showLikeButton: bool, showLikeButton: bool,
postJsonObject: {}, postJsonObject: {},
@ -390,7 +390,7 @@ def getLikeIconHtml(nickname: str, domainFull: str,
likeTitle = translate['Like this post'] likeTitle = translate['Like this post']
likeCount = noOfLikes(postJsonObject) likeCount = noOfLikes(postJsonObject)
logPostTiming(enableTimingLog, postStartTime, '12.1') _logPostTiming(enableTimingLog, postStartTime, '12.1')
likeCountStr = '' likeCountStr = ''
if likeCount > 0: if likeCount > 0:
@ -406,7 +406,7 @@ def getLikeIconHtml(nickname: str, domainFull: str,
likeLink = 'unlike' likeLink = 'unlike'
likeTitle = translate['Undo the like'] likeTitle = translate['Undo the like']
logPostTiming(enableTimingLog, postStartTime, '12.2') _logPostTiming(enableTimingLog, postStartTime, '12.2')
likeStr = '' likeStr = ''
if likeCountStr: if likeCountStr:
@ -430,7 +430,7 @@ def getLikeIconHtml(nickname: str, domainFull: str,
return likeStr return likeStr
def getBookmarkIconHtml(nickname: str, domainFull: str, def _getBookmarkIconHtml(nickname: str, domainFull: str,
postJsonObject: {}, postJsonObject: {},
isModerationPost: bool, isModerationPost: bool,
translate: {}, translate: {},
@ -452,7 +452,7 @@ def getBookmarkIconHtml(nickname: str, domainFull: str,
bookmarkIcon = 'bookmark.png' bookmarkIcon = 'bookmark.png'
bookmarkLink = 'unbookmark' bookmarkLink = 'unbookmark'
bookmarkTitle = translate['Undo the bookmark'] bookmarkTitle = translate['Undo the bookmark']
logPostTiming(enableTimingLog, postStartTime, '12.6') _logPostTiming(enableTimingLog, postStartTime, '12.6')
bookmarkStr = \ bookmarkStr = \
' <a class="imageAnchor" href="/users/' + nickname + '?' + \ ' <a class="imageAnchor" href="/users/' + nickname + '?' + \
bookmarkLink + '=' + postJsonObject['object']['id'] + \ bookmarkLink + '=' + postJsonObject['object']['id'] + \
@ -468,7 +468,7 @@ def getBookmarkIconHtml(nickname: str, domainFull: str,
return bookmarkStr return bookmarkStr
def getMuteIconHtml(isMuted: bool, def _getMuteIconHtml(isMuted: bool,
postActor: str, postActor: str,
messageId: str, messageId: str,
nickname: str, domainFull: str, nickname: str, domainFull: str,
@ -512,7 +512,7 @@ def getMuteIconHtml(isMuted: bool,
return muteStr return muteStr
def getDeleteIconHtml(nickname: str, domainFull: str, def _getDeleteIconHtml(nickname: str, domainFull: str,
allowDeletion: bool, allowDeletion: bool,
postActor: str, postActor: str,
messageId: str, messageId: str,
@ -541,7 +541,7 @@ def getDeleteIconHtml(nickname: str, domainFull: str,
return deleteStr return deleteStr
def getPublishedDateStr(postJsonObject: {}, def _getPublishedDateStr(postJsonObject: {},
showPublishedDateOnly: bool) -> str: showPublishedDateOnly: bool) -> str:
"""Return the html for the published date on a post """Return the html for the published date on a post
""" """
@ -575,7 +575,7 @@ def getPublishedDateStr(postJsonObject: {},
return publishedStr return publishedStr
def getBlogCitationsHtml(boxName: str, def _getBlogCitationsHtml(boxName: str,
postJsonObject: {}, postJsonObject: {},
translate: {}) -> str: translate: {}) -> str:
"""Returns blog citations as html """Returns blog citations as html
@ -609,7 +609,7 @@ def getBlogCitationsHtml(boxName: str,
return citationsStr return citationsStr
def boostOwnTootHtml(translate: {}) -> str: def _boostOwnTootHtml(translate: {}) -> str:
"""The html title for announcing your own post """The html title for announcing your own post
""" """
return ' <img loading="lazy" title="' + \ return ' <img loading="lazy" title="' + \
@ -619,7 +619,7 @@ def boostOwnTootHtml(translate: {}) -> str:
'/repeat_inactive.png" class="announceOrReply"/>\n' '/repeat_inactive.png" class="announceOrReply"/>\n'
def announceUnattributedHtml(translate: {}, def _announceUnattributedHtml(translate: {},
postJsonObject: {}) -> str: postJsonObject: {}) -> str:
"""Returns the html for an announce title where there """Returns the html for an announce title where there
is no attribution on the announced post is no attribution on the announced post
@ -634,7 +634,7 @@ def announceUnattributedHtml(translate: {},
'" class="announceOrReply">@unattributed</a>\n' '" class="announceOrReply">@unattributed</a>\n'
def announceWithoutDisplayNameHtml(translate: {}, def _announceWithoutDisplayNameHtml(translate: {},
announceNickname: str, announceNickname: str,
announceDomain: str, announceDomain: str,
postJsonObject: {}) -> str: postJsonObject: {}) -> str:
@ -650,7 +650,7 @@ def announceWithoutDisplayNameHtml(translate: {},
announceNickname + '@' + announceDomain + '</a>\n' announceNickname + '@' + announceDomain + '</a>\n'
def announceWithDisplayNameHtml(translate: {}, def _announceWithDisplayNameHtml(translate: {},
postJsonObject: {}, postJsonObject: {},
announceDisplayName: str) -> str: announceDisplayName: str) -> str:
"""Returns html for an announce having a display name """Returns html for an announce having a display name
@ -665,7 +665,7 @@ def announceWithDisplayNameHtml(translate: {},
'class="announceOrReply">' + announceDisplayName + '</a>\n' 'class="announceOrReply">' + announceDisplayName + '</a>\n'
def getPostTitleAnnounceHtml(baseDir: str, def _getPostTitleAnnounceHtml(baseDir: str,
httpPrefix: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
showRepeatIcon: bool, showRepeatIcon: bool,
@ -695,10 +695,10 @@ def getPostTitleAnnounceHtml(baseDir: str,
attributedTo = postJsonObject['object']['attributedTo'] attributedTo = postJsonObject['object']['attributedTo']
if attributedTo.startswith(postActor): if attributedTo.startswith(postActor):
titleStr += boostOwnTootHtml(translate) titleStr += _boostOwnTootHtml(translate)
else: else:
# boosting another person's post # boosting another person's post
logPostTiming(enableTimingLog, postStartTime, '13.2') _logPostTiming(enableTimingLog, postStartTime, '13.2')
announceNickname = None announceNickname = None
if attributedTo: if attributedTo:
announceNickname = getNicknameFromActor(attributedTo) announceNickname = getNicknameFromActor(attributedTo)
@ -710,7 +710,7 @@ def getPostTitleAnnounceHtml(baseDir: str,
announceDisplayName = \ announceDisplayName = \
getDisplayName(baseDir, attributedTo, personCache) getDisplayName(baseDir, attributedTo, personCache)
if announceDisplayName: if announceDisplayName:
logPostTiming(enableTimingLog, postStartTime, '13.3') _logPostTiming(enableTimingLog, postStartTime, '13.3')
# add any emoji to the display name # add any emoji to the display name
if ':' in announceDisplayName: if ':' in announceDisplayName:
@ -719,9 +719,9 @@ def getPostTitleAnnounceHtml(baseDir: str,
nickname, domain, nickname, domain,
announceDisplayName, announceDisplayName,
False) False)
logPostTiming(enableTimingLog, postStartTime, '13.3.1') _logPostTiming(enableTimingLog, postStartTime, '13.3.1')
titleStr += \ titleStr += \
announceWithDisplayNameHtml(translate, _announceWithDisplayNameHtml(translate,
postJsonObject, postJsonObject,
announceDisplayName) announceDisplayName)
# show avatar of person replied to # show avatar of person replied to
@ -731,7 +731,7 @@ def getPostTitleAnnounceHtml(baseDir: str,
getPersonAvatarUrl(baseDir, announceActor, getPersonAvatarUrl(baseDir, announceActor,
personCache, allowDownloads) personCache, allowDownloads)
logPostTiming(enableTimingLog, postStartTime, '13.4') _logPostTiming(enableTimingLog, postStartTime, '13.4')
if announceAvatarUrl: if announceAvatarUrl:
idx = 'Show options for this person' idx = 'Show options for this person'
@ -756,23 +756,23 @@ def getPostTitleAnnounceHtml(baseDir: str,
'/></a>\n </div>\n' '/></a>\n </div>\n'
else: else:
titleStr += \ titleStr += \
announceWithoutDisplayNameHtml(translate, _announceWithoutDisplayNameHtml(translate,
announceNickname, announceNickname,
announceDomain, announceDomain,
postJsonObject) postJsonObject)
else: else:
titleStr += \ titleStr += \
announceUnattributedHtml(translate, _announceUnattributedHtml(translate,
postJsonObject) postJsonObject)
else: else:
titleStr += \ titleStr += \
announceUnattributedHtml(translate, postJsonObject) _announceUnattributedHtml(translate, postJsonObject)
return (titleStr, replyAvatarImageInPost, return (titleStr, replyAvatarImageInPost,
containerClassIcons, containerClass) containerClassIcons, containerClass)
def replyToYourselfHtml(translate: {}, ) -> str: def _replyToYourselfHtml(translate: {}, ) -> str:
"""Returns html for a title which is a reply to yourself """Returns html for a title which is a reply to yourself
""" """
return ' <img loading="lazy" title="' + \ return ' <img loading="lazy" title="' + \
@ -782,7 +782,7 @@ def replyToYourselfHtml(translate: {}, ) -> str:
'/reply.png" class="announceOrReply"/>\n' '/reply.png" class="announceOrReply"/>\n'
def replyToUnknownHtml(translate: {}, def _replyToUnknownHtml(translate: {},
postJsonObject: {}) -> str: postJsonObject: {}) -> str:
"""Returns the html title for a reply to an unknown handle """Returns the html title for a reply to an unknown handle
""" """
@ -795,7 +795,7 @@ def replyToUnknownHtml(translate: {},
'" class="announceOrReply">@unknown</a>\n' '" class="announceOrReply">@unknown</a>\n'
def replyWithUnknownPathHtml(translate: {}, def _replyWithUnknownPathHtml(translate: {},
postJsonObject: {}, postJsonObject: {},
postDomain: str) -> str: postDomain: str) -> str:
"""Returns html title for a reply with an unknown path """Returns html title for a reply with an unknown path
@ -812,7 +812,7 @@ def replyWithUnknownPathHtml(translate: {},
postDomain + '</a>\n' postDomain + '</a>\n'
def getReplyHtml(translate: {}, def _getReplyHtml(translate: {},
inReplyTo: str, replyDisplayName: str) -> str: inReplyTo: str, replyDisplayName: str) -> str:
"""Returns html title for a reply """Returns html title for a reply
""" """
@ -827,7 +827,7 @@ def getReplyHtml(translate: {},
replyDisplayName + '</a>\n' replyDisplayName + '</a>\n'
def getReplyWithoutDisplayName(translate: {}, def _getReplyWithoutDisplayName(translate: {},
inReplyTo: str, inReplyTo: str,
replyNickname: str, replyDomain: str) -> str: replyNickname: str, replyDomain: str) -> str:
"""Returns html for a reply without a display name, """Returns html for a reply without a display name,
@ -842,7 +842,7 @@ def getReplyWithoutDisplayName(translate: {},
replyNickname + '@' + replyDomain + '</a>\n' replyNickname + '@' + replyDomain + '</a>\n'
def getPostTitleReplyHtml(baseDir: str, def _getPostTitleReplyHtml(baseDir: str,
httpPrefix: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
showRepeatIcon: bool, showRepeatIcon: bool,
@ -873,7 +873,7 @@ def getPostTitleReplyHtml(baseDir: str,
containerClassIcons = 'containericons darker' containerClassIcons = 'containericons darker'
containerClass = 'container darker' containerClass = 'container darker'
if postJsonObject['object']['inReplyTo'].startswith(postActor): if postJsonObject['object']['inReplyTo'].startswith(postActor):
titleStr += replyToYourselfHtml(translate) titleStr += _replyToYourselfHtml(translate)
return (titleStr, replyAvatarImageInPost, return (titleStr, replyAvatarImageInPost,
containerClassIcons, containerClass) containerClassIcons, containerClass)
@ -894,7 +894,7 @@ def getPostTitleReplyHtml(baseDir: str,
if replyDisplayName: if replyDisplayName:
# add emoji to the display name # add emoji to the display name
if ':' in replyDisplayName: if ':' in replyDisplayName:
logPostTiming(enableTimingLog, postStartTime, '13.5') _logPostTiming(enableTimingLog, postStartTime, '13.5')
replyDisplayName = \ replyDisplayName = \
addEmojiToDisplayName(baseDir, addEmojiToDisplayName(baseDir,
@ -903,12 +903,12 @@ def getPostTitleReplyHtml(baseDir: str,
domain, domain,
replyDisplayName, replyDisplayName,
False) False)
logPostTiming(enableTimingLog, postStartTime, '13.6') _logPostTiming(enableTimingLog, postStartTime, '13.6')
titleStr += \ titleStr += \
getReplyHtml(translate, inReplyTo, replyDisplayName) _getReplyHtml(translate, inReplyTo, replyDisplayName)
logPostTiming(enableTimingLog, postStartTime, '13.7') _logPostTiming(enableTimingLog, postStartTime, '13.7')
# show avatar of person replied to # show avatar of person replied to
replyAvatarUrl = \ replyAvatarUrl = \
@ -917,7 +917,7 @@ def getPostTitleReplyHtml(baseDir: str,
personCache, personCache,
allowDownloads) allowDownloads)
logPostTiming(enableTimingLog, postStartTime, '13.8') _logPostTiming(enableTimingLog, postStartTime, '13.8')
if replyAvatarUrl: if replyAvatarUrl:
replyAvatarImageInPost = \ replyAvatarImageInPost = \
@ -947,12 +947,13 @@ def getPostTitleReplyHtml(baseDir: str,
inReplyTo = \ inReplyTo = \
postJsonObject['object']['inReplyTo'] postJsonObject['object']['inReplyTo']
titleStr += \ titleStr += \
getReplyWithoutDisplayName(translate, _getReplyWithoutDisplayName(translate,
inReplyTo, inReplyTo,
replyNickname, replyDomain) replyNickname,
replyDomain)
else: else:
titleStr += \ titleStr += \
replyToUnknownHtml(translate, postJsonObject) _replyToUnknownHtml(translate, postJsonObject)
else: else:
postDomain = \ postDomain = \
postJsonObject['object']['inReplyTo'] postJsonObject['object']['inReplyTo']
@ -963,14 +964,14 @@ def getPostTitleReplyHtml(baseDir: str,
postDomain = postDomain.split('/', 1)[0] postDomain = postDomain.split('/', 1)[0]
if postDomain: if postDomain:
titleStr += \ titleStr += \
replyWithUnknownPathHtml(translate, _replyWithUnknownPathHtml(translate,
postJsonObject, postDomain) postJsonObject, postDomain)
return (titleStr, replyAvatarImageInPost, return (titleStr, replyAvatarImageInPost,
containerClassIcons, containerClass) containerClassIcons, containerClass)
def getPostTitleHtml(baseDir: str, def _getPostTitleHtml(baseDir: str,
httpPrefix: str, httpPrefix: str,
nickname: str, domain: str, nickname: str, domain: str,
showRepeatIcon: bool, showRepeatIcon: bool,
@ -998,7 +999,7 @@ def getPostTitleHtml(baseDir: str,
containerClassIcons, containerClass) containerClassIcons, containerClass)
if isAnnounced: if isAnnounced:
return getPostTitleAnnounceHtml(baseDir, return _getPostTitleAnnounceHtml(baseDir,
httpPrefix, httpPrefix,
nickname, domain, nickname, domain,
showRepeatIcon, showRepeatIcon,
@ -1017,7 +1018,7 @@ def getPostTitleHtml(baseDir: str,
containerClassIcons, containerClassIcons,
containerClass) containerClass)
return getPostTitleReplyHtml(baseDir, return _getPostTitleReplyHtml(baseDir,
httpPrefix, httpPrefix,
nickname, domain, nickname, domain,
showRepeatIcon, showRepeatIcon,
@ -1037,7 +1038,7 @@ def getPostTitleHtml(baseDir: str,
containerClass) containerClass)
def getFooterWithIcons(showIcons: bool, def _getFooterWithIcons(showIcons: bool,
containerClassIcons: str, containerClassIcons: str,
replyStr: str, announceStr: str, replyStr: str, announceStr: str,
likeStr: str, bookmarkStr: str, likeStr: str, bookmarkStr: str,
@ -1098,14 +1099,14 @@ def individualPostAsHtml(allowDownloads: bool,
# accurate timing of different parts of the code # accurate timing of different parts of the code
enableTimingLog = not allowDownloads enableTimingLog = not allowDownloads
logPostTiming(enableTimingLog, postStartTime, '1') _logPostTiming(enableTimingLog, postStartTime, '1')
avatarPosition = '' avatarPosition = ''
messageId = '' messageId = ''
if postJsonObject.get('id'): if postJsonObject.get('id'):
messageId = removeIdEnding(postJsonObject['id']) messageId = removeIdEnding(postJsonObject['id'])
logPostTiming(enableTimingLog, postStartTime, '2') _logPostTiming(enableTimingLog, postStartTime, '2')
messageIdStr = '' messageIdStr = ''
if messageId: if messageId:
@ -1119,7 +1120,7 @@ def individualPostAsHtml(allowDownloads: bool,
# get the html post from the recent posts cache if it exists there # get the html post from the recent posts cache if it exists there
postHtml = \ postHtml = \
getPostFromRecentCache(session, baseDir, _getPostFromRecentCache(session, baseDir,
httpPrefix, nickname, domain, httpPrefix, nickname, domain,
postJsonObject, postJsonObject,
postActor, postActor,
@ -1137,7 +1138,7 @@ def individualPostAsHtml(allowDownloads: bool,
if postHtml: if postHtml:
return postHtml return postHtml
logPostTiming(enableTimingLog, postStartTime, '4') _logPostTiming(enableTimingLog, postStartTime, '4')
avatarUrl = \ avatarUrl = \
getAvatarImageUrl(session, getAvatarImageUrl(session,
@ -1145,7 +1146,7 @@ def individualPostAsHtml(allowDownloads: bool,
postActor, personCache, postActor, personCache,
avatarUrl, allowDownloads) avatarUrl, allowDownloads)
logPostTiming(enableTimingLog, postStartTime, '5') _logPostTiming(enableTimingLog, postStartTime, '5')
# get the display name # get the display name
if domainFull not in postActor: if domainFull not in postActor:
@ -1156,7 +1157,7 @@ def individualPostAsHtml(allowDownloads: bool,
projectVersion, httpPrefix, projectVersion, httpPrefix,
nickname, domain, 'outbox', nickname, domain, 'outbox',
72367) 72367)
logPostTiming(enableTimingLog, postStartTime, '6') _logPostTiming(enableTimingLog, postStartTime, '6')
if avatarUrl2: if avatarUrl2:
avatarUrl = avatarUrl2 avatarUrl = avatarUrl2
@ -1168,10 +1169,10 @@ def individualPostAsHtml(allowDownloads: bool,
nickname, domain, nickname, domain,
displayName, False) displayName, False)
logPostTiming(enableTimingLog, postStartTime, '7') _logPostTiming(enableTimingLog, postStartTime, '7')
avatarLink = \ avatarLink = \
getAvatarImageHtml(showAvatarOptions, _getAvatarImageHtml(showAvatarOptions,
nickname, domainFull, nickname, domainFull,
avatarUrl, postActor, avatarUrl, postActor,
translate, avatarPosition, translate, avatarPosition,
@ -1215,7 +1216,7 @@ def individualPostAsHtml(allowDownloads: bool,
postJsonObject = postJsonAnnounce postJsonObject = postJsonAnnounce
isAnnounced = True isAnnounced = True
logPostTiming(enableTimingLog, postStartTime, '8') _logPostTiming(enableTimingLog, postStartTime, '8')
if not isinstance(postJsonObject['object'], dict): if not isinstance(postJsonObject['object'], dict):
return '' return ''
@ -1266,7 +1267,7 @@ def individualPostAsHtml(allowDownloads: bool,
'">@' + actorNickname + '@' + actorDomain + '</a>\n' '">@' + actorNickname + '@' + actorDomain + '</a>\n'
# benchmark 9 # benchmark 9
logPostTiming(enableTimingLog, postStartTime, '9') _logPostTiming(enableTimingLog, postStartTime, '9')
# Show a DM icon for DMs in the inbox timeline # Show a DM icon for DMs in the inbox timeline
if showDMicon: if showDMicon:
@ -1280,23 +1281,23 @@ def individualPostAsHtml(allowDownloads: bool,
if postJsonObject['object']['commentsEnabled'] is False: if postJsonObject['object']['commentsEnabled'] is False:
commentsEnabled = False commentsEnabled = False
replyStr = getReplyIconHtml(nickname, isPublicRepeat, replyStr = _getReplyIconHtml(nickname, isPublicRepeat,
showIcons, commentsEnabled, showIcons, commentsEnabled,
postJsonObject, pageNumberParam, postJsonObject, pageNumberParam,
translate) translate)
logPostTiming(enableTimingLog, postStartTime, '10') _logPostTiming(enableTimingLog, postStartTime, '10')
isEvent = isEventPost(postJsonObject) isEvent = isEventPost(postJsonObject)
logPostTiming(enableTimingLog, postStartTime, '11') _logPostTiming(enableTimingLog, postStartTime, '11')
editStr = getEditIconHtml(baseDir, nickname, domainFull, editStr = _getEditIconHtml(baseDir, nickname, domainFull,
postJsonObject, actorNickname, postJsonObject, actorNickname,
translate, isEvent) translate, isEvent)
announceStr = \ announceStr = \
getAnnounceIconHtml(nickname, domainFull, _getAnnounceIconHtml(nickname, domainFull,
postJsonObject, postJsonObject,
isPublicRepeat, isPublicRepeat,
isModerationPost, isModerationPost,
@ -1306,7 +1307,7 @@ def individualPostAsHtml(allowDownloads: bool,
timelinePostBookmark, timelinePostBookmark,
boxName) boxName)
logPostTiming(enableTimingLog, postStartTime, '12') _logPostTiming(enableTimingLog, postStartTime, '12')
# whether to show a like button # whether to show a like button
hideLikeButtonFile = \ hideLikeButtonFile = \
@ -1315,7 +1316,7 @@ def individualPostAsHtml(allowDownloads: bool,
if os.path.isfile(hideLikeButtonFile): if os.path.isfile(hideLikeButtonFile):
showLikeButton = False showLikeButton = False
likeStr = getLikeIconHtml(nickname, domainFull, likeStr = _getLikeIconHtml(nickname, domainFull,
isModerationPost, isModerationPost,
showLikeButton, showLikeButton,
postJsonObject, postJsonObject,
@ -1325,10 +1326,10 @@ def individualPostAsHtml(allowDownloads: bool,
timelinePostBookmark, timelinePostBookmark,
boxName) boxName)
logPostTiming(enableTimingLog, postStartTime, '12.5') _logPostTiming(enableTimingLog, postStartTime, '12.5')
bookmarkStr = \ bookmarkStr = \
getBookmarkIconHtml(nickname, domainFull, _getBookmarkIconHtml(nickname, domainFull,
postJsonObject, postJsonObject,
isModerationPost, isModerationPost,
translate, translate,
@ -1337,14 +1338,14 @@ def individualPostAsHtml(allowDownloads: bool,
pageNumberParam, pageNumberParam,
timelinePostBookmark) timelinePostBookmark)
logPostTiming(enableTimingLog, postStartTime, '12.9') _logPostTiming(enableTimingLog, postStartTime, '12.9')
isMuted = postIsMuted(baseDir, nickname, domain, postJsonObject, messageId) isMuted = postIsMuted(baseDir, nickname, domain, postJsonObject, messageId)
logPostTiming(enableTimingLog, postStartTime, '13') _logPostTiming(enableTimingLog, postStartTime, '13')
muteStr = \ muteStr = \
getMuteIconHtml(isMuted, _getMuteIconHtml(isMuted,
postActor, postActor,
messageId, messageId,
nickname, domainFull, nickname, domainFull,
@ -1355,7 +1356,7 @@ def individualPostAsHtml(allowDownloads: bool,
translate) translate)
deleteStr = \ deleteStr = \
getDeleteIconHtml(nickname, domainFull, _getDeleteIconHtml(nickname, domainFull,
allowDeletion, allowDeletion,
postActor, postActor,
messageId, messageId,
@ -1363,13 +1364,13 @@ def individualPostAsHtml(allowDownloads: bool,
pageNumberParam, pageNumberParam,
translate) translate)
logPostTiming(enableTimingLog, postStartTime, '13.1') _logPostTiming(enableTimingLog, postStartTime, '13.1')
# get the title: x replies to y, x announces y, etc # get the title: x replies to y, x announces y, etc
(titleStr2, (titleStr2,
replyAvatarImageInPost, replyAvatarImageInPost,
containerClassIcons, containerClassIcons,
containerClass) = getPostTitleHtml(baseDir, containerClass) = _getPostTitleHtml(baseDir,
httpPrefix, httpPrefix,
nickname, domain, nickname, domain,
showRepeatIcon, showRepeatIcon,
@ -1389,7 +1390,7 @@ def individualPostAsHtml(allowDownloads: bool,
containerClass) containerClass)
titleStr += titleStr2 titleStr += titleStr2
logPostTiming(enableTimingLog, postStartTime, '14') _logPostTiming(enableTimingLog, postStartTime, '14')
attachmentStr, galleryStr = \ attachmentStr, galleryStr = \
getPostAttachmentsAsHtml(postJsonObject, boxName, translate, getPostAttachmentsAsHtml(postJsonObject, boxName, translate,
@ -1398,9 +1399,9 @@ def individualPostAsHtml(allowDownloads: bool,
bookmarkStr, deleteStr, muteStr) bookmarkStr, deleteStr, muteStr)
publishedStr = \ publishedStr = \
getPublishedDateStr(postJsonObject, showPublishedDateOnly) _getPublishedDateStr(postJsonObject, showPublishedDateOnly)
logPostTiming(enableTimingLog, postStartTime, '15') _logPostTiming(enableTimingLog, postStartTime, '15')
publishedLink = messageId publishedLink = messageId
# blog posts should have no /statuses/ in their link # blog posts should have no /statuses/ in their link
@ -1427,7 +1428,7 @@ def individualPostAsHtml(allowDownloads: bool,
containerClassIcons = 'containericons dm' containerClassIcons = 'containericons dm'
containerClass = 'container dm' containerClass = 'container dm'
newFooterStr = getFooterWithIcons(showIcons, newFooterStr = _getFooterWithIcons(showIcons,
containerClassIcons, containerClassIcons,
replyStr, announceStr, replyStr, announceStr,
likeStr, bookmarkStr, likeStr, bookmarkStr,
@ -1466,7 +1467,7 @@ def individualPostAsHtml(allowDownloads: bool,
postJsonObject['object']['summary'], postJsonObject['object']['summary'],
postJsonObject['object']['content']) postJsonObject['object']['content'])
logPostTiming(enableTimingLog, postStartTime, '16') _logPostTiming(enableTimingLog, postStartTime, '16')
if not isPatch: if not isPatch:
objectContent = \ objectContent = \
@ -1509,7 +1510,7 @@ def individualPostAsHtml(allowDownloads: bool,
else: else:
contentStr += cwContentStr contentStr += cwContentStr
logPostTiming(enableTimingLog, postStartTime, '17') _logPostTiming(enableTimingLog, postStartTime, '17')
if postJsonObject['object'].get('tag') and not isPatch: if postJsonObject['object'].get('tag') and not isPatch:
contentStr = \ contentStr = \
@ -1531,7 +1532,7 @@ def individualPostAsHtml(allowDownloads: bool,
# show blog citations # show blog citations
citationsStr = \ citationsStr = \
getBlogCitationsHtml(boxName, postJsonObject, translate) _getBlogCitationsHtml(boxName, postJsonObject, translate)
postHtml = '' postHtml = ''
if boxName != 'tlmedia': if boxName != 'tlmedia':
@ -1546,18 +1547,18 @@ def individualPostAsHtml(allowDownloads: bool,
else: else:
postHtml = galleryStr postHtml = galleryStr
logPostTiming(enableTimingLog, postStartTime, '18') _logPostTiming(enableTimingLog, postStartTime, '18')
# save the created html to the recent posts cache # save the created html to the recent posts cache
if not showPublicOnly and storeToCache and \ if not showPublicOnly and storeToCache and \
boxName != 'tlmedia' and boxName != 'tlbookmarks' and \ boxName != 'tlmedia' and boxName != 'tlbookmarks' and \
boxName != 'bookmarks': boxName != 'bookmarks':
saveIndividualPostAsHtmlToCache(baseDir, nickname, domain, _saveIndividualPostAsHtmlToCache(baseDir, nickname, domain,
postJsonObject, postHtml) postJsonObject, postHtml)
updateRecentPostsCache(recentPostsCache, maxRecentPosts, updateRecentPostsCache(recentPostsCache, maxRecentPosts,
postJsonObject, postHtml) postJsonObject, postHtml)
logPostTiming(enableTimingLog, postStartTime, '19') _logPostTiming(enableTimingLog, postStartTime, '19')
return postHtml return postHtml

View File

@ -214,7 +214,7 @@ def htmlProfileAfterSearch(cssCache: {},
imageUrl = profileJson['image']['url'] imageUrl = profileJson['image']['url']
profileStr = \ profileStr = \
getProfileHeaderAfterSearch(baseDir, _getProfileHeaderAfterSearch(baseDir,
nickname, defaultTimeline, nickname, defaultTimeline,
searchNickname, searchNickname,
searchDomainFull, searchDomainFull,
@ -287,7 +287,7 @@ def htmlProfileAfterSearch(cssCache: {},
return htmlHeaderWithExternalStyle(cssFilename) + profileStr + htmlFooter() return htmlHeaderWithExternalStyle(cssFilename) + profileStr + htmlFooter()
def getProfileHeader(baseDir: str, nickname: str, domain: str, def _getProfileHeader(baseDir: str, nickname: str, domain: str,
domainFull: str, translate: {}, domainFull: str, translate: {},
defaultTimeline: str, defaultTimeline: str,
displayName: str, displayName: str,
@ -327,7 +327,7 @@ def getProfileHeader(baseDir: str, nickname: str, domain: str,
return htmlStr return htmlStr
def getProfileHeaderAfterSearch(baseDir: str, def _getProfileHeaderAfterSearch(baseDir: str,
nickname: str, defaultTimeline: str, nickname: str, defaultTimeline: str,
searchNickname: str, searchNickname: str,
searchDomainFull: str, searchDomainFull: str,
@ -568,7 +568,7 @@ def htmlProfile(rssIconAtTop: bool,
avatarUrl = profileJson['icon']['url'] avatarUrl = profileJson['icon']['url']
profileHeaderStr = \ profileHeaderStr = \
getProfileHeader(baseDir, nickname, domain, _getProfileHeader(baseDir, nickname, domain,
domainFull, translate, domainFull, translate,
defaultTimeline, displayName, defaultTimeline, displayName,
avatarDescription, avatarDescription,
@ -621,7 +621,7 @@ def htmlProfile(rssIconAtTop: bool,
if selected == 'posts': if selected == 'posts':
profileStr += \ profileStr += \
htmlProfilePosts(recentPostsCache, maxRecentPosts, _htmlProfilePosts(recentPostsCache, maxRecentPosts,
translate, translate,
baseDir, httpPrefix, authorized, baseDir, httpPrefix, authorized,
nickname, domain, port, nickname, domain, port,
@ -631,7 +631,7 @@ def htmlProfile(rssIconAtTop: bool,
showPublishedDateOnly) + licenseStr showPublishedDateOnly) + licenseStr
elif selected == 'following': elif selected == 'following':
profileStr += \ profileStr += \
htmlProfileFollowing(translate, baseDir, httpPrefix, _htmlProfileFollowing(translate, baseDir, httpPrefix,
authorized, nickname, authorized, nickname,
domain, port, session, domain, port, session,
wfRequest, personCache, extraJson, wfRequest, personCache, extraJson,
@ -640,7 +640,7 @@ def htmlProfile(rssIconAtTop: bool,
dormantMonths) dormantMonths)
elif selected == 'followers': elif selected == 'followers':
profileStr += \ profileStr += \
htmlProfileFollowing(translate, baseDir, httpPrefix, _htmlProfileFollowing(translate, baseDir, httpPrefix,
authorized, nickname, authorized, nickname,
domain, port, session, domain, port, session,
wfRequest, personCache, extraJson, wfRequest, personCache, extraJson,
@ -649,14 +649,14 @@ def htmlProfile(rssIconAtTop: bool,
maxItemsPerPage, dormantMonths) maxItemsPerPage, dormantMonths)
elif selected == 'roles': elif selected == 'roles':
profileStr += \ profileStr += \
htmlProfileRoles(translate, nickname, domainFull, _htmlProfileRoles(translate, nickname, domainFull,
extraJson) extraJson)
elif selected == 'skills': elif selected == 'skills':
profileStr += \ profileStr += \
htmlProfileSkills(translate, nickname, domainFull, extraJson) _htmlProfileSkills(translate, nickname, domainFull, extraJson)
elif selected == 'shares': elif selected == 'shares':
profileStr += \ profileStr += \
htmlProfileShares(actor, translate, _htmlProfileShares(actor, translate,
nickname, domainFull, nickname, domainFull,
extraJson) + licenseStr extraJson) + licenseStr
@ -666,7 +666,7 @@ def htmlProfile(rssIconAtTop: bool,
return profileStr return profileStr
def htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int, def _htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
translate: {}, translate: {},
baseDir: str, httpPrefix: str, baseDir: str, httpPrefix: str,
authorized: bool, authorized: bool,
@ -720,7 +720,7 @@ def htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
return profileStr return profileStr
def htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str, def _htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str,
authorized: bool, authorized: bool,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
session, wfRequest: {}, personCache: {}, session, wfRequest: {}, personCache: {},
@ -756,7 +756,7 @@ def htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str,
dormantMonths) dormantMonths)
profileStr += \ profileStr += \
individualFollowAsHtml(translate, baseDir, session, _individualFollowAsHtml(translate, baseDir, session,
wfRequest, personCache, wfRequest, personCache,
domain, followingActor, domain, followingActor,
authorized, nickname, authorized, nickname,
@ -778,7 +778,7 @@ def htmlProfileFollowing(translate: {}, baseDir: str, httpPrefix: str,
return profileStr return profileStr
def htmlProfileRoles(translate: {}, nickname: str, domain: str, def _htmlProfileRoles(translate: {}, nickname: str, domain: str,
rolesJson: {}) -> str: rolesJson: {}) -> str:
"""Shows roles on the profile screen """Shows roles on the profile screen
""" """
@ -801,7 +801,7 @@ def htmlProfileRoles(translate: {}, nickname: str, domain: str,
return profileStr return profileStr
def htmlProfileSkills(translate: {}, nickname: str, domain: str, def _htmlProfileSkills(translate: {}, nickname: str, domain: str,
skillsJson: {}) -> str: skillsJson: {}) -> str:
"""Shows skills on the profile screen """Shows skills on the profile screen
""" """
@ -817,7 +817,7 @@ def htmlProfileSkills(translate: {}, nickname: str, domain: str,
return profileStr return profileStr
def htmlProfileShares(actor: str, translate: {}, def _htmlProfileShares(actor: str, translate: {},
nickname: str, domain: str, sharesJson: {}) -> str: nickname: str, domain: str, sharesJson: {}) -> str:
"""Shows shares on the profile screen """Shows shares on the profile screen
""" """
@ -1450,7 +1450,7 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
return editProfileForm return editProfileForm
def individualFollowAsHtml(translate: {}, def _individualFollowAsHtml(translate: {},
baseDir: str, session, wfRequest: {}, baseDir: str, session, wfRequest: {},
personCache: {}, domain: str, personCache: {}, domain: str,
followUrl: str, followUrl: str,

View File

@ -27,7 +27,7 @@ from webapp_headerbuttons import headerButtonsTimeline
from posts import isModerator from posts import isModerator
def logTimelineTiming(enableTimingLog: bool, timelineStartTime, def _logTimelineTiming(enableTimingLog: bool, timelineStartTime,
boxName: str, debugId: str) -> None: boxName: str, debugId: str) -> None:
"""Create a log of timings for performance tuning """Create a log of timings for performance tuning
""" """
@ -127,7 +127,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
bannerFile, bannerFilename = \ bannerFile, bannerFilename = \
getBannerFile(baseDir, nickname, domain, theme) getBannerFile(baseDir, nickname, domain, theme)
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '1') _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '1')
# is the user a moderator? # is the user a moderator?
if not moderator: if not moderator:
@ -137,7 +137,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
if not editor: if not editor:
editor = isEditor(baseDir, nickname) editor = isEditor(baseDir, nickname)
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '2') _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '2')
# the appearance of buttons - highlighted or not # the appearance of buttons - highlighted or not
inboxButton = 'button' inboxButton = 'button'
@ -221,7 +221,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
'" src="/icons/person.png"/></a>\n' '" src="/icons/person.png"/></a>\n'
break break
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '3') _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '3')
# moderation / reports button # moderation / reports button
moderationButtonStr = '' moderationButtonStr = ''
@ -256,7 +256,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
tlStr = htmlHeaderWithExternalStyle(cssFilename) tlStr = htmlHeaderWithExternalStyle(cssFilename)
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '4') _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '4')
# if this is a news instance and we are viewing the news timeline # if this is a news instance and we are viewing the news timeline
newsHeader = False newsHeader = False
@ -487,17 +487,17 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
tlStr += '</div>\n</form>\n' tlStr += '</div>\n</form>\n'
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '6') _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '6')
if boxName == 'tlshares': if boxName == 'tlshares':
maxSharesPerAccount = itemsPerPage maxSharesPerAccount = itemsPerPage
return (tlStr + return (tlStr +
htmlSharesTimeline(translate, pageNumber, itemsPerPage, _htmlSharesTimeline(translate, pageNumber, itemsPerPage,
baseDir, actor, nickname, domain, port, baseDir, actor, nickname, domain, port,
maxSharesPerAccount, httpPrefix) + maxSharesPerAccount, httpPrefix) +
htmlFooter()) htmlFooter())
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '7') _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '7')
# page up arrow # page up arrow
if pageNumber > 1: if pageNumber > 1:
@ -543,12 +543,12 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
preparePostFromHtmlCache(currTlStr, preparePostFromHtmlCache(currTlStr,
boxName, boxName,
pageNumber) pageNumber)
logTimelineTiming(enableTimingLog, _logTimelineTiming(enableTimingLog,
timelineStartTime, timelineStartTime,
boxName, '10') boxName, '10')
if not currTlStr: if not currTlStr:
logTimelineTiming(enableTimingLog, _logTimelineTiming(enableTimingLog,
timelineStartTime, timelineStartTime,
boxName, '11') boxName, '11')
@ -570,7 +570,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
showIndividualPostIcons, showIndividualPostIcons,
manuallyApproveFollowers, manuallyApproveFollowers,
False, True) False, True)
logTimelineTiming(enableTimingLog, _logTimelineTiming(enableTimingLog,
timelineStartTime, boxName, '12') timelineStartTime, boxName, '12')
if currTlStr: if currTlStr:
@ -612,7 +612,7 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
rightColumnStr + ' </td>\n' rightColumnStr + ' </td>\n'
tlStr += ' </tr>\n' tlStr += ' </tr>\n'
logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '9') _logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '9')
tlStr += ' </tbody>\n' tlStr += ' </tbody>\n'
tlStr += '</table>\n' tlStr += '</table>\n'
@ -656,7 +656,7 @@ def htmlIndividualShare(actor: str, item: {}, translate: {},
return profileStr return profileStr
def htmlSharesTimeline(translate: {}, pageNumber: int, itemsPerPage: int, def _htmlSharesTimeline(translate: {}, pageNumber: int, itemsPerPage: int,
baseDir: str, actor: str, baseDir: str, actor: str,
nickname: str, domain: str, port: int, nickname: str, domain: str, port: int,
maxSharesPerAccount: int, httpPrefix: str) -> str: maxSharesPerAccount: int, httpPrefix: str) -> str:

View File

@ -167,7 +167,7 @@ def getContentWarningButton(postID: str, translate: {},
'</div></details>\n' '</div></details>\n'
def getActorPropertyUrl(actorJson: {}, propertyName: str) -> str: def _getActorPropertyUrl(actorJson: {}, propertyName: str) -> str:
"""Returns a url property from an actor """Returns a url property from an actor
""" """
if not actorJson.get('attachment'): if not actorJson.get('attachment'):
@ -206,10 +206,10 @@ def getActorPropertyUrl(actorJson: {}, propertyName: str) -> str:
def getBlogAddress(actorJson: {}) -> str: def getBlogAddress(actorJson: {}) -> str:
"""Returns blog address for the given actor """Returns blog address for the given actor
""" """
return getActorPropertyUrl(actorJson, 'Blog') return _getActorPropertyUrl(actorJson, 'Blog')
def setActorPropertyUrl(actorJson: {}, propertyName: str, url: str) -> None: def _setActorPropertyUrl(actorJson: {}, propertyName: str, url: str) -> None:
"""Sets a url for the given actor property """Sets a url for the given actor property
""" """
if not actorJson.get('attachment'): if not actorJson.get('attachment'):
@ -269,7 +269,7 @@ def setActorPropertyUrl(actorJson: {}, propertyName: str, url: str) -> None:
def setBlogAddress(actorJson: {}, blogAddress: str) -> None: def setBlogAddress(actorJson: {}, blogAddress: str) -> None:
"""Sets an blog address for the given actor """Sets an blog address for the given actor
""" """
setActorPropertyUrl(actorJson, 'Blog', removeHtml(blogAddress)) _setActorPropertyUrl(actorJson, 'Blog', removeHtml(blogAddress))
def updateAvatarImageCache(session, baseDir: str, httpPrefix: str, def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
@ -475,7 +475,7 @@ def postContainsPublic(postJsonObject: {}) -> bool:
return containsPublic return containsPublic
def getImageFile(baseDir: str, name: str, directory: str, def _getImageFile(baseDir: str, name: str, directory: str,
nickname: str, domain: str, theme: str) -> (str, str): nickname: str, domain: str, theme: str) -> (str, str):
""" """
returns the filenames for an image with the given name returns the filenames for an image with the given name
@ -495,28 +495,28 @@ def getImageFile(baseDir: str, name: str, directory: str,
def getBannerFile(baseDir: str, def getBannerFile(baseDir: str,
nickname: str, domain: str, theme: str) -> (str, str): nickname: str, domain: str, theme: str) -> (str, str):
return getImageFile(baseDir, 'banner', return _getImageFile(baseDir, 'banner',
baseDir + '/accounts/' + nickname + '@' + domain, baseDir + '/accounts/' + nickname + '@' + domain,
nickname, domain, theme) nickname, domain, theme)
def getSearchBannerFile(baseDir: str, def getSearchBannerFile(baseDir: str,
nickname: str, domain: str, theme: str) -> (str, str): nickname: str, domain: str, theme: str) -> (str, str):
return getImageFile(baseDir, 'search_banner', return _getImageFile(baseDir, 'search_banner',
baseDir + '/accounts/' + nickname + '@' + domain, baseDir + '/accounts/' + nickname + '@' + domain,
nickname, domain, theme) nickname, domain, theme)
def getLeftImageFile(baseDir: str, def getLeftImageFile(baseDir: str,
nickname: str, domain: str, theme: str) -> (str, str): nickname: str, domain: str, theme: str) -> (str, str):
return getImageFile(baseDir, 'left_col_image', return _getImageFile(baseDir, 'left_col_image',
baseDir + '/accounts/' + nickname + '@' + domain, baseDir + '/accounts/' + nickname + '@' + domain,
nickname, domain, theme) nickname, domain, theme)
def getRightImageFile(baseDir: str, def getRightImageFile(baseDir: str,
nickname: str, domain: str, theme: str) -> (str, str): nickname: str, domain: str, theme: str) -> (str, str):
return getImageFile(baseDir, 'right_col_image', return _getImageFile(baseDir, 'right_col_image',
baseDir + '/accounts/' + nickname + '@' + domain, baseDir + '/accounts/' + nickname + '@' + domain,
nickname, domain, theme) nickname, domain, theme)

View File

@ -25,7 +25,7 @@ from utils import saveJson
from utils import getProtocolPrefixes from utils import getProtocolPrefixes
def parseHandle(handle: str) -> (str, str): def _parseHandle(handle: str) -> (str, str):
if '.' not in handle: if '.' not in handle:
return None, None return None, None
prefixes = getProtocolPrefixes() prefixes = getProtocolPrefixes()
@ -54,7 +54,7 @@ def webfingerHandle(session, handle: str, httpPrefix: str,
print('WARN: No session specified for webfingerHandle') print('WARN: No session specified for webfingerHandle')
return None return None
nickname, domain = parseHandle(handle) nickname, domain = _parseHandle(handle)
if not nickname: if not nickname:
return None return None
wfDomain = domain wfDomain = domain
@ -97,7 +97,7 @@ def webfingerHandle(session, handle: str, httpPrefix: str,
return result return result
def generateMagicKey(publicKeyPem) -> str: def _generateMagicKey(publicKeyPem) -> str:
"""See magic_key method in """See magic_key method in
https://github.com/tootsuite/mastodon/blob/ https://github.com/tootsuite/mastodon/blob/
707ddf7808f90e3ab042d7642d368c2ce8e95e6f/app/models/account.rb 707ddf7808f90e3ab042d7642d368c2ce8e95e6f/app/models/account.rb
@ -170,7 +170,7 @@ def createWebfingerEndpoint(nickname: str, domain: str, port: int,
"type": "application/activity+json" "type": "application/activity+json"
}, },
{ {
"href": generateMagicKey(publicKeyPem), "href": _generateMagicKey(publicKeyPem),
"rel": "magic-public-key" "rel": "magic-public-key"
} }
], ],
@ -271,7 +271,7 @@ def webfingerLookup(path: str, baseDir: str,
return wfJson return wfJson
def webfingerUpdateFromProfile(wfJson: {}, actorJson: {}) -> bool: def _webfingerUpdateFromProfile(wfJson: {}, actorJson: {}) -> bool:
"""Updates webfinger Email/blog/xmpp links from profile """Updates webfinger Email/blog/xmpp links from profile
Returns true if one or more tags has been changed Returns true if one or more tags has been changed
""" """
@ -350,6 +350,6 @@ def webfingerUpdate(baseDir: str, nickname: str, domain: str,
if not actorJson: if not actorJson:
return return
if webfingerUpdateFromProfile(wfJson, actorJson): if _webfingerUpdateFromProfile(wfJson, actorJson):
if saveJson(wfJson, filename): if saveJson(wfJson, filename):
cachedWebfingers[handle] = wfJson cachedWebfingers[handle] = wfJson