__filename__ = "webapp_column_left.py" __author__ = "Bob Mottram" __license__ = "AGPL3+" __version__ = "1.1.0" __maintainer__ = "Bob Mottram" __email__ = "bob@freedombone.net" __status__ = "Production" import os from shutil import copyfile from utils import getConfigParam from utils import getNicknameFromActor from utils import isEditor from webapp_utils import sharesTimelineJson from webapp_utils import htmlPostSeparator from webapp_utils import getLeftImageFile from webapp_utils import getImageFile from webapp_utils import headerButtonsFrontScreen from webapp_utils import getIconsWebPath 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, domainFull: str, nickname: str, maxSharesInLeftColumn: int, translate: {}) -> []: """get any shares and turn them into the left column links format """ pageNumber = 1 actor = httpPrefix + '://' + domainFull + '/users/' + nickname sharesJson, lastPage = \ sharesTimelineJson(actor, pageNumber, maxSharesInLeftColumn, baseDir, maxSharesInLeftColumn) if not sharesJson: return [] linksList = [] ctr = 0 for published, item in sharesJson.items(): sharedesc = item['displayName'] contactActor = item['actor'] shareLink = actor + \ '?replydm=sharedesc:' + sharedesc + \ '?mention=' + contactActor linksList.append(sharedesc + ' ' + shareLink) ctr += 1 if ctr >= maxSharesInLeftColumn: break if linksList: linksList = ['* ' + translate['Shares']] + linksList return linksList def getLeftColumnContent(baseDir: str, nickname: str, domainFull: str, httpPrefix: str, translate: {}, iconsPath: str, editor: bool, showBackButton: bool, timelinePath: str, rssIconAtTop: bool, showHeaderImage: bool, frontPage: bool) -> str: """Returns html content for the left column """ htmlStr = '' separatorStr = htmlPostSeparator(baseDir, 'left') domain = domainFull if ':' in domain: domain = domain.split(':') editImageClass = '' if showHeaderImage: leftImageFile, leftColumnImageFilename = \ getLeftImageFile(baseDir, nickname, domain) if not os.path.isfile(leftColumnImageFilename): theme = getConfigParam(baseDir, 'theme').lower() if theme == 'default': theme = '' else: theme = '_' + theme themeLeftImageFile, themeLeftColumnImageFilename = \ getImageFile(baseDir, 'left_col_image', baseDir + '/img', nickname, domain) if os.path.isfile(themeLeftColumnImageFilename): leftColumnImageFilename = \ baseDir + '/accounts/' + \ nickname + '@' + domain + '/' + themeLeftImageFile copyfile(themeLeftColumnImageFilename, leftColumnImageFilename) leftImageFile = themeLeftImageFile # 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, domainFull, nickname, maxSharesInLeftColumn, translate) if linksList and sharesList: linksList = sharesList + linksList if linksList: for lineStr in linksList: if ' ' not in lineStr: if '#' not in lineStr: if '*' not in lineStr: continue lineStr = lineStr.strip() words = lineStr.split(' ') # get the link linkStr = None for word in words: if word == '#': continue if word == '*': continue if '://' in word: linkStr = word break if linkStr: lineStr = lineStr.replace(linkStr, '').strip() # avoid any dubious scripts being added if '<' not in lineStr: # remove trailing comma if present if lineStr.endswith(','): lineStr = lineStr[:len(lineStr)-1] # add link to the returned html htmlStr += \ '

' + \ lineStr + '

\n' linksFileContainsEntries = True else: if lineStr.startswith('#') or lineStr.startswith('*'): lineStr = lineStr[1:].strip() if firstSeparatorAdded: htmlStr += separatorStr firstSeparatorAdded = True htmlStr += \ '

' + \ lineStr + '

\n' else: htmlStr += \ '

' + lineStr + '

\n' linksFileContainsEntries = True if firstSeparatorAdded: htmlStr += separatorStr 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) -> 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' iconsPath = getIconsWebPath(baseDir) # is the user a site editor? if nickname == 'news': editor = False else: editor = isEditor(baseDir, nickname) domain = domainFull if ':' in domain: domain = domain.split(':')[0] htmlStr = htmlHeaderWithExternalStyle(cssFilename) bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain) htmlStr += \ '' + \ '\n' htmlStr += '
\n' htmlStr += '
' + \ headerButtonsFrontScreen(translate, nickname, 'links', authorized, iconsAsButtons, iconsPath) + '
' if linksExist(baseDir): htmlStr += \ getLeftColumnContent(baseDir, nickname, domainFull, httpPrefix, translate, iconsPath, editor, False, timelinePath, rssIconAtTop, False, False) else: if editor: htmlStr += '


\n' htmlStr += '
\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) -> str: """Shows the edit links screen """ if '/users/' not in path: return '' path = path.replace('/inbox', '').replace('/outbox', '') path = path.replace('/shares', '') 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) editLinksForm = htmlHeaderWithExternalStyle(cssFilename) # top banner editLinksForm += \ '\n' editLinksForm += '\n' editLinksForm += \ '
\n' editLinksForm += \ '
\n' editLinksForm += \ '

' + translate['Edit Links'] + '

' editLinksForm += \ '
\n' editLinksForm += \ '
\n' + \ ' \n' + \ '
\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.txt' 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.txt' 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