epicyon/webapp_timeline.py

1335 lines
57 KiB
Python
Raw Normal View History

2020-11-09 22:44:03 +00:00
__filename__ = "webapp_timeline.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
2021-01-26 10:07:42 +00:00
__version__ = "1.2.0"
2020-11-09 22:44:03 +00:00
__maintainer__ = "Bob Mottram"
__email__ = "bob@freedombone.net"
__status__ = "Production"
2021-06-15 15:08:12 +00:00
__module_group__ = "Timeline"
2020-11-09 22:44:03 +00:00
import os
import time
from shutil import copyfile
from utils import dangerousMarkup
2021-01-11 19:46:21 +00:00
from utils import getConfigParam
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 removeIdEnding
2021-07-13 21:59:53 +00:00
from utils import acctDir
2021-07-25 13:09:39 +00:00
from utils import isfloat
2020-11-09 22:44:03 +00:00
from follow import followerApprovalActive
from person import isPersonSnoozed
from markdown import markdownToHtml
2021-02-05 17:05:53 +00:00
from webapp_utils import htmlKeyboardNavigation
2021-02-06 10:35:47 +00:00
from webapp_utils import htmlHideFromScreenReader
2020-11-09 22:44:03 +00:00
from webapp_utils import htmlPostSeparator
from webapp_utils import getBannerFile
2020-11-10 15:12:07 +00:00
from webapp_utils import htmlHeaderWithExternalStyle
2020-11-09 22:44:03 +00:00
from webapp_utils import htmlFooter
from webapp_utils import sharesTimelineJson
2020-11-17 20:40:36 +00:00
from webapp_utils import htmlHighlightLabel
2020-11-09 22:44:03 +00:00
from webapp_post import preparePostFromHtmlCache
from webapp_post import individualPostAsHtml
from webapp_column_left import getLeftColumnContent
from webapp_column_right import getRightColumnContent
2020-11-17 20:40:36 +00:00
from webapp_headerbuttons import headerButtonsTimeline
2020-11-09 22:44:03 +00:00
from posts import isModerator
from announce import isSelfAnnounce
2020-11-09 22:44:03 +00:00
def _logTimelineTiming(enableTimingLog: bool, timelineStartTime,
boxName: str, 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() - timelineStartTime) * 1000)
if timeDiff > 100:
print('TIMELINE TIMING ' +
boxName + ' ' + debugId + ' = ' + str(timeDiff))
def _getHelpForTimeline(baseDir: str, boxName: str) -> str:
"""Shows help text for the given timeline
"""
# get the filename for help for this timeline
helpFilename = baseDir + '/accounts/help_' + boxName + '.md'
if not os.path.isfile(helpFilename):
language = \
getConfigParam(baseDir, 'language')
2021-02-26 12:24:55 +00:00
if not language:
language = 'en'
2021-02-27 10:10:05 +00:00
themeName = \
getConfigParam(baseDir, 'theme')
defaultFilename = None
if themeName:
defaultFilename = \
baseDir + '/theme/' + themeName + '/welcome/' + \
'help_' + boxName + '_' + language + '.md'
if not os.path.isfile(defaultFilename):
defaultFilename = None
if not defaultFilename:
defaultFilename = \
baseDir + '/defaultwelcome/' + \
'help_' + boxName + '_' + language + '.md'
if not os.path.isfile(defaultFilename):
defaultFilename = \
baseDir + '/defaultwelcome/help_' + boxName + '_en.md'
if os.path.isfile(defaultFilename):
copyfile(defaultFilename, helpFilename)
# show help text
if os.path.isfile(helpFilename):
instanceTitle = \
getConfigParam(baseDir, 'instanceTitle')
if not instanceTitle:
instanceTitle = 'Epicyon'
with open(helpFilename, 'r') as helpFile:
helpText = helpFile.read()
if dangerousMarkup(helpText, False):
return ''
helpText = helpText.replace('INSTANCE', instanceTitle)
2021-02-26 12:29:42 +00:00
return '<div class="container">\n' + \
markdownToHtml(helpText) + '\n' + \
2021-02-26 12:42:29 +00:00
'</div>\n'
return ''
2021-06-27 21:40:12 +00:00
def _htmlTimelineNewPost(manuallyApproveFollowers: bool,
boxName: str, iconsAsButtons: bool,
usersPath: str, translate: {}) -> str:
"""Returns html for the new post button
"""
newPostButtonStr = ''
if boxName == 'dm':
if not iconsAsButtons:
newPostButtonStr += \
'<a class="imageAnchor" href="' + usersPath + \
'/newdm?nodropdown"><img loading="lazy" src="/' + \
'icons/newpost.png" title="' + \
translate['Create a new DM'] + \
'" alt="| ' + translate['Create a new DM'] + \
'" class="timelineicon"/></a>\n'
else:
newPostButtonStr += \
'<a href="' + usersPath + '/newdm?nodropdown">' + \
'<button class="button"><span>' + \
translate['Post'] + ' </span></button></a>'
elif (boxName == 'tlblogs' or
boxName == 'tlnews' or
boxName == 'tlfeatures'):
if not iconsAsButtons:
newPostButtonStr += \
'<a class="imageAnchor" href="' + usersPath + \
'/newblog"><img loading="lazy" src="/' + \
'icons/newpost.png" title="' + \
translate['Create a new post'] + '" alt="| ' + \
translate['Create a new post'] + \
'" class="timelineicon"/></a>\n'
else:
newPostButtonStr += \
'<a href="' + usersPath + '/newblog">' + \
'<button class="button"><span>' + \
translate['Post'] + '</span></button></a>'
elif boxName == 'tlshares':
if not iconsAsButtons:
newPostButtonStr += \
'<a class="imageAnchor" href="' + usersPath + \
'/newshare?nodropdown"><img loading="lazy" src="/' + \
'icons/newpost.png" title="' + \
translate['Create a new shared item'] + '" alt="| ' + \
translate['Create a new shared item'] + \
'" class="timelineicon"/></a>\n'
else:
newPostButtonStr += \
'<a href="' + usersPath + '/newshare?nodropdown">' + \
'<button class="button"><span>' + \
translate['Post'] + '</span></button></a>'
else:
if not manuallyApproveFollowers:
if not iconsAsButtons:
newPostButtonStr += \
'<a class="imageAnchor" href="' + usersPath + \
'/newpost"><img loading="lazy" src="/' + \
'icons/newpost.png" title="' + \
translate['Create a new post'] + '" alt="| ' + \
translate['Create a new post'] + \
'" class="timelineicon"/></a>\n'
else:
newPostButtonStr += \
'<a href="' + usersPath + '/newpost">' + \
'<button class="button"><span>' + \
translate['Post'] + '</span></button></a>'
else:
if not iconsAsButtons:
newPostButtonStr += \
'<a class="imageAnchor" href="' + usersPath + \
'/newfollowers"><img loading="lazy" src="/' + \
'icons/newpost.png" title="' + \
translate['Create a new post'] + \
'" alt="| ' + translate['Create a new post'] + \
'" class="timelineicon"/></a>\n'
else:
newPostButtonStr += \
'<a href="' + usersPath + '/newfollowers">' + \
'<button class="button"><span>' + \
translate['Post'] + '</span></button></a>'
return newPostButtonStr
2021-06-27 22:01:58 +00:00
def _htmlTimelineModerationButtons(moderator: bool, boxName: str,
nickname: str, moderationActionStr: str,
translate: {}) -> str:
"""Returns html for the moderation screen buttons
"""
tlStr = ''
if moderator and boxName == 'moderation':
tlStr += \
'<form id="modtimeline" method="POST" action="/users/' + \
nickname + '/moderationaction">'
tlStr += '<div class="container">\n'
idx = 'Nickname or URL. Block using *@domain or nickname@domain'
tlStr += \
' <b>' + translate[idx] + '</b><br>\n'
if moderationActionStr:
tlStr += ' <input type="text" ' + \
'name="moderationAction" value="' + \
moderationActionStr + '" autofocus><br>\n'
else:
tlStr += ' <input type="text" ' + \
'name="moderationAction" value="" autofocus><br>\n'
tlStr += \
' <input type="submit" title="' + \
translate['Information about current blocks/suspensions'] + \
'" alt="' + \
translate['Information about current blocks/suspensions'] + \
' | " ' + \
'name="submitInfo" value="' + translate['Info'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Remove the above item'] + '" ' + \
'alt="' + translate['Remove the above item'] + ' | " ' + \
'name="submitRemove" value="' + \
translate['Remove'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Suspend the above account nickname'] + '" ' + \
'alt="' + \
translate['Suspend the above account nickname'] + ' | " ' + \
'name="submitSuspend" value="' + translate['Suspend'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Remove a suspension for an account nickname'] + '" ' + \
'alt="' + \
translate['Remove a suspension for an account nickname'] + \
' | " ' + \
'name="submitUnsuspend" value="' + \
translate['Unsuspend'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Block an account on another instance'] + '" ' + \
'alt="' + \
translate['Block an account on another instance'] + ' | " ' + \
'name="submitBlock" value="' + translate['Block'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Unblock an account on another instance'] + '" ' + \
'alt="' + \
translate['Unblock an account on another instance'] + ' | " ' + \
'name="submitUnblock" value="' + translate['Unblock'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Filter out words'] + '" ' + \
'alt="' + \
translate['Filter out words'] + ' | " ' + \
'name="submitFilter" value="' + translate['Filter'] + '">\n'
tlStr += \
' <input type="submit" title="' + \
translate['Unfilter words'] + '" ' + \
'alt="' + \
translate['Unfilter words'] + ' | " ' + \
'name="submitUnfilter" value="' + translate['Unfilter'] + '">\n'
tlStr += '</div>\n</form>\n'
return tlStr
2021-06-27 22:14:48 +00:00
def _htmlTimelineKeyboard(moderator: bool, textModeBanner: str, usersPath: str,
nickname: str, newCalendarEvent: bool,
newDM: bool, newReply: bool, newShare: bool,
followApprovals: bool,
accessKeys: {}, translate: {}) -> str:
"""Returns html for timeline keyboard navigation
"""
calendarStr = translate['Calendar']
if newCalendarEvent:
calendarStr = '<strong>' + calendarStr + '</strong>'
dmStr = translate['DM']
if newDM:
dmStr = '<strong>' + dmStr + '</strong>'
repliesStr = translate['Replies']
if newReply:
repliesStr = '<strong>' + repliesStr + '</strong>'
sharesStr = translate['Shares']
if newShare:
sharesStr = '<strong>' + sharesStr + '</strong>'
menuProfile = \
htmlHideFromScreenReader('👤') + ' ' + \
translate['Switch to profile view']
menuInbox = \
htmlHideFromScreenReader('📥') + ' ' + translate['Inbox']
menuOutbox = \
htmlHideFromScreenReader('📤') + ' ' + translate['Sent']
menuSearch = \
htmlHideFromScreenReader('🔍') + ' ' + \
translate['Search and follow']
menuCalendar = \
htmlHideFromScreenReader('📅') + ' ' + calendarStr
menuDM = \
htmlHideFromScreenReader('📩') + ' ' + dmStr
menuReplies = \
htmlHideFromScreenReader('📨') + ' ' + repliesStr
menuBookmarks = \
htmlHideFromScreenReader('🔖') + ' ' + translate['Bookmarks']
menuShares = \
htmlHideFromScreenReader('🤝') + ' ' + sharesStr
menuBlogs = \
htmlHideFromScreenReader('📝') + ' ' + translate['Blogs']
menuNewswire = \
htmlHideFromScreenReader('📰') + ' ' + translate['Newswire']
menuLinks = \
htmlHideFromScreenReader('🔗') + ' ' + translate['Links']
menuNewPost = \
htmlHideFromScreenReader('') + ' ' + translate['Create a new post']
menuModeration = \
htmlHideFromScreenReader('⚡️') + ' ' + translate['Mod']
navLinks = {
menuProfile: '/users/' + nickname,
menuInbox: usersPath + '/inbox#timelineposts',
menuSearch: usersPath + '/search',
menuNewPost: usersPath + '/newpost',
menuCalendar: usersPath + '/calendar',
menuDM: usersPath + '/dm#timelineposts',
menuReplies: usersPath + '/tlreplies#timelineposts',
menuOutbox: usersPath + '/outbox#timelineposts',
menuBookmarks: usersPath + '/tlbookmarks#timelineposts',
menuShares: usersPath + '/tlshares#timelineposts',
menuBlogs: usersPath + '/tlblogs#timelineposts',
menuNewswire: usersPath + '/newswiremobile',
menuLinks: usersPath + '/linksmobile'
}
navAccessKeys = {}
for variableName, key in accessKeys.items():
if not locals().get(variableName):
continue
navAccessKeys[locals()[variableName]] = key
if moderator:
navLinks[menuModeration] = usersPath + '/moderation#modtimeline'
return htmlKeyboardNavigation(textModeBanner, navLinks, navAccessKeys,
None, usersPath, translate, followApprovals)
2020-11-10 15:12:07 +00:00
def htmlTimeline(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int,
itemsPerPage: int, session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-10 15:12:07 +00:00
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,
2020-12-09 23:30:15 +00:00
authorized: bool,
2020-12-20 17:26:38 +00:00
moderationActionStr: str,
2020-12-23 23:59:49 +00:00
theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-10 15:12:07 +00:00
"""Show the timeline as html
2020-11-09 22:44:03 +00:00
"""
2020-12-01 17:23:34 +00:00
enableTimingLog = False
2020-11-10 15:12:07 +00:00
timelineStartTime = time.time()
2020-11-09 22:44:03 +00:00
2021-07-13 21:59:53 +00:00
accountDir = acctDir(baseDir, nickname, domain)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# 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', '')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# should the DM button be highlighted?
newDM = False
dmFile = accountDir + '/.newDM'
if os.path.isfile(dmFile):
newDM = True
if boxName == 'dm':
os.remove(dmFile)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# should the Replies button be highlighted?
newReply = False
replyFile = accountDir + '/.newReply'
if os.path.isfile(replyFile):
newReply = True
if boxName == 'tlreplies':
os.remove(replyFile)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# should the Shares button be highlighted?
newShare = False
newShareFile = accountDir + '/.newShare'
if os.path.isfile(newShareFile):
newShare = True
if boxName == 'tlshares':
os.remove(newShareFile)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# 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)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
separatorStr = ''
if boxName != 'tlmedia':
separatorStr = htmlPostSeparator(baseDir, None)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# the css filename
cssFilename = baseDir + '/epicyon-profile.css'
if os.path.isfile(baseDir + '/epicyon.css'):
cssFilename = baseDir + '/epicyon.css'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# filename of the banner shown at the top
2020-12-20 17:29:15 +00:00
bannerFile, bannerFilename = \
getBannerFile(baseDir, nickname, domain, theme)
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '1')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# is the user a moderator?
if not moderator:
moderator = isModerator(baseDir, nickname)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# is the user a site editor?
if not editor:
editor = isEditor(baseDir, nickname)
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '2')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# the appearance of buttons - highlighted or not
inboxButton = 'button'
blogsButton = 'button'
2020-11-27 12:42:51 +00:00
featuresButton = 'button'
2020-11-10 15:12:07 +00:00
newsButton = 'button'
dmButton = 'button'
if newDM:
dmButton = 'buttonhighlighted'
repliesButton = 'button'
if newReply:
repliesButton = 'buttonhighlighted'
mediaButton = 'button'
bookmarksButton = 'button'
# eventsButton = 'button'
2020-11-10 15:12:07 +00:00
sentButton = 'button'
sharesButton = 'button'
if newShare:
sharesButton = 'buttonhighlighted'
moderationButton = 'button'
if newReport:
moderationButton = 'buttonhighlighted'
if boxName == 'inbox':
inboxButton = 'buttonselected'
elif boxName == 'tlblogs':
blogsButton = 'buttonselected'
2020-11-27 12:42:51 +00:00
elif boxName == 'tlfeatures':
featuresButton = 'buttonselected'
2020-11-10 15:12:07 +00:00
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'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# get the full domain, including any port number
2020-12-16 11:19:16 +00:00
fullDomain = getFullDomain(domain, port)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
usersPath = '/users/' + nickname
actor = httpPrefix + '://' + fullDomain + usersPath
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
showIndividualPostIcons = True
# show an icon for new follow approvals
followApprovals = ''
followRequestsFilename = \
2021-07-13 21:59:53 +00:00
acctDir(baseDir, nickname, domain) + '/followrequests.txt'
2020-11-10 15:12:07 +00:00
if os.path.isfile(followRequestsFilename):
with open(followRequestsFilename, 'r') as f:
for line in f:
if len(line) > 0:
# show follow approvals icon
followApprovals = \
2020-11-09 22:44:03 +00:00
'<a href="' + usersPath + \
2021-04-23 12:24:34 +00:00
'/followers#buttonheader" ' + \
'accesskey="' + accessKeys['followButton'] + '">' + \
2020-11-10 15:12:07 +00:00
'<img loading="lazy" ' + \
'class="timelineicon" alt="' + \
translate['Approve follow requests'] + \
'" title="' + translate['Approve follow requests'] + \
2020-12-09 13:08:26 +00:00
'" src="/icons/person.png"/></a>\n'
2020-11-10 15:12:07 +00:00
break
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '3')
2020-11-10 15:12:07 +00:00
# moderation / reports button
moderationButtonStr = ''
if moderator and not minimal:
moderationButtonStr = \
2020-11-09 22:44:03 +00:00
'<a href="' + usersPath + \
2020-11-10 15:12:07 +00:00
'/moderation"><button class="' + \
moderationButton + '"><span>' + \
htmlHighlightLabel(translate['Mod'], newReport) + \
' </span></button></a>'
# shares, bookmarks and events buttons
sharesButtonStr = ''
bookmarksButtonStr = ''
eventsButtonStr = ''
if not minimal:
sharesButtonStr = \
'<a href="' + usersPath + '/tlshares"><button class="' + \
sharesButton + '"><span>' + \
htmlHighlightLabel(translate['Shares'], newShare) + \
2020-11-09 22:44:03 +00:00
'</span></button></a>'
2020-11-10 15:12:07 +00:00
bookmarksButtonStr = \
'<a href="' + usersPath + '/tlbookmarks"><button class="' + \
bookmarksButton + '"><span>' + translate['Bookmarks'] + \
'</span></button></a>'
2020-11-09 22:44:03 +00:00
2021-01-11 19:46:21 +00:00
instanceTitle = \
getConfigParam(baseDir, 'instanceTitle')
tlStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle)
2020-11-10 15:12:07 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '4')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# if this is a news instance and we are viewing the news timeline
newsHeader = False
2020-11-27 12:52:01 +00:00
if defaultTimeline == 'tlfeatures' and boxName == 'tlfeatures':
2020-11-10 15:12:07 +00:00
newsHeader = True
newPostButtonStr = ''
# start of headericons div
if not newsHeader:
2020-11-09 22:44:03 +00:00
if not iconsAsButtons:
2020-11-10 15:12:07 +00:00
newPostButtonStr += '<div class="headericons">'
# what screen to go to when a new post is created
2021-06-27 21:40:12 +00:00
newPostButtonStr += \
_htmlTimelineNewPost(manuallyApproveFollowers, boxName,
iconsAsButtons, usersPath, translate)
2020-11-09 22:44:03 +00:00
2021-02-05 15:30:51 +00:00
# keyboard navigation
2021-06-27 22:14:48 +00:00
tlStr += \
_htmlTimelineKeyboard(moderator, textModeBanner, usersPath, nickname,
newCalendarEvent, newDM, newReply, newShare,
followApprovals, accessKeys, translate)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# banner and row of buttons
tlStr += \
2020-12-27 16:57:15 +00:00
'<header>\n' + \
2020-11-10 15:12:07 +00:00
'<a href="/users/' + nickname + '" title="' + \
translate['Switch to profile view'] + '" alt="' + \
translate['Switch to profile view'] + '">\n'
2021-02-01 18:38:08 +00:00
tlStr += '<img loading="lazy" class="timeline-banner" ' + \
2021-02-01 19:48:46 +00:00
'alt="" ' + \
2021-02-01 18:38:08 +00:00
'src="' + usersPath + '/' + bannerFile + '" /></a>\n' + \
2020-12-27 16:57:15 +00:00
'</header>\n'
2020-11-10 15:12:07 +00:00
if fullWidthTimelineButtonHeader:
2020-11-09 22:44:03 +00:00
tlStr += \
2020-11-10 15:12:07 +00:00
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
translate, usersPath, mediaButton,
2020-11-27 12:42:51 +00:00
blogsButton, featuresButton,
newsButton, inboxButton,
2020-11-10 15:12:07 +00:00
dmButton, newDM, repliesButton,
newReply, minimal, sentButton,
sharesButtonStr, bookmarksButtonStr,
eventsButtonStr, moderationButtonStr,
newPostButtonStr, baseDir, nickname,
2020-12-09 13:31:54 +00:00
domain, timelineStartTime,
2020-11-10 15:12:07 +00:00
newCalendarEvent, calendarPath,
calendarImage, followApprovals,
2021-04-23 12:24:34 +00:00
iconsAsButtons, accessKeys)
2020-11-10 15:12:07 +00:00
# start the timeline
2021-07-06 12:50:38 +00:00
tlStr += \
'<table class="timeline">\n' + \
' <colgroup>\n' + \
' <col span="1" class="column-left">\n' + \
' <col span="1" class="column-center">\n' + \
' <col span="1" class="column-right">\n' + \
' </colgroup>\n' + \
' <tbody>\n' + \
' <tr>\n'
2020-11-10 15:12:07 +00:00
2020-12-16 11:19:16 +00:00
domainFull = getFullDomain(domain, port)
2020-11-10 15:12:07 +00:00
# left column
leftColumnStr = \
getLeftColumnContent(baseDir, nickname, domainFull,
2020-12-09 13:31:54 +00:00
httpPrefix, translate,
2020-11-10 15:12:07 +00:00
editor, False, None, rssIconAtTop,
2021-04-23 16:29:03 +00:00
True, False, theme, accessKeys)
2021-02-01 13:31:49 +00:00
tlStr += ' <td valign="top" class="col-left" ' + \
'id="links" tabindex="-1">' + \
2020-11-10 15:12:07 +00:00
leftColumnStr + ' </td>\n'
# center column containing posts
2021-02-15 15:21:07 +00:00
tlStr += ' <td valign="top" class="col-center">\n'
2020-11-10 15:12:07 +00:00
if not fullWidthTimelineButtonHeader:
2020-11-09 22:44:03 +00:00
tlStr += \
2020-11-10 15:12:07 +00:00
headerButtonsTimeline(defaultTimeline, boxName, pageNumber,
translate, usersPath, mediaButton,
2020-11-27 12:42:51 +00:00
blogsButton, featuresButton,
newsButton, inboxButton,
2020-11-10 15:12:07 +00:00
dmButton, newDM, repliesButton,
newReply, minimal, sentButton,
sharesButtonStr, bookmarksButtonStr,
eventsButtonStr, moderationButtonStr,
newPostButtonStr, baseDir, nickname,
2020-12-09 13:31:54 +00:00
domain, timelineStartTime,
2020-11-10 15:12:07 +00:00
newCalendarEvent, calendarPath,
calendarImage, followApprovals,
2021-04-23 12:24:34 +00:00
iconsAsButtons, accessKeys)
2020-11-09 22:44:03 +00:00
2021-02-15 15:21:07 +00:00
tlStr += ' <div id="timelineposts" class="timeline-posts">\n'
2020-11-18 18:22:05 +00:00
2020-11-10 15:12:07 +00:00
# second row of buttons for moderator actions
2021-06-27 22:01:58 +00:00
tlStr += \
_htmlTimelineModerationButtons(moderator, boxName, nickname,
moderationActionStr, translate)
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '6')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if boxName == 'tlshares':
maxSharesPerAccount = itemsPerPage
return (tlStr +
_htmlSharesTimeline(translate, pageNumber, itemsPerPage,
baseDir, actor, nickname, domain, port,
maxSharesPerAccount, httpPrefix) +
2020-11-10 15:12:07 +00:00
htmlFooter())
2020-11-09 22:44:03 +00:00
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '7')
2020-11-09 22:44:03 +00:00
2021-02-07 21:45:31 +00:00
# separator between posts which only appears in shell browsers
# such as Lynx and is not read by screen readers
if boxName != 'tlmedia':
textModeSeparator = \
'<div class="transparent"><hr></div>'
2021-02-18 20:10:26 +00:00
else:
textModeSeparator = ''
2021-02-07 21:45:31 +00:00
2020-11-10 15:12:07 +00:00
# page up arrow
if pageNumber > 1:
2021-02-07 21:45:31 +00:00
tlStr += textModeSeparator
2020-11-10 15:12:07 +00:00
tlStr += \
' <center>\n' + \
' <a href="' + usersPath + '/' + boxName + \
'?page=' + str(pageNumber - 1) + \
2021-04-23 13:20:28 +00:00
'" accesskey="' + accessKeys['Page up'] + '">' + \
'<img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pageup.png" title="' + \
2020-11-10 15:12:07 +00:00
translate['Page up'] + '" alt="' + \
translate['Page up'] + '"></a>\n' + \
' </center>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# show the posts
itemCtr = 0
if timelineJson:
# if this is the media timeline then add an extra gallery container
if boxName == 'tlmedia':
if pageNumber > 1:
tlStr += '<br>'
tlStr += '<div class="galleryContainer">\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# show each post in the timeline
for item in timelineJson['orderedItems']:
if item['type'] == 'Create' or \
2021-03-05 15:45:03 +00:00
item['type'] == 'Announce':
2020-11-10 15:12:07 +00:00
# is the actor who sent this post snoozed?
if isPersonSnoozed(baseDir, nickname, domain, item['actor']):
continue
if isSelfAnnounce(item):
continue
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# is the post in the memory cache of recent ones?
currTlStr = None
if boxName != 'tlmedia' and \
recentPostsCache.get('index'):
postId = \
removeIdEnding(item['id']).replace('/', '#')
if postId in recentPostsCache['index']:
if not item.get('muted'):
if recentPostsCache['html'].get(postId):
currTlStr = recentPostsCache['html'][postId]
currTlStr = \
2021-02-02 21:08:33 +00:00
preparePostFromHtmlCache(nickname,
currTlStr,
2020-11-10 15:12:07 +00:00
boxName,
pageNumber)
_logTimelineTiming(enableTimingLog,
timelineStartTime,
boxName, '10')
2021-03-05 15:48:37 +00:00
else:
print('Muted post in timeline ' + boxName)
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if not currTlStr:
_logTimelineTiming(enableTimingLog,
timelineStartTime,
boxName, '11')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
# read the post from disk
currTlStr = \
individualPostAsHtml(False, recentPostsCache,
maxRecentPosts,
2020-12-09 13:31:54 +00:00
translate, pageNumber,
baseDir, session,
cachedWebfingers,
2020-11-10 15:12:07 +00:00
personCache,
nickname, domain, port,
2020-11-10 15:12:07 +00:00
item, None, True,
allowDeletion,
httpPrefix, projectVersion,
boxName,
2020-11-10 15:12:07 +00:00
YTReplacementDomain,
showPublishedDateOnly,
2020-12-23 23:59:49 +00:00
peertubeInstances,
allowLocalNetworkAccess,
theme, systemLanguage,
2020-11-10 15:12:07 +00:00
boxName != 'dm',
showIndividualPostIcons,
manuallyApproveFollowers,
False, True)
_logTimelineTiming(enableTimingLog,
timelineStartTime, boxName, '12')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if currTlStr:
itemCtr += 1
2021-02-07 21:27:20 +00:00
tlStr += textModeSeparator + currTlStr
2020-11-10 15:12:07 +00:00
if separatorStr:
tlStr += separatorStr
2020-11-10 15:12:07 +00:00
if boxName == 'tlmedia':
tlStr += '</div>\n'
2020-11-09 22:44:03 +00:00
if itemCtr < 3:
print('Items added to html timeline ' + boxName + ': ' +
str(itemCtr) + ' ' + str(timelineJson['orderedItems']))
2020-11-10 15:12:07 +00:00
# page down arrow
2021-04-29 20:16:48 +00:00
if itemCtr > 0:
2021-02-07 21:41:57 +00:00
tlStr += textModeSeparator
2020-11-10 15:12:07 +00:00
tlStr += \
' <center>\n' + \
' <a href="' + usersPath + '/' + boxName + '?page=' + \
str(pageNumber + 1) + \
2021-04-23 13:20:28 +00:00
'" accesskey="' + accessKeys['Page down'] + '">' + \
'<img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pagedown.png" title="' + \
2020-11-10 15:12:07 +00:00
translate['Page down'] + '" alt="' + \
translate['Page down'] + '"></a>\n' + \
' </center>\n'
2021-02-07 21:41:57 +00:00
tlStr += textModeSeparator
elif itemCtr == 0:
tlStr += _getHelpForTimeline(baseDir, boxName)
2020-11-18 18:22:05 +00:00
2021-02-26 12:38:13 +00:00
# end of timeline-posts
tlStr += ' </div>\n'
2020-11-09 22:44:03 +00:00
2021-02-26 12:41:09 +00:00
# end of column-center
tlStr += ' </td>\n'
2020-11-10 15:12:07 +00:00
# right column
rightColumnStr = getRightColumnContent(baseDir, nickname, domainFull,
2020-12-09 13:31:54 +00:00
httpPrefix, translate,
2020-11-10 15:12:07 +00:00
moderator, editor,
newswire, positiveVoting,
False, None, True,
showPublishAsIcon,
rssIconAtTop, publishButtonAtTop,
2021-02-05 11:41:45 +00:00
authorized, True, theme,
2021-04-23 19:06:34 +00:00
defaultTimeline, accessKeys)
2021-02-01 13:31:49 +00:00
tlStr += ' <td valign="top" class="col-right" ' + \
'id="newswire" tabindex="-1">' + \
2020-11-10 15:12:07 +00:00
rightColumnStr + ' </td>\n'
tlStr += ' </tr>\n'
_logTimelineTiming(enableTimingLog, timelineStartTime, boxName, '9')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
tlStr += ' </tbody>\n'
tlStr += '</table>\n'
tlStr += htmlFooter()
return tlStr
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
def htmlIndividualShare(actor: str, item: {}, translate: {},
showContact: bool, removeButton: bool) -> str:
"""Returns an individual shared item as html
"""
profileStr = '<div class="container">\n'
profileStr += '<p class="share-title">' + item['displayName'] + '</p>\n'
if item.get('imageUrl'):
profileStr += '<a href="' + item['imageUrl'] + '">\n'
profileStr += \
'<img loading="lazy" src="' + item['imageUrl'] + \
'" alt="' + translate['Item image'] + '">\n</a>\n'
2021-07-24 11:34:05 +00:00
profileStr += '<p>' + item['summary'] + '</p>\n<p>'
if item.get('itemQty'):
profileStr += \
'<b>' + translate['Quantity'] + ':</b> ' + \
str(item['itemQty']) + ' '
2021-07-24 11:30:46 +00:00
profileStr += \
'<b>' + translate['Type'] + ':</b> ' + item['itemType'] + ' '
2020-11-10 15:12:07 +00:00
profileStr += \
'<b>' + translate['Category'] + ':</b> ' + item['category'] + ' '
profileStr += \
2021-07-24 22:08:11 +00:00
'<b>' + translate['Location'] + ':</b> ' + item['location']
if item.get('itemPrice') and item.get('itemCurrency'):
2021-07-25 13:09:39 +00:00
if isfloat(item['itemPrice']):
2021-07-24 22:08:11 +00:00
if float(item['itemPrice']) > 0:
profileStr += ' ' + \
'<b>' + translate['Price'] + ':</b> ' + \
item['itemPrice'] + ' ' + item['itemCurrency']
profileStr += '</p>\n'
sharedesc = item['displayName']
if '<' not in sharedesc and '?' not in sharedesc:
if showContact:
contactActor = item['actor']
profileStr += \
'<p><a href="' + actor + \
'?replydm=sharedesc:' + sharedesc + \
'?mention=' + contactActor + '"><button class="button">' + \
translate['Contact'] + '</button></a>\n'
if removeButton:
profileStr += \
' <a href="' + actor + '?rmshare=' + sharedesc + \
'"><button class="button">' + \
translate['Remove'] + '</button></a>\n'
2020-11-10 15:12:07 +00:00
profileStr += '</div>\n'
return profileStr
2020-11-09 22:44:03 +00:00
def _htmlSharesTimeline(translate: {}, pageNumber: int, itemsPerPage: int,
baseDir: str, actor: str,
nickname: str, domain: str, port: int,
maxSharesPerAccount: int, httpPrefix: str) -> str:
2020-11-10 15:12:07 +00:00
"""Show shared items timeline as html
"""
sharesJson, lastPage = \
sharesTimelineJson(actor, pageNumber, itemsPerPage,
baseDir, maxSharesPerAccount)
2020-12-16 11:19:16 +00:00
domainFull = getFullDomain(domain, port)
2020-11-10 15:12:07 +00:00
actor = httpPrefix + '://' + domainFull + '/users/' + nickname
timelineStr = ''
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if pageNumber > 1:
timelineStr += \
' <center>\n' + \
' <a href="' + actor + '/tlshares?page=' + \
str(pageNumber - 1) + \
'"><img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pageup.png" title="' + translate['Page up'] + \
2020-11-10 15:12:07 +00:00
'" alt="' + translate['Page up'] + '"></a>\n' + \
' </center>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
separatorStr = htmlPostSeparator(baseDir, None)
2021-02-26 13:31:31 +00:00
ctr = 0
2020-11-10 15:12:07 +00:00
for published, item in sharesJson.items():
showContactButton = False
if item['actor'] != actor:
showContactButton = True
showRemoveButton = False
if item['actor'] == actor:
showRemoveButton = True
2020-11-18 19:28:33 +00:00
timelineStr += \
2020-11-10 15:12:07 +00:00
htmlIndividualShare(actor, item, translate,
showContactButton, showRemoveButton)
2020-11-18 19:28:33 +00:00
timelineStr += separatorStr
2021-02-26 13:31:31 +00:00
ctr += 1
if ctr == 0:
timelineStr += _getHelpForTimeline(baseDir, 'tlshares')
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
if not lastPage:
timelineStr += \
' <center>\n' + \
' <a href="' + actor + '/tlshares?page=' + \
str(pageNumber + 1) + \
'"><img loading="lazy" class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pagedown.png" title="' + translate['Page down'] + \
2020-11-10 15:12:07 +00:00
'" alt="' + translate['Page down'] + '"></a>\n' + \
' </center>\n'
2020-11-09 22:44:03 +00:00
2020-11-10 15:12:07 +00:00
return timelineStr
2020-11-09 22:44:03 +00:00
def htmlShares(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int,
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the shares timeline as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, None,
'tlshares', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers,
False, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
def htmlInbox(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the inbox as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson,
'inbox', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
def htmlBookmarks(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, bookmarksJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the bookmarks as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, bookmarksJson,
'tlbookmarks', allowDeletion,
httpPrefix, projectVersion, manuallyApproveFollowers,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
def htmlInboxDMs(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the DM timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'dm', allowDeletion,
httpPrefix, projectVersion, False, minimal,
YTReplacementDomain, showPublishedDateOnly,
newswire, False, False, positiveVoting,
showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
def htmlInboxReplies(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the replies timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlreplies',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
def htmlInboxMedia(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the media timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlmedia',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
def htmlInboxBlogs(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the blogs timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlblogs',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
2020-11-27 11:22:47 +00:00
def htmlInboxFeatures(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-27 11:22:47 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-20 17:26:38 +00:00
authorized: bool,
2020-12-23 23:59:49 +00:00
theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-27 11:22:47 +00:00
"""Show the features timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-27 15:05:22 +00:00
nickname, domain, port, inboxJson, 'tlfeatures',
2020-11-27 11:22:47 +00:00
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, False, False,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-27 11:22:47 +00:00
2020-11-09 22:44:03 +00:00
def htmlInboxNews(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, inboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, moderator: bool, editor: bool,
positiveVoting: bool, showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the news timeline as html
"""
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, inboxJson, 'tlnews',
allowDeletion, httpPrefix, projectVersion, False,
minimal, YTReplacementDomain,
showPublishedDateOnly,
newswire, moderator, editor,
positiveVoting, showPublishAsIcon,
fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)
2020-11-09 22:44:03 +00:00
def htmlOutbox(cssCache: {}, defaultTimeline: str,
recentPostsCache: {}, maxRecentPosts: int,
translate: {}, pageNumber: int, itemsPerPage: int,
session, baseDir: str,
cachedWebfingers: {}, personCache: {},
2020-11-09 22:44:03 +00:00
nickname: str, domain: str, port: int, outboxJson: {},
allowDeletion: bool,
httpPrefix: str, projectVersion: str,
minimal: bool, YTReplacementDomain: str,
showPublishedDateOnly: bool,
newswire: {}, positiveVoting: bool,
showPublishAsIcon: bool,
fullWidthTimelineButtonHeader: bool,
iconsAsButtons: bool,
rssIconAtTop: bool,
publishButtonAtTop: bool,
2020-12-23 23:59:49 +00:00
authorized: bool, theme: str,
peertubeInstances: [],
2021-02-05 19:14:27 +00:00
allowLocalNetworkAccess: bool,
textModeBanner: str,
accessKeys: {}, systemLanguage: str) -> str:
2020-11-09 22:44:03 +00:00
"""Show the Outbox as html
"""
manuallyApproveFollowers = \
followerApprovalActive(baseDir, nickname, domain)
return htmlTimeline(cssCache, defaultTimeline,
recentPostsCache, maxRecentPosts,
translate, pageNumber,
itemsPerPage, session, baseDir,
cachedWebfingers, personCache,
2020-11-09 22:44:03 +00:00
nickname, domain, port, outboxJson, 'outbox',
allowDeletion, httpPrefix, projectVersion,
manuallyApproveFollowers, minimal,
YTReplacementDomain, showPublishedDateOnly,
newswire, False, False, positiveVoting,
showPublishAsIcon, fullWidthTimelineButtonHeader,
iconsAsButtons, rssIconAtTop, publishButtonAtTop,
authorized, None, theme, peertubeInstances,
allowLocalNetworkAccess, textModeBanner,
accessKeys, systemLanguage)