__filename__ = "webapp_person_options.py" __author__ = "Bob Mottram" __license__ = "AGPL3+" __version__ = "1.2.0" __maintainer__ = "Bob Mottram" __email__ = "bob@libreserver.org" __status__ = "Production" __module_group__ = "Web Interface" import os from shutil import copyfile from petnames import getPetName from person import isPersonSnoozed from posts import isModerator from utils import get_full_domain from utils import get_config_param from utils import is_dormant from utils import remove_html from utils import get_domain_from_actor from utils import get_nickname_from_actor from utils import is_featured_writer from utils import acct_dir from blocking import isBlocked from follow import isFollowerOfPerson from follow import isFollowingActor from followingCalendar import receivingCalendarEvents from notifyOnPost import notifyWhenPersonPosts from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlFooter from webapp_utils import getBrokenLinkSubstitute from webapp_utils import htmlKeyboardNavigation def htmlPersonOptions(defaultTimeline: str, css_cache: {}, translate: {}, base_dir: str, domain: str, domain_full: str, originPathStr: str, optionsActor: str, optionsProfileUrl: str, optionsLink: str, pageNumber: int, donateUrl: str, webAddress: str, xmppAddress: str, matrixAddress: str, ssbAddress: str, blogAddress: str, toxAddress: str, briarAddress: str, jamiAddress: str, cwtchAddress: str, EnigmaPubKey: str, PGPpubKey: str, PGPfingerprint: str, emailAddress: str, dormant_months: int, backToPath: str, lockedAccount: bool, movedTo: str, alsoKnownAs: [], text_mode_banner: str, news_instance: bool, authorized: bool, accessKeys: {}, isGroup: bool) -> str: """Show options for a person: view/follow/block/report """ optionsDomain, optionsPort = get_domain_from_actor(optionsActor) optionsDomainFull = get_full_domain(optionsDomain, optionsPort) if os.path.isfile(base_dir + '/accounts/options-background-custom.jpg'): if not os.path.isfile(base_dir + '/accounts/options-background.jpg'): copyfile(base_dir + '/accounts/options-background.jpg', base_dir + '/accounts/options-background.jpg') dormant = False followStr = 'Follow' if isGroup: followStr = 'Join' blockStr = 'Block' nickname = None optionsNickname = None followsYou = False if originPathStr.startswith('/users/'): nickname = originPathStr.split('/users/')[1] if '/' in nickname: nickname = nickname.split('/')[0] if '?' in nickname: nickname = nickname.split('?')[0] followerDomain, followerPort = get_domain_from_actor(optionsActor) if isFollowingActor(base_dir, nickname, domain, optionsActor): followStr = 'Unfollow' if isGroup: followStr = 'Leave' dormant = \ is_dormant(base_dir, nickname, domain, optionsActor, dormant_months) optionsNickname = get_nickname_from_actor(optionsActor) optionsDomainFull = get_full_domain(optionsDomain, optionsPort) followsYou = \ isFollowerOfPerson(base_dir, nickname, domain, optionsNickname, optionsDomainFull) if isBlocked(base_dir, nickname, domain, optionsNickname, optionsDomainFull): blockStr = 'Block' optionsLinkStr = '' if optionsLink: optionsLinkStr = \ ' \n' cssFilename = base_dir + '/epicyon-options.css' if os.path.isfile(base_dir + '/options.css'): cssFilename = base_dir + '/options.css' # To snooze, or not to snooze? That is the question snoozeButtonStr = 'Snooze' if nickname: if isPersonSnoozed(base_dir, nickname, domain, optionsActor): snoozeButtonStr = 'Unsnooze' donateStr = '' if donateUrl: donateStr = \ ' \n' instanceTitle = \ get_config_param(base_dir, 'instanceTitle') optionsStr = htmlHeaderWithExternalStyle(cssFilename, instanceTitle, None) optionsStr += htmlKeyboardNavigation(text_mode_banner, {}, {}) optionsStr += '

\n' optionsStr += '
\n' optionsStr += '
\n' optionsStr += '
\n' optionsStr += ' \n' optionsStr += ' \n' handle = get_nickname_from_actor(optionsActor) + '@' + optionsDomain handleShown = handle if lockedAccount: handleShown += '🔒' if movedTo: handleShown += ' ⌂' if dormant: handleShown += ' 💤' optionsStr += \ '

' + translate['Options for'] + \ ' @' + handleShown + '

\n' if followsYou: optionsStr += \ '

' + translate['Follows you'] + '

\n' if movedTo: newNickname = get_nickname_from_actor(movedTo) newDomain, newPort = get_domain_from_actor(movedTo) if newNickname and newDomain: newHandle = newNickname + '@' + newDomain optionsStr += \ '

' + \ translate['New account'] + \ ': @' + newHandle + '

\n' elif alsoKnownAs: otherAccountsHtml = \ '

' + \ translate['Other accounts'] + ': ' ctr = 0 if isinstance(alsoKnownAs, list): for altActor in alsoKnownAs: if altActor == optionsActor: continue if ctr > 0: otherAccountsHtml += ' ' ctr += 1 altDomain, altPort = get_domain_from_actor(altActor) otherAccountsHtml += \ '' + altDomain + '' elif isinstance(alsoKnownAs, str): if alsoKnownAs != optionsActor: ctr += 1 altDomain, altPort = get_domain_from_actor(alsoKnownAs) otherAccountsHtml += \ '' + altDomain + '' otherAccountsHtml += '

\n' if ctr > 0: optionsStr += otherAccountsHtml if emailAddress: optionsStr += \ '

