__filename__ = "webapp_column_left.py" __author__ = "Bob Mottram" __license__ = "AGPL3+" __version__ = "1.2.0" __maintainer__ = "Bob Mottram" __email__ = "bob@libreserver.org" __status__ = "Production" __module_group__ = "Web Interface Columns" import os from utils import get_config_param from utils import get_nickname_from_actor from utils import is_editor from utils import is_artist from utils import remove_domain_port from utils import local_actor_url from webapp_utils import shares_timeline_json from webapp_utils import html_post_separator from webapp_utils import get_left_image_file from webapp_utils import header_buttons_front_screen from webapp_utils import html_header_with_external_style from webapp_utils import html_footer from webapp_utils import get_banner_file from webapp_utils import edit_text_field from shares import share_category_icon def _links_exist(base_dir: str) -> bool: """Returns true if links have been created """ linksFilename = base_dir + '/accounts/links.txt' return os.path.isfile(linksFilename) def _get_left_column_shares(base_dir: str, http_prefix: str, domain: str, domain_full: str, nickname: str, maxSharesInLeftColumn: int, translate: {}, shared_items_federated_domains: []) -> []: """get any shares and turn them into the left column links format """ pageNumber = 1 actor = local_actor_url(http_prefix, nickname, domain_full) # NOTE: this could potentially be slow if the number of federated # shared items is large sharesJson, lastPage = \ shares_timeline_json(actor, pageNumber, maxSharesInLeftColumn, base_dir, domain, nickname, maxSharesInLeftColumn, shared_items_federated_domains, '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 html_show_share shareLink = actor + '?showshare=' + shareId if item.get('category'): shareLink += '?category=' + item['category'] shareCategory = share_category_icon(item['category']) linksList.append(shareCategory + sharedesc + ' ' + shareLink) ctr += 1 if ctr >= maxSharesInLeftColumn: break if linksList: linksList = ['* ' + translate['Shares']] + linksList return linksList def _get_left_column_wanted(base_dir: str, http_prefix: str, domain: str, domain_full: str, nickname: str, maxSharesInLeftColumn: int, translate: {}, shared_items_federated_domains: []) -> []: """get any wanted items and turn them into the left column links format """ pageNumber = 1 actor = local_actor_url(http_prefix, nickname, domain_full) # NOTE: this could potentially be slow if the number of federated # wanted items is large sharesJson, lastPage = \ shares_timeline_json(actor, pageNumber, maxSharesInLeftColumn, base_dir, domain, nickname, maxSharesInLeftColumn, shared_items_federated_domains, '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 html_show_share shareLink = actor + '?showwanted=' + shareId linksList.append(sharedesc + ' ' + shareLink) ctr += 1 if ctr >= maxSharesInLeftColumn: break if linksList: linksList = ['* ' + translate['Wanted']] + linksList return linksList def get_left_column_content(base_dir: str, nickname: str, domain_full: str, http_prefix: str, translate: {}, editor: bool, artist: bool, showBackButton: bool, timelinePath: str, rss_icon_at_top: bool, showHeaderImage: bool, frontPage: bool, theme: str, accessKeys: {}, shared_items_federated_domains: []) -> str: """Returns html content for the left column """ htmlStr = '' separatorStr = html_post_separator(base_dir, 'left') domain = remove_domain_port(domain_full) editImageClass = '' if showHeaderImage: leftImageFile, leftColumnImageFilename = \ get_left_image_file(base_dir, 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 rss_icon_at_top) and not showHeaderImage: htmlStr += '
' if editImageClass == 'leftColEdit': htmlStr += '\n
\n' htmlStr += '
\n' if editor: # show the edit icon htmlStr += \ ' ' + \ '' + \
            translate['Edit Links'] + ' | \n' if artist: # show the theme designer icon htmlStr += \ ' ' + \ '' + \
            translate['Theme Designer'] + ' | \n' # RSS icon if nickname != 'news': # rss feed for this account rssUrl = http_prefix + '://' + domain_full + \ '/blog/' + nickname + '/rss.xml' else: # rss feed for all accounts on the instance rssUrl = http_prefix + '://' + domain_full + '/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 rss_icon_at_top: htmlStr += rssIconStr htmlStr += '
