__filename__ = "webapp_column_left.py" __author__ = "Bob Mottram" __license__ = "AGPL3+" __version__ = "1.2.0" __maintainer__ = "Bob Mottram" __email__ = "bob@freedombone.net" __status__ = "Production" __module_group__ = "Web Interface Columns" import os from utils import getConfigParam from utils import getNicknameFromActor from utils import isEditor from utils import removeDomainPort from webapp_utils import sharesTimelineJson from webapp_utils import htmlPostSeparator from webapp_utils import getLeftImageFile from webapp_utils import headerButtonsFrontScreen from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlFooter from webapp_utils import getBannerFile def _linksExist(baseDir: str) -> bool: """Returns true if links have been created """ linksFilename = baseDir + '/accounts/links.txt' return os.path.isfile(linksFilename) def _getLeftColumnShares(baseDir: str, httpPrefix: str, domain: str, domainFull: str, nickname: str, maxSharesInLeftColumn: int, translate: {}, sharedItemsFederatedDomains: []) -> []: """get any shares and turn them into the left column links format """ pageNumber = 1 actor = httpPrefix + '://' + domainFull + '/users/' + nickname # NOTE: this could potentially be slow if the number of federated # shared items is large sharesJson, lastPage = \ sharesTimelineJson(actor, pageNumber, maxSharesInLeftColumn, baseDir, domain, nickname, maxSharesInLeftColumn, sharedItemsFederatedDomains, 'shares') if not sharesJson: return [] linksList = [] ctr = 0 for published, item in sharesJson.items(): sharedesc = item['displayName'] if '<' in sharedesc or '?' in sharedesc: continue shareId = item['shareId'] # selecting this link calls htmlShowShare shareLink = actor + '?showshare=' + shareId linksList.append(sharedesc + ' ' + shareLink) ctr += 1 if ctr >= maxSharesInLeftColumn: break if linksList: linksList = ['* ' + translate['Shares']] + linksList return linksList def _getLeftColumnWanted(baseDir: str, httpPrefix: str, domain: str, domainFull: str, nickname: str, maxSharesInLeftColumn: int, translate: {}, sharedItemsFederatedDomains: []) -> []: """get any wanted items and turn them into the left column links format """ pageNumber = 1 actor = httpPrefix + '://' + domainFull + '/users/' + nickname # NOTE: this could potentially be slow if the number of federated # wanted items is large sharesJson, lastPage = \ sharesTimelineJson(actor, pageNumber, maxSharesInLeftColumn, baseDir, domain, nickname, maxSharesInLeftColumn, sharedItemsFederatedDomains, 'wanted') if not sharesJson: return [] linksList = [] ctr = 0 for published, item in sharesJson.items(): sharedesc = item['displayName'] if '<' in sharedesc or '?' in sharedesc: continue shareId = item['shareId'] # selecting this link calls htmlShowShare shareLink = actor + '?showwanted=' + shareId linksList.append(sharedesc + ' ' + shareLink) ctr += 1 if ctr >= maxSharesInLeftColumn: break if linksList: linksList = ['* ' + translate['Wanted']] + linksList return linksList def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, httpPrefix: str, translate: {}, editor: bool, showBackButton: bool, timelinePath: str, rssIconAtTop: bool, showHeaderImage: bool, frontPage: bool, theme: str, accessKeys: {}, sharedItemsFederatedDomains: []) -> str: """Returns html content for the left column """ htmlStr = '' separatorStr = htmlPostSeparator(baseDir, 'left') domain = removeDomainPort(domainFull) editImageClass = '' if showHeaderImage: leftImageFile, leftColumnImageFilename = \ getLeftImageFile(baseDir, nickname, domain, theme) # show the image at the top of the column editImageClass = 'leftColEdit' if os.path.isfile(leftColumnImageFilename): editImageClass = 'leftColEditImage' htmlStr += \ '\n
\n \n' + \ '
\n' if showBackButton: htmlStr += \ '
' + \ '\n' if (editor or rssIconAtTop) and not showHeaderImage: htmlStr += '
' if editImageClass == 'leftColEdit': htmlStr += '\n
\n' htmlStr += '
\n' if editor: # show the edit icon htmlStr += \ ' ' + \ '' + \
            translate['Edit Links'] + ' | \n' # RSS icon if nickname != 'news': # rss feed for this account rssUrl = httpPrefix + '://' + domainFull + \ '/blog/' + nickname + '/rss.xml' else: # rss feed for all accounts on the instance rssUrl = httpPrefix + '://' + domainFull + '/blog/rss.xml' if not frontPage: rssTitle = translate['RSS feed for your blog'] else: rssTitle = translate['RSS feed for this site'] rssIconStr = \ ' ' + rssTitle + '\n' if rssIconAtTop: htmlStr += rssIconStr htmlStr += '
\n' if editImageClass == 'leftColEdit': htmlStr += '
\n' if (editor or rssIconAtTop) and not showHeaderImage: htmlStr += '

