epicyon/webapp_profile.py

2524 lines
105 KiB
Python
Raw Normal View History

2020-11-09 22:44:03 +00:00
__filename__ = "webapp_profile.py"
__author__ = "Bob Mottram"
__license__ = "AGPL3+"
2022-02-03 13:58:20 +00:00
__version__ = "1.3.0"
2020-11-09 22:44:03 +00:00
__maintainer__ = "Bob Mottram"
2021-09-10 16:14:50 +00:00
__email__ = "bob@libreserver.org"
2020-11-09 22:44:03 +00:00
__status__ = "Production"
2021-06-15 15:08:12 +00:00
__module_group__ = "Web Interface"
2020-11-09 22:44:03 +00:00
import os
from pprint import pprint
2021-12-29 21:55:09 +00:00
from webfinger import webfinger_handle
2021-12-27 21:59:07 +00:00
from utils import get_display_name
2021-12-26 17:33:24 +00:00
from utils import is_group_account
2021-12-26 10:57:03 +00:00
from utils import has_object_dict
2021-12-26 18:58:06 +00:00
from utils import get_occupation_name
2021-12-26 12:16:36 +00:00
from utils import get_locked_account
2021-12-26 12:45:03 +00:00
from utils import get_full_domain
2021-12-26 14:17:13 +00:00
from utils import is_artist
2021-12-26 12:54:51 +00:00
from utils import is_dormant
2021-12-27 22:19:18 +00:00
from utils import get_nickname_from_actor
2021-12-27 19:05:25 +00:00
from utils import get_domain_from_actor
2021-12-27 15:41:04 +00:00
from utils import is_system_account
2021-12-27 15:43:22 +00:00
from utils import remove_html
2021-12-26 15:13:34 +00:00
from utils import load_json
2021-12-26 14:08:58 +00:00
from utils import get_config_param
2021-12-26 15:44:28 +00:00
from utils import get_image_formats
2021-12-26 12:02:29 +00:00
from utils import acct_dir
2021-12-26 17:26:55 +00:00
from utils import get_supported_languages
2021-12-26 10:19:59 +00:00
from utils import local_actor_url
2021-12-28 10:25:50 +00:00
from utils import get_reply_interval_hours
2022-02-25 19:57:31 +00:00
from utils import get_account_timezone
2021-12-29 21:55:09 +00:00
from languages import get_actor_languages
from skills import get_skills
from theme import get_themes_list
2021-12-28 16:50:20 +00:00
from person import person_box_json
2021-12-29 21:55:09 +00:00
from person import get_actor_json
from person import get_person_avatar_url
from posts import get_person_box
2021-12-28 19:33:29 +00:00
from posts import is_moderator
2021-12-29 21:55:09 +00:00
from posts import parse_user_feed
from posts import is_create_inside_announce
2021-12-28 18:13:52 +00:00
from donate import get_donation_url
from donate import get_website
2021-12-28 17:33:54 +00:00
from xmpp import get_xmpp_address
2021-12-28 18:13:52 +00:00
from matrix import get_matrix_address
2021-12-28 17:33:54 +00:00
from ssb import get_ssb_address
from pgp import get_email_address
from pgp import get_pgp_fingerprint
from pgp import get_pgp_pub_key
2021-12-28 17:20:43 +00:00
from enigma import get_enigma_pub_key
2021-12-28 17:33:54 +00:00
from tox import get_tox_address
from briar import get_briar_address
from jami import get_jami_address
from cwtch import get_cwtch_address
2021-12-29 21:55:09 +00:00
from filters import is_filtered
from follow import is_follower_of_person
from follow import get_follower_domains
from webapp_frontscreen import html_front_screen
from webapp_utils import html_keyboard_navigation
from webapp_utils import html_hide_from_screen_reader
from webapp_utils import scheduled_posts_exist
from webapp_utils import html_header_with_external_style
from webapp_utils import html_header_with_person_markup
from webapp_utils import html_footer
from webapp_utils import add_emoji_to_display_name
from webapp_utils import get_banner_file
from webapp_utils import html_post_separator
from webapp_utils import edit_check_box
from webapp_utils import edit_text_field
from webapp_utils import edit_text_area
from webapp_utils import begin_edit_section
from webapp_utils import end_edit_section
2021-12-28 22:22:09 +00:00
from blog import get_blog_address
2021-12-29 21:55:09 +00:00
from webapp_post import individual_post_as_html
from webapp_timeline import html_individual_share
2021-12-28 21:55:38 +00:00
from blocking import get_cw_list_variable
2022-03-24 13:14:41 +00:00
from content import bold_reading_string
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
THEME_FORMATS = '.zip, .gz'
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _valid_profile_preview_post(post_json_object: {},
2021-12-30 23:46:06 +00:00
person_url: str) -> (bool, {}):
2021-11-19 13:47:02 +00:00
"""Returns true if the given post should appear on a person/group profile
after searching for a handle
"""
2021-12-30 23:46:06 +00:00
is_announced_feed_item = False
2021-12-29 21:55:09 +00:00
if is_create_inside_announce(post_json_object):
2021-12-30 23:46:06 +00:00
is_announced_feed_item = True
2021-12-25 22:09:19 +00:00
post_json_object = post_json_object['object']
if not post_json_object.get('type'):
2021-11-19 13:47:02 +00:00
return False, None
2021-12-25 22:09:19 +00:00
if post_json_object['type'] == 'Create':
2021-12-26 10:57:03 +00:00
if not has_object_dict(post_json_object):
2021-11-19 13:47:02 +00:00
return False, None
2021-12-25 22:09:19 +00:00
if post_json_object['type'] != 'Create' and \
post_json_object['type'] != 'Announce':
if post_json_object['type'] != 'Note' and \
post_json_object['type'] != 'Page':
2021-11-19 13:47:02 +00:00
return False, None
2021-12-25 22:09:19 +00:00
if not post_json_object.get('to'):
2021-11-19 13:47:02 +00:00
return False, None
2021-12-25 22:09:19 +00:00
if not post_json_object.get('id'):
2021-11-19 13:47:02 +00:00
return False, None
# wrap in create
2021-12-30 23:46:06 +00:00
cc_list = []
2021-12-25 22:09:19 +00:00
if post_json_object.get('cc'):
2021-12-30 23:46:06 +00:00
cc_list = post_json_object['cc']
new_post_json_object = {
2021-12-25 22:09:19 +00:00
'object': post_json_object,
'to': post_json_object['to'],
2021-12-30 23:46:06 +00:00
'cc': cc_list,
2021-12-25 22:09:19 +00:00
'id': post_json_object['id'],
2021-12-30 23:46:06 +00:00
'actor': person_url,
2021-11-19 13:47:02 +00:00
'type': 'Create'
}
2021-12-30 23:46:06 +00:00
post_json_object = new_post_json_object
2021-12-25 22:09:19 +00:00
if not post_json_object.get('actor'):
2021-11-19 13:47:02 +00:00
return False, None
2021-12-30 23:46:06 +00:00
if not is_announced_feed_item:
2022-03-12 20:09:43 +00:00
if has_object_dict(post_json_object):
if post_json_object['actor'] != person_url and \
post_json_object['object']['type'] != 'Page':
return False, None
2021-12-25 22:09:19 +00:00
return True, post_json_object
2021-11-19 13:47:02 +00:00
2021-12-29 21:55:09 +00:00
def html_profile_after_search(css_cache: {},
recent_posts_cache: {}, max_recent_posts: int,
translate: {},
base_dir: str, path: str, http_prefix: str,
nickname: str, domain: str, port: int,
2021-12-30 23:46:06 +00:00
profile_handle: str,
2021-12-29 21:55:09 +00:00
session, cached_webfingers: {}, person_cache: {},
debug: bool, project_version: str,
yt_replace_domain: str,
twitter_replacement_domain: str,
show_published_date_only: bool,
2021-12-30 23:46:06 +00:00
default_timeline: str,
2021-12-29 21:55:09 +00:00
peertube_instances: [],
allow_local_network_access: bool,
theme_name: str,
2021-12-30 23:46:06 +00:00
access_keys: {},
2021-12-29 21:55:09 +00:00
system_language: str,
max_like_count: int,
signing_priv_key_pem: str,
2022-02-25 19:12:40 +00:00
cw_lists: {}, lists_enabled: str,
timezone: str,
2022-03-24 13:14:41 +00:00
onion_domain: str, i2p_domain: str,
bold_reading: bool) -> str:
2020-11-09 22:44:03 +00:00
"""Show a profile page after a search for a fediverse address
"""
2021-06-03 19:46:35 +00:00
http = False
gnunet = False
2021-12-25 17:09:22 +00:00
if http_prefix == 'http':
2021-06-03 19:46:35 +00:00
http = True
2021-12-25 17:09:22 +00:00
elif http_prefix == 'gnunet':
2021-06-03 19:46:35 +00:00
gnunet = True
from_domain = domain
if onion_domain:
if '.onion/' in profile_handle or profile_handle.endswith('.onion'):
from_domain = onion_domain
http = True
if i2p_domain:
if '.i2p/' in profile_handle or profile_handle.endswith('.i2p'):
from_domain = i2p_domain
http = True
2021-12-30 23:46:06 +00:00
profile_json, as_header = \
get_actor_json(from_domain, profile_handle, http, gnunet, debug, False,
2021-12-29 21:55:09 +00:00
signing_priv_key_pem, session)
2021-12-26 10:08:06 +00:00
if not profile_json:
2020-11-09 22:44:03 +00:00
return None
2021-12-30 23:46:06 +00:00
person_url = profile_json['id']
search_domain, search_port = get_domain_from_actor(person_url)
if not search_domain:
return None
2021-12-30 23:46:06 +00:00
search_nickname = get_nickname_from_actor(person_url)
if not search_nickname:
return None
2021-12-30 23:46:06 +00:00
search_domain_full = get_full_domain(search_domain, search_port)
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
profile_str = ''
css_filename = base_dir + '/epicyon-profile.css'
2021-12-25 16:17:53 +00:00
if os.path.isfile(base_dir + '/epicyon.css'):
2021-12-30 23:46:06 +00:00
css_filename = base_dir + '/epicyon.css'
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
is_group = False
2021-12-26 10:08:06 +00:00
if profile_json.get('type'):
if profile_json['type'] == 'Group':
2021-12-30 23:46:06 +00:00
is_group = True
2021-09-21 18:57:12 +00:00
2021-12-30 23:46:06 +00:00
avatar_url = ''
2021-12-26 10:08:06 +00:00
if profile_json.get('icon'):
if profile_json['icon'].get('url'):
2021-12-30 23:46:06 +00:00
avatar_url = profile_json['icon']['url']
if not avatar_url:
avatar_url = get_person_avatar_url(base_dir, person_url,
person_cache, True)
display_name = search_nickname
2021-12-26 10:08:06 +00:00
if profile_json.get('name'):
2021-12-30 23:46:06 +00:00
display_name = profile_json['name']
2021-12-30 23:46:06 +00:00
locked_account = get_locked_account(profile_json)
if locked_account:
display_name += '🔒'
moved_to = ''
2021-12-26 10:08:06 +00:00
if profile_json.get('movedTo'):
2021-12-30 23:46:06 +00:00
moved_to = profile_json['movedTo']
if '"' in moved_to:
moved_to = moved_to.split('"')[1]
display_name += ''
2021-12-30 23:46:06 +00:00
follows_you = \
2021-12-29 21:55:09 +00:00
is_follower_of_person(base_dir,
nickname, domain,
2021-12-30 23:46:06 +00:00
search_nickname,
search_domain_full)
2021-12-30 23:46:06 +00:00
profile_description = ''
2021-12-26 10:08:06 +00:00
if profile_json.get('summary'):
2021-12-30 23:46:06 +00:00
profile_description = profile_json['summary']
outbox_url = None
2021-12-26 10:08:06 +00:00
if not profile_json.get('outbox'):
2020-11-12 17:05:38 +00:00
if debug:
2021-12-26 10:08:06 +00:00
pprint(profile_json)
2020-11-12 17:05:38 +00:00
print('DEBUG: No outbox found')
return None
2021-12-30 23:46:06 +00:00
outbox_url = profile_json['outbox']
2020-11-12 17:05:38 +00:00
# profileBackgroundImage = ''
2021-12-26 10:08:06 +00:00
# if profile_json.get('image'):
# if profile_json['image'].get('url'):
# profileBackgroundImage = profile_json['image']['url']
2020-11-12 17:05:38 +00:00
# url to return to
2021-12-30 23:46:06 +00:00
back_url = path
if not back_url.endswith('/inbox'):
back_url += '/inbox'
profile_description_short = profile_description
if '\n' in profile_description:
if len(profile_description.split('\n')) > 2:
profile_description_short = ''
2020-11-12 17:05:38 +00:00
else:
2021-12-30 23:46:06 +00:00
if '<br>' in profile_description:
if len(profile_description.split('<br>')) > 2:
profile_description_short = ''
2020-11-12 17:05:38 +00:00
# keep the profile description short
2021-12-30 23:46:06 +00:00
if len(profile_description_short) > 256:
profile_description_short = ''
2020-11-12 17:05:38 +00:00
# remove formatting from profile description used on title
2021-12-30 23:46:06 +00:00
avatar_description = ''
2021-12-26 10:08:06 +00:00
if profile_json.get('summary'):
if isinstance(profile_json['summary'], str):
2021-12-30 23:46:06 +00:00
avatar_description = \
2021-12-26 10:08:06 +00:00
profile_json['summary'].replace('<br>', '\n')
2021-12-30 23:46:06 +00:00
avatar_description = avatar_description.replace('<p>', '')
avatar_description = avatar_description.replace('</p>', '')
if '<' in avatar_description:
avatar_description = remove_html(avatar_description)
2020-11-12 22:41:41 +00:00
2021-12-30 23:46:06 +00:00
image_url = ''
2021-12-26 10:08:06 +00:00
if profile_json.get('image'):
if profile_json['image'].get('url'):
2021-12-30 23:46:06 +00:00
image_url = profile_json['image']['url']
2020-11-12 23:44:16 +00:00
2021-12-30 23:46:06 +00:00
also_known_as = None
2021-12-26 10:08:06 +00:00
if profile_json.get('alsoKnownAs'):
2021-12-30 23:46:06 +00:00
also_known_as = profile_json['alsoKnownAs']
2021-01-22 20:48:52 +00:00
2021-12-30 23:46:06 +00:00
joined_date = None
2021-12-26 10:08:06 +00:00
if profile_json.get('published'):
if 'T' in profile_json['published']:
2021-12-30 23:46:06 +00:00
joined_date = profile_json['published']
2021-12-30 23:46:06 +00:00
profile_str = \
2021-12-29 21:55:09 +00:00
_get_profile_header_after_search(base_dir,
2021-12-30 23:46:06 +00:00
nickname, default_timeline,
search_nickname,
search_domain_full,
2021-12-29 21:55:09 +00:00
translate,
2021-12-30 23:46:06 +00:00
display_name, follows_you,
profile_description_short,
avatar_url, image_url,
moved_to, profile_json['id'],
also_known_as, access_keys,
joined_date)
2020-11-12 22:41:41 +00:00
2021-12-26 12:45:03 +00:00
domain_full = get_full_domain(domain, port)
2020-11-20 12:14:22 +00:00
2021-12-30 23:46:06 +00:00
follow_is_permitted = True
2021-12-26 10:08:06 +00:00
if not profile_json.get('followers'):
# no followers collection specified within actor
2021-12-30 23:46:06 +00:00
follow_is_permitted = False
elif search_nickname == 'news' and search_domain_full == domain_full:
2020-11-20 12:20:34 +00:00
# currently the news actor is not something you can follow
2021-12-30 23:46:06 +00:00
follow_is_permitted = False
elif search_nickname == nickname and search_domain_full == domain_full:
2020-11-20 12:20:34 +00:00
# don't follow yourself!
2021-12-30 23:46:06 +00:00
follow_is_permitted = False
2020-11-20 12:20:34 +00:00
2021-12-30 23:46:06 +00:00
if follow_is_permitted:
follow_str = 'Follow'
if is_group:
follow_str = 'Join'
2021-09-21 18:57:12 +00:00
2021-12-30 23:46:06 +00:00
profile_str += \
2021-07-22 10:22:01 +00:00
'<div class="container">\n' + \
' <form method="POST" action="' + \
2021-12-30 23:46:06 +00:00
back_url + '/followconfirm">\n' + \
2021-07-22 10:22:01 +00:00
' <center>\n' + \
2020-11-20 12:14:22 +00:00
' <input type="hidden" name="actor" value="' + \
2021-12-30 23:46:06 +00:00
person_url + '">\n' + \
2021-04-23 12:04:42 +00:00
' <button type="submit" class="button" name="submitYes" ' + \
2021-12-30 23:46:06 +00:00
'accesskey="' + access_keys['followButton'] + '">' + \
translate[follow_str] + '</button>\n' + \
2021-07-28 14:02:07 +00:00
' <button type="submit" class="button" name="submitView" ' + \
2021-12-30 23:46:06 +00:00
'accesskey="' + access_keys['viewButton'] + '">' + \
2021-07-28 14:02:07 +00:00
translate['View'] + '</button>\n' + \
' </center>\n' + \
' </form>\n' + \
'</div>\n'
else:
2021-12-30 23:46:06 +00:00
profile_str += \
2021-07-28 14:02:07 +00:00
'<div class="container">\n' + \
' <form method="POST" action="' + \
2021-12-30 23:46:06 +00:00
back_url + '/followconfirm">\n' + \
2021-07-28 14:02:07 +00:00
' <center>\n' + \
' <input type="hidden" name="actor" value="' + \
2021-12-30 23:46:06 +00:00
person_url + '">\n' + \
2021-07-28 14:02:07 +00:00
' <button type="submit" class="button" name="submitView" ' + \
2021-12-30 23:46:06 +00:00
'accesskey="' + access_keys['viewButton'] + '">' + \
2021-07-28 14:02:07 +00:00
translate['View'] + '</button>\n' + \
' </center>\n' + \
' </form>\n' + \
'</div>\n'
2020-11-12 17:05:38 +00:00
2021-12-30 23:46:06 +00:00
user_feed = \
2021-12-29 21:55:09 +00:00
parse_user_feed(signing_priv_key_pem,
2021-12-30 23:46:06 +00:00
session, outbox_url, as_header, project_version,
http_prefix, from_domain, debug)
2021-12-30 23:46:06 +00:00
if user_feed:
2021-08-02 20:17:55 +00:00
i = 0
2021-12-30 23:46:06 +00:00
for item in user_feed:
show_item, post_json_object = \
_valid_profile_preview_post(item, person_url)
if not show_item:
continue
2020-12-18 18:12:33 +00:00
2021-12-30 23:46:06 +00:00
profile_str += \
2021-12-29 21:55:09 +00:00
individual_post_as_html(signing_priv_key_pem,
True, recent_posts_cache,
max_recent_posts,
translate, None, base_dir,
session, cached_webfingers,
person_cache,
nickname, domain, port,
2021-12-30 23:46:06 +00:00
post_json_object, avatar_url,
2021-12-29 21:55:09 +00:00
False, False,
http_prefix, project_version, 'inbox',
yt_replace_domain,
twitter_replacement_domain,
show_published_date_only,
peertube_instances,
allow_local_network_access,
theme_name, system_language,
max_like_count,
False, False, False,
False, False, False,
2022-02-25 19:12:40 +00:00
cw_lists, lists_enabled,
2022-03-24 13:14:41 +00:00
timezone, False,
bold_reading)
2021-08-02 20:17:55 +00:00
i += 1
if i >= 8:
2021-08-02 20:17:55 +00:00
break
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
instance_title = get_config_param(base_dir, 'instanceTitle')
return html_header_with_external_style(css_filename,
instance_title, None) + \
profile_str + html_footer()
2021-12-29 21:55:09 +00:00
def _get_profile_header(base_dir: str, http_prefix: str,
nickname: str, domain: str,
domain_full: str, translate: {},
2021-12-30 23:46:06 +00:00
default_timeline: str,
display_name: str,
avatar_description: str,
profile_description_short: str,
login_button: str, avatar_url: str,
theme: str, moved_to: str,
also_known_as: [],
pinned_content: str,
access_keys: {},
joined_date: str,
occupation_name: str) -> str:
2020-11-12 22:33:00 +00:00
"""The header of the profile screen, containing background
image and avatar
"""
2021-12-30 23:46:06 +00:00
html_str = \
2021-07-22 10:22:01 +00:00
'\n\n <figure class="profileHeader">\n' + \
' <a href="/users/' + \
2021-12-30 23:46:06 +00:00
nickname + '/' + default_timeline + '" title="' + \
2021-07-22 10:22:01 +00:00
translate['Switch to timeline view'] + '">\n' + \
' <img class="profileBackground" ' + \
'alt="" ' + \
2021-07-22 10:22:01 +00:00
'src="/users/' + nickname + '/image_' + theme + '.png" /></a>\n' + \
' <figcaption>\n' + \
2020-11-12 23:17:37 +00:00
' <a href="/users/' + \
2021-12-30 23:46:06 +00:00
nickname + '/' + default_timeline + '" title="' + \
2020-11-12 23:17:37 +00:00
translate['Switch to timeline view'] + '">\n' + \
2022-03-28 08:47:53 +00:00
' <img loading="lazy" decoding="async" ' + \
'src="' + avatar_url + '" alt="" class="title"></a>\n'
2021-05-12 18:31:41 +00:00
2021-12-30 23:46:06 +00:00
occupation_str = ''
if occupation_name:
occupation_str += \
' <b>' + occupation_name + '</b><br>\n'
2021-05-12 18:31:41 +00:00
2021-12-30 23:46:06 +00:00
html_str += ' <h1>' + display_name + '</h1>\n' + occupation_str
2021-05-12 18:31:41 +00:00
2021-12-30 23:46:06 +00:00
html_str += \
2021-12-26 10:00:46 +00:00
' <p><b>@' + nickname + '@' + domain_full + '</b><br>\n'
2021-12-30 23:46:06 +00:00
if joined_date:
html_str += \
2021-05-08 18:00:59 +00:00
' <p>' + translate['Joined'] + ' ' + \
2021-12-30 23:46:06 +00:00
joined_date.split('T')[0] + '<br>\n'
if moved_to:
new_nickname = get_nickname_from_actor(moved_to)
new_domain, new_port = get_domain_from_actor(moved_to)
new_domain_full = get_full_domain(new_domain, new_port)
if new_nickname and new_domain:
html_str += \
' <p>' + translate['New account'] + ': ' + \
2021-12-30 23:46:06 +00:00
'<a href="' + moved_to + '">@' + \
new_nickname + '@' + new_domain_full + '</a><br>\n'
elif also_known_as:
other_accounts_html = \
2021-01-22 20:59:43 +00:00
' <p>' + translate['Other accounts'] + ': '
2021-12-26 10:19:59 +00:00
actor = local_actor_url(http_prefix, nickname, domain_full)
ctr = 0
2021-12-30 23:46:06 +00:00
if isinstance(also_known_as, list):
for alt_actor in also_known_as:
if alt_actor == actor:
continue
2021-01-22 20:59:43 +00:00
if ctr > 0:
2021-12-30 23:46:06 +00:00
other_accounts_html += ' '
2021-01-22 20:59:43 +00:00
ctr += 1
2021-12-30 23:46:06 +00:00
alt_domain, _ = get_domain_from_actor(alt_actor)
other_accounts_html += \
'<a href="' + alt_actor + '">' + alt_domain + '</a>'
elif isinstance(also_known_as, str):
if also_known_as != actor:
ctr += 1
2021-12-30 23:46:06 +00:00
alt_domain, _ = get_domain_from_actor(also_known_as)
other_accounts_html += \
'<a href="' + also_known_as + '">' + alt_domain + '</a>'
other_accounts_html += '</p>\n'
if ctr > 0:
2021-12-30 23:46:06 +00:00
html_str += other_accounts_html
html_str += \
2020-11-12 23:00:36 +00:00
' <a href="/users/' + nickname + \
2020-11-12 22:33:00 +00:00
'/qrcode.png" alt="' + translate['QR Code'] + '" title="' + \
translate['QR Code'] + '">' + \
2021-02-01 18:42:39 +00:00
'<img class="qrcode" alt="' + translate['QR Code'] + \
2021-07-22 10:22:01 +00:00
'" src="/icons/qrcode.png" /></a></p>\n' + \
2021-12-30 23:46:06 +00:00
' <p>' + profile_description_short + '</p>\n' + login_button
if pinned_content:
html_str += pinned_content.replace('<p>', '<p>📎', 1)
# show vcard download link
html_str += \
' <a href="/users/' + nickname + '.vcf" ' + \
'download="contact_' + nickname + '@' + domain_full + '.vcf">' + \
'<img class="vcard" src="/icons/vcard.png" ' + \
'title="vCard" alt="vCard" /></a>\n'
2021-12-30 23:46:06 +00:00
html_str += \
2021-07-22 10:22:01 +00:00
' </figcaption>\n' + \
' </figure>\n\n'
2021-12-30 23:46:06 +00:00
return html_str
2020-11-12 22:33:00 +00:00
2021-12-29 21:55:09 +00:00
def _get_profile_header_after_search(base_dir: str,
2021-12-30 23:46:06 +00:00
nickname: str, default_timeline: str,
search_nickname: str,
search_domain_full: str,
2021-12-29 21:55:09 +00:00
translate: {},
2021-12-30 23:46:06 +00:00
display_name: str,
follows_you: bool,
profile_description_short: str,
avatar_url: str, image_url: str,
moved_to: str, actor: str,
also_known_as: [],
access_keys: {},
joined_date: str) -> str:
2020-11-12 23:38:58 +00:00
"""The header of a searched for handle, containing background
image and avatar
"""
2021-12-30 23:46:06 +00:00
if not image_url:
image_url = '/defaultprofilebackground'
html_str = \
2021-07-22 10:22:01 +00:00
'\n\n <figure class="profileHeader">\n' + \
' <a href="/users/' + \
2021-12-30 23:46:06 +00:00
nickname + '/' + default_timeline + '" title="' + \
2021-04-23 12:04:42 +00:00
translate['Switch to timeline view'] + '" ' + \
2021-12-30 23:46:06 +00:00
'accesskey="' + access_keys['menuTimeline'] + '">\n' + \
2021-07-22 10:22:01 +00:00
' <img class="profileBackground" ' + \
'alt="" ' + \
2021-12-30 23:46:06 +00:00
'src="' + image_url + '" /></a>\n' + \
2021-07-22 10:22:01 +00:00
' <figcaption>\n'
2021-12-30 23:46:06 +00:00
if avatar_url:
html_str += \
2021-07-22 10:22:01 +00:00
' <a href="/users/' + \
2021-12-30 23:46:06 +00:00
nickname + '/' + default_timeline + '" title="' + \
2021-07-22 10:22:01 +00:00
translate['Switch to timeline view'] + '">\n' + \
2022-03-28 08:47:53 +00:00
' <img loading="lazy" decoding="async" src="' + \
avatar_url + '" ' + 'alt="" class="title"></a>\n'
2021-12-30 23:46:06 +00:00
if not display_name:
display_name = search_nickname
html_str += \
' <h1>' + display_name + '</h1>\n' + \
' <p><b>@' + search_nickname + '@' + search_domain_full + \
'</b><br>\n'
if joined_date:
html_str += ' <p>' + translate['Joined'] + ' ' + \
joined_date.split('T')[0] + '</p>\n'
if follows_you:
html_str += ' <p><b>' + translate['Follows you'] + '</b></p>\n'
if moved_to:
new_nickname = get_nickname_from_actor(moved_to)
new_domain, new_port = get_domain_from_actor(moved_to)
new_domain_full = get_full_domain(new_domain, new_port)
if new_nickname and new_domain:
new_handle = new_nickname + '@' + new_domain_full
html_str += ' <p>' + translate['New account'] + \
': <a href="' + moved_to + '">@' + new_handle + '</a></p>\n'
elif also_known_as:
other_accounts_html = \
2021-01-22 20:48:52 +00:00
' <p>' + translate['Other accounts'] + ': '
ctr = 0
2021-12-30 23:46:06 +00:00
if isinstance(also_known_as, list):
for alt_actor in also_known_as:
if alt_actor == actor:
continue
2021-01-22 20:48:52 +00:00
if ctr > 0:
2021-12-30 23:46:06 +00:00
other_accounts_html += ' '
2021-01-22 20:48:52 +00:00
ctr += 1
2021-12-30 23:46:06 +00:00
alt_domain, _ = get_domain_from_actor(alt_actor)
other_accounts_html += \
'<a href="' + alt_actor + '">' + alt_domain + '</a>'
elif isinstance(also_known_as, str):
if also_known_as != actor:
ctr += 1
2021-12-30 23:46:06 +00:00
alt_domain, _ = get_domain_from_actor(also_known_as)
other_accounts_html += \
'<a href="' + also_known_as + '">' + alt_domain + '</a>'
2021-12-30 23:46:06 +00:00
other_accounts_html += '</p>\n'
if ctr > 0:
2021-12-30 23:46:06 +00:00
html_str += other_accounts_html
2021-12-30 23:46:06 +00:00
html_str += \
' <p>' + profile_description_short + '</p>\n' + \
2021-07-22 10:22:01 +00:00
' </figcaption>\n' + \
' </figure>\n\n'
2021-12-30 23:46:06 +00:00
return html_str
2020-11-12 23:38:58 +00:00
2021-12-29 21:55:09 +00:00
def html_profile(signing_priv_key_pem: str,
rss_icon_at_top: bool,
css_cache: {}, icons_as_buttons: bool,
2021-12-30 23:46:06 +00:00
default_timeline: str,
2021-12-29 21:55:09 +00:00
recent_posts_cache: {}, max_recent_posts: int,
translate: {}, project_version: str,
base_dir: str, http_prefix: str, authorized: bool,
profile_json: {}, selected: str,
session, cached_webfingers: {}, person_cache: {},
yt_replace_domain: str,
twitter_replacement_domain: str,
show_published_date_only: bool,
newswire: {}, theme: str, dormant_months: int,
peertube_instances: [],
allow_local_network_access: bool,
text_mode_banner: str,
2021-12-30 23:46:06 +00:00
debug: bool, access_keys: {}, city: str,
2021-12-29 21:55:09 +00:00
system_language: str, max_like_count: int,
shared_items_federated_domains: [],
2021-12-30 23:46:06 +00:00
extraJson: {}, page_number: int,
max_items_per_page: int,
2021-12-29 21:55:09 +00:00
cw_lists: {}, lists_enabled: str,
2022-02-25 19:12:40 +00:00
content_license_url: str,
2022-03-24 13:14:41 +00:00
timezone: str, bold_reading: bool) -> str:
2020-11-09 22:44:03 +00:00
"""Show the profile page as html
"""
2021-12-26 10:08:06 +00:00
nickname = profile_json['preferredUsername']
2020-11-09 22:44:03 +00:00
if not nickname:
return ""
2021-12-27 15:41:04 +00:00
if is_system_account(nickname):
2021-12-29 21:55:09 +00:00
return html_front_screen(signing_priv_key_pem,
rss_icon_at_top,
css_cache, icons_as_buttons,
2021-12-30 23:46:06 +00:00
default_timeline,
2021-12-29 21:55:09 +00:00
recent_posts_cache, max_recent_posts,
translate, project_version,
base_dir, http_prefix, authorized,
profile_json, selected,
session, cached_webfingers, person_cache,
yt_replace_domain,
twitter_replacement_domain,
show_published_date_only,
newswire, theme, extraJson,
2021-12-30 23:46:06 +00:00
allow_local_network_access, access_keys,
2021-12-29 21:55:09 +00:00
system_language, max_like_count,
shared_items_federated_domains, None,
2021-12-30 23:46:06 +00:00
page_number, max_items_per_page, cw_lists,
2021-12-29 21:55:09 +00:00
lists_enabled)
2021-12-27 19:05:25 +00:00
domain, port = get_domain_from_actor(profile_json['id'])
2020-11-09 22:44:03 +00:00
if not domain:
return ""
2021-12-30 23:46:06 +00:00
display_name = \
2021-12-29 21:55:09 +00:00
add_emoji_to_display_name(session, base_dir, http_prefix,
nickname, domain,
profile_json['name'], True)
2021-12-26 12:45:03 +00:00
domain_full = get_full_domain(domain, port)
2021-12-30 23:46:06 +00:00
profile_description = \
2021-12-29 21:55:09 +00:00
add_emoji_to_display_name(session, base_dir, http_prefix,
nickname, domain,
profile_json['summary'], False)
2021-12-30 23:46:06 +00:00
posts_button = 'button'
following_button = 'button'
followers_button = 'button'
roles_button = 'button'
skills_button = 'button'
# shares_button = 'button'
# wanted_button = 'button'
2020-11-09 22:44:03 +00:00
if selected == 'posts':
2021-12-30 23:46:06 +00:00
posts_button = 'buttonselected'
2020-11-09 22:44:03 +00:00
elif selected == 'following':
2021-12-30 23:46:06 +00:00
following_button = 'buttonselected'
2020-11-09 22:44:03 +00:00
elif selected == 'followers':
2021-12-30 23:46:06 +00:00
followers_button = 'buttonselected'
2020-11-09 22:44:03 +00:00
elif selected == 'roles':
2021-12-30 23:46:06 +00:00
roles_button = 'buttonselected'
2020-11-09 22:44:03 +00:00
elif selected == 'skills':
2021-12-30 23:46:06 +00:00
skills_button = 'buttonselected'
# elif selected == 'shares':
# shares_button = 'buttonselected'
# elif selected == 'wanted':
# wanted_button = 'buttonselected'
login_button = ''
follow_approvals_section = ''
follow_approvals = False
edit_profile_str = ''
logout_str = ''
2021-12-26 10:08:06 +00:00
actor = profile_json['id']
2021-12-30 23:46:06 +00:00
users_path = '/users/' + actor.split('/users/')[1]
donate_section = ''
donate_url = get_donation_url(profile_json)
website_url = get_website(profile_json, translate)
blog_address = get_blog_address(profile_json)
enigma_pub_key = get_enigma_pub_key(profile_json)
pgp_pub_key = get_pgp_pub_key(profile_json)
pgp_fingerprint = get_pgp_fingerprint(profile_json)
email_address = get_email_address(profile_json)
xmpp_address = get_xmpp_address(profile_json)
matrix_address = get_matrix_address(profile_json)
ssb_address = get_ssb_address(profile_json)
tox_address = get_tox_address(profile_json)
briar_address = get_briar_address(profile_json)
jami_address = get_jami_address(profile_json)
2021-12-30 20:48:38 +00:00
cwtch_address = get_cwtch_address(profile_json)
2021-12-30 23:46:06 +00:00
if donate_url or website_url or xmpp_address or matrix_address or \
ssb_address or tox_address or briar_address or \
jami_address or cwtch_address or pgp_pub_key or enigma_pub_key or \
pgp_fingerprint or email_address:
donate_section = '<div class="container">\n'
donate_section += ' <center>\n'
if donate_url and not is_system_account(nickname):
donate_section += \
' <p><a href="' + donate_url + \
2020-11-09 22:44:03 +00:00
'"><button class="donateButton">' + translate['Donate'] + \
'</button></a></p>\n'
2021-12-30 23:46:06 +00:00
if website_url:
donate_section += \
2021-08-12 21:08:55 +00:00
'<p>' + translate['Website'] + ': <a href="' + \
2021-12-30 23:46:06 +00:00
website_url + '">' + website_url + '</a></p>\n'
if email_address:
donate_section += \
2020-11-09 22:44:03 +00:00
'<p>' + translate['Email'] + ': <a href="mailto:' + \
2021-12-30 23:46:06 +00:00
email_address + '">' + email_address + '</a></p>\n'
if blog_address:
donate_section += \
2021-08-20 13:56:52 +00:00
'<p>Blog: <a href="' + \
2021-12-30 23:46:06 +00:00
blog_address + '">' + blog_address + '</a></p>\n'
if xmpp_address:
donate_section += \
2020-11-09 22:44:03 +00:00
'<p>' + translate['XMPP'] + ': <a href="xmpp:' + \
2021-12-30 23:46:06 +00:00
xmpp_address + '">' + xmpp_address + '</a></p>\n'
if matrix_address:
donate_section += \
'<p>' + translate['Matrix'] + ': ' + matrix_address + '</p>\n'
if ssb_address:
donate_section += \
2020-11-09 22:44:03 +00:00
'<p>SSB: <label class="ssbaddr">' + \
2021-12-30 23:46:06 +00:00
ssb_address + '</label></p>\n'
if tox_address:
donate_section += \
2020-11-09 22:44:03 +00:00
'<p>Tox: <label class="toxaddr">' + \
2021-12-30 23:46:06 +00:00
tox_address + '</label></p>\n'
if briar_address:
if briar_address.startswith('briar://'):
donate_section += \
2020-12-24 17:11:18 +00:00
'<p><label class="toxaddr">' + \
2021-12-30 23:46:06 +00:00
briar_address + '</label></p>\n'
2020-12-24 17:11:18 +00:00
else:
2021-12-30 23:46:06 +00:00
donate_section += \
2020-12-24 17:11:18 +00:00
'<p>briar://<label class="toxaddr">' + \
2021-12-30 23:46:06 +00:00
briar_address + '</label></p>\n'
if jami_address:
donate_section += \
2020-11-29 12:50:41 +00:00
'<p>Jami: <label class="toxaddr">' + \
2021-12-30 23:46:06 +00:00
jami_address + '</label></p>\n'
2021-12-30 20:48:38 +00:00
if cwtch_address:
2021-12-30 23:46:06 +00:00
donate_section += \
2021-06-27 11:48:03 +00:00
'<p>Cwtch: <label class="toxaddr">' + \
2021-12-30 20:48:38 +00:00
cwtch_address + '</label></p>\n'
2021-12-30 23:46:06 +00:00
if enigma_pub_key:
donate_section += \
2021-12-11 10:53:38 +00:00
'<p>Enigma: <label class="toxaddr">' + \
2021-12-30 23:46:06 +00:00
enigma_pub_key + '</label></p>\n'
if pgp_fingerprint:
donate_section += \
2020-11-09 22:44:03 +00:00
'<p class="pgp">PGP: ' + \
2021-12-30 23:46:06 +00:00
pgp_fingerprint.replace('\n', '<br>') + '</p>\n'
if pgp_pub_key:
donate_section += \
'<p class="pgp">' + \
pgp_pub_key.replace('\n', '<br>') + '</p>\n'
donate_section += ' </center>\n'
donate_section += '</div>\n'
2020-11-09 22:44:03 +00:00
if authorized:
2021-12-30 23:46:06 +00:00
edit_profile_str = \
'<a class="imageAnchor" href="' + users_path + '/editprofile">' + \
2022-03-28 08:47:53 +00:00
'<img loading="lazy" decoding="async" src="/icons' + \
2020-11-09 22:44:03 +00:00
'/edit.png" title="' + translate['Edit'] + \
'" alt="| ' + translate['Edit'] + '" class="timelineicon"/></a>\n'
2021-12-30 23:46:06 +00:00
logout_str = \
2020-11-09 22:44:03 +00:00
'<a class="imageAnchor" href="/logout">' + \
2022-03-28 08:47:53 +00:00
'<img loading="lazy" decoding="async" src="/icons' + \
2020-11-09 22:44:03 +00:00
'/logout.png" title="' + translate['Logout'] + \
'" alt="| ' + translate['Logout'] + \
'" class="timelineicon"/></a>\n'
# are there any follow requests?
2021-12-30 23:46:06 +00:00
follow_requests_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/followrequests.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(follow_requests_filename):
with open(follow_requests_filename, 'r') as foll_file:
for line in foll_file:
2020-11-09 22:44:03 +00:00
if len(line) > 0:
2021-12-30 23:46:06 +00:00
follow_approvals = True
followers_button = 'buttonhighlighted'
2020-11-09 22:44:03 +00:00
if selected == 'followers':
2021-12-30 23:46:06 +00:00
followers_button = 'buttonselectedhighlighted'
2020-11-09 22:44:03 +00:00
break
if selected == 'followers':
2021-12-30 23:46:06 +00:00
if follow_approvals:
curr_follower_domains = \
2021-12-29 21:55:09 +00:00
get_follower_domains(base_dir, nickname, domain)
2021-12-30 23:46:06 +00:00
with open(follow_requests_filename, 'r') as req_file:
for follower_handle in req_file:
if len(follower_handle) > 0:
follower_handle = follower_handle.replace('\n', '')
if '://' in follower_handle:
follower_actor = follower_handle
2020-11-09 22:44:03 +00:00
else:
2021-12-30 23:46:06 +00:00
nick = follower_handle.split('@')[0]
dom = follower_handle.split('@')[1]
follower_actor = \
2021-12-26 10:19:59 +00:00
local_actor_url(http_prefix, nick, dom)
# is this a new domain?
# if so then append a new instance indicator
2021-12-30 23:46:06 +00:00
follower_domain, _ = \
get_domain_from_actor(follower_actor)
new_follower_domain = ''
if follower_domain not in curr_follower_domains:
new_follower_domain = ''
base_path = '/users/' + nickname
follow_approvals_section += \
'<div class="container">'
follow_approvals_section += \
'<a href="' + follower_actor + '">'
follow_approvals_section += \
2020-11-09 22:44:03 +00:00
'<span class="followRequestHandle">' + \
2021-12-30 23:46:06 +00:00
follower_handle + \
new_follower_domain + '</span></a>'
# show Approve and Deny buttons
2021-12-30 23:46:06 +00:00
follow_approvals_section += \
'<a href="' + base_path + \
'/followapprove=' + follower_handle + '">'
follow_approvals_section += \
2020-11-09 22:44:03 +00:00
'<button class="followApprove">' + \
translate['Approve'] + '</button></a><br><br>'
2021-12-30 23:46:06 +00:00
follow_approvals_section += \
'<a href="' + base_path + \
'/followdeny=' + follower_handle + '">'
follow_approvals_section += \
2020-11-09 22:44:03 +00:00
'<button class="followDeny">' + \
translate['Deny'] + '</button></a>'
2021-12-30 23:46:06 +00:00
follow_approvals_section += '</div>'
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
profile_description_short = profile_description
if '\n' in profile_description:
if len(profile_description.split('\n')) > 2:
profile_description_short = ''
2020-11-09 22:44:03 +00:00
else:
2021-12-30 23:46:06 +00:00
if '<br>' in profile_description:
if len(profile_description.split('<br>')) > 2:
profile_description_short = ''
profile_description = profile_description.replace('<br>', '\n')
2020-11-09 22:44:03 +00:00
# keep the profile description short
2021-12-30 23:46:06 +00:00
if len(profile_description_short) > 256:
profile_description_short = ''
2020-11-09 22:44:03 +00:00
# remove formatting from profile description used on title
2021-12-30 23:46:06 +00:00
avatar_description = ''
2021-12-26 10:08:06 +00:00
if profile_json.get('summary'):
2021-12-30 23:46:06 +00:00
avatar_description = profile_json['summary'].replace('<br>', '\n')
avatar_description = avatar_description.replace('<p>', '')
avatar_description = avatar_description.replace('</p>', '')
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
moved_to = ''
2021-12-26 10:08:06 +00:00
if profile_json.get('movedTo'):
2021-12-30 23:46:06 +00:00
moved_to = profile_json['movedTo']
if '"' in moved_to:
moved_to = moved_to.split('"')[1]
2021-12-30 23:46:06 +00:00
also_known_as = None
2021-12-26 10:08:06 +00:00
if profile_json.get('alsoKnownAs'):
2021-12-30 23:46:06 +00:00
also_known_as = profile_json['alsoKnownAs']
2021-01-22 20:59:43 +00:00
2021-12-30 23:46:06 +00:00
joined_date = None
2021-12-26 10:08:06 +00:00
if profile_json.get('published'):
if 'T' in profile_json['published']:
2021-12-30 23:46:06 +00:00
joined_date = profile_json['published']
occupation_name = None
2021-12-26 10:08:06 +00:00
if profile_json.get('hasOccupation'):
2021-12-30 23:46:06 +00:00
occupation_name = get_occupation_name(profile_json)
2021-12-30 23:46:06 +00:00
avatar_url = profile_json['icon']['url']
2021-06-13 08:48:59 +00:00
# use alternate path for local avatars to avoid any caching issues
2021-12-30 23:46:06 +00:00
if '://' + domain_full + '/system/accounts/avatars/' in avatar_url:
avatar_url = \
avatar_url.replace('://' + domain_full +
'/system/accounts/avatars/',
'://' + domain_full + '/users/')
2021-01-24 18:09:21 +00:00
# get pinned post content
2021-12-30 23:46:06 +00:00
account_dir = acct_dir(base_dir, nickname, domain)
pinned_filename = account_dir + '/pinToProfile.txt'
pinned_content = None
if os.path.isfile(pinned_filename):
with open(pinned_filename, 'r') as pin_file:
pinned_content = pin_file.read()
profile_header_str = \
2021-12-29 21:55:09 +00:00
_get_profile_header(base_dir, http_prefix,
nickname, domain,
domain_full, translate,
2021-12-30 23:46:06 +00:00
default_timeline, display_name,
avatar_description,
profile_description_short,
login_button, avatar_url, theme,
moved_to, also_known_as,
pinned_content, access_keys,
joined_date, occupation_name)
2020-11-09 22:44:03 +00:00
2021-02-05 15:30:51 +00:00
# keyboard navigation
2021-12-30 23:46:06 +00:00
user_path_str = '/users/' + nickname
deft = default_timeline
is_group = False
followers_str = translate['Followers']
2021-12-26 17:33:24 +00:00
if is_group_account(base_dir, nickname, domain):
2021-12-30 23:46:06 +00:00
is_group = True
followers_str = translate['Members']
menu_timeline = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('🏠') + ' ' + \
2021-02-06 10:46:03 +00:00
translate['Switch to timeline view']
2021-12-30 23:46:06 +00:00
menu_edit = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('') + ' ' + translate['Edit']
2021-12-30 23:46:06 +00:00
if not is_group:
menu_following = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('👥') + ' ' + translate['Following']
2021-12-30 23:46:06 +00:00
menu_followers = \
html_hide_from_screen_reader('👪') + ' ' + followers_str
if not is_group:
menu_roles = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('🤚') + ' ' + translate['Roles']
2021-12-30 23:46:06 +00:00
menu_skills = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('🛠') + ' ' + translate['Skills']
2021-12-30 23:46:06 +00:00
menu_logout = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('') + ' ' + translate['Logout']
2021-12-30 23:46:06 +00:00
nav_links = {
menu_timeline: user_path_str + '/' + deft,
menu_edit: user_path_str + '/editprofile',
menu_following: user_path_str + '/following#timeline',
menu_followers: user_path_str + '/followers#timeline',
menu_roles: user_path_str + '/roles#timeline',
menu_skills: user_path_str + '/skills#timeline',
menu_logout: '/logout'
2021-02-05 17:55:49 +00:00
}
2021-12-26 14:17:13 +00:00
if is_artist(base_dir, nickname):
2021-12-30 23:46:06 +00:00
menu_theme_designer = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('🎨') + ' ' + \
translate['Theme Designer']
2021-12-30 23:46:06 +00:00
nav_links[menu_theme_designer] = user_path_str + '/themedesigner'
nav_access_keys = {}
for variable_name, key in access_keys.items():
if not locals().get(variable_name):
2021-04-22 14:12:59 +00:00
continue
2021-12-30 23:46:06 +00:00
nav_access_keys[locals()[variable_name]] = key
2021-04-22 14:12:59 +00:00
2021-12-30 23:46:06 +00:00
profile_str = html_keyboard_navigation(text_mode_banner,
nav_links, nav_access_keys)
2021-12-30 23:46:06 +00:00
profile_str += profile_header_str + donate_section
profile_str += '<div class="container" id="buttonheader">\n'
profile_str += ' <center>'
profile_str += \
' <a href="' + users_path + '#buttonheader"><button class="' + \
posts_button + '"><span>' + translate['Posts'] + \
' </span></button></a>'
2021-12-30 23:46:06 +00:00
if not is_group:
profile_str += \
' <a href="' + users_path + '/following#buttonheader">' + \
'<button class="' + following_button + '"><span>' + \
translate['Following'] + ' </span></button></a>'
2021-12-30 23:46:06 +00:00
profile_str += \
' <a href="' + users_path + '/followers#buttonheader">' + \
'<button class="' + followers_button + \
'"><span>' + followers_str + ' </span></button></a>'
if not is_group:
profile_str += \
' <a href="' + users_path + '/roles#buttonheader">' + \
'<button class="' + roles_button + '"><span>' + \
translate['Roles'] + \
' </span></button></a>'
2021-12-30 23:46:06 +00:00
profile_str += \
' <a href="' + users_path + '/skills#buttonheader">' + \
'<button class="' + skills_button + '"><span>' + \
translate['Skills'] + ' </span></button></a>'
2021-12-30 23:46:06 +00:00
# profile_str += \
# ' <a href="' + users_path + '/shares#buttonheader">' + \
# '<button class="' + shares_button + '"><span>' + \
# translate['Shares'] + ' </span></button></a>'
2021-12-30 23:46:06 +00:00
# profile_str += \
# ' <a href="' + users_path + '/wanted#buttonheader">' + \
# '<button class="' + wanted_button + '"><span>' + \
# translate['Wanted'] + ' </span></button></a>'
2021-12-30 23:46:06 +00:00
profile_str += logout_str + edit_profile_str
profile_str += ' </center>'
profile_str += '</div>'
2020-11-09 22:44:03 +00:00
2021-02-05 17:55:49 +00:00
# start of #timeline
2021-12-30 23:46:06 +00:00
profile_str += '<div id="timeline">\n'
2021-02-05 17:55:49 +00:00
2021-12-30 23:46:06 +00:00
profile_str += follow_approvals_section
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
css_filename = base_dir + '/epicyon-profile.css'
2021-12-25 16:17:53 +00:00
if os.path.isfile(base_dir + '/epicyon.css'):
2021-12-30 23:46:06 +00:00
css_filename = base_dir + '/epicyon.css'
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
license_str = \
'<a href="https://gitlab.com/bashrc2/epicyon">' + \
2022-03-28 08:47:53 +00:00
'<img loading="lazy" decoding="async" class="license" alt="' + \
translate['Get the source code'] + '" title="' + \
translate['Get the source code'] + '" src="/icons/agpl.png" /></a>'
if selected == 'posts':
2021-12-30 23:46:06 +00:00
profile_str += \
2021-12-29 21:55:09 +00:00
_html_profile_posts(recent_posts_cache, max_recent_posts,
translate,
base_dir, http_prefix, authorized,
nickname, domain, port,
session, cached_webfingers, person_cache,
project_version,
yt_replace_domain,
twitter_replacement_domain,
show_published_date_only,
peertube_instances,
allow_local_network_access,
theme, system_language,
max_like_count,
signing_priv_key_pem,
2022-02-25 19:12:40 +00:00
cw_lists, lists_enabled,
2022-03-24 13:14:41 +00:00
timezone, bold_reading) + license_str
2021-12-30 23:46:06 +00:00
if not is_group:
if selected == 'following':
2021-12-30 23:46:06 +00:00
profile_str += \
2021-12-29 21:55:09 +00:00
_html_profile_following(translate, base_dir, http_prefix,
authorized, nickname,
domain, port, session,
cached_webfingers,
person_cache, extraJson,
project_version, ["unfollow"],
selected,
2021-12-30 23:46:06 +00:00
users_path, page_number,
max_items_per_page,
2021-12-29 21:55:09 +00:00
dormant_months, debug,
signing_priv_key_pem)
if selected == 'followers':
2021-12-30 23:46:06 +00:00
profile_str += \
2021-12-29 21:55:09 +00:00
_html_profile_following(translate, base_dir, http_prefix,
authorized, nickname,
domain, port, session,
cached_webfingers,
person_cache, extraJson,
project_version, ["block"],
2021-12-30 23:46:06 +00:00
selected, users_path, page_number,
max_items_per_page, dormant_months, debug,
2021-12-29 21:55:09 +00:00
signing_priv_key_pem)
2021-12-30 23:46:06 +00:00
if not is_group:
if selected == 'roles':
2021-12-30 23:46:06 +00:00
profile_str += \
2021-12-29 21:55:09 +00:00
_html_profile_roles(translate, nickname, domain_full,
extraJson)
2021-09-21 17:47:25 +00:00
elif selected == 'skills':
2021-12-30 23:46:06 +00:00
profile_str += \
2021-12-29 21:55:09 +00:00
_html_profile_skills(translate, nickname, domain_full,
extraJson)
# elif selected == 'shares':
2021-12-30 23:46:06 +00:00
# profile_str += \
2021-12-29 21:55:09 +00:00
# _html_profile_shares(actor, translate,
2021-12-26 10:00:46 +00:00
# nickname, domain_full,
2021-12-30 23:46:06 +00:00
# extraJson, 'shares') + license_str
# elif selected == 'wanted':
2021-12-30 23:46:06 +00:00
# profile_str += \
2021-12-29 21:55:09 +00:00
# _html_profile_shares(actor, translate,
2021-12-26 10:00:46 +00:00
# nickname, domain_full,
2021-12-30 23:46:06 +00:00
# extraJson, 'wanted') + license_str
2021-02-05 17:55:49 +00:00
# end of #timeline
2021-12-30 23:46:06 +00:00
profile_str += '</div>'
2020-11-12 17:05:38 +00:00
2021-12-30 23:46:06 +00:00
instance_title = \
2021-12-26 14:08:58 +00:00
get_config_param(base_dir, 'instanceTitle')
2021-12-30 23:46:06 +00:00
profile_str = \
html_header_with_person_markup(css_filename, instance_title,
2021-12-29 21:55:09 +00:00
profile_json, city,
content_license_url) + \
2021-12-30 23:46:06 +00:00
profile_str + html_footer()
return profile_str
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _html_profile_posts(recent_posts_cache: {}, max_recent_posts: int,
translate: {},
base_dir: str, http_prefix: str,
authorized: bool,
nickname: str, domain: str, port: int,
session, cached_webfingers: {}, person_cache: {},
project_version: str,
yt_replace_domain: str,
twitter_replacement_domain: str,
show_published_date_only: bool,
peertube_instances: [],
allow_local_network_access: bool,
theme_name: str, system_language: str,
max_like_count: int,
signing_priv_key_pem: str,
2022-02-25 19:12:40 +00:00
cw_lists: {}, lists_enabled: str,
2022-03-24 13:14:41 +00:00
timezone: str, bold_reading: bool) -> str:
2020-11-09 22:44:03 +00:00
"""Shows posts on the profile screen
These should only be public posts
"""
2021-12-30 23:46:06 +00:00
separator_str = html_post_separator(base_dir, None)
profile_str = ''
max_items = 4
2020-11-09 22:44:03 +00:00
ctr = 0
2021-12-30 23:46:06 +00:00
curr_page = 1
box_name = 'outbox'
while ctr < max_items and curr_page < 4:
outbox_feed_path_str = \
'/users/' + nickname + '/' + box_name + '?page=' + \
str(curr_page)
outbox_feed = \
2021-12-28 16:50:20 +00:00
person_box_json({}, session, base_dir, domain,
port,
2021-12-30 23:46:06 +00:00
outbox_feed_path_str,
2021-12-28 16:50:20 +00:00
http_prefix,
2021-12-30 23:46:06 +00:00
10, box_name,
2021-12-28 16:50:20 +00:00
authorized, 0, False, 0)
2021-12-30 23:46:06 +00:00
if not outbox_feed:
2020-11-27 16:14:54 +00:00
break
2021-12-30 23:46:06 +00:00
if len(outbox_feed['orderedItems']) == 0:
2020-11-09 22:44:03 +00:00
break
2021-12-30 23:46:06 +00:00
for item in outbox_feed['orderedItems']:
2020-11-09 22:44:03 +00:00
if item['type'] == 'Create':
2021-12-30 23:46:06 +00:00
post_str = \
2021-12-29 21:55:09 +00:00
individual_post_as_html(signing_priv_key_pem,
True, recent_posts_cache,
max_recent_posts,
translate, None,
base_dir, session,
cached_webfingers,
person_cache,
nickname, domain, port, item,
None, True, False,
http_prefix, project_version,
'inbox',
yt_replace_domain,
twitter_replacement_domain,
show_published_date_only,
peertube_instances,
allow_local_network_access,
theme_name, system_language,
max_like_count,
False, False, False,
True, False, False,
2022-02-25 19:12:40 +00:00
cw_lists, lists_enabled,
2022-03-24 13:14:41 +00:00
timezone, False,
bold_reading)
2021-12-30 23:46:06 +00:00
if post_str:
profile_str += post_str + separator_str
2020-11-09 22:44:03 +00:00
ctr += 1
2021-12-30 23:46:06 +00:00
if ctr >= max_items:
2020-11-09 22:44:03 +00:00
break
2021-12-30 23:46:06 +00:00
curr_page += 1
return profile_str
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _html_profile_following(translate: {}, base_dir: str, http_prefix: str,
authorized: bool,
nickname: str, domain: str, port: int,
session, cached_webfingers: {}, person_cache: {},
2021-12-30 23:46:06 +00:00
following_json: {}, project_version: str,
2021-12-29 21:55:09 +00:00
buttons: [],
feedName: str, actor: str,
2021-12-30 23:46:06 +00:00
page_number: int,
max_items_per_page: int,
2021-12-29 21:55:09 +00:00
dormant_months: int, debug: bool,
signing_priv_key_pem: str) -> str:
2020-11-09 22:44:03 +00:00
"""Shows following on the profile screen
"""
2021-12-30 23:46:06 +00:00
profile_str = ''
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
if authorized and page_number:
if authorized and page_number > 1:
2020-11-09 22:44:03 +00:00
# page up arrow
2021-12-30 23:46:06 +00:00
profile_str += \
2020-11-09 22:44:03 +00:00
' <center>\n' + \
' <a href="' + actor + '/' + feedName + \
2021-12-30 23:46:06 +00:00
'?page=' + str(page_number - 1) + '#buttonheader' + \
2022-03-28 08:47:53 +00:00
'"><img loading="lazy" decoding="async" ' + \
'class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pageup.png" title="' + \
2020-11-09 22:44:03 +00:00
translate['Page up'] + '" alt="' + \
translate['Page up'] + '"></a>\n' + \
' </center>\n'
2021-12-30 23:46:06 +00:00
for following_actor in following_json['orderedItems']:
2020-12-13 12:48:04 +00:00
# is this a dormant followed account?
dormant = False
2020-12-13 12:45:29 +00:00
if authorized and feedName == 'following':
dormant = \
2021-12-30 23:46:06 +00:00
is_dormant(base_dir, nickname, domain, following_actor,
2021-12-26 12:54:51 +00:00
dormant_months)
2020-12-13 12:48:04 +00:00
2021-12-30 23:46:06 +00:00
profile_str += \
2021-12-29 21:55:09 +00:00
_individual_follow_as_html(signing_priv_key_pem,
translate, base_dir, session,
cached_webfingers, person_cache,
2021-12-30 23:46:06 +00:00
domain, following_actor,
2021-12-29 21:55:09 +00:00
authorized, nickname,
http_prefix, project_version, dormant,
debug, buttons)
2020-12-13 12:48:04 +00:00
2021-12-30 23:46:06 +00:00
if authorized and max_items_per_page and page_number:
if len(following_json['orderedItems']) >= max_items_per_page:
2020-11-09 22:44:03 +00:00
# page down arrow
2021-12-30 23:46:06 +00:00
profile_str += \
2020-11-09 22:44:03 +00:00
' <center>\n' + \
' <a href="' + actor + '/' + feedName + \
2021-12-30 23:46:06 +00:00
'?page=' + str(page_number + 1) + '#buttonheader' + \
2022-03-28 08:47:53 +00:00
'"><img loading="lazy" decoding="async" ' + \
'class="pageicon" src="/' + \
2020-12-09 13:08:26 +00:00
'icons/pagedown.png" title="' + \
2020-11-09 22:44:03 +00:00
translate['Page down'] + '" alt="' + \
translate['Page down'] + '"></a>\n' + \
' </center>\n'
2021-12-30 23:46:06 +00:00
return profile_str
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _html_profile_roles(translate: {}, nickname: str, domain: str,
rolesList: []) -> str:
2020-11-09 22:44:03 +00:00
"""Shows roles on the profile screen
"""
2021-12-30 23:46:06 +00:00
profile_str = ''
profile_str += \
'<div class="roles">\n<div class="roles-inner">\n'
for role in rolesList:
if translate.get(role):
2021-12-30 23:46:06 +00:00
profile_str += '<h3>' + translate[role] + '</h3>\n'
else:
2021-12-30 23:46:06 +00:00
profile_str += '<h3>' + role + '</h3>\n'
profile_str += '</div></div>\n'
if len(profile_str) == 0:
profile_str += \
2020-11-09 22:44:03 +00:00
'<p>@' + nickname + '@' + domain + ' has no roles assigned</p>\n'
else:
2021-12-30 23:46:06 +00:00
profile_str = '<div>' + profile_str + '</div>\n'
return profile_str
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _html_profile_skills(translate: {}, nickname: str, domain: str,
skillsJson: {}) -> str:
2020-11-09 22:44:03 +00:00
"""Shows skills on the profile screen
"""
2021-12-30 23:46:06 +00:00
profile_str = ''
2020-11-09 22:44:03 +00:00
for skill, level in skillsJson.items():
2021-12-30 23:46:06 +00:00
profile_str += \
2020-11-09 22:44:03 +00:00
'<div>' + skill + \
'<br><div id="myProgress"><div id="myBar" style="width:' + \
str(level) + '%"></div></div></div>\n<br>\n'
2021-12-30 23:46:06 +00:00
if len(profile_str) > 0:
profile_str = '<center><div class="skill-title">' + \
profile_str + '</div></center>\n'
return profile_str
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _html_profile_shares(actor: str, translate: {},
2021-12-30 23:46:06 +00:00
nickname: str, domain: str, shares_json: {},
shares_file_type: str) -> str:
2020-11-09 22:44:03 +00:00
"""Shows shares on the profile screen
"""
2021-12-30 23:46:06 +00:00
profile_str = ''
for item in shares_json['orderedItems']:
profile_str += html_individual_share(domain, item['shareId'],
actor, item, translate,
False, False,
shares_file_type)
if len(profile_str) > 0:
profile_str = '<div class="share-title">' + profile_str + '</div>\n'
return profile_str
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _grayscale_enabled(base_dir: str) -> bool:
2021-06-27 17:59:46 +00:00
"""Is grayscale UI enabled?
"""
2021-12-25 16:17:53 +00:00
return os.path.isfile(base_dir + '/accounts/.grayscale')
2021-06-27 17:59:46 +00:00
2021-12-29 21:55:09 +00:00
def _html_themes_dropdown(base_dir: str, translate: {}) -> str:
2021-06-27 17:59:46 +00:00
"""Returns the html for theme selection dropdown
"""
# Themes section
2021-12-29 21:55:09 +00:00
themes = get_themes_list(base_dir)
2021-12-30 23:46:06 +00:00
themes_dropdown = ' <label class="labels">' + \
2021-06-27 17:59:46 +00:00
translate['Theme'] + '</label><br>\n'
2021-12-29 21:55:09 +00:00
grayscale = _grayscale_enabled(base_dir)
2021-12-30 23:46:06 +00:00
themes_dropdown += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Grayscale'], 'grayscale', grayscale)
dyslexic_font = get_config_param(base_dir, 'dyslexicFont')
themes_dropdown += \
edit_check_box(translate['Dyslexic font'], 'dyslexicFont',
dyslexic_font)
2021-12-30 23:46:06 +00:00
themes_dropdown += ' <select id="themeDropdown" ' + \
2021-06-27 17:59:46 +00:00
'name="themeDropdown" class="theme">'
2021-12-25 23:35:50 +00:00
for theme_name in themes:
2021-12-30 23:46:06 +00:00
translated_theme_name = theme_name
2021-12-25 23:35:50 +00:00
if translate.get(theme_name):
2021-12-30 23:46:06 +00:00
translated_theme_name = translate[theme_name]
themes_dropdown += ' <option value="' + \
2021-12-25 23:35:50 +00:00
theme_name.lower() + '">' + \
2021-12-30 23:46:06 +00:00
translated_theme_name + '</option>'
themes_dropdown += ' </select><br>'
2021-12-25 16:17:53 +00:00
if os.path.isfile(base_dir + '/fonts/custom.woff') or \
os.path.isfile(base_dir + '/fonts/custom.woff2') or \
os.path.isfile(base_dir + '/fonts/custom.otf') or \
os.path.isfile(base_dir + '/fonts/custom.ttf'):
2021-12-30 23:46:06 +00:00
themes_dropdown += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Remove the custom font'],
'removeCustomFont', False)
2021-12-26 14:08:58 +00:00
theme_name = get_config_param(base_dir, 'theme')
2021-12-30 23:46:06 +00:00
themes_dropdown = \
themes_dropdown.replace('<option value="' + theme_name + '">',
'<option value="' + theme_name +
'" selected>')
return themes_dropdown
2021-06-27 17:59:46 +00:00
2021-12-29 21:55:09 +00:00
def _html_edit_profile_graphic_design(base_dir: str, translate: {}) -> str:
"""Graphic design section on Edit Profile screen
"""
2021-12-30 23:46:06 +00:00
graphics_str = begin_edit_section(translate['Graphic Design'])
2021-12-30 13:56:38 +00:00
low_bandwidth = get_config_param(base_dir, 'lowBandwidth')
2021-12-25 18:20:56 +00:00
if not low_bandwidth:
low_bandwidth = False
2021-12-30 23:46:06 +00:00
graphics_str += _html_themes_dropdown(base_dir, translate)
graphics_str += \
' <label class="labels">' + \
translate['Import Theme'] + '</label>\n'
2021-12-30 23:46:06 +00:00
graphics_str += ' <input type="file" id="import_theme" '
graphics_str += 'name="submitImportTheme" '
graphics_str += 'accept="' + THEME_FORMATS + '">\n'
graphics_str += \
' <label class="labels">' + \
translate['Export Theme'] + '</label><br>\n'
2021-12-30 23:46:06 +00:00
graphics_str += \
' <button type="submit" class="button" ' + \
2021-08-13 17:35:31 +00:00
'name="submitExportTheme">➤</button><br>\n'
2021-12-30 23:46:06 +00:00
graphics_str += \
2021-12-30 13:56:38 +00:00
edit_check_box(translate['Low Bandwidth'], 'lowBandwidth',
2021-12-29 21:55:09 +00:00
bool(low_bandwidth))
2021-12-30 23:46:06 +00:00
graphics_str += end_edit_section()
return graphics_str
2021-12-29 21:55:09 +00:00
def _html_edit_profile_twitter(base_dir: str, translate: {},
2021-12-30 23:46:06 +00:00
remove_twitter: str) -> str:
2021-09-18 17:08:14 +00:00
"""Edit twitter settings within profile
"""
# Twitter section
2021-12-30 23:46:06 +00:00
twitter_str = begin_edit_section(translate['Twitter'])
twitter_str += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Remove Twitter posts'],
2021-12-30 23:46:06 +00:00
'removeTwitter', remove_twitter)
2021-12-26 14:08:58 +00:00
twitter_replacement_domain = get_config_param(base_dir, "twitterdomain")
2021-12-25 20:55:47 +00:00
if not twitter_replacement_domain:
twitter_replacement_domain = ''
2021-12-30 23:46:06 +00:00
twitter_str += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Twitter Replacement Domain'],
'twitterdomain', twitter_replacement_domain)
2021-12-30 23:46:06 +00:00
twitter_str += end_edit_section()
return twitter_str
2021-09-18 17:08:14 +00:00
2021-12-29 21:55:09 +00:00
def _html_edit_profile_instance(base_dir: str, translate: {},
peertube_instances: [],
2021-12-30 23:46:06 +00:00
media_instance_str: str,
blogs_instance_str: str,
news_instance_str: str) -> (str, str,
str, str):
"""Edit profile instance settings
"""
2021-12-30 23:46:06 +00:00
image_formats = get_image_formats()
# Instance details section
2021-12-30 23:46:06 +00:00
instance_description = \
2021-12-26 14:08:58 +00:00
get_config_param(base_dir, 'instanceDescription')
2021-12-30 23:46:06 +00:00
custom_submit_text = \
2021-12-26 14:08:58 +00:00
get_config_param(base_dir, 'customSubmitText')
2021-12-30 23:46:06 +00:00
instance_description_short = \
2021-12-26 14:08:58 +00:00
get_config_param(base_dir, 'instanceDescriptionShort')
2021-12-30 23:46:06 +00:00
instance_title = \
2021-12-26 14:08:58 +00:00
get_config_param(base_dir, 'instanceTitle')
2021-12-25 17:13:38 +00:00
content_license_url = \
2021-12-30 13:56:38 +00:00
get_config_param(base_dir, 'contentLicenseUrl')
2021-12-25 17:13:38 +00:00
if not content_license_url:
content_license_url = 'https://creativecommons.org/licenses/by/4.0'
2021-12-30 23:46:06 +00:00
instance_str = begin_edit_section(translate['Instance Settings'])
2021-07-22 12:36:31 +00:00
2021-12-30 23:46:06 +00:00
instance_str += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Instance Title'],
2021-12-30 23:46:06 +00:00
'instanceTitle', instance_title)
instance_str += '<br>\n'
instance_str += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Instance Short Description'],
2021-12-30 23:46:06 +00:00
'instanceDescriptionShort', instance_description_short)
instance_str += '<br>\n'
instance_str += \
2021-12-29 21:55:09 +00:00
edit_text_area(translate['Instance Description'],
2021-12-30 23:46:06 +00:00
'instanceDescription', instance_description, 200,
2021-12-29 21:55:09 +00:00
'', True)
2021-12-30 23:46:06 +00:00
instance_str += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Content License'],
2021-12-30 13:56:38 +00:00
'contentLicenseUrl', content_license_url)
2021-12-30 23:46:06 +00:00
instance_str += '<br>\n'
instance_str += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Custom post submit button text'],
2021-12-30 23:46:06 +00:00
'customSubmitText', custom_submit_text)
instance_str += '<br>\n'
instance_str += \
' <label class="labels">' + \
2021-07-22 10:22:01 +00:00
translate['Instance Logo'] + '</label>' + \
' <input type="file" id="instanceLogo" name="instanceLogo"' + \
2021-12-30 23:46:06 +00:00
' accept="' + image_formats + '"><br>\n' + \
' <br><label class="labels">' + \
translate['Security'] + '</label><br>\n'
2021-12-30 23:46:06 +00:00
node_info_str = \
translate['Show numbers of accounts within instance metadata']
2021-12-30 13:56:38 +00:00
if get_config_param(base_dir, "showNodeInfoAccounts"):
2021-12-30 23:46:06 +00:00
instance_str += \
edit_check_box(node_info_str, 'showNodeInfoAccounts', True)
else:
2021-12-30 23:46:06 +00:00
instance_str += \
edit_check_box(node_info_str, 'showNodeInfoAccounts', False)
2021-12-30 23:46:06 +00:00
node_info_str = \
translate['Show version number within instance metadata']
2021-12-30 13:56:38 +00:00
if get_config_param(base_dir, "showNodeInfoVersion"):
2021-12-30 23:46:06 +00:00
instance_str += \
edit_check_box(node_info_str, 'showNodeInfoVersion', True)
else:
2021-12-30 23:46:06 +00:00
instance_str += \
edit_check_box(node_info_str, 'showNodeInfoVersion', False)
2021-12-30 13:56:38 +00:00
if get_config_param(base_dir, "verifyAllSignatures"):
2021-12-30 23:46:06 +00:00
instance_str += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Verify all signatures'],
'verifyallsignatures', True)
else:
2021-12-30 23:46:06 +00:00
instance_str += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Verify all signatures'],
'verifyallsignatures', False)
2021-12-30 23:46:06 +00:00
instance_str += translate['Enabling broch mode'] + '<br>\n'
2021-12-30 13:56:38 +00:00
if get_config_param(base_dir, "brochMode"):
2021-12-30 23:46:06 +00:00
instance_str += \
2021-12-30 13:56:38 +00:00
edit_check_box(translate['Broch mode'], 'brochMode', True)
else:
2021-12-30 23:46:06 +00:00
instance_str += \
2021-12-30 13:56:38 +00:00
edit_check_box(translate['Broch mode'], 'brochMode', False)
# Instance type
2021-12-30 23:46:06 +00:00
instance_str += \
' <br><label class="labels">' + \
2021-07-22 12:36:31 +00:00
translate['Type of instance'] + '</label><br>\n'
2021-12-30 23:46:06 +00:00
instance_str += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['This is a media instance'],
2021-12-30 23:46:06 +00:00
'mediaInstance', media_instance_str)
instance_str += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['This is a blogging instance'],
2021-12-30 23:46:06 +00:00
'blogsInstance', blogs_instance_str)
instance_str += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['This is a news instance'],
2021-12-30 23:46:06 +00:00
'newsInstance', news_instance_str)
2021-07-22 12:36:31 +00:00
2021-12-30 23:46:06 +00:00
instance_str += end_edit_section()
# Role assignments section
moderators = ''
2021-12-30 23:46:06 +00:00
moderators_file = base_dir + '/accounts/moderators.txt'
if os.path.isfile(moderators_file):
2021-12-31 09:51:10 +00:00
with open(moderators_file, 'r') as mod_file:
moderators = mod_file.read()
# site moderators
2021-12-30 23:46:06 +00:00
role_assign_str = \
2021-12-29 21:55:09 +00:00
begin_edit_section(translate['Role Assignment']) + \
2021-07-22 10:22:01 +00:00
' <b><label class="labels">' + \
translate['Moderators'] + '</label></b><br>\n' + \
' ' + \
translate['A list of moderator nicknames. One per line.'] + \
' <textarea id="message" name="moderators" placeholder="' + \
translate['List of moderator nicknames'] + \
'..." style="height:200px" spellcheck="false">' + \
moderators + '</textarea>'
# site editors
editors = ''
2021-12-30 23:46:06 +00:00
editors_file = base_dir + '/accounts/editors.txt'
if os.path.isfile(editors_file):
with open(editors_file, 'r') as edit_file:
editors = edit_file.read()
role_assign_str += \
2021-07-22 10:22:01 +00:00
' <b><label class="labels">' + \
translate['Site Editors'] + '</label></b><br>\n' + \
' ' + \
translate['A list of editor nicknames. One per line.'] + \
' <textarea id="message" name="editors" placeholder="" ' + \
'style="height:200px" spellcheck="false">' + \
editors + '</textarea>'
# counselors
counselors = ''
2021-12-30 23:46:06 +00:00
counselors_file = base_dir + '/accounts/counselors.txt'
if os.path.isfile(counselors_file):
with open(counselors_file, 'r') as co_file:
counselors = co_file.read()
role_assign_str += \
2021-12-29 21:55:09 +00:00
edit_text_area(translate['Counselors'], 'counselors', counselors,
200, '', False)
# artists
artists = ''
2021-12-30 23:46:06 +00:00
artists_file = base_dir + '/accounts/artists.txt'
if os.path.isfile(artists_file):
with open(artists_file, 'r') as art_file:
artists = art_file.read()
role_assign_str += \
2021-12-29 21:55:09 +00:00
edit_text_area(translate['Artists'], 'artists', artists,
200, '', False)
2021-12-30 23:46:06 +00:00
role_assign_str += end_edit_section()
# Video section
2021-12-30 23:46:06 +00:00
peertube_str = begin_edit_section(translate['Video Settings'])
peertube_instances_str = ''
2021-12-25 23:38:53 +00:00
for url in peertube_instances:
2021-12-30 23:46:06 +00:00
peertube_instances_str += url + '\n'
peertube_str += \
2021-12-29 21:55:09 +00:00
edit_text_area(translate['Peertube Instances'], 'ptInstances',
2021-12-30 23:46:06 +00:00
peertube_instances_str, 200, '', False)
peertube_str += \
2021-07-22 12:36:31 +00:00
' <br>\n'
2021-12-26 14:08:58 +00:00
yt_replace_domain = get_config_param(base_dir, "youtubedomain")
2021-12-25 17:15:52 +00:00
if not yt_replace_domain:
yt_replace_domain = ''
2021-12-30 23:46:06 +00:00
peertube_str += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['YouTube Replacement Domain'],
'ytdomain', yt_replace_domain)
2021-12-30 23:46:06 +00:00
peertube_str += end_edit_section()
2021-12-30 23:46:06 +00:00
libretranslate_url = get_config_param(base_dir, 'libretranslateUrl')
libretranslate_api_key = get_config_param(base_dir, 'libretranslateApiKey')
libretranslate_str = \
2021-12-29 21:55:09 +00:00
_html_edit_profile_libre_translate(translate,
2021-12-30 23:46:06 +00:00
libretranslate_url,
libretranslate_api_key)
2021-12-30 23:46:06 +00:00
return instance_str, role_assign_str, peertube_str, libretranslate_str
2021-12-29 21:55:09 +00:00
def _html_edit_profile_danger_zone(translate: {}) -> str:
"""danger zone section of Edit Profile screen
"""
2021-12-30 23:46:06 +00:00
edit_profile_form = begin_edit_section(translate['Danger Zone'])
2021-07-22 12:36:31 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-07-22 10:22:01 +00:00
' <b><label class="labels">' + \
2021-07-22 12:36:31 +00:00
translate['Danger Zone'] + '</label></b><br>\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Deactivate this account'],
'deactivateThisAccount', False)
2021-07-22 12:36:31 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += end_edit_section()
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_system_monitor(nickname: str, translate: {}) -> str:
"""Links to performance graphs
"""
2021-12-30 23:46:06 +00:00
system_monitor_str = begin_edit_section(translate['System Monitor'])
system_monitor_str += '<p><a href="/users/' + nickname + \
2021-10-20 10:41:58 +00:00
'/performance?graph=get">📊 GET</a></p>'
2021-12-30 23:46:06 +00:00
system_monitor_str += '<p><a href="/users/' + nickname + \
2021-10-20 10:41:58 +00:00
'/performance?graph=post">📊 POST</a></p>'
2021-12-30 23:46:06 +00:00
system_monitor_str += end_edit_section()
return system_monitor_str
2021-12-29 21:55:09 +00:00
def _html_edit_profile_skills(base_dir: str, nickname: str, domain: str,
translate: {}) -> str:
"""skills section of Edit Profile screen
"""
2021-12-29 21:55:09 +00:00
skills = get_skills(base_dir, nickname, domain)
2021-12-30 23:46:06 +00:00
skills_str = ''
skill_ctr = 1
if skills:
2021-12-30 23:46:06 +00:00
for skill_desc, skill_value in skills.items():
if is_filtered(base_dir, nickname, domain, skill_desc):
continue
2021-12-30 23:46:06 +00:00
skills_str += \
'<p><input type="text" placeholder="' + translate['Skill'] + \
2021-12-30 23:46:06 +00:00
' ' + str(skill_ctr) + '" name="skillName' + str(skill_ctr) + \
'" value="' + skill_desc + '" style="width:40%">' + \
'<input type="range" min="1" max="100" ' + \
'class="slider" name="skillValue' + \
2021-12-30 23:46:06 +00:00
str(skill_ctr) + '" value="' + str(skill_value) + '"></p>'
skill_ctr += 1
2021-12-30 23:46:06 +00:00
skills_str += \
'<p><input type="text" placeholder="Skill ' + str(skill_ctr) + \
'" name="skillName' + str(skill_ctr) + \
2021-07-22 10:22:01 +00:00
'" value="" style="width:40%">' + \
'<input type="range" min="1" max="100" ' + \
'class="slider" name="skillValue' + \
2021-12-30 23:46:06 +00:00
str(skill_ctr) + '" value="50"></p>' + end_edit_section()
idx = 'If you want to participate within organizations then you ' + \
'can indicate some skills that you have and approximate ' + \
'proficiency levels. This helps organizers to construct ' + \
'teams with an appropriate combination of skills.'
2021-12-30 23:46:06 +00:00
edit_profile_form = \
2021-12-29 21:55:09 +00:00
begin_edit_section(translate['Skills']) + \
2021-07-22 10:22:01 +00:00
' <b><label class="labels">' + \
translate['Skills'] + '</label></b><br>\n' + \
' <label class="labels">' + \
2021-12-30 23:46:06 +00:00
translate[idx] + '</label>\n' + skills_str
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_edit_profile_git_projects(base_dir: str, nickname: str, domain: str,
translate: {}) -> str:
"""git projects section of edit profile screen
"""
2021-12-30 23:46:06 +00:00
git_projects_str = ''
git_projects_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/gitprojects.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(git_projects_filename):
with open(git_projects_filename, 'r') as git_file:
git_projects_str = git_file.read()
2021-12-30 23:46:06 +00:00
edit_profile_form = begin_edit_section(translate['Git Projects'])
2021-07-22 19:00:37 +00:00
idx = 'List of project names that you wish to receive git patches for'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
edit_text_area(translate[idx], 'gitProjects', git_projects_str,
2021-12-29 21:55:09 +00:00
100, '', False)
2021-12-30 23:46:06 +00:00
edit_profile_form += end_edit_section()
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_edit_profile_shared_items(base_dir: str, nickname: str, domain: str,
translate: {}) -> str:
"""shared items section of edit profile screen
"""
2021-12-30 23:46:06 +00:00
shared_items_str = ''
shared_items_federated_domains_str = \
2021-12-30 13:56:38 +00:00
get_config_param(base_dir, 'sharedItemsFederatedDomains')
2021-12-30 23:46:06 +00:00
if shared_items_federated_domains_str:
shared_items_federated_domains_list = \
shared_items_federated_domains_str.split(',')
for shared_federated_domain in shared_items_federated_domains_list:
shared_items_str += shared_federated_domain.strip() + '\n'
2021-12-30 23:46:06 +00:00
edit_profile_form = begin_edit_section(translate['Shares'])
idx = 'List of domains which can access the shared items catalog'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_area(translate[idx], 'shareDomainList',
2021-12-30 23:46:06 +00:00
shared_items_str, 200, '', False)
edit_profile_form += end_edit_section()
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_edit_profile_filtering(base_dir: str, nickname: str, domain: str,
user_agents_blocked: str,
2022-03-06 12:56:26 +00:00
crawlers_allowed: str,
2021-12-30 23:46:06 +00:00
translate: {}, reply_interval_hours: int,
2021-12-29 21:55:09 +00:00
cw_lists: {}, lists_enabled: str) -> str:
"""Filtering and blocking section of edit profile screen
"""
2021-12-30 23:46:06 +00:00
filter_str = ''
filter_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/filters.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(filter_filename):
with open(filter_filename, 'r') as filterfile:
filter_str = filterfile.read()
2021-12-30 23:46:06 +00:00
filter_bio_str = ''
filter_bio_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/filters_bio.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(filter_bio_filename):
with open(filter_bio_filename, 'r') as filterfile:
filter_bio_str = filterfile.read()
2021-12-14 14:27:56 +00:00
2021-12-30 23:46:06 +00:00
switch_str = ''
switch_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/replacewords.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(switch_filename):
with open(switch_filename, 'r') as switchfile:
switch_str = switchfile.read()
2021-12-30 23:46:06 +00:00
auto_tags = ''
auto_tags_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/autotags.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(auto_tags_filename):
with open(auto_tags_filename, 'r') as auto_file:
auto_tags = auto_file.read()
2021-12-30 23:46:06 +00:00
auto_cw = ''
auto_cw_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/autocw.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(auto_cw_filename):
with open(auto_cw_filename, 'r') as cw_file:
auto_cw = cw_file.read()
2021-12-30 23:46:06 +00:00
blocked_str = ''
blocked_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/blocking.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(blocked_filename):
with open(blocked_filename, 'r') as blockedfile:
blocked_str = blockedfile.read()
2021-12-30 23:46:06 +00:00
dm_allowed_instances_str = ''
dm_allowed_instances_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/dmAllowedInstances.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(dm_allowed_instances_filename):
with open(dm_allowed_instances_filename, 'r') as dm_file:
dm_allowed_instances_str = dm_file.read()
2021-12-30 23:46:06 +00:00
allowed_instances_str = ''
allowed_instances_filename = \
2021-12-26 12:02:29 +00:00
acct_dir(base_dir, nickname, domain) + '/allowedinstances.txt'
2021-12-30 23:46:06 +00:00
if os.path.isfile(allowed_instances_filename):
with open(allowed_instances_filename, 'r') as allow_file:
allowed_instances_str = allow_file.read()
2021-12-30 23:46:06 +00:00
edit_profile_form = begin_edit_section(translate['Filtering and Blocking'])
idx = 'Hours after posting during which replies are allowed'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
' <label class="labels">' + \
translate[idx] + \
':</label> <input type="number" name="replyhours" ' + \
'min="0" max="999999999999" step="1" ' + \
2021-12-30 23:46:06 +00:00
'value="' + str(reply_interval_hours) + '"><br>\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
'<label class="labels">' + \
translate['City for spoofed GPS image metadata'] + \
'</label><br>\n'
city = ''
2021-12-30 23:46:06 +00:00
city_filename = acct_dir(base_dir, nickname, domain) + '/city.txt'
if os.path.isfile(city_filename):
with open(city_filename, 'r') as city_file:
city = city_file.read().replace('\n', '')
locations_filename = base_dir + '/custom_locations.txt'
if not os.path.isfile(locations_filename):
locations_filename = base_dir + '/locations.txt'
cities = []
2021-12-30 23:46:06 +00:00
with open(locations_filename, 'r') as loc_file:
cities = loc_file.readlines()
cities.sort()
2021-12-30 23:46:06 +00:00
edit_profile_form += ' <select id="cityDropdown" ' + \
'name="cityDropdown" class="theme">\n'
city = city.lower()
2021-12-30 23:46:06 +00:00
for city_name in cities:
if ':' not in city_name:
continue
2021-12-30 23:46:06 +00:00
city_selected = ''
city_name = city_name.split(':')[0]
city_name = city_name.lower()
if city:
2021-12-30 23:46:06 +00:00
if city in city_name:
city_selected = ' selected'
edit_profile_form += \
' <option value="' + city_name + \
'"' + city_selected.title() + '>' + \
city_name + '</option>\n'
edit_profile_form += ' </select><br>\n'
edit_profile_form += \
' <b><label class="labels">' + \
2021-07-22 10:22:01 +00:00
translate['Filtered words'] + '</label></b>\n' + \
' <br><label class="labels">' + \
translate['One per line'] + '</label>\n' + \
' <textarea id="message" ' + \
'name="filteredWords" style="height:200px" spellcheck="false">' + \
2021-12-30 23:46:06 +00:00
filter_str + '</textarea>\n' + \
' <br><b><label class="labels">' + \
translate['Filtered words within bio'] + '</label></b>\n' + \
' <br><label class="labels">' + \
translate['One per line'] + '</label>\n' + \
' <textarea id="message" ' + \
'name="filteredWordsBio" style="height:200px" spellcheck="false">' + \
2021-12-30 23:46:06 +00:00
filter_bio_str + '</textarea>\n' + \
' <br><b><label class="labels">' + \
2021-07-22 10:22:01 +00:00
translate['Word Replacements'] + '</label></b>\n' + \
' <br><label class="labels">A -> B</label>\n' + \
2021-12-30 12:23:55 +00:00
' <textarea id="message" name="switchwords" ' + \
'style="height:200px" spellcheck="false">' + \
2021-12-30 23:46:06 +00:00
switch_str + '</textarea>\n' + \
' <br><b><label class="labels">' + \
2021-07-22 10:22:01 +00:00
translate['Autogenerated Hashtags'] + '</label></b>\n' + \
' <br><label class="labels">A -> #B</label>\n' + \
' <textarea id="message" name="autoTags" ' + \
'style="height:200px" spellcheck="false">' + \
2021-12-30 23:46:06 +00:00
auto_tags + '</textarea>\n' + \
' <br><b><label class="labels">' + \
2021-07-22 10:22:01 +00:00
translate['Autogenerated Content Warnings'] + '</label></b>\n' + \
' <br><label class="labels">A -> B</label>\n' + \
' <textarea id="message" name="autoCW" ' + \
2021-12-30 23:46:06 +00:00
'style="height:200px" spellcheck="true">' + auto_cw + '</textarea>\n'
idx = 'Blocked accounts, one per line, in the form ' + \
'nickname@domain or *@blockeddomain'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
edit_text_area(translate['Blocked accounts'], 'blocked', blocked_str,
2021-12-29 21:55:09 +00:00
200, '', False)
idx = 'Direct messages are always allowed from these instances.'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_area(translate['Direct Message permitted instances'],
2021-12-30 23:46:06 +00:00
'dmAllowedInstances', dm_allowed_instances_str,
2021-12-29 21:55:09 +00:00
200, '', False)
idx = 'Federate only with a defined set of instances. ' + \
'One domain name per line.'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-07-22 10:22:01 +00:00
' <br><b><label class="labels">' + \
translate['Federation list'] + '</label></b>\n' + \
' <br><label class="labels">' + \
2021-07-22 10:22:01 +00:00
translate[idx] + '</label>\n' + \
' <textarea id="message" name="allowedInstances" ' + \
'style="height:200px" spellcheck="false">' + \
2021-12-30 23:46:06 +00:00
allowed_instances_str + '</textarea>\n'
2021-12-28 19:33:29 +00:00
if is_moderator(base_dir, nickname):
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-10-24 09:57:10 +00:00
'<a href="/users/' + nickname + '/crawlers">' + \
translate['Known Web Crawlers'] + '</a><br>\n'
2021-12-30 13:56:38 +00:00
user_agents_blocked_str = ''
2021-12-30 23:46:06 +00:00
for uagent in user_agents_blocked:
2021-12-30 13:56:38 +00:00
if user_agents_blocked_str:
user_agents_blocked_str += '\n'
2021-12-30 23:46:06 +00:00
user_agents_blocked_str += uagent
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_area(translate['Blocked User Agents'],
2021-12-30 13:56:38 +00:00
'userAgentsBlockedStr', user_agents_blocked_str,
2021-12-29 21:55:09 +00:00
200, '', False)
2021-10-21 19:45:39 +00:00
2022-03-06 15:28:02 +00:00
edit_profile_form += \
'<a href="/users/' + nickname + '/bots.txt">' + \
translate['Known Search Bots'] + '</a><br>\n'
2022-03-06 12:56:26 +00:00
crawlers_allowed_str = ''
for uagent in crawlers_allowed:
if crawlers_allowed_str:
crawlers_allowed_str += '\n'
crawlers_allowed_str += uagent
edit_profile_form += \
2022-03-06 15:05:58 +00:00
edit_text_area(translate['Web Bots Allowed'],
2022-03-06 12:56:26 +00:00
'crawlersAllowedStr', crawlers_allowed_str,
200, '', False)
2021-12-30 23:46:06 +00:00
cw_lists_str = ''
for name, _ in cw_lists.items():
variablename = get_cw_list_variable(name)
list_is_enabled = False
2021-12-25 18:12:13 +00:00
if lists_enabled:
if name in lists_enabled:
2021-12-30 23:46:06 +00:00
list_is_enabled = True
2021-10-21 19:45:39 +00:00
if translate.get(name):
name = translate[name]
2021-12-30 23:46:06 +00:00
cw_lists_str += \
edit_check_box(name, variablename, list_is_enabled)
if cw_lists_str:
2021-10-21 19:45:39 +00:00
idx = 'Add content warnings for the following sites'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-10-21 19:45:39 +00:00
'<label class="labels">' + translate[idx] + ':</label>\n' + \
2021-12-30 23:46:06 +00:00
'<br>' + cw_lists_str
2021-10-21 16:58:01 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += end_edit_section()
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_edit_profile_change_password(translate: {}) -> str:
"""Change password section of edit profile screen
"""
2021-12-30 23:46:06 +00:00
edit_profile_form = \
2021-12-29 21:55:09 +00:00
begin_edit_section(translate['Change Password']) + \
'<label class="labels">' + translate['Change Password'] + \
2021-07-06 10:18:56 +00:00
'</label><br>\n' + \
2021-07-20 08:44:32 +00:00
' <input type="password" name="password" ' + \
2021-07-06 10:18:56 +00:00
'value=""><br>\n' + \
'<label class="labels">' + translate['Confirm Password'] + \
2021-07-06 10:18:56 +00:00
'</label><br>\n' + \
2021-07-20 08:44:32 +00:00
' <input type="password" name="passwordconfirm" value="">\n' + \
2021-12-29 21:55:09 +00:00
end_edit_section()
2021-12-30 23:46:06 +00:00
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_edit_profile_libre_translate(translate: {},
2021-12-30 23:46:06 +00:00
libretranslate_url: str,
libretranslate_api_key: str) -> str:
2021-07-19 19:40:04 +00:00
"""Change automatic translation settings
"""
2021-12-30 23:46:06 +00:00
edit_profile_form = begin_edit_section('LibreTranslate')
2021-07-19 19:40:04 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
edit_text_field('URL', 'libretranslateUrl', libretranslate_url,
2021-12-29 21:55:09 +00:00
'http://0.0.0.0:5000')
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field('API Key', 'libretranslateApiKey',
2021-12-30 23:46:06 +00:00
libretranslate_api_key)
2021-07-22 13:26:43 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += end_edit_section()
return edit_profile_form
2021-07-19 19:40:04 +00:00
2021-12-29 21:55:09 +00:00
def _html_edit_profile_background(news_instance: bool, translate: {}) -> str:
"""Background images section of edit profile screen
"""
idx = 'The files attached below should be no larger than ' + \
'10MB in total uploaded at once.'
2021-12-30 23:46:06 +00:00
edit_profile_form = \
2021-12-29 21:55:09 +00:00
begin_edit_section(translate['Background Images']) + \
' <label class="labels">' + translate[idx] + '</label><br><br>\n'
2021-12-25 20:20:08 +00:00
if not news_instance:
2021-12-30 23:46:06 +00:00
image_formats = get_image_formats()
edit_profile_form += \
' <label class="labels">' + \
2021-07-06 10:18:56 +00:00
translate['Background image'] + '</label>\n' + \
' <input type="file" id="image" name="image"' + \
2021-12-30 23:46:06 +00:00
' accept="' + image_formats + '">\n' + \
2021-07-06 10:18:56 +00:00
' <br><label class="labels">' + \
translate['Timeline banner image'] + '</label>\n' + \
' <input type="file" id="banner" name="banner"' + \
2021-12-30 23:46:06 +00:00
' accept="' + image_formats + '">\n' + \
2021-07-06 10:18:56 +00:00
' <br><label class="labels">' + \
translate['Search banner image'] + '</label>\n' + \
' <input type="file" id="search_banner" ' + \
'name="search_banner"' + \
2021-12-30 23:46:06 +00:00
' accept="' + image_formats + '">\n' + \
2021-07-06 10:18:56 +00:00
' <br><label class="labels">' + \
translate['Left column image'] + '</label>\n' + \
' <input type="file" id="left_col_image" ' + \
'name="left_col_image"' + \
2021-12-30 23:46:06 +00:00
' accept="' + image_formats + '">\n' + \
2021-07-06 10:18:56 +00:00
' <br><label class="labels">' + \
translate['Right column image'] + '</label>\n' + \
' <input type="file" id="right_col_image" ' + \
'name="right_col_image"' + \
2021-12-30 23:46:06 +00:00
' accept="' + image_formats + '">\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += end_edit_section()
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_edit_profile_contact_info(nickname: str,
2021-12-30 23:46:06 +00:00
email_address: str,
xmpp_address: str,
matrix_address: str,
ssb_address: str,
tox_address: str,
briar_address: str,
jami_address: str,
2021-12-30 20:48:38 +00:00
cwtch_address: str,
2021-12-29 21:55:09 +00:00
translate: {}) -> str:
"""Contact Information section of edit profile screen
"""
2021-12-30 23:46:06 +00:00
edit_profile_form = begin_edit_section(translate['Contact Details'])
edit_profile_form += edit_text_field(translate['Email'],
'email', email_address)
edit_profile_form += edit_text_field(translate['XMPP'],
'xmppAddress', xmpp_address)
edit_profile_form += edit_text_field(translate['Matrix'],
'matrixAddress', matrix_address)
edit_profile_form += edit_text_field('SSB', 'ssbAddress', ssb_address)
edit_profile_form += edit_text_field('Tox', 'toxAddress', tox_address)
edit_profile_form += edit_text_field('Briar', 'briarAddress',
briar_address)
edit_profile_form += edit_text_field('Jami', 'jamiAddress', jami_address)
edit_profile_form += edit_text_field('Cwtch', 'cwtchAddress',
cwtch_address)
edit_profile_form += \
'<a href="/users/' + nickname + \
'/followingaccounts"><label class="labels">' + \
translate['Following'] + '</label></a><br>\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += end_edit_section()
return edit_profile_form
2021-12-30 23:46:06 +00:00
def _html_edit_profile_encryption_keys(pgp_fingerprint: str,
pgp_pub_key: str,
enigma_pub_key: str,
2021-12-29 21:55:09 +00:00
translate: {}) -> str:
"""Contact Information section of edit profile screen
"""
2021-12-30 23:46:06 +00:00
edit_profile_form = begin_edit_section(translate['Encryption Keys'])
enigma_url = 'https://github.com/enigma-reloaded/enigma-reloaded'
edit_profile_form += \
edit_text_field('<a href="' + enigma_url + '">Enigma</a>',
'enigmapubkey', enigma_pub_key)
edit_profile_form += edit_text_field(translate['PGP Fingerprint'],
'openpgp', pgp_fingerprint)
edit_profile_form += \
edit_text_area(translate['PGP'], 'pgp', pgp_pub_key, 600,
2021-12-29 21:55:09 +00:00
'-----BEGIN PGP PUBLIC KEY BLOCK-----', False)
2021-07-22 10:22:01 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += end_edit_section()
return edit_profile_form
2021-12-30 23:46:06 +00:00
def _html_edit_profile_options(is_admin: bool,
manually_approves_followers: str,
is_bot: str, is_group: str,
follow_dms: str, remove_twitter: str,
notify_likes: str, notify_reactions: str,
hide_like_button: str,
hide_reaction_button: str,
2022-03-24 13:14:41 +00:00
translate: {}, bold_reading: bool) -> str:
"""option checkboxes section of edit profile screen
"""
2021-12-30 23:46:06 +00:00
edit_profile_form = ' <div class="container">\n'
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Approve follower requests'],
2021-12-30 23:46:06 +00:00
'approveFollowers', manually_approves_followers)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['This is a bot account'],
2021-12-30 23:46:06 +00:00
'isBot', is_bot)
if is_admin:
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['This is a group account'],
2021-12-30 23:46:06 +00:00
'isGroup', is_group)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Only people I follow can send me DMs'],
2021-12-30 23:46:06 +00:00
'followDMs', follow_dms)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Remove Twitter posts'],
2021-12-30 23:46:06 +00:00
'removeTwitter', remove_twitter)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Notify when posts are liked'],
2021-12-30 23:46:06 +00:00
'notifyLikes', notify_likes)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Notify on emoji reactions'],
2021-12-30 23:46:06 +00:00
'notifyReactions', notify_reactions)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate["Don't show the Like button"],
2021-12-30 23:46:06 +00:00
'hideLikeButton', hide_like_button)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate["Don't show the Reaction button"],
2021-12-30 23:46:06 +00:00
'hideReactionButton', hide_reaction_button)
2022-03-24 13:14:41 +00:00
bold_str = bold_reading_string(translate['Bold reading'])
edit_profile_form += \
edit_check_box(bold_str, 'boldReading', bold_reading)
2021-12-30 23:46:06 +00:00
edit_profile_form += ' </div>\n'
return edit_profile_form
2021-12-26 17:26:55 +00:00
def _get_supported_languagesSorted(base_dir: str) -> str:
"""Returns a list of supported languages
"""
2021-12-26 17:26:55 +00:00
lang_list = get_supported_languages(base_dir)
2021-12-26 10:35:37 +00:00
if not lang_list:
2021-07-18 18:57:08 +00:00
return ''
2021-12-26 10:35:37 +00:00
lang_list.sort()
2021-12-30 23:46:06 +00:00
languages_str = ''
2021-12-26 10:35:37 +00:00
for lang in lang_list:
2021-12-30 23:46:06 +00:00
if languages_str:
languages_str += ' / ' + lang
2021-07-18 18:57:08 +00:00
else:
2021-12-30 23:46:06 +00:00
languages_str = lang
return languages_str
2021-12-30 23:46:06 +00:00
def _html_edit_profile_main(base_dir: str, display_nickname: str, bio_str: str,
moved_to: str, donate_url: str, website_url: str,
blog_address: str, actor_json: {},
2022-02-25 19:57:31 +00:00
translate: {},
nickname: str, domain: str) -> str:
"""main info on edit profile screen
"""
2021-12-30 23:46:06 +00:00
image_formats = get_image_formats()
2021-12-30 23:46:06 +00:00
edit_profile_form = ' <div class="container">\n'
2021-07-06 10:18:56 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Nickname'], 'displayNickname',
2021-12-30 23:46:06 +00:00
display_nickname)
2021-07-06 10:18:56 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
edit_text_area(translate['Your bio'], 'bio', bio_str, 200, '', True)
2021-07-06 10:18:56 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
' <label class="labels">' + translate['Avatar image'] + \
2021-07-06 10:18:56 +00:00
'</label>\n' + \
' <input type="file" id="avatar" name="avatar"' + \
2021-12-30 23:46:06 +00:00
' accept="' + image_formats + '">\n'
2021-12-30 23:46:06 +00:00
occupation_name = ''
2021-12-26 10:29:52 +00:00
if actor_json.get('hasOccupation'):
2021-12-30 23:46:06 +00:00
occupation_name = get_occupation_name(actor_json)
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Occupation'], 'occupationName',
2021-12-30 23:46:06 +00:00
occupation_name)
2021-12-30 23:46:06 +00:00
also_known_as_str = ''
2021-12-26 10:29:52 +00:00
if actor_json.get('alsoKnownAs'):
2021-12-30 23:46:06 +00:00
also_known_as = actor_json['alsoKnownAs']
ctr = 0
2021-12-30 23:46:06 +00:00
for alt_actor in also_known_as:
if ctr > 0:
2021-12-30 23:46:06 +00:00
also_known_as_str += ', '
ctr += 1
2021-12-30 23:46:06 +00:00
also_known_as_str += alt_actor
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Other accounts'], 'alsoKnownAs',
2021-12-30 23:46:06 +00:00
also_known_as_str, 'https://...')
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Moved to new account address'], 'movedTo',
2021-12-30 23:46:06 +00:00
moved_to, 'https://...')
2021-07-06 10:18:56 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Donations link'], 'donateUrl',
2021-12-30 23:46:06 +00:00
donate_url, 'https://...')
2021-07-06 10:18:56 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Website'], 'websiteUrl',
2021-12-30 23:46:06 +00:00
website_url, 'https://...')
2021-08-12 20:40:23 +00:00
2021-12-30 23:46:06 +00:00
edit_profile_form += \
edit_text_field('Blog', 'blogAddress', blog_address, 'https://...')
2021-12-30 23:46:06 +00:00
languages_list_str = _get_supported_languagesSorted(base_dir)
show_languages = get_actor_languages(actor_json)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_text_field(translate['Languages'], 'showLanguages',
2021-12-30 23:46:06 +00:00
show_languages, languages_list_str)
2021-07-22 13:26:43 +00:00
2022-02-25 19:57:31 +00:00
timezone = get_account_timezone(base_dir, nickname, domain)
edit_profile_form += \
edit_text_field(translate['Time Zone'], 'timeZone',
timezone, 'Europe/London')
2021-12-30 23:46:06 +00:00
edit_profile_form += ' </div>\n'
return edit_profile_form
2021-12-29 21:55:09 +00:00
def _html_edit_profile_top_banner(base_dir: str,
nickname: str, domain: str, domain_full: str,
2021-12-30 23:46:06 +00:00
default_timeline: str, banner_file: str,
path: str, access_keys: {},
2021-12-29 21:55:09 +00:00
translate: {}) -> str:
"""top banner on edit profile screen
"""
2021-12-30 23:46:06 +00:00
edit_profile_form = \
'<a href="/users/' + nickname + '/' + default_timeline + '">' + \
2022-03-28 08:47:53 +00:00
'<img loading="lazy" decoding="async" ' + \
'class="timeline-banner" src="' + \
2021-12-30 23:46:06 +00:00
'/users/' + nickname + '/' + banner_file + '" alt="" /></a>\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += \
'<form enctype="multipart/form-data" method="POST" ' + \
'accept-charset="UTF-8" action="' + path + '/profiledata">\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += ' <div class="vertical-center">\n'
edit_profile_form += \
' <h1>' + translate['Profile for'] + \
2021-12-26 10:00:46 +00:00
' ' + nickname + '@' + domain_full + '</h1>'
2021-12-30 23:46:06 +00:00
edit_profile_form += ' <div class="container">\n'
edit_profile_form += \
' <center>\n' + \
' <input type="submit" name="submitProfile" ' + \
2021-12-30 23:46:06 +00:00
'accesskey="' + access_keys['submitButton'] + '" ' + \
'value="' + translate['Submit'] + '">\n' + \
' </center>\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += ' </div>\n'
2021-12-29 21:55:09 +00:00
if scheduled_posts_exist(base_dir, nickname, domain):
2021-12-30 23:46:06 +00:00
edit_profile_form += ' <div class="container">\n'
edit_profile_form += \
2021-12-29 21:55:09 +00:00
edit_check_box(translate['Remove scheduled posts'],
2021-12-30 13:56:38 +00:00
'removeScheduledPosts', False)
2021-12-30 23:46:06 +00:00
edit_profile_form += ' </div>\n'
return edit_profile_form
2022-03-24 13:14:41 +00:00
def html_edit_profile(server, css_cache: {}, translate: {},
base_dir: str, path: str,
2021-12-29 21:55:09 +00:00
domain: str, port: int, http_prefix: str,
2021-12-30 23:46:06 +00:00
default_timeline: str, theme: str,
2021-12-29 21:55:09 +00:00
peertube_instances: [],
text_mode_banner: str, city: str,
2022-03-06 12:56:26 +00:00
user_agents_blocked: [],
crawlers_allowed: [],
2021-12-30 23:46:06 +00:00
access_keys: {},
2021-12-29 21:55:09 +00:00
default_reply_interval_hrs: int,
cw_lists: {}, lists_enabled: str) -> str:
2020-11-09 22:44:03 +00:00
"""Shows the edit profile screen
"""
path = path.replace('/inbox', '').replace('/outbox', '')
2021-08-09 19:37:18 +00:00
path = path.replace('/shares', '').replace('/wanted', '')
2021-12-27 22:19:18 +00:00
nickname = get_nickname_from_actor(path)
2020-11-09 22:44:03 +00:00
if not nickname:
return ''
2021-12-26 12:45:03 +00:00
domain_full = get_full_domain(domain, port)
2020-11-09 22:44:03 +00:00
2022-03-24 13:14:41 +00:00
bold_reading = False
2022-03-24 13:21:40 +00:00
if server.bold_reading.get(nickname):
2022-03-24 13:14:41 +00:00
bold_reading = True
2021-12-30 23:46:06 +00:00
actor_filename = acct_dir(base_dir, nickname, domain) + '.json'
if not os.path.isfile(actor_filename):
2020-11-09 22:44:03 +00:00
return ''
# filename of the banner shown at the top
2021-12-30 23:46:06 +00:00
banner_file, _ = \
2021-12-29 21:55:09 +00:00
get_banner_file(base_dir, nickname, domain, theme)
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
display_nickname = nickname
is_bot = is_group = follow_dms = remove_twitter = ''
notify_likes = notify_reactions = ''
hide_like_button = hide_reaction_button = media_instance_str = ''
blogs_instance_str = news_instance_str = moved_to = twitter_str = ''
bio_str = donate_url = website_url = email_address = ''
pgp_pub_key = enigma_pub_key = ''
pgp_fingerprint = xmpp_address = matrix_address = ''
ssb_address = blog_address = tox_address = jami_address = ''
cwtch_address = briar_address = manually_approves_followers = ''
actor_json = load_json(actor_filename)
2021-12-26 10:29:52 +00:00
if actor_json:
if actor_json.get('movedTo'):
2021-12-30 23:46:06 +00:00
moved_to = actor_json['movedTo']
donate_url = get_donation_url(actor_json)
website_url = get_website(actor_json, translate)
xmpp_address = get_xmpp_address(actor_json)
matrix_address = get_matrix_address(actor_json)
ssb_address = get_ssb_address(actor_json)
blog_address = get_blog_address(actor_json)
tox_address = get_tox_address(actor_json)
briar_address = get_briar_address(actor_json)
jami_address = get_jami_address(actor_json)
2021-12-30 20:48:38 +00:00
cwtch_address = get_cwtch_address(actor_json)
2021-12-30 23:46:06 +00:00
email_address = get_email_address(actor_json)
enigma_pub_key = get_enigma_pub_key(actor_json)
pgp_pub_key = get_pgp_pub_key(actor_json)
pgp_fingerprint = get_pgp_fingerprint(actor_json)
2021-12-26 10:29:52 +00:00
if actor_json.get('name'):
2021-12-29 21:55:09 +00:00
if not is_filtered(base_dir, nickname, domain, actor_json['name']):
2021-12-30 23:46:06 +00:00
display_nickname = actor_json['name']
2021-12-26 10:29:52 +00:00
if actor_json.get('summary'):
2021-12-30 23:46:06 +00:00
bio_str = \
2021-12-26 10:29:52 +00:00
actor_json['summary'].replace('<p>', '').replace('</p>', '')
2021-12-30 23:46:06 +00:00
if is_filtered(base_dir, nickname, domain, bio_str):
bio_str = ''
2021-12-26 10:29:52 +00:00
if actor_json.get('manuallyApprovesFollowers'):
if actor_json['manuallyApprovesFollowers']:
2021-12-30 23:46:06 +00:00
manually_approves_followers = 'checked'
2020-11-09 22:44:03 +00:00
else:
2021-12-30 23:46:06 +00:00
manually_approves_followers = ''
2021-12-26 10:29:52 +00:00
if actor_json.get('type'):
if actor_json['type'] == 'Service':
2021-12-30 23:46:06 +00:00
is_bot = 'checked'
is_group = ''
2021-12-26 10:29:52 +00:00
elif actor_json['type'] == 'Group':
2021-12-30 23:46:06 +00:00
is_group = 'checked'
is_bot = ''
account_dir = acct_dir(base_dir, nickname, domain)
if os.path.isfile(account_dir + '/.followDMs'):
follow_dms = 'checked'
if os.path.isfile(account_dir + '/.removeTwitter'):
remove_twitter = 'checked'
if os.path.isfile(account_dir + '/.notifyLikes'):
notify_likes = 'checked'
if os.path.isfile(account_dir + '/.notifyReactions'):
notify_reactions = 'checked'
if os.path.isfile(account_dir + '/.hideLikeButton'):
hide_like_button = 'checked'
if os.path.isfile(account_dir + '/.hideReactionButton'):
hide_reaction_button = 'checked'
2020-11-09 22:44:03 +00:00
2021-12-30 13:56:38 +00:00
media_instance = get_config_param(base_dir, "mediaInstance")
2021-12-25 20:25:07 +00:00
if media_instance:
if media_instance is True:
2021-12-30 23:46:06 +00:00
media_instance_str = 'checked'
blogs_instance_str = news_instance_str = ''
2020-11-09 22:44:03 +00:00
2021-12-30 13:56:38 +00:00
news_instance = get_config_param(base_dir, "newsInstance")
2021-12-25 20:20:08 +00:00
if news_instance:
if news_instance is True:
2021-12-30 23:46:06 +00:00
news_instance_str = 'checked'
blogs_instance_str = media_instance_str = ''
2020-11-09 22:44:03 +00:00
2021-12-30 13:56:38 +00:00
blogs_instance = get_config_param(base_dir, "blogsInstance")
2021-12-25 20:22:25 +00:00
if blogs_instance:
if blogs_instance is True:
2021-12-30 23:46:06 +00:00
blogs_instance_str = 'checked'
media_instance_str = news_instance_str = ''
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
css_filename = base_dir + '/epicyon-profile.css'
2021-12-25 16:17:53 +00:00
if os.path.isfile(base_dir + '/epicyon.css'):
2021-12-30 23:46:06 +00:00
css_filename = base_dir + '/epicyon.css'
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
instance_str = ''
role_assign_str = ''
peertube_str = ''
libretranslate_str = ''
system_monitor_str = ''
graphics_str = ''
shares_federation_str = ''
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
admin_nickname = get_config_param(base_dir, 'admin')
2021-12-26 14:17:13 +00:00
if is_artist(base_dir, nickname) or \
2021-12-30 23:46:06 +00:00
path.startswith('/users/' + str(admin_nickname) + '/'):
graphics_str = _html_edit_profile_graphic_design(base_dir, translate)
is_admin = False
if admin_nickname:
if path.startswith('/users/' + admin_nickname + '/'):
is_admin = True
twitter_str = \
_html_edit_profile_twitter(base_dir, translate, remove_twitter)
# shared items section
2021-12-30 23:46:06 +00:00
shares_federation_str = \
2021-12-29 21:55:09 +00:00
_html_edit_profile_shared_items(base_dir, nickname,
domain, translate)
2021-12-30 23:46:06 +00:00
instance_str, role_assign_str, peertube_str, libretranslate_str = \
2021-12-29 21:55:09 +00:00
_html_edit_profile_instance(base_dir, translate,
peertube_instances,
2021-12-30 23:46:06 +00:00
media_instance_str,
blogs_instance_str,
news_instance_str)
system_monitor_str = _html_system_monitor(nickname, translate)
2020-12-24 11:56:17 +00:00
2021-12-30 23:46:06 +00:00
instance_title = get_config_param(base_dir, 'instanceTitle')
edit_profile_form = \
html_header_with_external_style(css_filename, instance_title, None)
2020-11-09 22:44:03 +00:00
# keyboard navigation
2021-12-30 23:46:06 +00:00
user_path_str = '/users/' + nickname
user_timeline_str = '/users/' + nickname + '/' + default_timeline
menu_timeline = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('🏠') + ' ' + \
2021-02-06 10:46:03 +00:00
translate['Switch to timeline view']
2021-12-30 23:46:06 +00:00
menu_profile = \
2021-12-29 21:55:09 +00:00
html_hide_from_screen_reader('👤') + ' ' + \
2021-02-06 10:46:03 +00:00
translate['Switch to profile view']
2021-12-30 23:46:06 +00:00
nav_links = {
menu_profile: user_path_str,
menu_timeline: user_timeline_str
2021-02-05 17:05:53 +00:00
}
2021-12-30 23:46:06 +00:00
nav_access_keys = {
menu_profile: 'p',
menu_timeline: 't'
2021-04-22 11:51:19 +00:00
}
2021-12-30 23:46:06 +00:00
edit_profile_form += \
html_keyboard_navigation(text_mode_banner, nav_links, nav_access_keys)
# top banner
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
_html_edit_profile_top_banner(base_dir, nickname, domain, domain_full,
2021-12-30 23:46:06 +00:00
default_timeline, banner_file,
path, access_keys, translate)
2020-11-09 22:44:03 +00:00
# main info
2021-12-30 23:46:06 +00:00
edit_profile_form += \
_html_edit_profile_main(base_dir, display_nickname, bio_str,
moved_to, donate_url, website_url,
2022-02-25 19:57:31 +00:00
blog_address, actor_json, translate,
nickname, domain)
2021-03-06 11:57:40 +00:00
# Option checkboxes
2021-12-30 23:46:06 +00:00
edit_profile_form += \
_html_edit_profile_options(is_admin, manually_approves_followers,
is_bot, is_group, follow_dms,
remove_twitter,
notify_likes, notify_reactions,
hide_like_button, hide_reaction_button,
2022-03-24 13:14:41 +00:00
translate, bold_reading)
2021-03-06 11:57:40 +00:00
# Contact information
2021-12-30 23:46:06 +00:00
edit_profile_form += \
_html_edit_profile_contact_info(nickname, email_address,
xmpp_address, matrix_address,
ssb_address, tox_address,
briar_address, jami_address,
2021-12-30 20:48:38 +00:00
cwtch_address, translate)
# Encryption Keys
2021-12-30 23:46:06 +00:00
edit_profile_form += \
_html_edit_profile_encryption_keys(pgp_fingerprint,
pgp_pub_key, enigma_pub_key,
translate)
2021-03-06 11:55:09 +00:00
# Customize images and banners
2021-12-30 23:46:06 +00:00
edit_profile_form += \
_html_edit_profile_background(news_instance, translate)
2021-03-06 11:55:09 +00:00
# Change password
2021-12-30 23:46:06 +00:00
edit_profile_form += _html_edit_profile_change_password(translate)
2020-11-09 22:44:03 +00:00
2021-07-19 19:40:04 +00:00
# automatic translations
2021-12-30 23:46:06 +00:00
edit_profile_form += libretranslate_str
2021-07-19 19:40:04 +00:00
# system monitor
2021-12-30 23:46:06 +00:00
edit_profile_form += system_monitor_str
# Filtering and blocking section
2021-12-30 23:46:06 +00:00
reply_interval_hours = \
get_reply_interval_hours(base_dir, nickname, domain,
default_reply_interval_hrs)
edit_profile_form += \
2021-12-29 21:55:09 +00:00
_html_edit_profile_filtering(base_dir, nickname, domain,
2022-03-06 12:56:26 +00:00
user_agents_blocked, crawlers_allowed,
translate, reply_interval_hours,
2021-12-29 21:55:09 +00:00
cw_lists, lists_enabled)
# git projects section
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
_html_edit_profile_git_projects(base_dir, nickname, domain, translate)
# Skills section
2021-12-30 23:46:06 +00:00
edit_profile_form += \
2021-12-29 21:55:09 +00:00
_html_edit_profile_skills(base_dir, nickname, domain, translate)
2021-12-30 23:46:06 +00:00
edit_profile_form += role_assign_str + peertube_str + graphics_str
edit_profile_form += shares_federation_str + twitter_str + instance_str
2021-03-06 15:18:56 +00:00
# danger zone section
2021-12-30 23:46:06 +00:00
edit_profile_form += _html_edit_profile_danger_zone(translate)
2021-12-30 23:46:06 +00:00
edit_profile_form += ' <div class="container">\n'
edit_profile_form += \
' <center>\n' + \
' <input type="submit" name="submitProfile" value="' + \
translate['Submit'] + '">\n' + \
' </center>\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += ' </div>\n'
2021-12-30 23:46:06 +00:00
edit_profile_form += ' </div>\n'
edit_profile_form += '</form>\n'
edit_profile_form += html_footer()
return edit_profile_form
2020-11-09 22:44:03 +00:00
2021-12-29 21:55:09 +00:00
def _individual_follow_as_html(signing_priv_key_pem: str,
translate: {},
base_dir: str, session,
cached_webfingers: {},
person_cache: {}, domain: str,
followUrl: str,
authorized: bool,
2021-12-30 23:46:06 +00:00
actor_nickname: str,
2021-12-29 21:55:09 +00:00
http_prefix: str,
project_version: str,
dormant: bool,
debug: bool,
buttons=[]) -> str:
2020-11-09 22:44:03 +00:00
"""An individual follow entry on the profile screen
"""
2021-12-30 23:46:06 +00:00
follow_url_nickname = get_nickname_from_actor(followUrl)
if not follow_url_nickname:
return ''
2021-12-30 23:46:06 +00:00
follow_url_domain, follow_url_port = get_domain_from_actor(followUrl)
follow_url_domain_full = \
get_full_domain(follow_url_domain, follow_url_port)
title_str = '@' + follow_url_nickname + '@' + follow_url_domain_full
avatar_url = get_person_avatar_url(base_dir, followUrl, person_cache, True)
if not avatar_url:
avatar_url = followUrl + '/avatar.png'
display_name = get_display_name(base_dir, followUrl, person_cache)
is_group = False
if not display_name:
# lookup the correct webfinger for the followUrl
2021-12-30 23:46:06 +00:00
follow_url_handle = follow_url_nickname + '@' + follow_url_domain_full
follow_url_wf = \
webfinger_handle(session, follow_url_handle, http_prefix,
2021-12-29 21:55:09 +00:00
cached_webfingers,
domain, __version__, debug, False,
signing_priv_key_pem)
2021-12-30 23:46:06 +00:00
origin_domain = domain
(_, _, _, _, _, avatar_url2,
display_name, is_group) = get_person_box(signing_priv_key_pem,
origin_domain,
base_dir, session,
follow_url_wf,
person_cache,
project_version,
http_prefix,
follow_url_nickname,
domain, 'outbox', 43036)
if avatar_url2:
avatar_url = avatar_url2
if display_name:
display_name = \
2021-12-29 21:55:09 +00:00
add_emoji_to_display_name(None, base_dir, http_prefix,
2021-12-30 23:46:06 +00:00
actor_nickname, domain,
display_name, False)
title_str = display_name
2021-01-12 10:23:25 +00:00
if dormant:
2021-12-30 23:46:06 +00:00
title_str += ' 💤'
2020-11-09 22:44:03 +00:00
2021-12-30 23:46:06 +00:00
buttons_str = ''
2020-11-09 22:44:03 +00:00
if authorized:
2021-12-30 23:46:06 +00:00
for btn in buttons:
if btn == 'block':
buttons_str += \
'<a href="/users/' + actor_nickname + \
2020-11-09 22:44:03 +00:00
'?options=' + followUrl + \
2021-12-30 23:46:06 +00:00
';1;' + avatar_url + \
'"><button class="buttonunfollow">' + \
2020-11-09 22:44:03 +00:00
translate['Block'] + '</button></a>\n'
2021-12-30 23:46:06 +00:00
elif btn == 'unfollow':
unfollow_str = 'Unfollow'
if is_group or \
2021-12-26 17:33:24 +00:00
is_group_account(base_dir,
2021-12-30 23:46:06 +00:00
follow_url_nickname, follow_url_domain):
unfollow_str = 'Leave'
buttons_str += \
'<a href="/users/' + actor_nickname + \
2020-11-09 22:44:03 +00:00
'?options=' + followUrl + \
2021-12-30 23:46:06 +00:00
';1;' + avatar_url + \
'"><button class="buttonunfollow">' + \
translate[unfollow_str] + '</button></a>\n'
result_str = '<div class="container">\n'
result_str += \
'<a href="/users/' + actor_nickname + '?options=' + \
followUrl + ';1;' + avatar_url + '">\n'
2022-03-28 08:47:53 +00:00
result_str += '<p><img loading="lazy" decoding="async" ' + \
'src="' + avatar_url + '" alt=" ">'
2021-12-30 23:46:06 +00:00
result_str += title_str + '</a>' + buttons_str + '</p>\n'
result_str += '</div>\n'
return result_str