\n' if editImageClass == 'leftColEdit': htmlStr += '
\n' if (editor or rss_icon_at_top) and not showHeaderImage: htmlStr += '

' # if showHeaderImage: # htmlStr += '
' # flag used not to show the first separator firstSeparatorAdded = False linksFilename = base_dir + '/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 = \ _get_left_column_shares(base_dir, http_prefix, domain, domain_full, nickname, maxSharesInLeftColumn, translate, shared_items_federated_domains) if linksList and sharesList: linksList = sharesList + linksList wantedList = \ _get_left_column_wanted(base_dir, http_prefix, domain, domain_full, nickname, maxSharesInLeftColumn, translate, shared_items_federated_domains) 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 rss_icon_at_top: htmlStr += '
' + rssIconStr + '
' return htmlStr def html_links_mobile(css_cache: {}, base_dir: str, nickname: str, domain_full: str, http_prefix: str, translate, timelinePath: str, authorized: bool, rss_icon_at_top: bool, icons_as_buttons: bool, defaultTimeline: str, theme: str, accessKeys: {}, shared_items_federated_domains: []) -> str: """Show the left column links within mobile view """ htmlStr = '' # the css filename cssFilename = base_dir + '/epicyon-profile.css' if os.path.isfile(base_dir + '/epicyon.css'): cssFilename = base_dir + '/epicyon.css' # is the user a site editor? if nickname == 'news': editor = False artist = False else: editor = is_editor(base_dir, nickname) artist = is_artist(base_dir, nickname) domain = remove_domain_port(domain_full) instanceTitle = \ get_config_param(base_dir, 'instanceTitle') htmlStr = html_header_with_external_style(cssFilename, instanceTitle, None) bannerFile, bannerFilename = \ get_banner_file(base_dir, nickname, domain, theme) htmlStr += \ '' + \ '\n' htmlStr += '
\n' htmlStr += '
' + \ header_buttons_front_screen(translate, nickname, 'links', authorized, icons_as_buttons) + '
' htmlStr += \ get_left_column_content(base_dir, nickname, domain_full, http_prefix, translate, editor, artist, False, timelinePath, rss_icon_at_top, False, False, theme, accessKeys, shared_items_federated_domains) if editor and not _links_exist(base_dir): 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' + html_footer() return htmlStr def html_edit_links(css_cache: {}, translate: {}, base_dir: str, path: str, domain: str, port: int, http_prefix: 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 = get_nickname_from_actor(path) if not nickname: return '' # is the user a moderator? if not is_editor(base_dir, nickname): return '' cssFilename = base_dir + '/epicyon-links.css' if os.path.isfile(base_dir + '/links.css'): cssFilename = base_dir + '/links.css' # filename of the banner shown at the top bannerFile, bannerFilename = \ get_banner_file(base_dir, nickname, domain, theme) instanceTitle = \ get_config_param(base_dir, 'instanceTitle') editLinksForm = \ html_header_with_external_style(cssFilename, instanceTitle, None) # top banner editLinksForm += \ '
\n' + \ '\n' editLinksForm += \ '\n' + \ '
\n' editLinksForm += \ '
\n' editLinksForm += \ '
\n' editLinksForm += \ '
\n' editLinksForm += \ '

' + translate['Edit Links'] + '

' editLinksForm += \ ' \n' editLinksForm += \ '
\n' linksFilename = base_dir + '/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.'] + \ '
' newColLinkStr = translate['New link title and URL'] editLinksForm += edit_text_field(None, 'newColLink', '', newColLinkStr) editLinksForm += \ ' ' editLinksForm += \ '
' # the admin can edit terms of service and about text adminNickname = get_config_param(base_dir, 'admin') if adminNickname: if nickname == adminNickname: aboutFilename = base_dir + '/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 = base_dir + '/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 += html_footer() return editLinksForm