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

main
Bob Mottram 2020-08-29 17:56:23 +01:00
commit 14cff36a70
30 changed files with 1022 additions and 201 deletions

View File

@ -121,7 +121,7 @@ def storeBasicCredentials(baseDir: str, nickname: str, password: str) -> bool:
if os.path.isfile(passwordFile):
if nickname + ':' in open(passwordFile).read():
with open(passwordFile, "r") as fin:
with open(passwordFile + '.new', "w") as fout:
with open(passwordFile + '.new', 'w+') as fout:
for line in fin:
if not line.startswith(nickname + ':'):
fout.write(line)
@ -133,7 +133,7 @@ def storeBasicCredentials(baseDir: str, nickname: str, password: str) -> bool:
with open(passwordFile, 'a+') as passfile:
passfile.write(storeStr + '\n')
else:
with open(passwordFile, "w") as passfile:
with open(passwordFile, 'w+') as passfile:
passfile.write(storeStr + '\n')
return True
@ -145,7 +145,7 @@ def removePassword(baseDir: str, nickname: str) -> None:
passwordFile = baseDir + '/accounts/passwords'
if os.path.isfile(passwordFile):
with open(passwordFile, "r") as fin:
with open(passwordFile + '.new', "w") as fout:
with open(passwordFile + '.new', 'w+') as fout:
for line in fin:
if not line.startswith(nickname + ':'):
fout.write(line)

View File