' # if showHeaderImage: # htmlStr += '
' # flag used not to show the first separator firstSeparatorAdded = False linksFilename = baseDir + '/accounts/links.txt' linksFileContainsEntries = False linksList = None if os.path.isfile(linksFilename): with open(linksFilename, 'r') as f: linksList = f.readlines() if not frontPage: # show a number of shares maxSharesInLeftColumn = 3 sharesList = \ _getLeftColumnShares(baseDir, httpPrefix, domain, domainFull, nickname, maxSharesInLeftColumn, translate, sharedItemsFederatedDomains) if linksList and sharesList: linksList = sharesList + linksList wantedList = \ _getLeftColumnWanted(baseDir, httpPrefix, domain, domainFull, nickname, maxSharesInLeftColumn, translate, sharedItemsFederatedDomains) if linksList and wantedList: linksList = wantedList + linksList newTabStr = ' target="_blank" rel="nofollow noopener noreferrer"' if linksList: htmlStr += '\n' if firstSeparatorAdded: htmlStr += separatorStr htmlStr += \ '

' + translate['Shares Catalog'] + '

' htmlStr += \ '

' + \ translate['Key Shortcuts'] + '

' htmlStr += \ '

' + \ translate['About this Instance'] + '

' htmlStr += \ '

' + \ translate['Terms of Service'] + '

' if linksFileContainsEntries and not rssIconAtTop: htmlStr += '
' + rssIconStr + '
' return htmlStr def htmlLinksMobile(cssCache: {}, baseDir: str, nickname: str, domainFull: str, httpPrefix: str, translate, timelinePath: str, authorized: bool, rssIconAtTop: bool, iconsAsButtons: bool, defaultTimeline: str, theme: str, accessKeys: {}, sharedItemsFederatedDomains: []) -> str: """Show the left column links within mobile view """ htmlStr = '' # the css filename cssFilename = baseDir + '/epicyon-profile.css' if os.path.isfile(baseDir + '/epicyon.css'): cssFilename = baseDir + '/epicyon.css' # is the user a site editor? if nickname == 'news': editor = False else: editor = isEditor(baseDir, nickname) domain = removeDomainPort(domainFull) instanceTitle = \ getConfigParam(baseDir, 'instanceTitle') htmlStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle) bannerFile, bannerFilename = \ getBannerFile(baseDir, nickname, domain, theme) htmlStr += \ '' + \ '\n' htmlStr += '
\n' htmlStr += '
' + \ headerButtonsFrontScreen(translate, nickname, 'links', authorized, iconsAsButtons) + '
' if _linksExist(baseDir): htmlStr += \ getLeftColumnContent(baseDir, nickname, domainFull, httpPrefix, translate, editor, False, timelinePath, rssIconAtTop, False, False, theme, accessKeys, sharedItemsFederatedDomains) else: if editor: htmlStr += '


\n
\n ' htmlStr += translate['Select the edit icon to add web links'] htmlStr += '\n
\n' # end of col-left-mobile htmlStr += '
\n' htmlStr += '
\n' + htmlFooter() return htmlStr def htmlEditLinks(cssCache: {}, translate: {}, baseDir: str, path: str, domain: str, port: int, httpPrefix: str, defaultTimeline: str, theme: str, accessKeys: {}) -> str: """Shows the edit links screen """ if '/users/' not in path: return '' path = path.replace('/inbox', '').replace('/outbox', '') path = path.replace('/shares', '').replace('/wanted', '') nickname = getNicknameFromActor(path) if not nickname: return '' # is the user a moderator? if not isEditor(baseDir, nickname): return '' cssFilename = baseDir + '/epicyon-links.css' if os.path.isfile(baseDir + '/links.css'): cssFilename = baseDir + '/links.css' # filename of the banner shown at the top bannerFile, bannerFilename = \ getBannerFile(baseDir, nickname, domain, theme) instanceTitle = \ getConfigParam(baseDir, 'instanceTitle') editLinksForm = htmlHeaderWithExternalStyle(cssFilename, instanceTitle) # top banner editLinksForm += \ '
\n' + \ '\n' editLinksForm += \ '\n' + \ '
\n' editLinksForm += \ '
\n' editLinksForm += \ '
\n' editLinksForm += \ '
\n' editLinksForm += \ '

' + translate['Edit Links'] + '

' editLinksForm += \ ' \n' editLinksForm += \ '
\n' linksFilename = baseDir + '/accounts/links.txt' linksStr = '' if os.path.isfile(linksFilename): with open(linksFilename, 'r') as fp: linksStr = fp.read() editLinksForm += \ '
' editLinksForm += \ ' ' + \ translate['One link per line. Description followed by the link.'] + \ '
' editLinksForm += \ ' ' editLinksForm += \ '
' # the admin can edit terms of service and about text adminNickname = getConfigParam(baseDir, 'admin') if adminNickname: if nickname == adminNickname: aboutFilename = baseDir + '/accounts/about.md' aboutStr = '' if os.path.isfile(aboutFilename): with open(aboutFilename, 'r') as fp: aboutStr = fp.read() editLinksForm += \ '
' editLinksForm += \ ' ' + \ translate['About this Instance'] + \ '
' editLinksForm += \ ' ' editLinksForm += \ '
' TOSFilename = baseDir + '/accounts/tos.md' TOSStr = '' if os.path.isfile(TOSFilename): with open(TOSFilename, 'r') as fp: TOSStr = fp.read() editLinksForm += \ '
' editLinksForm += \ ' ' + \ translate['Terms of Service'] + \ '
' editLinksForm += \ ' ' editLinksForm += \ '
' editLinksForm += htmlFooter() return editLinksForm