__filename__ = "webapp_timeline.py" __author__ = "Bob Mottram" __license__ = "AGPL3+" __version__ = "1.1.0" __maintainer__ = "Bob Mottram" __email__ = "bob@freedombone.net" __status__ = "Production" import os import time from utils import isEditor from utils import removeIdEnding from follow import followerApprovalActive from person import isPersonSnoozed from webapp_utils import getIconsWebPath from webapp_utils import htmlPostSeparator from webapp_utils import getBannerFile from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlFooter from webapp_utils import sharesTimelineJson from webapp_utils import htmlHighlightLabel from webapp_post import preparePostFromHtmlCache from webapp_post import individualPostAsHtml from webapp_column_left import getLeftColumnContent from webapp_column_right import getRightColumnContent from webapp_headerbuttons import headerButtonsTimeline from posts import isModerator def logTimelineTiming(enableTimingLog: bool, timelineStartTime, boxName: str, debugId: str) -> None: """Create a log of timings for performance tuning """ if not enableTimingLog: return timeDiff = int((time.time() - timelineStartTime) * 1000) if timeDiff > 100: print('TIMELINE TIMING ' + boxName + ' ' + debugId + ' = ' + str(timeDiff)) def htmlTimeline(cssCache: {}, defaultTimeline: str, recentPostsCache: {}, maxRecentPosts: int, translate: {}, pageNumber: int, itemsPerPage: int, session, baseDir: str, wfRequest: {}, personCache: {}, nickname: str, domain: str, port: int, timelineJson: {}, boxName: str, allowDeletion: bool, httpPrefix: str, projectVersion: str, manuallyApproveFollowers: bool, minimal: bool, YTReplacementDomain: str, showPublishedDateOnly: bool, newswire: {}, moderator: bool, editor: bool, positiveVoting: bool, showPublishAsIcon: bool, fullWidthTimelineButtonHeader: bool, iconsAsButtons: bool, rssIconAtTop: bool, publishButtonAtTop: bool, authorized: bool) -> str: """Show the timeline as html """ enableTimingLog = False timelineStartTime = time.time() accountDir = baseDir + '/accounts/' + nickname + '@' + domain # should the calendar icon be highlighted? newCalendarEvent = False calendarImage = 'calendar.png' calendarPath = '/calendar' calendarFile = accountDir + '/.newCalendar' if os.path.isfile(calendarFile): newCalendarEvent = True calendarImage = 'calendar_notify.png' with open(calendarFile, 'r') as calfile: calendarPath = calfile.read().replace('##sent##', '') calendarPath = calendarPath.replace('\n', '').replace('\r', '') # should the DM button be highlighted? newDM = False dmFile = accountDir + '/.newDM' if os.path.isfile(dmFile): newDM = True if boxName == 'dm': os.remove(dmFile) # should the Replies button be highlighted? newReply = False replyFile = accountDir + '/.newReply' if os.path.isfile(replyFile): newReply = True if boxName == 'tlreplies': os.remove(replyFile) # should the Shares button be highlighted? newShare = False newShareFile = accountDir + '/.newShare' if os.path.isfile(newShareFile): newShare = True if boxName == 'tlshares': os.remove(newShareFile) # should the Moderation/reports button be highlighted? newReport = False newReportFile = accountDir + '/.newReport' if os.path.isfile(newReportFile): newReport = True if boxName == 'moderation': os.remove(newReportFile) # directory where icons are found # This changes depending upon theme iconsPath = getIconsWebPath(baseDir) separatorStr = '' if boxName != 'tlmedia': separatorStr = htmlPostSeparator(baseDir, None) # the css filename cssFilename = baseDir + '/epicyon-profile.css' if os.path.isfile(baseDir + '/epicyon.css'): cssFilename = baseDir + '/epicyon.css' # filename of the banner shown at the top bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain) logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '1') # is the user a moderator? if not moderator: moderator = isModerator(baseDir, nickname) # is the user a site editor? if not editor: editor = isEditor(baseDir, nickname) logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '2') # the appearance of buttons - highlighted or not inboxButton = 'button' blogsButton = 'button' featuresButton = 'button' newsButton = 'button' dmButton = 'button' if newDM: dmButton = 'buttonhighlighted' repliesButton = 'button' if newReply: repliesButton = 'buttonhighlighted' mediaButton = 'button' bookmarksButton = 'button' eventsButton = 'button' sentButton = 'button' sharesButton = 'button' if newShare: sharesButton = 'buttonhighlighted' moderationButton = 'button' if newReport: moderationButton = 'buttonhighlighted' if boxName == 'inbox': inboxButton = 'buttonselected' elif boxName == 'tlblogs': blogsButton = 'buttonselected' elif boxName == 'tlfeatures': featuresButton = 'buttonselected' elif boxName == 'tlnews': newsButton = 'buttonselected' elif boxName == 'dm': dmButton = 'buttonselected' if newDM: dmButton = 'buttonselectedhighlighted' elif boxName == 'tlreplies': repliesButton = 'buttonselected' if newReply: repliesButton = 'buttonselectedhighlighted' elif boxName == 'tlmedia': mediaButton = 'buttonselected' elif boxName == 'outbox': sentButton = 'buttonselected' elif boxName == 'moderation': moderationButton = 'buttonselected' if newReport: moderationButton = 'buttonselectedhighlighted' elif boxName == 'tlshares': sharesButton = 'buttonselected' if newShare: sharesButton = 'buttonselectedhighlighted' elif boxName == 'tlbookmarks' or boxName == 'bookmarks': bookmarksButton = 'buttonselected' elif boxName == 'tlevents': eventsButton = 'buttonselected' # get the full domain, including any port number fullDomain = domain if port != 80 and port != 443: if ':' not in domain: fullDomain = domain + ':' + str(port) usersPath = '/users/' + nickname actor = httpPrefix + '://' + fullDomain + usersPath showIndividualPostIcons = True # show an icon for new follow approvals followApprovals = '' followRequestsFilename = \ baseDir + '/accounts/' + \ nickname + '@' + domain + '/followrequests.txt' if os.path.isfile(followRequestsFilename): with open(followRequestsFilename, 'r') as f: for line in f: if len(line) > 0: # show follow approvals icon followApprovals = \ '' + \ '\n' break logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '3') # moderation / reports button moderationButtonStr = '' if moderator and not minimal: moderationButtonStr = \ '' # shares, bookmarks and events buttons sharesButtonStr = '' bookmarksButtonStr = '' eventsButtonStr = '' if not minimal: sharesButtonStr = \ '' bookmarksButtonStr = \ '' eventsButtonStr = \ '' tlStr = htmlHeaderWithExternalStyle(cssFilename) logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '4') # if this is a news instance and we are viewing the news timeline newsHeader = False if defaultTimeline == 'tlfeatures' and boxName == 'tlfeatures': newsHeader = True newPostButtonStr = '' # start of headericons div if not newsHeader: if not iconsAsButtons: newPostButtonStr += '
' + item['summary'] + '
\n' profileStr += \ '' + translate['Type'] + ': ' + item['itemType'] + ' ' profileStr += \ '' + translate['Category'] + ': ' + item['category'] + ' ' profileStr += \ '' + translate['Location'] + ': ' + item['location'] + '
\n' if showContact: contactActor = item['actor'] profileStr += \ '