@ -73,7 +73,7 @@ def noOfBlogReplies(baseDir: str, httpPrefix: str, translate: {},
if lines and removals:
print('Rewriting ' + postFilename + ' to remove ' +
str(len(removals)) + ' entries')
with open(postFilename, "w") as f:
with open(postFilename, 'w+') as f:
for replyPostId in lines:
replyPostId = replyPostId.replace('\n', '').replace('\r', '')
if replyPostId not in removals:

View File

@ -14,7 +14,8 @@ from utils import getFileCaseInsensitive
def storePersonInCache(baseDir: str, personUrl: str,
personJson: {}, personCache: {}) -> None:
personJson: {}, personCache: {},
allowWriteToFile: bool) -> None:
"""Store an actor in the cache
"""
currTime = datetime.datetime.utcnow()
@ -26,6 +27,7 @@ def storePersonInCache(baseDir: str, personUrl: str,
return
# store to file
if allowWriteToFile:
if os.path.isdir(baseDir+'/cache/actors'):
cacheFilename = baseDir + '/cache/actors/' + \
personUrl.replace('/', '#')+'.json'
@ -33,18 +35,21 @@ def storePersonInCache(baseDir: str, personUrl: str,
saveJson(personJson, cacheFilename)
def getPersonFromCache(baseDir: str, personUrl: str, personCache: {}) -> {}:
def getPersonFromCache(baseDir: str, personUrl: str, personCache: {},
allowWriteToFile: bool) -> {}:
"""Get an actor from the cache
"""
# if the actor is not in memory then try to load it from file
loadedFromFile = False
if not personCache.get(personUrl):
# does the person exist as a cached file?
cacheFilename = baseDir + '/cache/actors/' + \
personUrl.replace('/', '#')+'.json'
if os.path.isfile(getFileCaseInsensitive(cacheFilename)):
personJson = loadJson(getFileCaseInsensitive(cacheFilename))
if personJson:
storePersonInCache(baseDir, personUrl, personJson, personCache)
storePersonInCache(baseDir, personUrl, personJson,
personCache, False)
loadedFromFile = True
if personCache.get(personUrl):

582
daemon.py

File diff suppressed because it is too large Load Diff

View File

@ -210,7 +210,7 @@ def unfollowPerson(baseDir: str, nickname: str, domain: str,
return
with open(filename, "r") as f:
lines = f.readlines()
with open(filename, "w") as f:
with open(filename, 'w+') as f:
for line in lines:
if line.strip("\n").strip("\r").lower() != handleToUnfollowLower:
f.write(line)

4
git.py
View File

@ -210,12 +210,12 @@ def receiveGitPatch(baseDir: str, nickname: str, domain: str,
return False
patchStr = \
gitAddFromHandle(patchStr, '@' + fromNickname + '@' + fromDomain)
with open(patchFilename, "w") as patchFile:
with open(patchFilename, 'w+') as patchFile:
patchFile.write(patchStr)
patchNotifyFilename = \
baseDir + '/accounts/' + \
nickname + '@' + domain + '/.newPatchContent'
with open(patchNotifyFilename, "w") as patchFile:
with open(patchNotifyFilename, 'w+') as patchFile:
patchFile.write(patchStr)
return True
return False

View File

@ -244,7 +244,7 @@ def getTodaysEvents(baseDir: str, nickname: str, domain: str,
# if some posts have been deleted then regenerate the calendar file
if recreateEventsFile:
calendarFile = open(calendarFilename, "w")
calendarFile = open(calendarFilename, 'w+')
for postId in calendarPostIds:
calendarFile.write(postId + '\n')
calendarFile.close()
@ -412,7 +412,7 @@ def getThisWeeksEvents(baseDir: str, nickname: str, domain: str) -> {}:
# if some posts have been deleted then regenerate the calendar file
if recreateEventsFile:
calendarFile = open(calendarFilename, "w")
calendarFile = open(calendarFilename, 'w+')
for postId in calendarPostIds:
calendarFile.write(postId + '\n')
calendarFile.close()
@ -494,7 +494,7 @@ def getCalendarEvents(baseDir: str, nickname: str, domain: str,
# if some posts have been deleted then regenerate the calendar file
if recreateEventsFile:
calendarFile = open(calendarFilename, "w")
calendarFile = open(calendarFilename, 'w+')
for postId in calendarPostIds:
calendarFile.write(postId + '\n')
calendarFile.close()

View File

@ -199,7 +199,8 @@ def getPersonPubKey(baseDir: str, session, personUrl: str,
if debug:
print('DEBUG: Obtaining public key for shared inbox')
personUrl = personUrl.replace('/users/inbox', '/inbox')
personJson = getPersonFromCache(baseDir, personUrl, personCache)
personJson = \
getPersonFromCache(baseDir, personUrl, personCache, True)
if not personJson:
if debug:
print('DEBUG: Obtaining public key for ' + personUrl)
@ -228,7 +229,7 @@ def getPersonPubKey(baseDir: str, session, personUrl: str,
if debug:
print('DEBUG: Public key not found for ' + personUrl)
storePersonInCache(baseDir, personUrl, personJson, personCache)
storePersonInCache(baseDir, personUrl, personJson, personCache, True)
return pubKey
@ -272,6 +273,8 @@ def inboxPermittedMessage(domain: str, messageJson: {},
return False
if messageJson['object'].get('inReplyTo'):
inReplyTo = messageJson['object']['inReplyTo']
if not isinstance(inReplyTo, str):
return False
if not urlPermitted(inReplyTo, federationList, "inbox:write"):
return False
@ -863,7 +866,8 @@ def personReceiveUpdate(baseDir: str,
'cached actor when updating')
return False
# save to cache in memory
storePersonInCache(baseDir, personJson['id'], personJson, personCache)
storePersonInCache(baseDir, personJson['id'], personJson,
personCache, True)
# save to cache on file
if saveJson(personJson, actorFilename):
print('actor updated for ' + personJson['id'])
@ -1596,6 +1600,8 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
if not messageJson['object'].get('to'):
return False
replyTo = messageJson['object']['inReplyTo']
if not isinstance(replyTo, str):
return False
if debug:
print('DEBUG: post contains a reply')
# is this a reply to a post on this domain?
@ -1636,7 +1642,7 @@ def populateReplies(baseDir: str, httpPrefix: str, domain: str,
repliesFile.write(messageId + '\n')
repliesFile.close()
else:
repliesFile = open(postRepliesFilename, "w")
repliesFile = open(postRepliesFilename, 'w+')
repliesFile.write(messageId + '\n')
repliesFile.close()
return True
@ -1760,6 +1766,9 @@ def obtainAvatarForReplyPost(session, baseDir: str, httpPrefix: str,
if not lookupActor:
return
if not isinstance(lookupActor, str):
return
if not ('/users/' in lookupActor or
'/accounts/' in lookupActor or
'/channel/' in lookupActor or
@ -2355,11 +2364,15 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
if nickname != 'inbox':
# replies index will be updated
updateIndexList.append('tlreplies')
inReplyTo = postJsonObject['object']['inReplyTo']
if inReplyTo:
if isinstance(inReplyTo, str):
if not isMuted(baseDir, nickname, domain,
postJsonObject['object']['inReplyTo']):
inReplyTo):
replyNotify(baseDir, handle,
httpPrefix + '://' + domain +
'/users/' + nickname + '/tlreplies')
'/users/' + nickname +
'/tlreplies')
else:
isReplyToMutedPost = True
@ -2386,7 +2399,7 @@ def inboxAfterCapabilities(recentPostsCache: {}, maxRecentPosts: int,
# This enables you to ignore a threat that's getting boring
if isReplyToMutedPost:
print('MUTE REPLY: ' + destinationFilename)
muteFile = open(destinationFilename + '.muted', "w")
muteFile = open(destinationFilename + '.muted', 'w+')
if muteFile:
muteFile.write('\n')
muteFile.close()

View File

@ -350,7 +350,7 @@ def createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
if not os.path.isdir(baseDir + privateKeysSubdir):
os.mkdir(baseDir + privateKeysSubdir)
filename = baseDir + privateKeysSubdir + '/' + handle + '.key'
with open(filename, "w") as text_file:
with open(filename, 'w+') as text_file:
print(privateKeyPem, file=text_file)
# save the public key
@ -358,7 +358,7 @@ def createPersonBase(baseDir: str, nickname: str, domain: str, port: int,
if not os.path.isdir(baseDir + publicKeysSubdir):
os.mkdir(baseDir + publicKeysSubdir)
filename = baseDir + publicKeysSubdir + '/' + handle + '.pem'
with open(filename, "w") as text_file:
with open(filename, 'w+') as text_file:
print(publicKeyPem, file=text_file)
if password:
@ -454,22 +454,22 @@ def createPerson(baseDir: str, nickname: str, domain: str, port: int,
setRole(baseDir, nickname, domain, 'instance', 'delegator')
setConfigParam(baseDir, 'admin', nickname)
if not os.path.isdir(baseDir + '/accounts'):
os.mkdir(baseDir + '/accounts')
if not os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
os.mkdir(baseDir + '/accounts/' + nickname + '@' + domain)
if manualFollowerApproval:
followDMsFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/.followDMs'
with open(followDMsFilename, "w") as fFile:
with open(followDMsFilename, 'w+') as fFile:
fFile.write('\n')
# notify when posts are liked
notifyLikesFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/.notifyLikes'
with open(notifyLikesFilename, "w") as fFile:
fFile.write('\n')
if not os.path.isdir(baseDir + '/accounts'):
os.mkdir(baseDir + '/accounts')
if not os.path.isdir(baseDir + '/accounts/' + nickname + '@' + domain):
os.mkdir(baseDir + '/accounts/' + nickname + '@' + domain)
with open(notifyLikesFilename, 'w+') as nFile:
nFile.write('\n')
if os.path.isfile(baseDir + '/img/default-avatar.png'):
copyfile(baseDir + '/img/default-avatar.png',

View File

@ -209,7 +209,8 @@ def getPersonBox(baseDir: str, session, wfRequest: {},
personUrl = httpPrefix + '://' + domain + '/users/' + nickname
if not personUrl:
return None, None, None, None, None, None, None, None
personJson = getPersonFromCache(baseDir, personUrl, personCache)
personJson = \
getPersonFromCache(baseDir, personUrl, personCache, True)
if not personJson:
if '/channel/' in personUrl or '/accounts/' in personUrl:
asHeader = {
@ -265,7 +266,7 @@ def getPersonBox(baseDir: str, session, wfRequest: {},
if personJson.get('name'):
displayName = personJson['name']
storePersonInCache(baseDir, personUrl, personJson, personCache)
storePersonInCache(baseDir, personUrl, personJson, personCache, True)
return boxJson, pubKeyId, pubKey, personId, sharedInbox, \
capabilityAcquisition, avatarUrl, displayName
@ -388,6 +389,7 @@ def getPosts(session, outboxUrl: str, maxPosts: int,
inReplyTo = ''
if item['object'].get('inReplyTo'):
if item['object']['inReplyTo']:
if isinstance(item['object']['inReplyTo'], str):
# No replies to non-permitted domains
if not urlPermitted(item['object']['inReplyTo'],
federationList,
@ -483,6 +485,7 @@ def getPostDomains(session, outboxUrl: str, maxPosts: int,
if not isinstance(item['object'], dict):
continue
if item['object'].get('inReplyTo'):
if isinstance(item['object']['inReplyTo'], str):
postDomain, postPort = \
getDomainFromActor(item['object']['inReplyTo'])
if postDomain not in postDomains:
@ -2675,6 +2678,7 @@ def isReply(postJsonObject: {}, actor: str) -> bool:
postJsonObject['object']['type'] != 'Article':
return False
if postJsonObject['object'].get('inReplyTo'):
if isinstance(postJsonObject['object']['inReplyTo'], str):
if postJsonObject['object']['inReplyTo'].startswith(actor):
return True
if not postJsonObject['object'].get('tag'):
@ -3532,7 +3536,7 @@ def mutePost(baseDir: str, nickname: str, domain: str, postId: str,
return
print('MUTE: ' + postFilename)
muteFile = open(postFilename + '.muted', "w")
muteFile = open(postFilename + '.muted', 'w+')
if muteFile:
muteFile.write('\n')
muteFile.close()

View File

@ -25,6 +25,8 @@ def questionUpdateVotes(baseDir: str, nickname: str, domain: str,
return None
if not replyJson['object']['inReplyTo']:
return None
if not isinstance(replyJson['object']['inReplyTo'], str):
return None
if not replyJson['object'].get('name'):
return None
inReplyTo = replyJson['object']['inReplyTo']
@ -64,7 +66,7 @@ def questionUpdateVotes(baseDir: str, nickname: str, domain: str,
votersFilename = questionPostFilename.replace('.json', '.voters')
if not os.path.isfile(votersFilename):
# create a new voters file
votersFile = open(votersFilename, "w")
votersFile = open(votersFilename, 'w+')
if votersFile:
votersFile.write(replyJson['actor'] +
votersFileSeparator +
@ -97,7 +99,7 @@ def questionUpdateVotes(baseDir: str, nickname: str, domain: str,
else:
newlines.append(voteLine)
if saveVotersFile:
with open(votersFilename, "w") as votersFile:
with open(votersFilename, 'w+') as votersFile:
for voteLine in newlines:
votersFile.write(voteLine)
else:

View File

@ -52,7 +52,7 @@ def addModerator(baseDir: str, nickname: str, domain: str) -> None:
if moderator == nickname:
return
lines.append(nickname)
with open(moderatorsFile, "w") as f:
with open(moderatorsFile, 'w+') as f:
for moderator in lines:
moderator = moderator.strip('\n').strip('\r')
if len(moderator) > 1:
@ -74,7 +74,7 @@ def removeModerator(baseDir: str, nickname: str):
return
with open(moderatorsFile, "r") as f:
lines = f.readlines()
with open(moderatorsFile, "w") as f:
with open(moderatorsFile, 'w+') as f:
for moderator in lines:
moderator = moderator.strip('\n').strip('\r')
if len(moderator) > 1 and moderator != nickname:

View File

@ -209,8 +209,8 @@ def testCache():
"test": "This is a test"
}
personCache = {}
storePersonInCache(None, personUrl, personJson, personCache)
result = getPersonFromCache(None, personUrl, personCache)
storePersonInCache(None, personUrl, personJson, personCache, True)
result = getPersonFromCache(None, personUrl, personCache, True)
assert result['id'] == 123456
assert result['test'] == 'This is a test'
@ -2064,6 +2064,9 @@ def testTranslations():
langDict = {}
for lang in languagesStr:
langJson = loadJson('translations/' + lang + '.json')
if not langJson:
print('Missing language file ' +
'translations/' + lang + '.json')
assert langJson
langDict[lang] = langJson

View File

@ -282,5 +282,6 @@
"Create a new event": "أنشئ حدثًا جديدًا",
"Moderation policy or code of conduct": "سياسة الوسطية أو قواعد السلوك",
"Edit event": "تحرير الحدث",
"Notify when posts are liked": "يخطر عندما يتم اعجاب المشاركات"
"Notify when posts are liked": "يخطر عندما يتم اعجاب المشاركات",
"Don't show the Like button": "لا تظهر زر أعجبني"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Creeu un esdeveniment nou",
"Moderation policy or code of conduct": "Política de moderació o codi de conducta",
"Edit event": "Edita lesdeveniment",
"Notify when posts are liked": "Notifiqueu-ho quan us agradin les publicacions"
"Notify when posts are liked": "Notifiqueu-ho quan us agradin les publicacions",
"Don't show the Like button": "No mostreu el botó M'agrada"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Creu digwyddiad newydd",
"Moderation policy or code of conduct": "Polisi cymedroli neu god ymddygiad",
"Edit event": "Golygu digwyddiad",
"Notify when posts are liked": "Hysbysu pryd mae swyddi'n cael eu hoffi"
"Notify when posts are liked": "Hysbysu pryd mae swyddi'n cael eu hoffi",
"Don't show the Like button": "Peidiwch â dangos y botwm Hoffi"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Erstellen Sie ein neues Ereignis",
"Moderation policy or code of conduct": "Moderationsrichtlinie oder Verhaltenskodex",
"Edit event": "Ereignis bearbeiten",
"Notify when posts are liked": "Benachrichtigen, wenn Beiträge gefallen"
"Notify when posts are liked": "Benachrichtigen, wenn Beiträge gefallen",
"Don't show the Like button": "Zeigen Sie nicht die Schaltfläche \"Gefällt mir\" an"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Create a new event",
"Moderation policy or code of conduct": "Moderation policy or code of conduct",
"Edit event": "Edit event",
"Notify when posts are liked": "Notify when posts are liked"
"Notify when posts are liked": "Notify when posts are liked",
"Don't show the Like button": "Don't show the Like button"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Crea un nuevo evento",
"Moderation policy or code of conduct": "Política de moderación o código de conducta",
"Edit event": "Editar evento",
"Notify when posts are liked": "Notificar cuando les gusten las publicaciones"
"Notify when posts are liked": "Notificar cuando les gusten las publicaciones",
"Don't show the Like button": "No mostrar el botón Me gusta"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Créer un nouvel événement",
"Moderation policy or code of conduct": "Politique de modération ou code de conduite",
"Edit event": "Modifier l'événement",
"Notify when posts are liked": "Notifier lorsque les messages sont aimés"
"Notify when posts are liked": "Notifier lorsque les messages sont aimés",
"Don't show the Like button": "Ne pas afficher le bouton J'aime"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Cruthaigh imeacht nua",
"Moderation policy or code of conduct": "Beartas modhnóireachta nó cód iompair",
"Edit event": "Cuir imeacht in eagar",
"Notify when posts are liked": "Cuir in iúl cathain is maith poist"
"Notify when posts are liked": "Cuir in iúl cathain is maith poist",
"Don't show the Like button": "Ná taispeáin an cnaipe Cosúil"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "एक नई घटना बनाएँ",
"Moderation policy or code of conduct": "मॉडरेशन पॉलिसी या आचार संहिता",
"Edit event": "घटना संपादित करें",
"Notify when posts are liked": "पोस्ट पसंद आने पर सूचित करें"
"Notify when posts are liked": "पोस्ट पसंद आने पर सूचित करें",
"Don't show the Like button": "लाइक बटन न दिखाएं"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Crea un nuovo evento",
"Moderation policy or code of conduct": "Politica di moderazione o codice di condotta",
"Edit event": "Modifica evento",
"Notify when posts are liked": "Avvisa quando i post sono piaciuti"
"Notify when posts are liked": "Avvisa quando i post sono piaciuti",
"Don't show the Like button": "Non mostrare il pulsante Mi piace"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "新しいイベントを作成する",
"Moderation policy or code of conduct": "モデレートポリシーまたは行動規範",
"Edit event": "イベントを編集",
"Notify when posts are liked": "投稿が高く評価されたときに通知する"
"Notify when posts are liked": "投稿が高く評価されたときに通知する",
"Don't show the Like button": "「いいね!」ボタンを表示しない"
}

View File

@ -278,5 +278,6 @@
"Create a new event": "Create a new event",
"Moderation policy or code of conduct": "Moderation policy or code of conduct",
"Edit event": "Edit event",
"Notify when posts are liked": "Notify when posts are liked"
"Notify when posts are liked": "Notify when posts are liked",
"Don't show the Like button": "Don't show the Like button"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Crie um novo evento",
"Moderation policy or code of conduct": "Política de moderação ou código de conduta",
"Edit event": "Editar evento",
"Notify when posts are liked": "Notificar quando as postagens forem curtidas"
"Notify when posts are liked": "Notificar quando as postagens forem curtidas",
"Don't show the Like button": "Não mostrar o botão Curtir"
}

View File

@ -282,5 +282,6 @@
"Create a new event": "Создать новое мероприятие",
"Moderation policy or code of conduct": "Политика модерации или кодекс поведения",
"Edit event": "Изменить мероприятие",
"Notify when posts are liked": "Уведомлять, когда публикации нравятся"
"Notify when posts are liked": "Уведомлять, когда публикации нравятся",
"Don't show the Like button": "Не показывать кнопку \"Нравится\""
}

View File

@ -282,5 +282,6 @@
"Create a new event": "建立新活动",
"Moderation policy or code of conduct": "审核政策或行为准则",
"Edit event": "编辑活动",
"Notify when posts are liked": "通知喜欢的帖子"
"Notify when posts are liked": "通知喜欢的帖子",
"Don't show the Like button": "不显示“赞”按钮"
}

View File

@ -75,12 +75,12 @@ def saveJson(jsonObject: {}, filename: str) -> bool:
return False
def loadJson(filename: str, delaySec=2) -> {}:
def loadJson(filename: str, delaySec=2, maxTries=5) -> {}:
"""Makes a few attempts to load a json formatted file
"""
jsonObject = None
tries = 0
while tries < 5:
while tries < maxTries:
try:
with open(filename, 'r') as fp:
data = fp.read()
@ -351,7 +351,7 @@ def followPerson(baseDir: str, nickname: str, domain: str,
for line in lines:
if handleToFollow not in line:
newLines += line
with open(unfollowedFilename, "w") as f:
with open(unfollowedFilename, 'w+') as f:
f.write(newLines)
if not os.path.isdir(baseDir + '/accounts'):
@ -383,7 +383,7 @@ def followPerson(baseDir: str, nickname: str, domain: str,
followNickname, followDomain)
if debug:
print('DEBUG: creating new following file to follow ' + handleToFollow)
with open(filename, "w") as followfile:
with open(filename, 'w+') as followfile:
followfile.write(handleToFollow + '\n')
return True
@ -473,6 +473,8 @@ def isReplyToBlogPost(baseDir: str, nickname: str, domain: str,
return False
if not postJsonObject['object'].get('inReplyTo'):
return False
if not isinstance(postJsonObject['object']['inReplyTo'], str):
return False
blogsIndexFilename = baseDir + '/accounts/' + \
nickname + '@' + domain + '/tlblogs.index'
if not os.path.isfile(blogsIndexFilename):
@ -905,11 +907,19 @@ def searchBoxPosts(baseDir: str, nickname: str, domain: str,
def getFileCaseInsensitive(path: str) -> str:
"""Returns a case specific filename given a case insensitive version of it
"""
# does the given file exist? If so then we don't need
# to do a directory search
if os.path.isfile(path):
return path
if path != path.lower():
if os.path.isfile(path.lower()):
return path.lower()
directory, filename = os.path.split(path)
directory, filename = (directory or '.'), filename.lower()
for f in os.listdir(directory):
if f.lower() == filename:
newpath = os.path.join(directory, f)
if os.path.isfile(newpath) and f.lower() == filename:
if os.path.isfile(newpath):
return newpath
return path

View File

@ -199,7 +199,8 @@ def setBlogAddress(actorJson: {}, blogAddress: str) -> None:
def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
actor: str, avatarUrl: str,
personCache: {}, force=False) -> str:
personCache: {}, allowDownloads: bool,
force=False) -> str:
"""Updates the cached avatar for the given actor
"""
if not avatarUrl:
@ -232,7 +233,8 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
avatarImageFilename = avatarImagePath + '.webp'
else:
return None
if not os.path.isfile(avatarImageFilename) or force:
if (not os.path.isfile(avatarImageFilename) or force) and allowDownloads:
try:
print('avatar image url: ' + avatarUrl)
result = session.get(avatarUrl,
@ -282,18 +284,23 @@ def updateAvatarImageCache(session, baseDir: str, httpPrefix: str,
"public keys don't match when downloading actor for " +
actor)
return None
storePersonInCache(baseDir, actor, personJson, personCache)
return getPersonAvatarUrl(baseDir, actor, personCache)
storePersonInCache(baseDir, actor, personJson, personCache,
allowDownloads)
return getPersonAvatarUrl(baseDir, actor, personCache,
allowDownloads)
return None
return avatarImageFilename.replace(baseDir + '/cache', '')
def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {}) -> str:
def getPersonAvatarUrl(baseDir: str, personUrl: str, personCache: {},
allowDownloads: bool) -> str:
"""Returns the avatar url for the person
"""
personJson = getPersonFromCache(baseDir, personUrl, personCache)
personJson = \
getPersonFromCache(baseDir, personUrl, personCache, allowDownloads)
if not personJson:
return None
# get from locally stored image
actorStr = personJson['id'].replace('/', '-')
avatarImagePath = baseDir + '/cache/avatars/' + actorStr
@ -796,7 +803,7 @@ def htmlHashtagSearch(nickname: str, domain: str, port: int,
showIndividualPostIcons = True
allowDeletion = False
hashtagSearchForm += \
individualPostAsHtml(recentPostsCache,
individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest,
@ -1025,7 +1032,7 @@ def htmlHistorySearch(translate: {}, baseDir: str,
showIndividualPostIcons = True
allowDeletion = False
historySearchForm += \
individualPostAsHtml(recentPostsCache,
individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest,
@ -1084,6 +1091,7 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
followDMs = ''
removeTwitter = ''
notifyLikes = ''
hideLikeButton = ''
mediaInstanceStr = ''
displayNickname = nickname
bioStr = ''
@ -1134,6 +1142,9 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
if os.path.isfile(baseDir + '/accounts/' +
nickname + '@' + domain + '/.notifyLikes'):
notifyLikes = 'checked'
if os.path.isfile(baseDir + '/accounts/' +
nickname + '@' + domain + '/.hideLikeButton'):
hideLikeButton = 'checked'
mediaInstance = getConfigParam(baseDir, "mediaInstance")
if mediaInstance:
@ -1473,6 +1484,10 @@ def htmlEditProfile(translate: {}, baseDir: str, path: str,
' <input type="checkbox" class="profilecheckbox" ' + \
'name="notifyLikes" ' + notifyLikes + '> ' + \
translate['Notify when posts are liked'] + '<br>\n'
editProfileForm += \
' <input type="checkbox" class="profilecheckbox" ' + \
'name="hideLikeButton" ' + hideLikeButton + '> ' + \
translate["Don't show the Like button"] + '<br>\n'
editProfileForm += \
' <br><b><label class="labels">' + \
@ -2493,7 +2508,8 @@ def htmlProfilePosts(recentPostsCache: {}, maxRecentPosts: int,
for item in outboxFeed['orderedItems']:
if item['type'] == 'Create':
postStr = \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest,
personCache,
@ -3053,7 +3069,7 @@ def individualFollowAsHtml(translate: {},
nickname = getNicknameFromActor(followUrl)
domain, port = getDomainFromActor(followUrl)
titleStr = '@' + nickname + '@' + domain
avatarUrl = getPersonAvatarUrl(baseDir, followUrl, personCache)
avatarUrl = getPersonAvatarUrl(baseDir, followUrl, personCache, True)
if not avatarUrl:
avatarUrl = followUrl + '/avatar.png'
if domain not in followUrl:
@ -3778,7 +3794,8 @@ def getPostAttachmentsAsHtml(postJsonObject: {}, boxName: str, translate: {},
return attachmentStr, galleryStr
def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
def individualPostAsHtml(allowDownloads: bool,
recentPostsCache: {}, maxRecentPosts: int,
iconsDir: str, translate: {},
pageNumber: int, baseDir: str,
session, wfRequest: {}, personCache: {},
@ -3795,17 +3812,30 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
storeToCache=True) -> str:
""" Shows a single post as html
"""
# benchmark
postStartTime = time.time()
postActor = postJsonObject['actor']
# ZZZzzz
if isPersonSnoozed(baseDir, nickname, domain, postActor):
return ''
# benchmark 1
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 1 = ' + str(timeDiff))
avatarPosition = ''
messageId = ''
if postJsonObject.get('id'):
messageId = removeIdEnding(postJsonObject['id'])
# benchmark 2
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 2 = ' + str(timeDiff))
messageIdStr = ''
if messageId:
messageIdStr = ';' + messageId
@ -3827,9 +3857,26 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
# update avatar if needed
if not avatarUrl:
avatarUrl = \
getPersonAvatarUrl(baseDir, postActor, personCache)
getPersonAvatarUrl(baseDir, postActor, personCache,
allowDownloads)
# benchmark 2.1
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 2.1 = ' + str(timeDiff))
updateAvatarImageCache(session, baseDir, httpPrefix,
postActor, avatarUrl, personCache)
postActor, avatarUrl, personCache,
allowDownloads)
# benchmark 2.2
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 2.2 = ' + str(timeDiff))
postHtml = \
loadIndividualPostAsHtmlFromCache(baseDir, nickname, domain,
@ -3838,17 +3885,38 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
postHtml = preparePostFromHtmlCache(postHtml, boxName, pageNumber)
updateRecentPostsCache(recentPostsCache, maxRecentPosts,
postJsonObject, postHtml)
# benchmark 3
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 3 = ' + str(timeDiff))
return postHtml
# benchmark 4
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 4 = ' + str(timeDiff))
if not avatarUrl:
avatarUrl = \
getPersonAvatarUrl(baseDir, postActor, personCache)
getPersonAvatarUrl(baseDir, postActor, personCache,
allowDownloads)
avatarUrl = \
updateAvatarImageCache(session, baseDir, httpPrefix,
postActor, avatarUrl, personCache)
postActor, avatarUrl, personCache,
allowDownloads)
else:
updateAvatarImageCache(session, baseDir, httpPrefix,
postActor, avatarUrl, personCache)
postActor, avatarUrl, personCache,
allowDownloads)
# benchmark 5
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 5 = ' + str(timeDiff))
if not avatarUrl:
avatarUrl = postActor + '/avatar.png'
@ -3861,6 +3929,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
personCache,
projectVersion, httpPrefix,
nickname, domain, 'outbox')
# benchmark 6
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 6 = ' + str(timeDiff))
if avatarUrl2:
avatarUrl = avatarUrl2
if displayName:
@ -3870,6 +3944,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
nickname, domain,
displayName, False)
# benchmark 7
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 7 = ' + str(timeDiff))
avatarLink = ' <a class="imageAnchor" href="' + postActor + '">'
avatarLink += \
' <img loading="lazy" src="' + avatarUrl + '" title="' + \
@ -3923,6 +4003,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject = postJsonAnnounce
isAnnounced = True
# benchmark 8
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 8 = ' + str(timeDiff))
if not isinstance(postJsonObject['object'], dict):
return ''
@ -3971,6 +4057,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
';' + str(pageNumber) + ';' + avatarUrl + messageIdStr + \
'">@' + actorNickname + '@' + actorDomain + '</a>\n'
# benchmark 9
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 9 = ' + str(timeDiff))
# Show a DM icon for DMs in the inbox timeline
if showDMicon:
titleStr = \
@ -4028,8 +4120,20 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
translate['Reply to this post'] + \
' |" src="/' + iconsDir + '/reply.png"/></a>\n'
# benchmark 10
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 10 = ' + str(timeDiff))
isEvent = isEventPost(postJsonObject)
# benchmark 11
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 11 = ' + str(timeDiff))
editStr = ''
if fullDomain + '/users/' + nickname in postJsonObject['actor']:
if '/statuses/' in postJsonObject['object']['id']:
@ -4083,12 +4187,32 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
'" alt="' + translate['Repeat this post'] + \
' |" src="/' + iconsDir + '/' + announceIcon + '"/></a>\n'
# benchmark 12
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 12 = ' + str(timeDiff))
# whether to show a like button
hideLikeButtonFile = \
baseDir + '/accounts/' + nickname + '@' + domain + '/.hideLikeButton'
showLikeButton = True
if os.path.isfile(hideLikeButtonFile):
showLikeButton = False
likeStr = ''
if not isModerationPost:
if not isModerationPost and showLikeButton:
likeIcon = 'like_inactive.png'
likeLink = 'like'
likeTitle = translate['Like this post']
likeCount = noOfLikes(postJsonObject)
# benchmark 12.1
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 12.1 = ' + str(timeDiff))
likeCountStr = ''
if likeCount > 0:
if likeCount > 1:
@ -4100,6 +4224,13 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
if likedByPerson(postJsonObject, nickname, fullDomain):
likeLink = 'unlike'
likeTitle = translate['Undo the like']
# benchmark 12.2
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 12.2 = ' + str(timeDiff))
likeStr = \
'<a class="imageAnchor" href="/users/' + nickname + '?' + \
likeLink + '=' + postJsonObject['object']['id'] + \
@ -4113,6 +4244,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
'" alt="' + likeTitle + \
' |" src="/' + iconsDir + '/' + likeIcon + '"/></a>\n'
# benchmark 12.5
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 12.5 = ' + str(timeDiff))
bookmarkStr = ''
if not isModerationPost:
bookmarkIcon = 'bookmark_inactive.png'
@ -4122,6 +4259,11 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
bookmarkIcon = 'bookmark.png'
bookmarkLink = 'unbookmark'
bookmarkTitle = translate['Undo the bookmark']
# benchmark 12.6
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 12.6 = ' + str(timeDiff))
bookmarkStr = \
'<a class="imageAnchor" href="/users/' + nickname + '?' + \
bookmarkLink + '=' + postJsonObject['object']['id'] + \
@ -4134,8 +4276,20 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
bookmarkTitle + ' |" src="/' + iconsDir + \
'/' + bookmarkIcon + '"/></a>\n'
# benchmark 12.9
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 12.9 = ' + str(timeDiff))
isMuted = postIsMuted(baseDir, nickname, domain, postJsonObject, messageId)
# benchmark 13
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 13 = ' + str(timeDiff))
deleteStr = ''
muteStr = ''
if (allowDeletion or
@ -4174,6 +4328,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
' |" title="' + translate['Undo mute'] + \
'" src="/' + iconsDir+'/unmute.png"/></a>\n'
# benchmark 13.1
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 13.1 = ' + str(timeDiff))
replyAvatarImageInPost = ''
if showRepeatIcon:
if isAnnounced:
@ -4189,22 +4349,45 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
'" src="/' + iconsDir + \
'/repeat_inactive.png" class="announceOrReply"/>\n'
else:
# benchmark 13.2
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 13.2 = ' + str(timeDiff))
announceNickname = None
if attributedTo:
announceNickname = getNicknameFromActor(attributedTo)
if announceNickname:
announceDomain, announcePort = \
getDomainFromActor(attributedTo)
getPersonFromCache(baseDir, attributedTo, personCache)
getPersonFromCache(baseDir, attributedTo,
personCache, allowDownloads)
announceDisplayName = \
getDisplayName(baseDir, attributedTo, personCache)
if announceDisplayName:
# benchmark 13.3
if not allowDownloads:
timeDiff = \
int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 13.3 = ' + str(timeDiff))
if ':' in announceDisplayName:
announceDisplayName = \
addEmojiToDisplayName(baseDir, httpPrefix,
nickname, domain,
announceDisplayName,
False)
# benchmark 13.3.1
if not allowDownloads:
timeDiff = \
int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 13.3.1 = ' + str(timeDiff))
titleStr += \
' <img loading="lazy" title="' + \
translate['announces'] + '" alt="' + \
@ -4218,7 +4401,16 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject['object']['attributedTo']
announceAvatarUrl = \
getPersonAvatarUrl(baseDir, announceActor,
personCache)
personCache, allowDownloads)
# benchmark 13.4
if not allowDownloads:
timeDiff = \
int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 13.4 = ' + str(timeDiff))
if announceAvatarUrl:
idx = 'Show options for this person'
replyAvatarImageInPost = \
@ -4283,12 +4475,22 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
getDomainFromActor(replyActor)
if replyNickname and replyDomain:
getPersonFromCache(baseDir, replyActor,
personCache)
personCache,
allowDownloads)
replyDisplayName = \
getDisplayName(baseDir, replyActor,
personCache)
if replyDisplayName:
if ':' in replyDisplayName:
# benchmark 13.5
if not allowDownloads:
timeDiff = \
int((time.time() -
postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' +
boxName + ' 13.5 = ' +
str(timeDiff))
repDisp = replyDisplayName
replyDisplayName = \
addEmojiToDisplayName(baseDir,
@ -4297,6 +4499,15 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
domain,
repDisp,
False)
# benchmark 13.6
if not allowDownloads:
timeDiff = \
int((time.time() -
postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' +
boxName + ' 13.6 = ' +
str(timeDiff))
titleStr += \
' <img loading="lazy" title="' + \
translate['replying to'] + \
@ -4308,11 +4519,29 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
'<a href="' + inReplyTo + \
'">' + replyDisplayName + '</a>\n'
# benchmark 13.7
if not allowDownloads:
timeDiff = int((time.time() -
postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 13.7 = ' + str(timeDiff))
# show avatar of person replied to
replyAvatarUrl = \
getPersonAvatarUrl(baseDir,
replyActor,
personCache)
personCache,
allowDownloads)
# benchmark 13.8
if not allowDownloads:
timeDiff = int((time.time() -
postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName +
' 13.8 = ' + str(timeDiff))
if replyAvatarUrl:
replyAvatarImageInPost = \
'<div class=' + \
@ -4379,6 +4608,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject['object']['inReplyTo'] + \
'">' + postDomain + '</a>\n'
# benchmark 14
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 14 = ' + str(timeDiff))
attachmentStr, galleryStr = \
getPostAttachmentsAsHtml(postJsonObject, boxName, translate,
isMuted, avatarLink.strip(),
@ -4402,6 +4637,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
datetimeObject = parse(publishedStr)
publishedStr = datetimeObject.strftime("%a %b %d, %H:%M")
# benchmark 15
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 15 = ' + str(timeDiff))
publishedLink = messageId
# blog posts should have no /statuses/ in their link
if isBlogPost(postJsonObject):
@ -4459,6 +4700,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject['object']['summary'],
postJsonObject['object']['content'])
# benchmark 16
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 16 = ' + str(timeDiff))
if not isPatch:
objectContent = \
removeLongWords(postJsonObject['object']['content'], 40, [])
@ -4499,6 +4746,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
else:
contentStr += cwContentStr
# benchmark 17
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 17 = ' + str(timeDiff))
if postJsonObject['object'].get('tag') and not isPatch:
contentStr = \
replaceEmojiFromTags(contentStr,
@ -4527,6 +4780,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
else:
postHtml = galleryStr
# benchmark 18
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 18 = ' + str(timeDiff))
if not showPublicOnly and storeToCache and \
boxName != 'tlmedia' and boxName != 'tlbookmarks' and \
boxName != 'bookmarks':
@ -4535,6 +4794,12 @@ def individualPostAsHtml(recentPostsCache: {}, maxRecentPosts: int,
updateRecentPostsCache(recentPostsCache, maxRecentPosts,
postJsonObject, postHtml)
# benchmark 19
if not allowDownloads:
timeDiff = int((time.time() - postStartTime) * 1000)
if timeDiff > 100:
print('TIMING INDIV ' + boxName + ' 19 = ' + str(timeDiff))
return postHtml
@ -4581,6 +4846,8 @@ def htmlTimeline(defaultTimeline: str,
YTReplacementDomain: str) -> str:
"""Show the timeline as html
"""
timelineStartTime = time.time()
accountDir = baseDir + '/accounts/' + nickname + '@' + domain
# should the calendar icon be highlighted?
@ -4651,6 +4918,11 @@ def htmlTimeline(defaultTimeline: str,
if not os.path.isfile(bannerFilename):
bannerFile = 'banner.webp'
# benchmark 1
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 1 = ' + str(timeDiff))
with open(cssFilename, 'r') as cssFile:
# load css
profileStyle = \
@ -4665,6 +4937,11 @@ def htmlTimeline(defaultTimeline: str,
# is the user a moderator?
moderator = isModerator(baseDir, nickname)
# benchmark 2
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 2 = ' + str(timeDiff))
# the appearance of buttons - highlighted or not
inboxButton = 'button'
blogsButton = 'button'
@ -4744,6 +5021,11 @@ def htmlTimeline(defaultTimeline: str,
'" src="/' + iconsDir + '/person.png"/></a>\n'
break
# benchmark 3
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 3 = ' + str(timeDiff))
# moderation / reports button
moderationButtonStr = ''
if moderator and not minimal:
@ -4777,6 +5059,11 @@ def htmlTimeline(defaultTimeline: str,
tlStr = htmlHeader(cssFilename, profileStyle)
# benchmark 4
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 4 = ' + str(timeDiff))
# what screen to go to when a new post is created
if boxName == 'dm':
newPostButtonStr = \
@ -4919,6 +5206,11 @@ def htmlTimeline(defaultTimeline: str,
translate['Search and follow'] + '" alt="| ' + \
translate['Search and follow'] + '" class="timelineicon"/></a>\n'
# benchmark 5
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 5 = ' + str(timeDiff))
# the calendar button
calendarAltText = translate['Calendar']
if newCalendarEvent:
@ -4979,6 +5271,11 @@ def htmlTimeline(defaultTimeline: str,
'" name="submitInfo" value="' + translate['Info'] + '">\n'
tlStr += '</div>\n</form>\n'
# benchmark 6
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 6 = ' + str(timeDiff))
if boxName == 'tlshares':
maxSharesPerAccount = itemsPerPage
return (tlStr +
@ -4987,6 +5284,11 @@ def htmlTimeline(defaultTimeline: str,
maxSharesPerAccount, httpPrefix) +
htmlFooter())
# benchmark 7
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 7 = ' + str(timeDiff))
# show todays events buttons on the first inbox page
if boxName == 'inbox' and pageNumber == 1:
if todaysEventsCheck(baseDir, nickname, domain):
@ -5015,6 +5317,11 @@ def htmlTimeline(defaultTimeline: str,
translate['Happening This Week'] + '</button></a>\n' + \
'</center>\n'
# benchmark 8
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 8 = ' + str(timeDiff))
# page up arrow
if pageNumber > 1:
tlStr += \
@ -5036,6 +5343,8 @@ def htmlTimeline(defaultTimeline: str,
# show each post in the timeline
for item in timelineJson['orderedItems']:
timelinePostStartTime = time.time()
if item['type'] == 'Create' or \
item['type'] == 'Announce' or \
item['type'] == 'Update':
@ -5057,10 +5366,27 @@ def htmlTimeline(defaultTimeline: str,
preparePostFromHtmlCache(currTlStr,
boxName,
pageNumber)
# benchmark cache post
timeDiff = \
int((time.time() -
timelinePostStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE POST CACHE TIMING ' +
boxName + ' = ' + str(timeDiff))
if not currTlStr:
# benchmark cache post
timeDiff = \
int((time.time() -
timelinePostStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE POST DISK TIMING START ' +
boxName + ' = ' + str(timeDiff))
# read the post from disk
currTlStr = \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(False, recentPostsCache,
maxRecentPosts,
iconsDir, translate, pageNumber,
baseDir, session, wfRequest,
personCache,
@ -5074,6 +5400,13 @@ def htmlTimeline(defaultTimeline: str,
showIndividualPostIcons,
manuallyApproveFollowers,
False, True)
# benchmark cache post
timeDiff = \
int((time.time() -
timelinePostStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE POST DISK TIMING ' +
boxName + ' = ' + str(timeDiff))
if currTlStr:
itemCtr += 1
@ -5081,6 +5414,11 @@ def htmlTimeline(defaultTimeline: str,
if boxName == 'tlmedia':
tlStr += '</div>\n'
# benchmark 9
timeDiff = int((time.time() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' + boxName + ' 9 = ' + str(timeDiff))
# page down arrow
if itemCtr > 2:
tlStr += \
@ -5337,7 +5675,7 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
postStr += followStr + '</p>\n'
postStr += \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest, personCache,
nickname, domain, port, postJsonObject,
@ -5358,7 +5696,8 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
postJsonObject = loadJson(postFilename)
if postJsonObject:
postStr = \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest,
personCache,
@ -5385,7 +5724,8 @@ def htmlIndividualPost(recentPostsCache: {}, maxRecentPosts: int,
# add items to the html output
for item in repliesJson['orderedItems']:
postStr += \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest,
personCache,
@ -5419,7 +5759,8 @@ def htmlPostReplies(recentPostsCache: {}, maxRecentPosts: int,
if repliesJson.get('orderedItems'):
for item in repliesJson['orderedItems']:
repliesStr += \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(True, recentPostsCache,
maxRecentPosts,
iconsDir, translate, None,
baseDir, session, wfRequest, personCache,
nickname, domain, port, item,
@ -5552,7 +5893,7 @@ def htmlDeletePost(recentPostsCache: {}, maxRecentPosts: int,
httpPrefix + '://')
deletePostStr = htmlHeader(cssFilename, profileStyle)
deletePostStr += \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
iconsDir, translate, pageNumber,
baseDir, session, wfRequest, personCache,
nickname, domain, port, postJsonObject,
@ -6251,6 +6592,7 @@ def htmlCalendar(translate: {},
else:
daysInMonth = \
(date(year + 1, 1, 1) - date(year, monthNumber, 1)).days
# print('daysInMonth ' + str(monthNumber) + ': ' + str(daysInMonth))
cssFilename = baseDir + '/epicyon-calendar.css'
if os.path.isfile(baseDir + '/calendar.css'):
@ -6304,7 +6646,9 @@ def htmlCalendar(translate: {},
dayOfMonth = 0
dow = weekDayOfMonthStart(monthNumber, year)
for weekOfMonth in range(1, 6):
for weekOfMonth in range(1, 7):
if dayOfMonth == daysInMonth:
continue
calendarStr += ' <tr>\n'
for dayNumber in range(1, 8):
if (weekOfMonth > 1 and dayOfMonth < daysInMonth) or \
@ -6636,7 +6980,8 @@ def htmlProfileAfterSearch(recentPostsCache: {}, maxRecentPosts: int,
if profileJson['icon'].get('url'):
avatarUrl = profileJson['icon']['url']
if not avatarUrl:
avatarUrl = getPersonAvatarUrl(baseDir, personUrl, personCache)
avatarUrl = getPersonAvatarUrl(baseDir, personUrl,
personCache, True)
displayName = searchNickname
if profileJson.get('name'):
displayName = profileJson['name']
@ -6730,7 +7075,7 @@ def htmlProfileAfterSearch(recentPostsCache: {}, maxRecentPosts: int,
if not item.get('object'):
continue
profileStr += \
individualPostAsHtml(recentPostsCache, maxRecentPosts,
individualPostAsHtml(True, recentPostsCache, maxRecentPosts,
iconsDir, translate, None, baseDir,
session, cachedWebfingers, personCache,
nickname, domain, port,