' + translate['Email'] + \ ': ' + remove_html(emailAddress) + '

\n' if xmppAddress: optionsStr += \ '

' + translate['XMPP'] + \ ': ' + \ xmppAddress + '

\n' if matrixAddress: optionsStr += \ '

' + translate['Matrix'] + ': ' + \ remove_html(matrixAddress) + '

\n' if ssbAddress: optionsStr += \ '

SSB: ' + remove_html(ssbAddress) + '

\n' if blogAddress: optionsStr += \ '

Blog: ' + \ remove_html(blogAddress) + '

\n' if toxAddress: optionsStr += \ '

Tox: ' + remove_html(toxAddress) + '

\n' if briarAddress: if briarAddress.startswith('briar://'): optionsStr += \ '

' + \ remove_html(briarAddress) + '

\n' else: optionsStr += \ '

briar://' + \ remove_html(briarAddress) + '

\n' if jamiAddress: optionsStr += \ '

Jami: ' + remove_html(jamiAddress) + '

\n' if cwtchAddress: optionsStr += \ '

Cwtch: ' + remove_html(cwtchAddress) + '

\n' if EnigmaPubKey: optionsStr += \ '

Enigma: ' + remove_html(EnigmaPubKey) + '

\n' if PGPfingerprint: optionsStr += '

PGP: ' + \ remove_html(PGPfingerprint).replace('\n', '
') + '

\n' if PGPpubKey: optionsStr += '

' + \ remove_html(PGPpubKey).replace('\n', '
') + '

\n' optionsStr += '
\n' optionsStr += ' \n' optionsStr += ' \n' optionsStr += ' \n' if authorized: if originPathStr == '/users/' + nickname: if optionsNickname: # handle = optionsNickname + '@' + optionsDomainFull petname = getPetName(base_dir, nickname, domain, handle) optionsStr += \ ' ' + translate['Petname'] + ': \n' + \ ' \n' \ '
\n' # Notify when a post arrives from this person if isFollowingActor(base_dir, nickname, domain, optionsActor): checkboxStr = \ ' 🔔' + \ translate['Notify me when this account posts'] + \ '\n
\n' if not notifyWhenPersonPosts(base_dir, nickname, domain, optionsNickname, optionsDomainFull): checkboxStr = checkboxStr.replace(' checked>', '>') optionsStr += checkboxStr checkboxStr = \ ' ' + \ translate['Receive calendar events from this account'] + \ '\n
\n' if not receivingCalendarEvents(base_dir, nickname, domain, optionsNickname, optionsDomainFull): checkboxStr = checkboxStr.replace(' checked>', '>') optionsStr += checkboxStr # checkbox for permission to post to newswire newswirePostsPermitted = False if optionsDomainFull == domain_full: adminNickname = get_config_param(base_dir, 'admin') if (nickname == adminNickname or (isModerator(base_dir, nickname) and not isModerator(base_dir, optionsNickname))): newswireBlockedFilename = \ base_dir + '/accounts/' + \ optionsNickname + '@' + optionsDomain + '/.nonewswire' checkboxStr = \ ' ' + \ translate['Allow news posts'] + \ '\n
\n' if os.path.isfile(newswireBlockedFilename): checkboxStr = checkboxStr.replace(' checked>', '>') else: newswirePostsPermitted = True optionsStr += checkboxStr # whether blogs created by this account are moderated on # the newswire if newswirePostsPermitted: moderatedFilename = \ base_dir + '/accounts/' + \ optionsNickname + '@' + \ optionsDomain + '/.newswiremoderated' checkboxStr = \ ' ' + \ translate['News posts are moderated'] + \ '\n
\n' if not os.path.isfile(moderatedFilename): checkboxStr = checkboxStr.replace(' checked>', '>') optionsStr += checkboxStr # checkbox for permission to post to featured articles if news_instance and optionsDomainFull == domain_full: adminNickname = get_config_param(base_dir, 'admin') if (nickname == adminNickname or (isModerator(base_dir, nickname) and not isModerator(base_dir, optionsNickname))): checkboxStr = \ ' ' + \ translate['Featured writer'] + \ '\n
\n' if not is_featured_writer(base_dir, optionsNickname, optionsDomain): checkboxStr = checkboxStr.replace(' checked>', '>') optionsStr += checkboxStr optionsStr += optionsLinkStr backPath = '/' if nickname: backPath = '/users/' + nickname + '/' + defaultTimeline if 'moderation' in backToPath: backPath = '/users/' + nickname + '/moderation' if authorized and originPathStr == '/users/' + nickname: optionsStr += \ ' \n' else: optionsStr += \ ' \n' if authorized: optionsStr += \ ' \n' optionsStr += donateStr if authorized: optionsStr += \ ' \n' optionsStr += \ ' \n' optionsStr += \ ' \n' optionsStr += \ ' \n' optionsStr += \ ' \n' if isModerator(base_dir, nickname): optionsStr += \ ' \n' personNotes = '' if originPathStr == '/users/' + nickname: personNotesFilename = \ acct_dir(base_dir, nickname, domain) + \ '/notes/' + handle + '.txt' if os.path.isfile(personNotesFilename): with open(personNotesFilename, 'r') as fp: personNotes = fp.read() optionsStr += \ '

' + translate['Notes'] + ': \n' optionsStr += '
\n' optionsStr += \ ' \n' optionsStr += \ '
\n' + \ '
\n' + \ '
\n' + \ '
\n' optionsStr += htmlFooter() return optionsStr