| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | __filename__ = "webapp_post.py" | 
					
						
							|  |  |  | __author__ = "Bob Mottram" | 
					
						
							|  |  |  | __license__ = "AGPL3+" | 
					
						
							|  |  |  | __version__ = "1.1.0" | 
					
						
							|  |  |  | __maintainer__ = "Bob Mottram" | 
					
						
							|  |  |  | __email__ = "bob@freedombone.net" | 
					
						
							|  |  |  | __status__ = "Production" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import time | 
					
						
							|  |  |  | from dateutil.parser import parse | 
					
						
							|  |  |  | from auth import createPassword | 
					
						
							|  |  |  | from git import isGitPatch | 
					
						
							|  |  |  | from datetime import datetime | 
					
						
							|  |  |  | from cache import getPersonFromCache | 
					
						
							|  |  |  | from bookmarks import bookmarkedByPerson | 
					
						
							|  |  |  | from like import likedByPerson | 
					
						
							|  |  |  | from like import noOfLikes | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from follow import isFollowingActor | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | from posts import postIsMuted | 
					
						
							|  |  |  | from posts import getPersonBox | 
					
						
							|  |  |  | from posts import isDM | 
					
						
							|  |  |  | from posts import downloadAnnounce | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from posts import populateRepliesJson | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  | from utils import getFullDomain | 
					
						
							| 
									
										
										
										
											2020-12-01 21:44:27 +00:00
										 |  |  | from utils import isEditor | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from utils import locatePost | 
					
						
							|  |  |  | from utils import loadJson | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | from utils import getCachedPostDirectory | 
					
						
							|  |  |  | from utils import getCachedPostFilename | 
					
						
							|  |  |  | from utils import getProtocolPrefixes | 
					
						
							|  |  |  | from utils import isNewsPost | 
					
						
							|  |  |  | from utils import isBlogPost | 
					
						
							|  |  |  | from utils import getDisplayName | 
					
						
							|  |  |  | from utils import isPublicPost | 
					
						
							|  |  |  | from utils import updateRecentPostsCache | 
					
						
							|  |  |  | from utils import removeIdEnding | 
					
						
							|  |  |  | from utils import getNicknameFromActor | 
					
						
							|  |  |  | from utils import getDomainFromActor | 
					
						
							|  |  |  | from utils import isEventPost | 
					
						
							|  |  |  | from content import replaceEmojiFromTags | 
					
						
							|  |  |  | from content import htmlReplaceQuoteMarks | 
					
						
							|  |  |  | from content import htmlReplaceEmailQuote | 
					
						
							|  |  |  | from content import removeTextFormatting | 
					
						
							|  |  |  | from content import removeLongWords | 
					
						
							|  |  |  | from content import getMentionsFromHtml | 
					
						
							|  |  |  | from content import switchWords | 
					
						
							|  |  |  | from person import isPersonSnoozed | 
					
						
							|  |  |  | from announce import announcedByPerson | 
					
						
							| 
									
										
										
										
											2020-12-20 11:00:17 +00:00
										 |  |  | from webapp_utils import getAvatarImageUrl | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | from webapp_utils import getPersonAvatarUrl | 
					
						
							|  |  |  | from webapp_utils import updateAvatarImageCache | 
					
						
							|  |  |  | from webapp_utils import loadIndividualPostAsHtmlFromCache | 
					
						
							|  |  |  | from webapp_utils import addEmojiToDisplayName | 
					
						
							|  |  |  | from webapp_utils import postContainsPublic | 
					
						
							|  |  |  | from webapp_utils import getContentWarningButton | 
					
						
							|  |  |  | from webapp_utils import getPostAttachmentsAsHtml | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  | from webapp_utils import htmlHeaderWithExternalStyle | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | from webapp_utils import htmlFooter | 
					
						
							| 
									
										
										
										
											2020-12-12 10:38:48 +00:00
										 |  |  | from webapp_utils import getBrokenLinkSubstitute | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | from webapp_media import addEmbeddedElements | 
					
						
							|  |  |  | from webapp_question import insertQuestion | 
					
						
							|  |  |  | from devices import E2EEdecryptMessageFromDevice | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _logPostTiming(enableTimingLog: bool, postStartTime, debugId: str) -> None: | 
					
						
							| 
									
										
										
										
											2020-12-01 17:23:34 +00:00
										 |  |  |     """Create a log of timings for performance tuning
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not enableTimingLog: | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  |     timeDiff = int((time.time() - postStartTime) * 1000) | 
					
						
							|  |  |  |     if timeDiff > 100: | 
					
						
							|  |  |  |         print('TIMING INDIV ' + debugId + ' = ' + str(timeDiff)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | def preparePostFromHtmlCache(postHtml: str, boxName: str, | 
					
						
							|  |  |  |                              pageNumber: int) -> str: | 
					
						
							|  |  |  |     """Sets the page number on a cached html post
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     # if on the bookmarks timeline then remain there | 
					
						
							|  |  |  |     if boxName == 'tlbookmarks' or boxName == 'bookmarks': | 
					
						
							|  |  |  |         postHtml = postHtml.replace('?tl=inbox', '?tl=tlbookmarks') | 
					
						
							|  |  |  |         if '?page=' in postHtml: | 
					
						
							|  |  |  |             pageNumberStr = postHtml.split('?page=')[1] | 
					
						
							|  |  |  |             if '?' in pageNumberStr: | 
					
						
							|  |  |  |                 pageNumberStr = pageNumberStr.split('?')[0] | 
					
						
							|  |  |  |             postHtml = postHtml.replace('?page=' + pageNumberStr, '?page=-999') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     withPageNumber = postHtml.replace(';-999;', ';' + str(pageNumber) + ';') | 
					
						
							|  |  |  |     withPageNumber = withPageNumber.replace('?page=-999', | 
					
						
							|  |  |  |                                             '?page=' + str(pageNumber)) | 
					
						
							|  |  |  |     return withPageNumber | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _saveIndividualPostAsHtmlToCache(baseDir: str, | 
					
						
							|  |  |  |                                      nickname: str, domain: str, | 
					
						
							|  |  |  |                                      postJsonObject: {}, | 
					
						
							|  |  |  |                                      postHtml: str) -> bool: | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |     """Saves the given html for a post to a cache file
 | 
					
						
							|  |  |  |     This is so that it can be quickly reloaded on subsequent | 
					
						
							|  |  |  |     refresh of the timeline | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     htmlPostCacheDir = \ | 
					
						
							|  |  |  |         getCachedPostDirectory(baseDir, nickname, domain) | 
					
						
							|  |  |  |     cachedPostFilename = \ | 
					
						
							|  |  |  |         getCachedPostFilename(baseDir, nickname, domain, postJsonObject) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # create the cache directory if needed | 
					
						
							|  |  |  |     if not os.path.isdir(htmlPostCacheDir): | 
					
						
							|  |  |  |         os.mkdir(htmlPostCacheDir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         with open(cachedPostFilename, 'w+') as fp: | 
					
						
							|  |  |  |             fp.write(postHtml) | 
					
						
							|  |  |  |             return True | 
					
						
							|  |  |  |     except Exception as e: | 
					
						
							|  |  |  |         print('ERROR: saving post to cache ' + str(e)) | 
					
						
							|  |  |  |     return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getPostFromRecentCache(session, | 
					
						
							|  |  |  |                             baseDir: str, | 
					
						
							|  |  |  |                             httpPrefix: str, | 
					
						
							|  |  |  |                             nickname: str, domain: str, | 
					
						
							|  |  |  |                             postJsonObject: {}, | 
					
						
							|  |  |  |                             postActor: str, | 
					
						
							|  |  |  |                             personCache: {}, | 
					
						
							|  |  |  |                             allowDownloads: bool, | 
					
						
							|  |  |  |                             showPublicOnly: bool, | 
					
						
							|  |  |  |                             storeToCache: bool, | 
					
						
							|  |  |  |                             boxName: str, | 
					
						
							|  |  |  |                             avatarUrl: str, | 
					
						
							|  |  |  |                             enableTimingLog: bool, | 
					
						
							|  |  |  |                             postStartTime, | 
					
						
							|  |  |  |                             pageNumber: int, | 
					
						
							|  |  |  |                             recentPostsCache: {}, | 
					
						
							|  |  |  |                             maxRecentPosts: int) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 12:47:52 +00:00
										 |  |  |     """Attempts to get the html post from the recent posts cache in memory
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if boxName == 'tlmedia': | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if showPublicOnly: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tryCache = False | 
					
						
							|  |  |  |     bmTimeline = boxName == 'bookmarks' or boxName == 'tlbookmarks' | 
					
						
							|  |  |  |     if storeToCache or bmTimeline: | 
					
						
							|  |  |  |         tryCache = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not tryCache: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # update avatar if needed | 
					
						
							|  |  |  |     if not avatarUrl: | 
					
						
							|  |  |  |         avatarUrl = \ | 
					
						
							|  |  |  |             getPersonAvatarUrl(baseDir, postActor, personCache, | 
					
						
							|  |  |  |                                allowDownloads) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _logPostTiming(enableTimingLog, postStartTime, '2.1') | 
					
						
							| 
									
										
										
										
											2020-11-30 12:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     updateAvatarImageCache(session, baseDir, httpPrefix, | 
					
						
							|  |  |  |                            postActor, avatarUrl, personCache, | 
					
						
							|  |  |  |                            allowDownloads) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '2.2') | 
					
						
							| 
									
										
										
										
											2020-11-30 12:47:52 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     postHtml = \ | 
					
						
							|  |  |  |         loadIndividualPostAsHtmlFromCache(baseDir, nickname, domain, | 
					
						
							|  |  |  |                                           postJsonObject) | 
					
						
							|  |  |  |     if not postHtml: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     postHtml = preparePostFromHtmlCache(postHtml, boxName, pageNumber) | 
					
						
							|  |  |  |     updateRecentPostsCache(recentPostsCache, maxRecentPosts, | 
					
						
							|  |  |  |                            postJsonObject, postHtml) | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '3') | 
					
						
							| 
									
										
										
										
											2020-11-30 12:47:52 +00:00
										 |  |  |     return postHtml | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getAvatarImageHtml(showAvatarOptions: bool, | 
					
						
							|  |  |  |                         nickname: str, domainFull: str, | 
					
						
							|  |  |  |                         avatarUrl: str, postActor: str, | 
					
						
							|  |  |  |                         translate: {}, avatarPosition: str, | 
					
						
							|  |  |  |                         pageNumber: int, messageIdStr: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |     """Get html for the avatar image
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     avatarLink = '' | 
					
						
							|  |  |  |     if '/users/news/' not in avatarUrl: | 
					
						
							|  |  |  |         avatarLink = '        <a class="imageAnchor" href="' + postActor + '">' | 
					
						
							|  |  |  |         avatarLink += \ | 
					
						
							| 
									
										
										
										
											2020-12-12 11:25:50 +00:00
										 |  |  |             '<img loading="lazy" src="' + avatarUrl + '" title="' + \ | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |             translate['Show profile'] + '" alt=" "' + avatarPosition + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |             getBrokenLinkSubstitute() + '/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if showAvatarOptions and \ | 
					
						
							|  |  |  |        domainFull + '/users/' + nickname not in postActor: | 
					
						
							|  |  |  |         if '/users/news/' not in avatarUrl: | 
					
						
							|  |  |  |             avatarLink = \ | 
					
						
							|  |  |  |                 '        <a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |                 nickname + '?options=' + postActor + \ | 
					
						
							|  |  |  |                 ';' + str(pageNumber) + ';' + avatarUrl + messageIdStr + '">\n' | 
					
						
							|  |  |  |             avatarLink += \ | 
					
						
							|  |  |  |                 '        <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |                 translate['Show options for this person'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-05 23:48:39 +00:00
										 |  |  |                 '" src="' + avatarUrl + '" ' + avatarPosition + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                 getBrokenLinkSubstitute() + '/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             # don't link to the person options for the news account | 
					
						
							|  |  |  |             avatarLink += \ | 
					
						
							|  |  |  |                 '        <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |                 translate['Show options for this person'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-05 23:48:39 +00:00
										 |  |  |                 '" src="' + avatarUrl + '" ' + avatarPosition + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                 getBrokenLinkSubstitute() + '/>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |     return avatarLink.strip() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getReplyIconHtml(nickname: str, isPublicRepeat: bool, | 
					
						
							|  |  |  |                       showIcons: bool, commentsEnabled: bool, | 
					
						
							|  |  |  |                       postJsonObject: {}, pageNumberParam: str, | 
					
						
							|  |  |  |                       translate: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 16:00:36 +00:00
										 |  |  |     """Returns html for the reply icon/button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     replyStr = '' | 
					
						
							| 
									
										
										
										
											2020-12-01 09:51:55 +00:00
										 |  |  |     if not (showIcons and commentsEnabled): | 
					
						
							|  |  |  |         return replyStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # reply is permitted - create reply icon | 
					
						
							|  |  |  |     replyToLink = postJsonObject['object']['id'] | 
					
						
							|  |  |  |     if postJsonObject['object'].get('attributedTo'): | 
					
						
							|  |  |  |         if isinstance(postJsonObject['object']['attributedTo'], str): | 
					
						
							|  |  |  |             replyToLink += \ | 
					
						
							|  |  |  |                 '?mention=' + postJsonObject['object']['attributedTo'] | 
					
						
							|  |  |  |     if postJsonObject['object'].get('content'): | 
					
						
							|  |  |  |         mentionedActors = \ | 
					
						
							|  |  |  |             getMentionsFromHtml(postJsonObject['object']['content']) | 
					
						
							|  |  |  |         if mentionedActors: | 
					
						
							|  |  |  |             for actorUrl in mentionedActors: | 
					
						
							|  |  |  |                 if '?mention=' + actorUrl not in replyToLink: | 
					
						
							|  |  |  |                     replyToLink += '?mention=' + actorUrl | 
					
						
							|  |  |  |                     if len(replyToLink) > 500: | 
					
						
							|  |  |  |                         break | 
					
						
							|  |  |  |     replyToLink += pageNumberParam | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     replyStr = '' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:03:21 +00:00
										 |  |  |     replyToThisPostStr = translate['Reply to this post'] | 
					
						
							| 
									
										
										
										
											2020-12-01 09:51:55 +00:00
										 |  |  |     if isPublicRepeat: | 
					
						
							|  |  |  |         replyStr += \ | 
					
						
							|  |  |  |             '        <a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |             nickname + '?replyto=' + replyToLink + \ | 
					
						
							|  |  |  |             '?actor=' + postJsonObject['actor'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:03:21 +00:00
										 |  |  |             '" title="' + replyToThisPostStr + '">\n' | 
					
						
							| 
									
										
										
										
											2020-12-01 09:51:55 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         if isDM(postJsonObject): | 
					
						
							| 
									
										
										
										
											2020-11-30 16:00:36 +00:00
										 |  |  |             replyStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-01 09:51:55 +00:00
										 |  |  |                 '        ' + \ | 
					
						
							|  |  |  |                 '<a class="imageAnchor" href="/users/' + nickname + \ | 
					
						
							|  |  |  |                 '?replydm=' + replyToLink + \ | 
					
						
							| 
									
										
										
										
											2020-11-30 16:00:36 +00:00
										 |  |  |                 '?actor=' + postJsonObject['actor'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:03:21 +00:00
										 |  |  |                 '" title="' + replyToThisPostStr + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 16:00:36 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2020-12-01 09:51:55 +00:00
										 |  |  |             replyStr += \ | 
					
						
							|  |  |  |                 '        ' + \ | 
					
						
							|  |  |  |                 '<a class="imageAnchor" href="/users/' + nickname + \ | 
					
						
							|  |  |  |                 '?replyfollowers=' + replyToLink + \ | 
					
						
							|  |  |  |                 '?actor=' + postJsonObject['actor'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:03:21 +00:00
										 |  |  |                 '" title="' + replyToThisPostStr + '">\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 16:00:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-01 09:51:55 +00:00
										 |  |  |     replyStr += \ | 
					
						
							|  |  |  |         '        ' + \ | 
					
						
							|  |  |  |         '<img loading="lazy" title="' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:03:21 +00:00
										 |  |  |         replyToThisPostStr + '" alt="' + replyToThisPostStr + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         ' |" src="/icons/reply.png"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 16:00:36 +00:00
										 |  |  |     return replyStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getEditIconHtml(baseDir: str, nickname: str, domainFull: str, | 
					
						
							|  |  |  |                      postJsonObject: {}, actorNickname: str, | 
					
						
							|  |  |  |                      translate: {}, isEvent: bool) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 16:48:30 +00:00
										 |  |  |     """Returns html for the edit icon/button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     editStr = '' | 
					
						
							| 
									
										
										
										
											2020-12-01 09:58:21 +00:00
										 |  |  |     actor = postJsonObject['actor'] | 
					
						
							|  |  |  |     if (actor.endswith(domainFull + '/users/' + nickname) or | 
					
						
							| 
									
										
										
										
											2020-11-30 16:48:30 +00:00
										 |  |  |         (isEditor(baseDir, nickname) and | 
					
						
							| 
									
										
										
										
											2020-12-01 09:58:21 +00:00
										 |  |  |          actor.endswith(domainFull + '/users/news'))): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         postId = postJsonObject['object']['id'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-01 10:12:25 +00:00
										 |  |  |         if '/statuses/' not in postId: | 
					
						
							|  |  |  |             return editStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if isBlogPost(postJsonObject): | 
					
						
							|  |  |  |             editBlogPostStr = translate['Edit blog post'] | 
					
						
							|  |  |  |             if not isNewsPost(postJsonObject): | 
					
						
							| 
									
										
										
										
											2020-11-30 16:48:30 +00:00
										 |  |  |                 editStr += \ | 
					
						
							|  |  |  |                     '        ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:12:25 +00:00
										 |  |  |                     '<a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |                     nickname + \ | 
					
						
							|  |  |  |                     '/tlblogs?editblogpost=' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 09:58:21 +00:00
										 |  |  |                     postId.split('/statuses/')[1] + \ | 
					
						
							| 
									
										
										
										
											2020-11-30 16:48:30 +00:00
										 |  |  |                     '?actor=' + actorNickname + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:12:25 +00:00
										 |  |  |                     '" title="' + editBlogPostStr + '">' + \ | 
					
						
							| 
									
										
										
										
											2020-11-30 16:48:30 +00:00
										 |  |  |                     '<img loading="lazy" title="' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:12:25 +00:00
										 |  |  |                     editBlogPostStr + '" alt="' + editBlogPostStr + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |                     ' |" src="/icons/edit.png"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:12:25 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 editStr += \ | 
					
						
							|  |  |  |                     '        ' + \ | 
					
						
							|  |  |  |                     '<a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |                     nickname + '/editnewspost=' + \ | 
					
						
							|  |  |  |                     postId.split('/statuses/')[1] + \ | 
					
						
							|  |  |  |                     '?actor=' + actorNickname + \ | 
					
						
							|  |  |  |                     '" title="' + editBlogPostStr + '">' + \ | 
					
						
							|  |  |  |                     '<img loading="lazy" title="' + \ | 
					
						
							|  |  |  |                     editBlogPostStr + '" alt="' + editBlogPostStr + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |                     ' |" src="/icons/edit.png"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:12:25 +00:00
										 |  |  |         elif isEvent: | 
					
						
							|  |  |  |             editEventStr = translate['Edit event'] | 
					
						
							|  |  |  |             editStr += \ | 
					
						
							|  |  |  |                 '        ' + \ | 
					
						
							|  |  |  |                 '<a class="imageAnchor" href="/users/' + nickname + \ | 
					
						
							|  |  |  |                 '/tlblogs?editeventpost=' + \ | 
					
						
							|  |  |  |                 postId.split('/statuses/')[1] + \ | 
					
						
							|  |  |  |                 '?actor=' + actorNickname + \ | 
					
						
							|  |  |  |                 '" title="' + editEventStr + '">' + \ | 
					
						
							|  |  |  |                 '<img loading="lazy" title="' + \ | 
					
						
							|  |  |  |                 editEventStr + '" alt="' + editEventStr + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |                 ' |" src="/icons/edit.png"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 16:48:30 +00:00
										 |  |  |     return editStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getAnnounceIconHtml(nickname: str, domainFull: str, | 
					
						
							|  |  |  |                          postJsonObject: {}, | 
					
						
							|  |  |  |                          isPublicRepeat: bool, | 
					
						
							|  |  |  |                          isModerationPost: bool, | 
					
						
							|  |  |  |                          showRepeatIcon: bool, | 
					
						
							|  |  |  |                          translate: {}, | 
					
						
							|  |  |  |                          pageNumberParam: str, | 
					
						
							|  |  |  |                          timelinePostBookmark: str, | 
					
						
							|  |  |  |                          boxName: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 16:57:59 +00:00
										 |  |  |     """Returns html for announce icon/button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     announceStr = '' | 
					
						
							|  |  |  |     if not isModerationPost and showRepeatIcon: | 
					
						
							|  |  |  |         # don't allow announce/repeat of your own posts | 
					
						
							|  |  |  |         announceIcon = 'repeat_inactive.png' | 
					
						
							|  |  |  |         announceLink = 'repeat' | 
					
						
							|  |  |  |         if not isPublicRepeat: | 
					
						
							|  |  |  |             announceLink = 'repeatprivate' | 
					
						
							|  |  |  |         announceTitle = translate['Repeat this post'] | 
					
						
							| 
									
										
										
										
											2020-12-01 10:15:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 16:57:59 +00:00
										 |  |  |         if announcedByPerson(postJsonObject, nickname, domainFull): | 
					
						
							|  |  |  |             announceIcon = 'repeat.png' | 
					
						
							|  |  |  |             if not isPublicRepeat: | 
					
						
							|  |  |  |                 announceLink = 'unrepeatprivate' | 
					
						
							|  |  |  |             announceTitle = translate['Undo the repeat'] | 
					
						
							| 
									
										
										
										
											2020-12-01 10:15:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 16:57:59 +00:00
										 |  |  |         announceStr = \ | 
					
						
							|  |  |  |             '        <a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |             nickname + '?' + announceLink + \ | 
					
						
							|  |  |  |             '=' + postJsonObject['object']['id'] + pageNumberParam + \ | 
					
						
							|  |  |  |             '?actor=' + postJsonObject['actor'] + \ | 
					
						
							|  |  |  |             '?bm=' + timelinePostBookmark + \ | 
					
						
							|  |  |  |             '?tl=' + boxName + '" title="' + announceTitle + '">\n' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:15:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 16:57:59 +00:00
										 |  |  |         announceStr += \ | 
					
						
							|  |  |  |             '          ' + \ | 
					
						
							|  |  |  |             '<img loading="lazy" title="' + translate['Repeat this post'] + \ | 
					
						
							|  |  |  |             '" alt="' + translate['Repeat this post'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |             ' |" src="/icons/' + announceIcon + '"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 16:57:59 +00:00
										 |  |  |     return announceStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getLikeIconHtml(nickname: str, domainFull: str, | 
					
						
							|  |  |  |                      isModerationPost: bool, | 
					
						
							|  |  |  |                      showLikeButton: bool, | 
					
						
							|  |  |  |                      postJsonObject: {}, | 
					
						
							|  |  |  |                      enableTimingLog: bool, | 
					
						
							|  |  |  |                      postStartTime, | 
					
						
							|  |  |  |                      translate: {}, pageNumberParam: str, | 
					
						
							|  |  |  |                      timelinePostBookmark: str, | 
					
						
							|  |  |  |                      boxName: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 17:06:55 +00:00
										 |  |  |     """Returns html for like icon/button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     likeStr = '' | 
					
						
							|  |  |  |     if not isModerationPost and showLikeButton: | 
					
						
							|  |  |  |         likeIcon = 'like_inactive.png' | 
					
						
							|  |  |  |         likeLink = 'like' | 
					
						
							|  |  |  |         likeTitle = translate['Like this post'] | 
					
						
							|  |  |  |         likeCount = noOfLikes(postJsonObject) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _logPostTiming(enableTimingLog, postStartTime, '12.1') | 
					
						
							| 
									
										
										
										
											2020-11-30 17:06:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         likeCountStr = '' | 
					
						
							|  |  |  |         if likeCount > 0: | 
					
						
							|  |  |  |             if likeCount <= 10: | 
					
						
							|  |  |  |                 likeCountStr = ' (' + str(likeCount) + ')' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 likeCountStr = ' (10+)' | 
					
						
							|  |  |  |             if likedByPerson(postJsonObject, nickname, domainFull): | 
					
						
							|  |  |  |                 if likeCount == 1: | 
					
						
							|  |  |  |                     # liked by the reader only | 
					
						
							|  |  |  |                     likeCountStr = '' | 
					
						
							|  |  |  |                 likeIcon = 'like.png' | 
					
						
							|  |  |  |                 likeLink = 'unlike' | 
					
						
							|  |  |  |                 likeTitle = translate['Undo the like'] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _logPostTiming(enableTimingLog, postStartTime, '12.2') | 
					
						
							| 
									
										
										
										
											2020-11-30 17:06:55 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         likeStr = '' | 
					
						
							|  |  |  |         if likeCountStr: | 
					
						
							|  |  |  |             # show the number of likes next to icon | 
					
						
							|  |  |  |             likeStr += '<label class="likesCount">' | 
					
						
							|  |  |  |             likeStr += likeCountStr.replace('(', '').replace(')', '').strip() | 
					
						
							|  |  |  |             likeStr += '</label>\n' | 
					
						
							|  |  |  |         likeStr += \ | 
					
						
							|  |  |  |             '        <a class="imageAnchor" href="/users/' + nickname + '?' + \ | 
					
						
							|  |  |  |             likeLink + '=' + postJsonObject['object']['id'] + \ | 
					
						
							|  |  |  |             pageNumberParam + \ | 
					
						
							|  |  |  |             '?actor=' + postJsonObject['actor'] + \ | 
					
						
							|  |  |  |             '?bm=' + timelinePostBookmark + \ | 
					
						
							|  |  |  |             '?tl=' + boxName + '" title="' + \ | 
					
						
							|  |  |  |             likeTitle + likeCountStr + '">\n' | 
					
						
							|  |  |  |         likeStr += \ | 
					
						
							|  |  |  |             '          ' + \ | 
					
						
							|  |  |  |             '<img loading="lazy" title="' + likeTitle + likeCountStr + \ | 
					
						
							|  |  |  |             '" alt="' + likeTitle + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |             ' |" src="/icons/' + likeIcon + '"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 17:06:55 +00:00
										 |  |  |     return likeStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getBookmarkIconHtml(nickname: str, domainFull: str, | 
					
						
							|  |  |  |                          postJsonObject: {}, | 
					
						
							|  |  |  |                          isModerationPost: bool, | 
					
						
							|  |  |  |                          translate: {}, | 
					
						
							|  |  |  |                          enableTimingLog: bool, | 
					
						
							|  |  |  |                          postStartTime, boxName: str, | 
					
						
							|  |  |  |                          pageNumberParam: str, | 
					
						
							|  |  |  |                          timelinePostBookmark: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 17:36:06 +00:00
										 |  |  |     """Returns html for bookmark icon/button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     bookmarkStr = '' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:15:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if isModerationPost: | 
					
						
							|  |  |  |         return bookmarkStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bookmarkIcon = 'bookmark_inactive.png' | 
					
						
							|  |  |  |     bookmarkLink = 'bookmark' | 
					
						
							|  |  |  |     bookmarkTitle = translate['Bookmark this post'] | 
					
						
							|  |  |  |     if bookmarkedByPerson(postJsonObject, nickname, domainFull): | 
					
						
							|  |  |  |         bookmarkIcon = 'bookmark.png' | 
					
						
							|  |  |  |         bookmarkLink = 'unbookmark' | 
					
						
							|  |  |  |         bookmarkTitle = translate['Undo the bookmark'] | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '12.6') | 
					
						
							| 
									
										
										
										
											2020-12-01 10:15:26 +00:00
										 |  |  |     bookmarkStr = \ | 
					
						
							|  |  |  |         '        <a class="imageAnchor" href="/users/' + nickname + '?' + \ | 
					
						
							|  |  |  |         bookmarkLink + '=' + postJsonObject['object']['id'] + \ | 
					
						
							|  |  |  |         pageNumberParam + \ | 
					
						
							|  |  |  |         '?actor=' + postJsonObject['actor'] + \ | 
					
						
							|  |  |  |         '?bm=' + timelinePostBookmark + \ | 
					
						
							|  |  |  |         '?tl=' + boxName + '" title="' + bookmarkTitle + '">\n' | 
					
						
							|  |  |  |     bookmarkStr += \ | 
					
						
							|  |  |  |         '        ' + \ | 
					
						
							|  |  |  |         '<img loading="lazy" title="' + bookmarkTitle + '" alt="' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         bookmarkTitle + ' |" src="/icons' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:15:26 +00:00
										 |  |  |         '/' + bookmarkIcon + '"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 17:36:06 +00:00
										 |  |  |     return bookmarkStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getMuteIconHtml(isMuted: bool, | 
					
						
							|  |  |  |                      postActor: str, | 
					
						
							|  |  |  |                      messageId: str, | 
					
						
							|  |  |  |                      nickname: str, domainFull: str, | 
					
						
							|  |  |  |                      allowDeletion: bool, | 
					
						
							|  |  |  |                      pageNumberParam: str, | 
					
						
							|  |  |  |                      boxName: str, | 
					
						
							|  |  |  |                      timelinePostBookmark: str, | 
					
						
							|  |  |  |                      translate: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 17:48:35 +00:00
										 |  |  |     """Returns html for mute icon/button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     muteStr = '' | 
					
						
							|  |  |  |     if (allowDeletion or | 
					
						
							|  |  |  |         ('/' + domainFull + '/' in postActor and | 
					
						
							|  |  |  |          messageId.startswith(postActor))): | 
					
						
							|  |  |  |         return muteStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not isMuted: | 
					
						
							|  |  |  |         muteStr = \ | 
					
						
							|  |  |  |             '        <a class="imageAnchor" href="/users/' + nickname + \ | 
					
						
							|  |  |  |             '?mute=' + messageId + pageNumberParam + '?tl=' + boxName + \ | 
					
						
							|  |  |  |             '?bm=' + timelinePostBookmark + \ | 
					
						
							|  |  |  |             '" title="' + translate['Mute this post'] + '">\n' | 
					
						
							|  |  |  |         muteStr += \ | 
					
						
							|  |  |  |             '          ' + \ | 
					
						
							|  |  |  |             '<img loading="lazy" alt="' + \ | 
					
						
							|  |  |  |             translate['Mute this post'] + \ | 
					
						
							|  |  |  |             ' |" title="' + translate['Mute this post'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |             '" src="/icons/mute.png"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 17:48:35 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         muteStr = \ | 
					
						
							|  |  |  |             '        <a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |             nickname + '?unmute=' + messageId + \ | 
					
						
							|  |  |  |             pageNumberParam + '?tl=' + boxName + '?bm=' + \ | 
					
						
							|  |  |  |             timelinePostBookmark + '" title="' + \ | 
					
						
							|  |  |  |             translate['Undo mute'] + '">\n' | 
					
						
							|  |  |  |         muteStr += \ | 
					
						
							|  |  |  |             '          ' + \ | 
					
						
							|  |  |  |             '<img loading="lazy" alt="' + translate['Undo mute'] + \ | 
					
						
							|  |  |  |             ' |" title="' + translate['Undo mute'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |             '" src="/icons/unmute.png"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 17:48:35 +00:00
										 |  |  |     return muteStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getDeleteIconHtml(nickname: str, domainFull: str, | 
					
						
							|  |  |  |                        allowDeletion: bool, | 
					
						
							|  |  |  |                        postActor: str, | 
					
						
							|  |  |  |                        messageId: str, | 
					
						
							|  |  |  |                        postJsonObject: {}, | 
					
						
							|  |  |  |                        pageNumberParam: str, | 
					
						
							|  |  |  |                        translate: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 18:03:02 +00:00
										 |  |  |     """Returns html for delete icon/button
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     deleteStr = '' | 
					
						
							|  |  |  |     if (allowDeletion or | 
					
						
							|  |  |  |         ('/' + domainFull + '/' in postActor and | 
					
						
							|  |  |  |          messageId.startswith(postActor))): | 
					
						
							|  |  |  |         if '/users/' + nickname + '/' in messageId: | 
					
						
							|  |  |  |             if not isNewsPost(postJsonObject): | 
					
						
							|  |  |  |                 deleteStr = \ | 
					
						
							|  |  |  |                     '        <a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |                     nickname + \ | 
					
						
							|  |  |  |                     '?delete=' + messageId + pageNumberParam + \ | 
					
						
							|  |  |  |                     '" title="' + translate['Delete this post'] + '">\n' | 
					
						
							|  |  |  |                 deleteStr += \ | 
					
						
							|  |  |  |                     '          ' + \ | 
					
						
							|  |  |  |                     '<img loading="lazy" alt="' + \ | 
					
						
							|  |  |  |                     translate['Delete this post'] + \ | 
					
						
							|  |  |  |                     ' |" title="' + translate['Delete this post'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |                     '" src="/icons/delete.png"/></a>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 18:03:02 +00:00
										 |  |  |     return deleteStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getPublishedDateStr(postJsonObject: {}, | 
					
						
							|  |  |  |                          showPublishedDateOnly: bool) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 18:03:02 +00:00
										 |  |  |     """Return the html for the published date on a post
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     publishedStr = '' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:19:53 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if not postJsonObject['object'].get('published'): | 
					
						
							|  |  |  |         return publishedStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     publishedStr = postJsonObject['object']['published'] | 
					
						
							|  |  |  |     if '.' not in publishedStr: | 
					
						
							|  |  |  |         if '+' not in publishedStr: | 
					
						
							|  |  |  |             datetimeObject = \ | 
					
						
							|  |  |  |                 datetime.strptime(publishedStr, "%Y-%m-%dT%H:%M:%SZ") | 
					
						
							| 
									
										
										
										
											2020-11-30 18:03:02 +00:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2020-12-01 10:19:53 +00:00
										 |  |  |             datetimeObject = \ | 
					
						
							|  |  |  |                 datetime.strptime(publishedStr.split('+')[0] + 'Z', | 
					
						
							|  |  |  |                                   "%Y-%m-%dT%H:%M:%SZ") | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         publishedStr = \ | 
					
						
							|  |  |  |             publishedStr.replace('T', ' ').split('.')[0] | 
					
						
							|  |  |  |         datetimeObject = parse(publishedStr) | 
					
						
							|  |  |  |     if not showPublishedDateOnly: | 
					
						
							|  |  |  |         publishedStr = datetimeObject.strftime("%a %b %d, %H:%M") | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         publishedStr = datetimeObject.strftime("%a %b %d") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # if the post has replies then append a symbol to indicate this | 
					
						
							|  |  |  |     if postJsonObject.get('hasReplies'): | 
					
						
							|  |  |  |         if postJsonObject['hasReplies'] is True: | 
					
						
							|  |  |  |             publishedStr = '[' + publishedStr + ']' | 
					
						
							| 
									
										
										
										
											2020-11-30 18:03:02 +00:00
										 |  |  |     return publishedStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getBlogCitationsHtml(boxName: str, | 
					
						
							|  |  |  |                           postJsonObject: {}, | 
					
						
							|  |  |  |                           translate: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-30 20:52:58 +00:00
										 |  |  |     """Returns blog citations as html
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     # show blog citations | 
					
						
							|  |  |  |     citationsStr = '' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:19:53 +00:00
										 |  |  |     if not (boxName == 'tlblogs' or boxName == 'tlfeatures'): | 
					
						
							|  |  |  |         return citationsStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not postJsonObject['object'].get('tag'): | 
					
						
							|  |  |  |         return citationsStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for tagJson in postJsonObject['object']['tag']: | 
					
						
							|  |  |  |         if not isinstance(tagJson, dict): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if not tagJson.get('type'): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if tagJson['type'] != 'Article': | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if not tagJson.get('name'): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         if not tagJson.get('url'): | 
					
						
							|  |  |  |             continue | 
					
						
							|  |  |  |         citationsStr += \ | 
					
						
							|  |  |  |             '<li><a href="' + tagJson['url'] + '">' + \ | 
					
						
							|  |  |  |             '<cite>' + tagJson['name'] + '</cite></a></li>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if citationsStr: | 
					
						
							| 
									
										
										
										
											2020-12-01 10:30:24 +00:00
										 |  |  |         citationsStr = '<p><b>' + translate['Citations'] + ':</b></p>' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 10:19:53 +00:00
										 |  |  |             '<ul>\n' + citationsStr + '</ul>\n' | 
					
						
							| 
									
										
										
										
											2020-11-30 20:52:58 +00:00
										 |  |  |     return citationsStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _boostOwnTootHtml(translate: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |     """The html title for announcing your own post
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '        <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['announces'] + \ | 
					
						
							|  |  |  |         '" alt="' + translate['announces'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         '" src="/icons' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |         '/repeat_inactive.png" class="announceOrReply"/>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _announceUnattributedHtml(translate: {}, | 
					
						
							|  |  |  |                               postJsonObject: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |     """Returns the html for an announce title where there
 | 
					
						
							|  |  |  |     is no attribution on the announced post | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '    <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['announces'] + '" alt="' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         translate['announces'] + '" src="/icons' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |         '/repeat_inactive.png" ' + \ | 
					
						
							|  |  |  |         'class="announceOrReply"/>\n' + \ | 
					
						
							|  |  |  |         '      <a href="' + \ | 
					
						
							|  |  |  |         postJsonObject['object']['id'] + \ | 
					
						
							|  |  |  |         '" class="announceOrReply">@unattributed</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _announceWithoutDisplayNameHtml(translate: {}, | 
					
						
							|  |  |  |                                     announceNickname: str, | 
					
						
							|  |  |  |                                     announceDomain: str, | 
					
						
							|  |  |  |                                     postJsonObject: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 11:43:13 +00:00
										 |  |  |     """Returns html for an announce title where there is no display name
 | 
					
						
							|  |  |  |     only a handle nick@domain | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '    <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['announces'] + '" alt="' + translate['announces'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         '" src="/icons/repeat_inactive.png" ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 11:43:13 +00:00
										 |  |  |         'class="announceOrReply"/>\n' + \ | 
					
						
							|  |  |  |         '      <a href="' + postJsonObject['object']['id'] + '" ' + \ | 
					
						
							|  |  |  |         'class="announceOrReply">@' + \ | 
					
						
							|  |  |  |         announceNickname + '@' + announceDomain + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _announceWithDisplayNameHtml(translate: {}, | 
					
						
							|  |  |  |                                  postJsonObject: {}, | 
					
						
							|  |  |  |                                  announceDisplayName: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 12:04:59 +00:00
										 |  |  |     """Returns html for an announce having a display name
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '          <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['announces'] + '" alt="' + \ | 
					
						
							|  |  |  |         translate['announces'] + '" src="/' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         'icons/repeat_inactive.png" ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 12:04:59 +00:00
										 |  |  |         'class="announceOrReply"/>\n' + \ | 
					
						
							|  |  |  |         '        <a href="' + \ | 
					
						
							|  |  |  |         postJsonObject['object']['id'] + '" ' + \ | 
					
						
							|  |  |  |         'class="announceOrReply">' + announceDisplayName + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getPostTitleAnnounceHtml(baseDir: str, | 
					
						
							|  |  |  |                               httpPrefix: str, | 
					
						
							|  |  |  |                               nickname: str, domain: str, | 
					
						
							|  |  |  |                               showRepeatIcon: bool, | 
					
						
							|  |  |  |                               isAnnounced: bool, | 
					
						
							|  |  |  |                               postJsonObject: {}, | 
					
						
							|  |  |  |                               postActor: str, | 
					
						
							|  |  |  |                               translate: {}, | 
					
						
							|  |  |  |                               enableTimingLog: bool, | 
					
						
							|  |  |  |                               postStartTime, | 
					
						
							|  |  |  |                               boxName: str, | 
					
						
							|  |  |  |                               personCache: {}, | 
					
						
							|  |  |  |                               allowDownloads: bool, | 
					
						
							|  |  |  |                               avatarPosition: str, | 
					
						
							|  |  |  |                               pageNumber: int, | 
					
						
							|  |  |  |                               messageIdStr: str, | 
					
						
							|  |  |  |                               containerClassIcons: str, | 
					
						
							|  |  |  |                               containerClass: str) -> (str, str, str, str): | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |     """Returns the announce title of a post containing names of participants
 | 
					
						
							|  |  |  |     x announces y | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     titleStr = '' | 
					
						
							|  |  |  |     replyAvatarImageInPost = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if postJsonObject['object'].get('attributedTo'): | 
					
						
							|  |  |  |         attributedTo = '' | 
					
						
							|  |  |  |         if isinstance(postJsonObject['object']['attributedTo'], str): | 
					
						
							|  |  |  |             attributedTo = postJsonObject['object']['attributedTo'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if attributedTo.startswith(postActor): | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             titleStr += _boostOwnTootHtml(translate) | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             # boosting another person's post | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _logPostTiming(enableTimingLog, postStartTime, '13.2') | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |             announceNickname = None | 
					
						
							|  |  |  |             if attributedTo: | 
					
						
							|  |  |  |                 announceNickname = getNicknameFromActor(attributedTo) | 
					
						
							|  |  |  |             if announceNickname: | 
					
						
							|  |  |  |                 announceDomain, announcePort = \ | 
					
						
							|  |  |  |                     getDomainFromActor(attributedTo) | 
					
						
							|  |  |  |                 getPersonFromCache(baseDir, attributedTo, | 
					
						
							|  |  |  |                                    personCache, allowDownloads) | 
					
						
							|  |  |  |                 announceDisplayName = \ | 
					
						
							|  |  |  |                     getDisplayName(baseDir, attributedTo, personCache) | 
					
						
							|  |  |  |                 if announceDisplayName: | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                     _logPostTiming(enableTimingLog, postStartTime, '13.3') | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-01 11:43:13 +00:00
										 |  |  |                     # add any emoji to the display name | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |                     if ':' in announceDisplayName: | 
					
						
							|  |  |  |                         announceDisplayName = \ | 
					
						
							|  |  |  |                             addEmojiToDisplayName(baseDir, httpPrefix, | 
					
						
							|  |  |  |                                                   nickname, domain, | 
					
						
							|  |  |  |                                                   announceDisplayName, | 
					
						
							|  |  |  |                                                   False) | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                     _logPostTiming(enableTimingLog, postStartTime, '13.3.1') | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |                     titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                         _announceWithDisplayNameHtml(translate, | 
					
						
							|  |  |  |                                                      postJsonObject, | 
					
						
							|  |  |  |                                                      announceDisplayName) | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |                     # show avatar of person replied to | 
					
						
							|  |  |  |                     announceActor = \ | 
					
						
							|  |  |  |                         postJsonObject['object']['attributedTo'] | 
					
						
							|  |  |  |                     announceAvatarUrl = \ | 
					
						
							|  |  |  |                         getPersonAvatarUrl(baseDir, announceActor, | 
					
						
							|  |  |  |                                            personCache, allowDownloads) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                     _logPostTiming(enableTimingLog, postStartTime, '13.4') | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if announceAvatarUrl: | 
					
						
							|  |  |  |                         idx = 'Show options for this person' | 
					
						
							|  |  |  |                         if '/users/news/' not in announceAvatarUrl: | 
					
						
							|  |  |  |                             replyAvatarImageInPost = \ | 
					
						
							|  |  |  |                                 '        ' \ | 
					
						
							|  |  |  |                                 '<div class=' + \ | 
					
						
							|  |  |  |                                 '"timeline-avatar-reply">\n' \ | 
					
						
							|  |  |  |                                 '            ' + \ | 
					
						
							|  |  |  |                                 '<a class="imageAnchor" ' + \ | 
					
						
							|  |  |  |                                 'href="/users/' + nickname + \ | 
					
						
							|  |  |  |                                 '?options=' + \ | 
					
						
							|  |  |  |                                 announceActor + ';' + \ | 
					
						
							|  |  |  |                                 str(pageNumber) + \ | 
					
						
							|  |  |  |                                 ';' + announceAvatarUrl + \ | 
					
						
							|  |  |  |                                 messageIdStr + '">' \ | 
					
						
							|  |  |  |                                 '<img loading="lazy" src="' + \ | 
					
						
							| 
									
										
										
										
											2020-12-06 15:35:49 +00:00
										 |  |  |                                 announceAvatarUrl + '" ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |                                 'title="' + translate[idx] + \ | 
					
						
							|  |  |  |                                 '" alt=" "' + avatarPosition + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                                 getBrokenLinkSubstitute() + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |                                 '/></a>\n    </div>\n' | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                         _announceWithoutDisplayNameHtml(translate, | 
					
						
							|  |  |  |                                                         announceNickname, | 
					
						
							|  |  |  |                                                         announceDomain, | 
					
						
							|  |  |  |                                                         postJsonObject) | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |             else: | 
					
						
							|  |  |  |                 titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                     _announceUnattributedHtml(translate, | 
					
						
							|  |  |  |                                               postJsonObject) | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |             _announceUnattributedHtml(translate, postJsonObject) | 
					
						
							| 
									
										
										
										
											2020-12-01 11:12:38 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return (titleStr, replyAvatarImageInPost, | 
					
						
							|  |  |  |             containerClassIcons, containerClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 21:24:46 +00:00
										 |  |  | def _replyToYourselfHtml(translate: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |     """Returns html for a title which is a reply to yourself
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '    <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['replying to themselves'] + \ | 
					
						
							|  |  |  |         '" alt="' + translate['replying to themselves'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         '" src="/icons' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |         '/reply.png" class="announceOrReply"/>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _replyToUnknownHtml(translate: {}, | 
					
						
							|  |  |  |                         postJsonObject: {}) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 13:17:51 +00:00
										 |  |  |     """Returns the html title for a reply to an unknown handle
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '        <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['replying to'] + '" alt="' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         translate['replying to'] + '" src="/icons' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 13:17:51 +00:00
										 |  |  |         '/reply.png" class="announceOrReply"/>\n' + \ | 
					
						
							|  |  |  |         '        <a href="' + \ | 
					
						
							|  |  |  |         postJsonObject['object']['inReplyTo'] + \ | 
					
						
							|  |  |  |         '" class="announceOrReply">@unknown</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _replyWithUnknownPathHtml(translate: {}, | 
					
						
							|  |  |  |                               postJsonObject: {}, | 
					
						
							|  |  |  |                               postDomain: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 13:24:22 +00:00
										 |  |  |     """Returns html title for a reply with an unknown path
 | 
					
						
							|  |  |  |     eg. does not contain /statuses/ | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '        <img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['replying to'] + \ | 
					
						
							|  |  |  |         '" alt="' + translate['replying to'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         '" src="/icons/reply.png" ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 13:24:22 +00:00
										 |  |  |         'class="announceOrReply"/>\n' + \ | 
					
						
							|  |  |  |         '        <a href="' + \ | 
					
						
							|  |  |  |         postJsonObject['object']['inReplyTo'] + \ | 
					
						
							|  |  |  |         '" class="announceOrReply">' + \ | 
					
						
							|  |  |  |         postDomain + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getReplyHtml(translate: {}, | 
					
						
							|  |  |  |                   inReplyTo: str, replyDisplayName: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 13:32:08 +00:00
										 |  |  |     """Returns html title for a reply
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '        ' + \ | 
					
						
							|  |  |  |         '<img loading="lazy" title="' + \ | 
					
						
							|  |  |  |         translate['replying to'] + '" alt="' + \ | 
					
						
							|  |  |  |         translate['replying to'] + '" src="/' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         'icons/reply.png" ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 13:32:08 +00:00
										 |  |  |         'class="announceOrReply"/>\n' + \ | 
					
						
							|  |  |  |         '        <a href="' + inReplyTo + \ | 
					
						
							|  |  |  |         '" class="announceOrReply">' + \ | 
					
						
							|  |  |  |         replyDisplayName + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getReplyWithoutDisplayName(translate: {}, | 
					
						
							|  |  |  |                                 inReplyTo: str, | 
					
						
							|  |  |  |                                 replyNickname: str, replyDomain: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 13:52:41 +00:00
										 |  |  |     """Returns html for a reply without a display name,
 | 
					
						
							|  |  |  |     only a handle nick@domain | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     return '        ' + \ | 
					
						
							|  |  |  |         '<img loading="lazy" title="' + translate['replying to'] + \ | 
					
						
							|  |  |  |         '" alt="' + translate['replying to'] + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |         '" src="/icons/reply.png" ' + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 13:52:41 +00:00
										 |  |  |         'class="announceOrReply"/>\n' + '        <a href="' + \ | 
					
						
							|  |  |  |         inReplyTo + '" class="announceOrReply">@' + \ | 
					
						
							|  |  |  |         replyNickname + '@' + replyDomain + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getPostTitleReplyHtml(baseDir: str, | 
					
						
							|  |  |  |                            httpPrefix: str, | 
					
						
							|  |  |  |                            nickname: str, domain: str, | 
					
						
							|  |  |  |                            showRepeatIcon: bool, | 
					
						
							|  |  |  |                            isAnnounced: bool, | 
					
						
							|  |  |  |                            postJsonObject: {}, | 
					
						
							|  |  |  |                            postActor: str, | 
					
						
							|  |  |  |                            translate: {}, | 
					
						
							|  |  |  |                            enableTimingLog: bool, | 
					
						
							|  |  |  |                            postStartTime, | 
					
						
							|  |  |  |                            boxName: str, | 
					
						
							|  |  |  |                            personCache: {}, | 
					
						
							|  |  |  |                            allowDownloads: bool, | 
					
						
							|  |  |  |                            avatarPosition: str, | 
					
						
							|  |  |  |                            pageNumber: int, | 
					
						
							|  |  |  |                            messageIdStr: str, | 
					
						
							|  |  |  |                            containerClassIcons: str, | 
					
						
							|  |  |  |                            containerClass: str) -> (str, str, str, str): | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |     """Returns the reply title of a post containing names of participants
 | 
					
						
							|  |  |  |     x replies to y | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     titleStr = '' | 
					
						
							|  |  |  |     replyAvatarImageInPost = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not postJsonObject['object'].get('inReplyTo'): | 
					
						
							|  |  |  |         return (titleStr, replyAvatarImageInPost, | 
					
						
							|  |  |  |                 containerClassIcons, containerClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     containerClassIcons = 'containericons darker' | 
					
						
							|  |  |  |     containerClass = 'container darker' | 
					
						
							|  |  |  |     if postJsonObject['object']['inReplyTo'].startswith(postActor): | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         titleStr += _replyToYourselfHtml(translate) | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |         return (titleStr, replyAvatarImageInPost, | 
					
						
							|  |  |  |                 containerClassIcons, containerClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if '/statuses/' in postJsonObject['object']['inReplyTo']: | 
					
						
							|  |  |  |         inReplyTo = postJsonObject['object']['inReplyTo'] | 
					
						
							|  |  |  |         replyActor = inReplyTo.split('/statuses/')[0] | 
					
						
							|  |  |  |         replyNickname = getNicknameFromActor(replyActor) | 
					
						
							|  |  |  |         if replyNickname: | 
					
						
							|  |  |  |             replyDomain, replyPort = \ | 
					
						
							|  |  |  |                 getDomainFromActor(replyActor) | 
					
						
							|  |  |  |             if replyNickname and replyDomain: | 
					
						
							|  |  |  |                 getPersonFromCache(baseDir, replyActor, | 
					
						
							|  |  |  |                                    personCache, | 
					
						
							|  |  |  |                                    allowDownloads) | 
					
						
							|  |  |  |                 replyDisplayName = \ | 
					
						
							|  |  |  |                     getDisplayName(baseDir, replyActor, | 
					
						
							|  |  |  |                                    personCache) | 
					
						
							|  |  |  |                 if replyDisplayName: | 
					
						
							| 
									
										
										
										
											2020-12-01 13:32:08 +00:00
										 |  |  |                     # add emoji to the display name | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |                     if ':' in replyDisplayName: | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                         _logPostTiming(enableTimingLog, postStartTime, '13.5') | 
					
						
							| 
									
										
										
										
											2020-12-01 13:46:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |                         replyDisplayName = \ | 
					
						
							|  |  |  |                             addEmojiToDisplayName(baseDir, | 
					
						
							|  |  |  |                                                   httpPrefix, | 
					
						
							|  |  |  |                                                   nickname, | 
					
						
							|  |  |  |                                                   domain, | 
					
						
							| 
									
										
										
										
											2020-12-01 13:32:08 +00:00
										 |  |  |                                                   replyDisplayName, | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |                                                   False) | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                         _logPostTiming(enableTimingLog, postStartTime, '13.6') | 
					
						
							| 
									
										
										
										
											2020-12-01 13:32:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |                     titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                         _getReplyHtml(translate, inReplyTo, replyDisplayName) | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                     _logPostTiming(enableTimingLog, postStartTime, '13.7') | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     # show avatar of person replied to | 
					
						
							|  |  |  |                     replyAvatarUrl = \ | 
					
						
							|  |  |  |                         getPersonAvatarUrl(baseDir, | 
					
						
							|  |  |  |                                            replyActor, | 
					
						
							|  |  |  |                                            personCache, | 
					
						
							|  |  |  |                                            allowDownloads) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                     _logPostTiming(enableTimingLog, postStartTime, '13.8') | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if replyAvatarUrl: | 
					
						
							|  |  |  |                         replyAvatarImageInPost = \ | 
					
						
							|  |  |  |                             '        <div class=' + \ | 
					
						
							|  |  |  |                             '"timeline-avatar-reply">\n' | 
					
						
							|  |  |  |                         replyAvatarImageInPost += \ | 
					
						
							|  |  |  |                             '          ' + \ | 
					
						
							|  |  |  |                             '<a class="imageAnchor" ' + \ | 
					
						
							|  |  |  |                             'href="/users/' + nickname + \ | 
					
						
							|  |  |  |                             '?options=' + replyActor + \ | 
					
						
							|  |  |  |                             ';' + str(pageNumber) + ';' + \ | 
					
						
							|  |  |  |                             replyAvatarUrl + \ | 
					
						
							|  |  |  |                             messageIdStr + '">\n' | 
					
						
							|  |  |  |                         replyAvatarImageInPost += \ | 
					
						
							|  |  |  |                             '          ' + \ | 
					
						
							|  |  |  |                             '<img loading="lazy" src="' + \ | 
					
						
							|  |  |  |                             replyAvatarUrl + '" ' | 
					
						
							|  |  |  |                         replyAvatarImageInPost += \ | 
					
						
							|  |  |  |                             'title="' + \ | 
					
						
							|  |  |  |                             translate['Show profile'] | 
					
						
							|  |  |  |                         replyAvatarImageInPost += \ | 
					
						
							|  |  |  |                             '" alt=" "' + \ | 
					
						
							| 
									
										
										
										
											2020-12-06 15:40:23 +00:00
										 |  |  |                             avatarPosition + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                             getBrokenLinkSubstitute() + \ | 
					
						
							| 
									
										
										
										
											2020-12-06 15:35:49 +00:00
										 |  |  |                             '/></a>\n        </div>\n' | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |                 else: | 
					
						
							|  |  |  |                     inReplyTo = \ | 
					
						
							|  |  |  |                         postJsonObject['object']['inReplyTo'] | 
					
						
							|  |  |  |                     titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                         _getReplyWithoutDisplayName(translate, | 
					
						
							|  |  |  |                                                     inReplyTo, | 
					
						
							|  |  |  |                                                     replyNickname, | 
					
						
							|  |  |  |                                                     replyDomain) | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |         else: | 
					
						
							|  |  |  |             titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                 _replyToUnknownHtml(translate, postJsonObject) | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  |     else: | 
					
						
							|  |  |  |         postDomain = \ | 
					
						
							|  |  |  |             postJsonObject['object']['inReplyTo'] | 
					
						
							|  |  |  |         prefixes = getProtocolPrefixes() | 
					
						
							|  |  |  |         for prefix in prefixes: | 
					
						
							|  |  |  |             postDomain = postDomain.replace(prefix, '') | 
					
						
							|  |  |  |         if '/' in postDomain: | 
					
						
							|  |  |  |             postDomain = postDomain.split('/', 1)[0] | 
					
						
							|  |  |  |         if postDomain: | 
					
						
							|  |  |  |             titleStr += \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |                 _replyWithUnknownPathHtml(translate, | 
					
						
							|  |  |  |                                           postJsonObject, postDomain) | 
					
						
							| 
									
										
										
										
											2020-12-01 12:30:17 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return (titleStr, replyAvatarImageInPost, | 
					
						
							|  |  |  |             containerClassIcons, containerClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  | def _getPostTitleHtml(baseDir: str, | 
					
						
							|  |  |  |                       httpPrefix: str, | 
					
						
							|  |  |  |                       nickname: str, domain: str, | 
					
						
							|  |  |  |                       showRepeatIcon: bool, | 
					
						
							|  |  |  |                       isAnnounced: bool, | 
					
						
							|  |  |  |                       postJsonObject: {}, | 
					
						
							|  |  |  |                       postActor: str, | 
					
						
							|  |  |  |                       translate: {}, | 
					
						
							|  |  |  |                       enableTimingLog: bool, | 
					
						
							|  |  |  |                       postStartTime, | 
					
						
							|  |  |  |                       boxName: str, | 
					
						
							|  |  |  |                       personCache: {}, | 
					
						
							|  |  |  |                       allowDownloads: bool, | 
					
						
							|  |  |  |                       avatarPosition: str, | 
					
						
							|  |  |  |                       pageNumber: int, | 
					
						
							|  |  |  |                       messageIdStr: str, | 
					
						
							|  |  |  |                       containerClassIcons: str, | 
					
						
							|  |  |  |                       containerClass: str) -> (str, str, str, str): | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  |     """Returns the title of a post containing names of participants
 | 
					
						
							|  |  |  |     x replies to y, x announces y, etc | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  |     titleStr = '' | 
					
						
							|  |  |  |     replyAvatarImageInPost = '' | 
					
						
							| 
									
										
										
										
											2020-12-01 10:30:24 +00:00
										 |  |  |     if not showRepeatIcon: | 
					
						
							|  |  |  |         return (titleStr, replyAvatarImageInPost, | 
					
						
							|  |  |  |                 containerClassIcons, containerClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if isAnnounced: | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         return _getPostTitleAnnounceHtml(baseDir, | 
					
						
							|  |  |  |                                          httpPrefix, | 
					
						
							|  |  |  |                                          nickname, domain, | 
					
						
							|  |  |  |                                          showRepeatIcon, | 
					
						
							|  |  |  |                                          isAnnounced, | 
					
						
							|  |  |  |                                          postJsonObject, | 
					
						
							|  |  |  |                                          postActor, | 
					
						
							|  |  |  |                                          translate, | 
					
						
							|  |  |  |                                          enableTimingLog, | 
					
						
							|  |  |  |                                          postStartTime, | 
					
						
							|  |  |  |                                          boxName, | 
					
						
							|  |  |  |                                          personCache, | 
					
						
							|  |  |  |                                          allowDownloads, | 
					
						
							|  |  |  |                                          avatarPosition, | 
					
						
							|  |  |  |                                          pageNumber, | 
					
						
							|  |  |  |                                          messageIdStr, | 
					
						
							|  |  |  |                                          containerClassIcons, | 
					
						
							|  |  |  |                                          containerClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return _getPostTitleReplyHtml(baseDir, | 
					
						
							|  |  |  |                                   httpPrefix, | 
					
						
							|  |  |  |                                   nickname, domain, | 
					
						
							|  |  |  |                                   showRepeatIcon, | 
					
						
							|  |  |  |                                   isAnnounced, | 
					
						
							|  |  |  |                                   postJsonObject, | 
					
						
							|  |  |  |                                   postActor, | 
					
						
							|  |  |  |                                   translate, | 
					
						
							|  |  |  |                                   enableTimingLog, | 
					
						
							|  |  |  |                                   postStartTime, | 
					
						
							|  |  |  |                                   boxName, | 
					
						
							|  |  |  |                                   personCache, | 
					
						
							|  |  |  |                                   allowDownloads, | 
					
						
							|  |  |  |                                   avatarPosition, | 
					
						
							|  |  |  |                                   pageNumber, | 
					
						
							|  |  |  |                                   messageIdStr, | 
					
						
							|  |  |  |                                   containerClassIcons, | 
					
						
							|  |  |  |                                   containerClass) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def _getFooterWithIcons(showIcons: bool, | 
					
						
							|  |  |  |                         containerClassIcons: str, | 
					
						
							|  |  |  |                         replyStr: str, announceStr: str, | 
					
						
							|  |  |  |                         likeStr: str, bookmarkStr: str, | 
					
						
							|  |  |  |                         deleteStr: str, muteStr: str, editStr: str, | 
					
						
							|  |  |  |                         postJsonObject: {}, publishedLink: str, | 
					
						
							|  |  |  |                         timeClass: str, publishedStr: str) -> str: | 
					
						
							| 
									
										
										
										
											2020-12-01 14:08:12 +00:00
										 |  |  |     """Returns the html for a post footer containing icons
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not showIcons: | 
					
						
							|  |  |  |         return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     footerStr = '\n      <div class="' + containerClassIcons + '">\n' | 
					
						
							| 
									
										
										
										
											2020-12-01 14:11:50 +00:00
										 |  |  |     footerStr += replyStr + announceStr + likeStr + bookmarkStr | 
					
						
							|  |  |  |     footerStr += deleteStr + muteStr + editStr | 
					
						
							| 
									
										
										
										
											2020-12-01 14:08:12 +00:00
										 |  |  |     if not isNewsPost(postJsonObject): | 
					
						
							|  |  |  |         footerStr += '        <a href="' + publishedLink + '" class="' + \ | 
					
						
							|  |  |  |             timeClass + '">' + publishedStr + '</a>\n' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         footerStr += '        <a href="' + \ | 
					
						
							|  |  |  |             publishedLink.replace('/news/', '/news/statuses/') + \ | 
					
						
							| 
									
										
										
										
											2020-12-01 14:11:50 +00:00
										 |  |  |             '" class="' + timeClass + '">' + publishedStr + '</a>\n' | 
					
						
							| 
									
										
										
										
											2020-12-01 14:08:12 +00:00
										 |  |  |     footerStr += '      </div>\n' | 
					
						
							|  |  |  |     return footerStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  | def individualPostAsHtml(allowDownloads: bool, | 
					
						
							|  |  |  |                          recentPostsCache: {}, maxRecentPosts: int, | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                          translate: {}, | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  |                          pageNumber: int, baseDir: str, | 
					
						
							|  |  |  |                          session, wfRequest: {}, personCache: {}, | 
					
						
							|  |  |  |                          nickname: str, domain: str, port: int, | 
					
						
							|  |  |  |                          postJsonObject: {}, | 
					
						
							|  |  |  |                          avatarUrl: str, showAvatarOptions: bool, | 
					
						
							|  |  |  |                          allowDeletion: bool, | 
					
						
							|  |  |  |                          httpPrefix: str, projectVersion: str, | 
					
						
							|  |  |  |                          boxName: str, YTReplacementDomain: str, | 
					
						
							|  |  |  |                          showPublishedDateOnly: bool, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                          peertubeInstances: [], | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  |                          showRepeats=True, | 
					
						
							|  |  |  |                          showIcons=False, | 
					
						
							|  |  |  |                          manuallyApprovesFollowers=False, | 
					
						
							|  |  |  |                          showPublicOnly=False, | 
					
						
							|  |  |  |                          storeToCache=True) -> str: | 
					
						
							|  |  |  |     """ Shows a single post as html
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     if not postJsonObject: | 
					
						
							|  |  |  |         return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # benchmark | 
					
						
							|  |  |  |     postStartTime = time.time() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     postActor = postJsonObject['actor'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # ZZZzzz | 
					
						
							|  |  |  |     if isPersonSnoozed(baseDir, nickname, domain, postActor): | 
					
						
							|  |  |  |         return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # if downloads of avatar images aren't enabled then we can do more | 
					
						
							|  |  |  |     # accurate timing of different parts of the code | 
					
						
							|  |  |  |     enableTimingLog = not allowDownloads | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '1') | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     avatarPosition = '' | 
					
						
							|  |  |  |     messageId = '' | 
					
						
							|  |  |  |     if postJsonObject.get('id'): | 
					
						
							|  |  |  |         messageId = removeIdEnding(postJsonObject['id']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '2') | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     messageIdStr = '' | 
					
						
							|  |  |  |     if messageId: | 
					
						
							|  |  |  |         messageIdStr = ';' + messageId | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  |     domainFull = getFullDomain(domain, port) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     pageNumberParam = '' | 
					
						
							|  |  |  |     if pageNumber: | 
					
						
							|  |  |  |         pageNumberParam = '?page=' + str(pageNumber) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 14:45:12 +00:00
										 |  |  |     # get the html post from the recent posts cache if it exists there | 
					
						
							| 
									
										
										
										
											2020-11-30 12:47:52 +00:00
										 |  |  |     postHtml = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getPostFromRecentCache(session, baseDir, | 
					
						
							|  |  |  |                                 httpPrefix, nickname, domain, | 
					
						
							|  |  |  |                                 postJsonObject, | 
					
						
							|  |  |  |                                 postActor, | 
					
						
							|  |  |  |                                 personCache, | 
					
						
							|  |  |  |                                 allowDownloads, | 
					
						
							|  |  |  |                                 showPublicOnly, | 
					
						
							|  |  |  |                                 storeToCache, | 
					
						
							|  |  |  |                                 boxName, | 
					
						
							|  |  |  |                                 avatarUrl, | 
					
						
							|  |  |  |                                 enableTimingLog, | 
					
						
							|  |  |  |                                 postStartTime, | 
					
						
							|  |  |  |                                 pageNumber, | 
					
						
							|  |  |  |                                 recentPostsCache, | 
					
						
							|  |  |  |                                 maxRecentPosts) | 
					
						
							| 
									
										
										
										
											2020-11-30 12:47:52 +00:00
										 |  |  |     if postHtml: | 
					
						
							|  |  |  |         return postHtml | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '4') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 14:45:12 +00:00
										 |  |  |     avatarUrl = \ | 
					
						
							|  |  |  |         getAvatarImageUrl(session, | 
					
						
							|  |  |  |                           baseDir, httpPrefix, | 
					
						
							|  |  |  |                           postActor, personCache, | 
					
						
							|  |  |  |                           avatarUrl, allowDownloads) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '5') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |     # get the display name | 
					
						
							|  |  |  |     if domainFull not in postActor: | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |         (inboxUrl, pubKeyId, pubKey, | 
					
						
							|  |  |  |          fromPersonId, sharedInbox, | 
					
						
							|  |  |  |          avatarUrl2, displayName) = getPersonBox(baseDir, session, wfRequest, | 
					
						
							|  |  |  |                                                  personCache, | 
					
						
							|  |  |  |                                                  projectVersion, httpPrefix, | 
					
						
							| 
									
										
										
										
											2020-12-18 17:49:17 +00:00
										 |  |  |                                                  nickname, domain, 'outbox', | 
					
						
							|  |  |  |                                                  72367) | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _logPostTiming(enableTimingLog, postStartTime, '6') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if avatarUrl2: | 
					
						
							|  |  |  |             avatarUrl = avatarUrl2 | 
					
						
							|  |  |  |         if displayName: | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |             # add any emoji to the display name | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |             if ':' in displayName: | 
					
						
							|  |  |  |                 displayName = \ | 
					
						
							|  |  |  |                     addEmojiToDisplayName(baseDir, httpPrefix, | 
					
						
							|  |  |  |                                           nickname, domain, | 
					
						
							|  |  |  |                                           displayName, False) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '7') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |     avatarLink = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getAvatarImageHtml(showAvatarOptions, | 
					
						
							|  |  |  |                             nickname, domainFull, | 
					
						
							|  |  |  |                             avatarUrl, postActor, | 
					
						
							|  |  |  |                             translate, avatarPosition, | 
					
						
							|  |  |  |                             pageNumber, messageIdStr) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     avatarImageInPost = \ | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |         '      <div class="timeline-avatar">' + avatarLink + '</div>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # don't create new html within the bookmarks timeline | 
					
						
							|  |  |  |     # it should already have been created for the inbox | 
					
						
							|  |  |  |     if boxName == 'tlbookmarks' or boxName == 'bookmarks': | 
					
						
							|  |  |  |         return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     timelinePostBookmark = removeIdEnding(postJsonObject['id']) | 
					
						
							|  |  |  |     timelinePostBookmark = timelinePostBookmark.replace('://', '-') | 
					
						
							|  |  |  |     timelinePostBookmark = timelinePostBookmark.replace('/', '-') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # If this is the inbox timeline then don't show the repeat icon on any DMs | 
					
						
							|  |  |  |     showRepeatIcon = showRepeats | 
					
						
							|  |  |  |     isPublicRepeat = False | 
					
						
							|  |  |  |     showDMicon = False | 
					
						
							|  |  |  |     if showRepeats: | 
					
						
							|  |  |  |         if isDM(postJsonObject): | 
					
						
							|  |  |  |             showDMicon = True | 
					
						
							|  |  |  |             showRepeatIcon = False | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             if not isPublicPost(postJsonObject): | 
					
						
							|  |  |  |                 isPublicRepeat = True | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     titleStr = '' | 
					
						
							|  |  |  |     galleryStr = '' | 
					
						
							|  |  |  |     isAnnounced = False | 
					
						
							|  |  |  |     if postJsonObject['type'] == 'Announce': | 
					
						
							|  |  |  |         postJsonAnnounce = \ | 
					
						
							|  |  |  |             downloadAnnounce(session, baseDir, httpPrefix, | 
					
						
							|  |  |  |                              nickname, domain, postJsonObject, | 
					
						
							|  |  |  |                              projectVersion, translate, | 
					
						
							|  |  |  |                              YTReplacementDomain) | 
					
						
							|  |  |  |         if not postJsonAnnounce: | 
					
						
							|  |  |  |             return '' | 
					
						
							|  |  |  |         postJsonObject = postJsonAnnounce | 
					
						
							|  |  |  |         isAnnounced = True | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '8') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if not isinstance(postJsonObject['object'], dict): | 
					
						
							|  |  |  |         return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # if this post should be public then check its recipients | 
					
						
							|  |  |  |     if showPublicOnly: | 
					
						
							|  |  |  |         if not postContainsPublic(postJsonObject): | 
					
						
							|  |  |  |             return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     isModerationPost = False | 
					
						
							|  |  |  |     if postJsonObject['object'].get('moderationStatus'): | 
					
						
							|  |  |  |         isModerationPost = True | 
					
						
							|  |  |  |     containerClass = 'container' | 
					
						
							|  |  |  |     containerClassIcons = 'containericons' | 
					
						
							|  |  |  |     timeClass = 'time-right' | 
					
						
							|  |  |  |     actorNickname = getNicknameFromActor(postActor) | 
					
						
							|  |  |  |     if not actorNickname: | 
					
						
							|  |  |  |         # single user instance | 
					
						
							|  |  |  |         actorNickname = 'dev' | 
					
						
							|  |  |  |     actorDomain, actorPort = getDomainFromActor(postActor) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     displayName = getDisplayName(baseDir, postActor, personCache) | 
					
						
							|  |  |  |     if displayName: | 
					
						
							|  |  |  |         if ':' in displayName: | 
					
						
							|  |  |  |             displayName = \ | 
					
						
							|  |  |  |                 addEmojiToDisplayName(baseDir, httpPrefix, | 
					
						
							|  |  |  |                                       nickname, domain, | 
					
						
							|  |  |  |                                       displayName, False) | 
					
						
							|  |  |  |         titleStr += \ | 
					
						
							|  |  |  |             '        <a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |             nickname + '?options=' + postActor + \ | 
					
						
							|  |  |  |             ';' + str(pageNumber) + ';' + avatarUrl + messageIdStr + \ | 
					
						
							|  |  |  |             '">' + displayName + '</a>\n' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         if not messageId: | 
					
						
							|  |  |  |             # pprint(postJsonObject) | 
					
						
							|  |  |  |             print('ERROR: no messageId') | 
					
						
							|  |  |  |         if not actorNickname: | 
					
						
							|  |  |  |             # pprint(postJsonObject) | 
					
						
							|  |  |  |             print('ERROR: no actorNickname') | 
					
						
							|  |  |  |         if not actorDomain: | 
					
						
							|  |  |  |             # pprint(postJsonObject) | 
					
						
							|  |  |  |             print('ERROR: no actorDomain') | 
					
						
							|  |  |  |         titleStr += \ | 
					
						
							|  |  |  |             '        <a class="imageAnchor" href="/users/' + \ | 
					
						
							|  |  |  |             nickname + '?options=' + postActor + \ | 
					
						
							|  |  |  |             ';' + str(pageNumber) + ';' + avatarUrl + messageIdStr + \ | 
					
						
							|  |  |  |             '">@' + actorNickname + '@' + actorDomain + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # benchmark 9 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '9') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # Show a DM icon for DMs in the inbox timeline | 
					
						
							|  |  |  |     if showDMicon: | 
					
						
							|  |  |  |         titleStr = \ | 
					
						
							|  |  |  |             titleStr + ' <img loading="lazy" src="/' + \ | 
					
						
							| 
									
										
										
										
											2020-12-09 13:08:26 +00:00
										 |  |  |             'icons/dm.png" class="DMicon"/>\n' | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # check if replying is permitted | 
					
						
							|  |  |  |     commentsEnabled = True | 
					
						
							|  |  |  |     if 'commentsEnabled' in postJsonObject['object']: | 
					
						
							|  |  |  |         if postJsonObject['object']['commentsEnabled'] is False: | 
					
						
							|  |  |  |             commentsEnabled = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     replyStr = _getReplyIconHtml(nickname, isPublicRepeat, | 
					
						
							|  |  |  |                                  showIcons, commentsEnabled, | 
					
						
							|  |  |  |                                  postJsonObject, pageNumberParam, | 
					
						
							|  |  |  |                                  translate) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '10') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     isEvent = isEventPost(postJsonObject) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '11') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     editStr = _getEditIconHtml(baseDir, nickname, domainFull, | 
					
						
							|  |  |  |                                postJsonObject, actorNickname, | 
					
						
							|  |  |  |                                translate, isEvent) | 
					
						
							| 
									
										
										
										
											2020-11-30 20:52:58 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     announceStr = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getAnnounceIconHtml(nickname, domainFull, | 
					
						
							|  |  |  |                              postJsonObject, | 
					
						
							|  |  |  |                              isPublicRepeat, | 
					
						
							|  |  |  |                              isModerationPost, | 
					
						
							|  |  |  |                              showRepeatIcon, | 
					
						
							|  |  |  |                              translate, | 
					
						
							|  |  |  |                              pageNumberParam, | 
					
						
							|  |  |  |                              timelinePostBookmark, | 
					
						
							|  |  |  |                              boxName) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     _logPostTiming(enableTimingLog, postStartTime, '12') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     # whether to show a like button | 
					
						
							|  |  |  |     hideLikeButtonFile = \ | 
					
						
							|  |  |  |         baseDir + '/accounts/' + nickname + '@' + domain + '/.hideLikeButton' | 
					
						
							|  |  |  |     showLikeButton = True | 
					
						
							|  |  |  |     if os.path.isfile(hideLikeButtonFile): | 
					
						
							|  |  |  |         showLikeButton = False | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     likeStr = _getLikeIconHtml(nickname, domainFull, | 
					
						
							|  |  |  |                                isModerationPost, | 
					
						
							|  |  |  |                                showLikeButton, | 
					
						
							|  |  |  |                                postJsonObject, | 
					
						
							|  |  |  |                                enableTimingLog, | 
					
						
							|  |  |  |                                postStartTime, | 
					
						
							|  |  |  |                                translate, pageNumberParam, | 
					
						
							|  |  |  |                                timelinePostBookmark, | 
					
						
							|  |  |  |                                boxName) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '12.5') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 17:36:06 +00:00
										 |  |  |     bookmarkStr = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getBookmarkIconHtml(nickname, domainFull, | 
					
						
							|  |  |  |                              postJsonObject, | 
					
						
							|  |  |  |                              isModerationPost, | 
					
						
							|  |  |  |                              translate, | 
					
						
							|  |  |  |                              enableTimingLog, | 
					
						
							|  |  |  |                              postStartTime, boxName, | 
					
						
							|  |  |  |                              pageNumberParam, | 
					
						
							|  |  |  |                              timelinePostBookmark) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '12.9') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     isMuted = postIsMuted(baseDir, nickname, domain, postJsonObject, messageId) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '13') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 17:48:35 +00:00
										 |  |  |     muteStr = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getMuteIconHtml(isMuted, | 
					
						
							|  |  |  |                          postActor, | 
					
						
							|  |  |  |                          messageId, | 
					
						
							|  |  |  |                          nickname, domainFull, | 
					
						
							|  |  |  |                          allowDeletion, | 
					
						
							|  |  |  |                          pageNumberParam, | 
					
						
							|  |  |  |                          boxName, | 
					
						
							|  |  |  |                          timelinePostBookmark, | 
					
						
							|  |  |  |                          translate) | 
					
						
							| 
									
										
										
										
											2020-11-30 17:48:35 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 18:03:02 +00:00
										 |  |  |     deleteStr = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getDeleteIconHtml(nickname, domainFull, | 
					
						
							|  |  |  |                            allowDeletion, | 
					
						
							|  |  |  |                            postActor, | 
					
						
							|  |  |  |                            messageId, | 
					
						
							|  |  |  |                            postJsonObject, | 
					
						
							|  |  |  |                            pageNumberParam, | 
					
						
							|  |  |  |                            translate) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '13.1') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  |     # get the title: x replies to y, x announces y, etc | 
					
						
							|  |  |  |     (titleStr2, | 
					
						
							|  |  |  |      replyAvatarImageInPost, | 
					
						
							|  |  |  |      containerClassIcons, | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |      containerClass) = _getPostTitleHtml(baseDir, | 
					
						
							|  |  |  |                                          httpPrefix, | 
					
						
							|  |  |  |                                          nickname, domain, | 
					
						
							|  |  |  |                                          showRepeatIcon, | 
					
						
							|  |  |  |                                          isAnnounced, | 
					
						
							|  |  |  |                                          postJsonObject, | 
					
						
							|  |  |  |                                          postActor, | 
					
						
							|  |  |  |                                          translate, | 
					
						
							|  |  |  |                                          enableTimingLog, | 
					
						
							|  |  |  |                                          postStartTime, | 
					
						
							|  |  |  |                                          boxName, | 
					
						
							|  |  |  |                                          personCache, | 
					
						
							|  |  |  |                                          allowDownloads, | 
					
						
							|  |  |  |                                          avatarPosition, | 
					
						
							|  |  |  |                                          pageNumber, | 
					
						
							|  |  |  |                                          messageIdStr, | 
					
						
							|  |  |  |                                          containerClassIcons, | 
					
						
							|  |  |  |                                          containerClass) | 
					
						
							| 
									
										
										
										
											2020-11-30 23:23:21 +00:00
										 |  |  |     titleStr += titleStr2 | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '14') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     attachmentStr, galleryStr = \ | 
					
						
							|  |  |  |         getPostAttachmentsAsHtml(postJsonObject, boxName, translate, | 
					
						
							| 
									
										
										
										
											2020-11-30 15:20:10 +00:00
										 |  |  |                                  isMuted, avatarLink, | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |                                  replyStr, announceStr, likeStr, | 
					
						
							|  |  |  |                                  bookmarkStr, deleteStr, muteStr) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 18:03:02 +00:00
										 |  |  |     publishedStr = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getPublishedDateStr(postJsonObject, showPublishedDateOnly) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '15') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     publishedLink = messageId | 
					
						
							|  |  |  |     # blog posts should have no /statuses/ in their link | 
					
						
							|  |  |  |     if isBlogPost(postJsonObject): | 
					
						
							|  |  |  |         # is this a post to the local domain? | 
					
						
							|  |  |  |         if '://' + domain in messageId: | 
					
						
							|  |  |  |             publishedLink = messageId.replace('/statuses/', '/') | 
					
						
							|  |  |  |     # if this is a local link then make it relative so that it works | 
					
						
							|  |  |  |     # on clearnet or onion address | 
					
						
							|  |  |  |     if domain + '/users/' in publishedLink or \ | 
					
						
							|  |  |  |        domain + ':' + str(port) + '/users/' in publishedLink: | 
					
						
							|  |  |  |         publishedLink = '/users/' + publishedLink.split('/users/')[1] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not isNewsPost(postJsonObject): | 
					
						
							|  |  |  |         footerStr = '<a href="' + publishedLink + \ | 
					
						
							|  |  |  |             '" class="' + timeClass + '">' + publishedStr + '</a>\n' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         footerStr = '<a href="' + \ | 
					
						
							|  |  |  |             publishedLink.replace('/news/', '/news/statuses/') + \ | 
					
						
							|  |  |  |             '" class="' + timeClass + '">' + publishedStr + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # change the background color for DMs in inbox timeline | 
					
						
							|  |  |  |     if showDMicon: | 
					
						
							|  |  |  |         containerClassIcons = 'containericons dm' | 
					
						
							|  |  |  |         containerClass = 'container dm' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     newFooterStr = _getFooterWithIcons(showIcons, | 
					
						
							|  |  |  |                                        containerClassIcons, | 
					
						
							|  |  |  |                                        replyStr, announceStr, | 
					
						
							|  |  |  |                                        likeStr, bookmarkStr, | 
					
						
							|  |  |  |                                        deleteStr, muteStr, editStr, | 
					
						
							|  |  |  |                                        postJsonObject, publishedLink, | 
					
						
							|  |  |  |                                        timeClass, publishedStr) | 
					
						
							| 
									
										
										
										
											2020-12-01 14:08:12 +00:00
										 |  |  |     if newFooterStr: | 
					
						
							|  |  |  |         footerStr = newFooterStr | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     postIsSensitive = False | 
					
						
							|  |  |  |     if postJsonObject['object'].get('sensitive'): | 
					
						
							|  |  |  |         # sensitive posts should have a summary | 
					
						
							|  |  |  |         if postJsonObject['object'].get('summary'): | 
					
						
							|  |  |  |             postIsSensitive = postJsonObject['object']['sensitive'] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             # add a generic summary if none is provided | 
					
						
							|  |  |  |             postJsonObject['object']['summary'] = translate['Sensitive'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # add an extra line if there is a content warning, | 
					
						
							|  |  |  |     # for better vertical spacing on mobile | 
					
						
							|  |  |  |     if postIsSensitive: | 
					
						
							|  |  |  |         footerStr = '<br>' + footerStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not postJsonObject['object'].get('summary'): | 
					
						
							|  |  |  |         postJsonObject['object']['summary'] = '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if postJsonObject['object'].get('cipherText'): | 
					
						
							|  |  |  |         postJsonObject['object']['content'] = \ | 
					
						
							|  |  |  |             E2EEdecryptMessageFromDevice(postJsonObject['object']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not postJsonObject['object'].get('content'): | 
					
						
							|  |  |  |         return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     isPatch = isGitPatch(baseDir, nickname, domain, | 
					
						
							|  |  |  |                          postJsonObject['object']['type'], | 
					
						
							|  |  |  |                          postJsonObject['object']['summary'], | 
					
						
							|  |  |  |                          postJsonObject['object']['content']) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '16') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if not isPatch: | 
					
						
							|  |  |  |         objectContent = \ | 
					
						
							|  |  |  |             removeLongWords(postJsonObject['object']['content'], 40, []) | 
					
						
							|  |  |  |         objectContent = removeTextFormatting(objectContent) | 
					
						
							|  |  |  |         objectContent = \ | 
					
						
							|  |  |  |             switchWords(baseDir, nickname, domain, objectContent) | 
					
						
							|  |  |  |         objectContent = htmlReplaceEmailQuote(objectContent) | 
					
						
							|  |  |  |         objectContent = htmlReplaceQuoteMarks(objectContent) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         objectContent = \ | 
					
						
							|  |  |  |             postJsonObject['object']['content'] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if not postIsSensitive: | 
					
						
							|  |  |  |         contentStr = objectContent + attachmentStr | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |         contentStr = addEmbeddedElements(translate, contentStr, | 
					
						
							|  |  |  |                                          peertubeInstances) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |         contentStr = insertQuestion(baseDir, translate, | 
					
						
							|  |  |  |                                     nickname, domain, port, | 
					
						
							|  |  |  |                                     contentStr, postJsonObject, | 
					
						
							|  |  |  |                                     pageNumber) | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         postID = 'post' + str(createPassword(8)) | 
					
						
							|  |  |  |         contentStr = '' | 
					
						
							|  |  |  |         if postJsonObject['object'].get('summary'): | 
					
						
							|  |  |  |             contentStr += \ | 
					
						
							|  |  |  |                 '<b>' + str(postJsonObject['object']['summary']) + '</b>\n ' | 
					
						
							|  |  |  |             if isModerationPost: | 
					
						
							|  |  |  |                 containerClass = 'container report' | 
					
						
							|  |  |  |         # get the content warning text | 
					
						
							|  |  |  |         cwContentStr = objectContent + attachmentStr | 
					
						
							|  |  |  |         if not isPatch: | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |             cwContentStr = addEmbeddedElements(translate, cwContentStr, | 
					
						
							|  |  |  |                                                peertubeInstances) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |             cwContentStr = \ | 
					
						
							|  |  |  |                 insertQuestion(baseDir, translate, nickname, domain, port, | 
					
						
							|  |  |  |                                cwContentStr, postJsonObject, pageNumber) | 
					
						
							|  |  |  |         if not isBlogPost(postJsonObject): | 
					
						
							|  |  |  |             # get the content warning button | 
					
						
							|  |  |  |             contentStr += \ | 
					
						
							|  |  |  |                 getContentWarningButton(postID, translate, cwContentStr) | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             contentStr += cwContentStr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '17') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if postJsonObject['object'].get('tag') and not isPatch: | 
					
						
							|  |  |  |         contentStr = \ | 
					
						
							|  |  |  |             replaceEmojiFromTags(contentStr, | 
					
						
							|  |  |  |                                  postJsonObject['object']['tag'], | 
					
						
							|  |  |  |                                  'content') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if isMuted: | 
					
						
							|  |  |  |         contentStr = '' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         if not isPatch: | 
					
						
							|  |  |  |             contentStr = '      <div class="message">' + \ | 
					
						
							|  |  |  |                 contentStr + \ | 
					
						
							|  |  |  |                 '      </div>\n' | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             contentStr = \ | 
					
						
							|  |  |  |                 '<div class="gitpatch"><pre><code>' + contentStr + \ | 
					
						
							|  |  |  |                 '</code></pre></div>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # show blog citations | 
					
						
							| 
									
										
										
										
											2020-11-30 20:52:58 +00:00
										 |  |  |     citationsStr = \ | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _getBlogCitationsHtml(boxName, postJsonObject, translate) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     postHtml = '' | 
					
						
							|  |  |  |     if boxName != 'tlmedia': | 
					
						
							|  |  |  |         postHtml = '    <div id="' + timelinePostBookmark + \ | 
					
						
							|  |  |  |             '" class="' + containerClass + '">\n' | 
					
						
							|  |  |  |         postHtml += avatarImageInPost | 
					
						
							|  |  |  |         postHtml += '      <div class="post-title">\n' + \ | 
					
						
							|  |  |  |             '        ' + titleStr + \ | 
					
						
							|  |  |  |             replyAvatarImageInPost + '      </div>\n' | 
					
						
							|  |  |  |         postHtml += contentStr + citationsStr + footerStr + '\n' | 
					
						
							|  |  |  |         postHtml += '    </div>\n' | 
					
						
							|  |  |  |     else: | 
					
						
							|  |  |  |         postHtml = galleryStr | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '18') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-30 20:52:58 +00:00
										 |  |  |     # save the created html to the recent posts cache | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |     if not showPublicOnly and storeToCache and \ | 
					
						
							|  |  |  |        boxName != 'tlmedia' and boxName != 'tlbookmarks' and \ | 
					
						
							|  |  |  |        boxName != 'bookmarks': | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |         _saveIndividualPostAsHtmlToCache(baseDir, nickname, domain, | 
					
						
							|  |  |  |                                          postJsonObject, postHtml) | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  |         updateRecentPostsCache(recentPostsCache, maxRecentPosts, | 
					
						
							|  |  |  |                                postJsonObject, postHtml) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-22 18:06:23 +00:00
										 |  |  |     _logPostTiming(enableTimingLog, postStartTime, '19') | 
					
						
							| 
									
										
										
										
											2020-11-09 19:42:09 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return postHtml | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def htmlIndividualPost(cssCache: {}, | 
					
						
							|  |  |  |                        recentPostsCache: {}, maxRecentPosts: int, | 
					
						
							|  |  |  |                        translate: {}, | 
					
						
							|  |  |  |                        baseDir: str, session, wfRequest: {}, personCache: {}, | 
					
						
							|  |  |  |                        nickname: str, domain: str, port: int, authorized: bool, | 
					
						
							|  |  |  |                        postJsonObject: {}, httpPrefix: str, | 
					
						
							|  |  |  |                        projectVersion: str, likedBy: str, | 
					
						
							|  |  |  |                        YTReplacementDomain: str, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                        showPublishedDateOnly: bool, | 
					
						
							|  |  |  |                        peertubeInstances: []) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Show an individual post as html
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     postStr = '' | 
					
						
							|  |  |  |     if likedBy: | 
					
						
							|  |  |  |         likedByNickname = getNicknameFromActor(likedBy) | 
					
						
							|  |  |  |         likedByDomain, likedByPort = getDomainFromActor(likedBy) | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  |         likedByDomain = getFullDomain(likedByDomain, likedByPort) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         likedByHandle = likedByNickname + '@' + likedByDomain | 
					
						
							|  |  |  |         postStr += \ | 
					
						
							|  |  |  |             '<p>' + translate['Liked by'] + \ | 
					
						
							|  |  |  |             ' <a href="' + likedBy + '">@' + \ | 
					
						
							|  |  |  |             likedByHandle + '</a>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 11:19:16 +00:00
										 |  |  |         domainFull = getFullDomain(domain, port) | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |         actor = '/users/' + nickname | 
					
						
							|  |  |  |         followStr = '  <form method="POST" ' + \ | 
					
						
							|  |  |  |             'accept-charset="UTF-8" action="' + actor + '/searchhandle">\n' | 
					
						
							|  |  |  |         followStr += \ | 
					
						
							|  |  |  |             '    <input type="hidden" name="actor" value="' + actor + '">\n' | 
					
						
							|  |  |  |         followStr += \ | 
					
						
							|  |  |  |             '    <input type="hidden" name="searchtext" value="' + \ | 
					
						
							|  |  |  |             likedByHandle + '">\n' | 
					
						
							|  |  |  |         if not isFollowingActor(baseDir, nickname, domainFull, likedBy): | 
					
						
							|  |  |  |             followStr += '    <button type="submit" class="button" ' + \ | 
					
						
							|  |  |  |                 'name="submitSearch">' + translate['Follow'] + '</button>\n' | 
					
						
							|  |  |  |         followStr += '    <button type="submit" class="button" ' + \ | 
					
						
							|  |  |  |             'name="submitBack">' + translate['Go Back'] + '</button>\n' | 
					
						
							|  |  |  |         followStr += '  </form>\n' | 
					
						
							|  |  |  |         postStr += followStr + '</p>\n' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     postStr += \ | 
					
						
							|  |  |  |         individualPostAsHtml(True, recentPostsCache, maxRecentPosts, | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                              translate, None, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                              baseDir, session, wfRequest, personCache, | 
					
						
							|  |  |  |                              nickname, domain, port, postJsonObject, | 
					
						
							|  |  |  |                              None, True, False, | 
					
						
							|  |  |  |                              httpPrefix, projectVersion, 'inbox', | 
					
						
							|  |  |  |                              YTReplacementDomain, | 
					
						
							|  |  |  |                              showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                              peertubeInstances, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                              False, authorized, False, False, False) | 
					
						
							|  |  |  |     messageId = removeIdEnding(postJsonObject['id']) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # show the previous posts | 
					
						
							|  |  |  |     if isinstance(postJsonObject['object'], dict): | 
					
						
							|  |  |  |         while postJsonObject['object'].get('inReplyTo'): | 
					
						
							|  |  |  |             postFilename = \ | 
					
						
							|  |  |  |                 locatePost(baseDir, nickname, domain, | 
					
						
							|  |  |  |                            postJsonObject['object']['inReplyTo']) | 
					
						
							|  |  |  |             if not postFilename: | 
					
						
							|  |  |  |                 break | 
					
						
							|  |  |  |             postJsonObject = loadJson(postFilename) | 
					
						
							|  |  |  |             if postJsonObject: | 
					
						
							|  |  |  |                 postStr = \ | 
					
						
							|  |  |  |                     individualPostAsHtml(True, recentPostsCache, | 
					
						
							|  |  |  |                                          maxRecentPosts, | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                                          translate, None, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                          baseDir, session, wfRequest, | 
					
						
							|  |  |  |                                          personCache, | 
					
						
							|  |  |  |                                          nickname, domain, port, | 
					
						
							|  |  |  |                                          postJsonObject, | 
					
						
							|  |  |  |                                          None, True, False, | 
					
						
							|  |  |  |                                          httpPrefix, projectVersion, 'inbox', | 
					
						
							|  |  |  |                                          YTReplacementDomain, | 
					
						
							|  |  |  |                                          showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                                          peertubeInstances, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                          False, authorized, | 
					
						
							|  |  |  |                                          False, False, False) + postStr | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # show the following posts | 
					
						
							|  |  |  |     postFilename = locatePost(baseDir, nickname, domain, messageId) | 
					
						
							|  |  |  |     if postFilename: | 
					
						
							|  |  |  |         # is there a replies file for this post? | 
					
						
							|  |  |  |         repliesFilename = postFilename.replace('.json', '.replies') | 
					
						
							|  |  |  |         if os.path.isfile(repliesFilename): | 
					
						
							|  |  |  |             # get items from the replies file | 
					
						
							|  |  |  |             repliesJson = { | 
					
						
							|  |  |  |                 'orderedItems': [] | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             populateRepliesJson(baseDir, nickname, domain, | 
					
						
							|  |  |  |                                 repliesFilename, authorized, repliesJson) | 
					
						
							|  |  |  |             # add items to the html output | 
					
						
							|  |  |  |             for item in repliesJson['orderedItems']: | 
					
						
							|  |  |  |                 postStr += \ | 
					
						
							|  |  |  |                     individualPostAsHtml(True, recentPostsCache, | 
					
						
							|  |  |  |                                          maxRecentPosts, | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                                          translate, None, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                          baseDir, session, wfRequest, | 
					
						
							|  |  |  |                                          personCache, | 
					
						
							|  |  |  |                                          nickname, domain, port, item, | 
					
						
							|  |  |  |                                          None, True, False, | 
					
						
							|  |  |  |                                          httpPrefix, projectVersion, 'inbox', | 
					
						
							|  |  |  |                                          YTReplacementDomain, | 
					
						
							|  |  |  |                                          showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                                          peertubeInstances, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                          False, authorized, | 
					
						
							|  |  |  |                                          False, False, False) | 
					
						
							|  |  |  |     cssFilename = baseDir + '/epicyon-profile.css' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/epicyon.css'): | 
					
						
							|  |  |  |         cssFilename = baseDir + '/epicyon.css' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     return htmlHeaderWithExternalStyle(cssFilename) + postStr + htmlFooter() | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def htmlPostReplies(cssCache: {}, | 
					
						
							|  |  |  |                     recentPostsCache: {}, maxRecentPosts: int, | 
					
						
							|  |  |  |                     translate: {}, baseDir: str, | 
					
						
							|  |  |  |                     session, wfRequest: {}, personCache: {}, | 
					
						
							|  |  |  |                     nickname: str, domain: str, port: int, repliesJson: {}, | 
					
						
							|  |  |  |                     httpPrefix: str, projectVersion: str, | 
					
						
							|  |  |  |                     YTReplacementDomain: str, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                     showPublishedDateOnly: bool, | 
					
						
							|  |  |  |                     peertubeInstances: []) -> str: | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |     """Show the replies to an individual post as html
 | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     repliesStr = '' | 
					
						
							|  |  |  |     if repliesJson.get('orderedItems'): | 
					
						
							|  |  |  |         for item in repliesJson['orderedItems']: | 
					
						
							|  |  |  |             repliesStr += \ | 
					
						
							|  |  |  |                 individualPostAsHtml(True, recentPostsCache, | 
					
						
							|  |  |  |                                      maxRecentPosts, | 
					
						
							| 
									
										
										
										
											2020-12-09 13:31:54 +00:00
										 |  |  |                                      translate, None, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                      baseDir, session, wfRequest, personCache, | 
					
						
							|  |  |  |                                      nickname, domain, port, item, | 
					
						
							|  |  |  |                                      None, True, False, | 
					
						
							|  |  |  |                                      httpPrefix, projectVersion, 'inbox', | 
					
						
							|  |  |  |                                      YTReplacementDomain, | 
					
						
							|  |  |  |                                      showPublishedDateOnly, | 
					
						
							| 
									
										
										
										
											2020-12-23 23:59:49 +00:00
										 |  |  |                                      peertubeInstances, | 
					
						
							| 
									
										
										
										
											2020-11-09 22:44:03 +00:00
										 |  |  |                                      False, False, False, False, False) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cssFilename = baseDir + '/epicyon-profile.css' | 
					
						
							|  |  |  |     if os.path.isfile(baseDir + '/epicyon.css'): | 
					
						
							|  |  |  |         cssFilename = baseDir + '/epicyon.css' | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-12 17:05:38 +00:00
										 |  |  |     return htmlHeaderWithExternalStyle(cssFilename) + repliesStr + htmlFooter() |