mirror of https://gitlab.com/bashrc2/epicyon
Variable types
parent
c12c28dd76
commit
3a7a2ee0f5
|
|
@ -173,32 +173,31 @@ def html_theme_designer(base_dir: str,
|
||||||
theme_name: str, access_keys: {}) -> str:
|
theme_name: str, access_keys: {}) -> str:
|
||||||
"""Edit theme settings
|
"""Edit theme settings
|
||||||
"""
|
"""
|
||||||
theme_filename = base_dir + '/theme/' + theme_name + '/theme.json'
|
theme_filename: str = base_dir + '/theme/' + theme_name + '/theme.json'
|
||||||
theme_json = {}
|
theme_json: dict = {}
|
||||||
if is_a_file(theme_filename):
|
if is_a_file(theme_filename):
|
||||||
theme_json = load_json(theme_filename)
|
theme_json = load_json(theme_filename)
|
||||||
|
|
||||||
# set custom theme parameters
|
# set custom theme parameters
|
||||||
custom_variables_file = data_dir(base_dir) + '/theme.json'
|
custom_variables_file: str = data_dir(base_dir) + '/theme.json'
|
||||||
if is_a_file(custom_variables_file):
|
if is_a_file(custom_variables_file):
|
||||||
custom_theme_params = load_json(custom_variables_file)
|
custom_theme_params: str = load_json(custom_variables_file)
|
||||||
if custom_theme_params:
|
if custom_theme_params:
|
||||||
for variable_name, value in custom_theme_params.items():
|
for variable_name, value in custom_theme_params.items():
|
||||||
theme_json[variable_name] = value
|
theme_json[variable_name] = value
|
||||||
|
|
||||||
theme_form: str = ''
|
theme_form: str = ''
|
||||||
css_filename = base_dir + '/epicyon-profile.css'
|
css_filename: str = base_dir + '/epicyon-profile.css'
|
||||||
if is_a_file(base_dir + '/epicyon.css'):
|
if is_a_file(base_dir + '/epicyon.css'):
|
||||||
css_filename = base_dir + '/epicyon.css'
|
css_filename = base_dir + '/epicyon.css'
|
||||||
|
|
||||||
banner_file, _ = \
|
banner_file, _ = \
|
||||||
get_banner_file(base_dir, nickname, domain, theme_name)
|
get_banner_file(base_dir, nickname, domain, theme_name)
|
||||||
banner_path = '/users/' + nickname + '/' + banner_file
|
banner_path: str = '/users/' + nickname + '/' + banner_file
|
||||||
|
|
||||||
instance_title = \
|
instance_title: str = get_config_param(base_dir, 'instanceTitle')
|
||||||
get_config_param(base_dir, 'instanceTitle')
|
preload_images: list[str] = [banner_path]
|
||||||
preload_images = [banner_path]
|
theme_form: str = \
|
||||||
theme_form = \
|
|
||||||
html_header_with_external_style(css_filename, instance_title, None,
|
html_header_with_external_style(css_filename, instance_title, None,
|
||||||
preload_images)
|
preload_images)
|
||||||
theme_form += \
|
theme_form += \
|
||||||
|
|
@ -216,8 +215,8 @@ def html_theme_designer(base_dir: str,
|
||||||
theme_form += ' <form method="POST" action="' + \
|
theme_form += ' <form method="POST" action="' + \
|
||||||
'/users/' + nickname + '/changeThemeSettings">\n'
|
'/users/' + nickname + '/changeThemeSettings">\n'
|
||||||
|
|
||||||
reset_key = access_keys['menuLogout']
|
reset_key: str = access_keys['menuLogout']
|
||||||
submit_key = access_keys['submitButton']
|
submit_key: str = access_keys['submitButton']
|
||||||
theme_form += \
|
theme_form += \
|
||||||
' <center>\n' + \
|
' <center>\n' + \
|
||||||
' <button type="submit" class="button" ' + \
|
' <button type="submit" class="button" ' + \
|
||||||
|
|
@ -230,13 +229,13 @@ def html_theme_designer(base_dir: str,
|
||||||
|
|
||||||
contrast_warning: str = ''
|
contrast_warning: str = ''
|
||||||
if theme_json.get('main-bg-color'):
|
if theme_json.get('main-bg-color'):
|
||||||
background = theme_json['main-bg-color']
|
background: str = theme_json['main-bg-color']
|
||||||
if theme_json.get('main-fg-color'):
|
if theme_json.get('main-fg-color'):
|
||||||
foreground = theme_json['main-fg-color']
|
foreground: str = theme_json['main-fg-color']
|
||||||
contrast = color_contrast(background, foreground)
|
contrast: float = color_contrast(background, foreground)
|
||||||
if contrast:
|
if contrast:
|
||||||
if contrast < 4.5:
|
if contrast < 4.5:
|
||||||
contrast_warning = '⚠️ '
|
contrast_warning: str = '⚠️ '
|
||||||
theme_form += \
|
theme_form += \
|
||||||
' <center><label class="labels">' + \
|
' <center><label class="labels">' + \
|
||||||
contrast_warning + '<b>' + \
|
contrast_warning + '<b>' + \
|
||||||
|
|
@ -250,15 +249,15 @@ def html_theme_designer(base_dir: str,
|
||||||
table_str += ' </colgroup>\n'
|
table_str += ' </colgroup>\n'
|
||||||
table_str += ' <tbody>\n'
|
table_str += ' <tbody>\n'
|
||||||
|
|
||||||
font_str = ' <div class="container">\n' + table_str
|
font_str: str = ' <div class="container">\n' + table_str
|
||||||
color_str = ' <div class="container">\n' + table_str
|
color_str: str = ' <div class="container">\n' + table_str
|
||||||
dimension_str = ' <div class="container">\n' + table_str
|
dimension_str: str = ' <div class="container">\n' + table_str
|
||||||
switch_str = ' <div class="container">\n' + table_str
|
switch_str: str = ' <div class="container">\n' + table_str
|
||||||
for variable_name, value in theme_json.items():
|
for variable_name, value in theme_json.items():
|
||||||
if 'font-size' in variable_name:
|
if 'font-size' in variable_name:
|
||||||
variable_name_str = variable_name.replace('-', ' ')
|
variable_name_str: str = variable_name.replace('-', ' ')
|
||||||
variable_name_str = variable_name_str.title()
|
variable_name_str = variable_name_str.title()
|
||||||
variable_name_label = variable_name_str
|
variable_name_label: str = variable_name_str
|
||||||
if contrast_warning:
|
if contrast_warning:
|
||||||
if variable_name in ('main-bg-color', 'main-fg-color'):
|
if variable_name in ('main-bg-color', 'main-fg-color'):
|
||||||
variable_name_label = contrast_warning + variable_name_str
|
variable_name_label = contrast_warning + variable_name_str
|
||||||
|
|
@ -333,8 +332,8 @@ def html_theme_designer(base_dir: str,
|
||||||
dimension_str += ' </table>\n </div>\n'
|
dimension_str += ' </table>\n </div>\n'
|
||||||
switch_str += ' </table>\n </div>\n'
|
switch_str += ' </table>\n </div>\n'
|
||||||
|
|
||||||
theme_formats = '.zip, .gz'
|
theme_formats: str = '.zip, .gz'
|
||||||
export_import_str = ' <div class="container">\n'
|
export_import_str: str = ' <div class="container">\n'
|
||||||
export_import_str += \
|
export_import_str += \
|
||||||
' <label class="labels">' + \
|
' <label class="labels">' + \
|
||||||
translate['Import Theme'] + '</label>\n'
|
translate['Import Theme'] + '</label>\n'
|
||||||
|
|
@ -362,7 +361,7 @@ def _relative_luminance(color: str) -> float:
|
||||||
"""
|
"""
|
||||||
color = color.lstrip('#')
|
color = color.lstrip('#')
|
||||||
rgb = list(int(color[i:i+2], 16) for i in (0, 2, 4))
|
rgb = list(int(color[i:i+2], 16) for i in (0, 2, 4))
|
||||||
srgb = (
|
srgb: list[float] = (
|
||||||
rgb[0] / 255.0,
|
rgb[0] / 255.0,
|
||||||
rgb[1] / 255.0,
|
rgb[1] / 255.0,
|
||||||
rgb[2] / 255.0
|
rgb[2] / 255.0
|
||||||
|
|
@ -397,8 +396,8 @@ def color_contrast(background: str, foreground: str) -> float:
|
||||||
foreground = color_to_hex[foreground]
|
foreground = color_to_hex[foreground]
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
background_luminance = _relative_luminance(background)
|
background_luminance: float = _relative_luminance(background)
|
||||||
foreground_luminance = _relative_luminance(foreground)
|
foreground_luminance: float = _relative_luminance(foreground)
|
||||||
if background_luminance > foreground_luminance:
|
if background_luminance > foreground_luminance:
|
||||||
return (0.05 + background_luminance) / (0.05 + foreground_luminance)
|
return (0.05 + background_luminance) / (0.05 + foreground_luminance)
|
||||||
return (0.05 + foreground_luminance) / (0.05 + background_luminance)
|
return (0.05 + foreground_luminance) / (0.05 + background_luminance)
|
||||||
|
|
|
||||||
|
|
@ -62,7 +62,7 @@ def _log_timeline_timing(enable_timing_log: bool, timeline_start_time,
|
||||||
"""
|
"""
|
||||||
if not enable_timing_log:
|
if not enable_timing_log:
|
||||||
return
|
return
|
||||||
time_diff = int((time.time() - timeline_start_time) * 1000)
|
time_diff: int = int((time.time() - timeline_start_time) * 1000)
|
||||||
if time_diff > 100:
|
if time_diff > 100:
|
||||||
print('TIMELINE TIMING ' +
|
print('TIMELINE TIMING ' +
|
||||||
box_name + ' ' + debug_id + ' = ' + str(time_diff))
|
box_name + ' ' + debug_id + ' = ' + str(time_diff))
|
||||||
|
|
@ -72,15 +72,13 @@ def _get_help_for_timeline(base_dir: str, box_name: str) -> str:
|
||||||
"""Shows help text for the given timeline
|
"""Shows help text for the given timeline
|
||||||
"""
|
"""
|
||||||
# get the filename for help for this timeline
|
# get the filename for help for this timeline
|
||||||
help_filename = data_dir(base_dir) + '/help_' + box_name + '.md'
|
help_filename: str = data_dir(base_dir) + '/help_' + box_name + '.md'
|
||||||
if not is_a_file(help_filename):
|
if not is_a_file(help_filename):
|
||||||
language = \
|
language: str = get_config_param(base_dir, 'language')
|
||||||
get_config_param(base_dir, 'language')
|
|
||||||
if not language:
|
if not language:
|
||||||
language = 'en'
|
language = 'en'
|
||||||
theme_name = \
|
theme_name: str = get_config_param(base_dir, 'theme')
|
||||||
get_config_param(base_dir, 'theme')
|
default_filename: str = None
|
||||||
default_filename = None
|
|
||||||
if theme_name:
|
if theme_name:
|
||||||
default_filename = \
|
default_filename = \
|
||||||
base_dir + '/theme/' + theme_name + '/welcome/' + \
|
base_dir + '/theme/' + theme_name + '/welcome/' + \
|
||||||
|
|
@ -99,18 +97,17 @@ def _get_help_for_timeline(base_dir: str, box_name: str) -> str:
|
||||||
|
|
||||||
# show help text
|
# show help text
|
||||||
if is_a_file(help_filename):
|
if is_a_file(help_filename):
|
||||||
instance_title = \
|
instance_title: str = get_config_param(base_dir, 'instanceTitle')
|
||||||
get_config_param(base_dir, 'instanceTitle')
|
|
||||||
if not instance_title:
|
if not instance_title:
|
||||||
instance_title = 'Epicyon'
|
instance_title = 'Epicyon'
|
||||||
help_text = \
|
help_text: str = \
|
||||||
load_string(help_filename,
|
load_string(help_filename,
|
||||||
'EX: _get_help_for_timeline unable to read ' +
|
'EX: _get_help_for_timeline unable to read ' +
|
||||||
help_filename)
|
help_filename)
|
||||||
if help_text:
|
if help_text:
|
||||||
if dangerous_markup(help_text, False, []):
|
if dangerous_markup(help_text, False, []):
|
||||||
return ''
|
return ''
|
||||||
help_text = help_text.replace('INSTANCE', instance_title)
|
help_text: str = help_text.replace('INSTANCE', instance_title)
|
||||||
return '<div class="container">\n' + \
|
return '<div class="container">\n' + \
|
||||||
markdown_to_html(help_text) + '\n' + \
|
markdown_to_html(help_text) + '\n' + \
|
||||||
'</div>\n'
|
'</div>\n'
|
||||||
|
|
@ -285,22 +282,22 @@ def _html_timeline_keyboard(moderator: bool, text_mode_banner: str,
|
||||||
access_keys: {}, translate: {}) -> str:
|
access_keys: {}, translate: {}) -> str:
|
||||||
"""Returns html for timeline keyboard navigation
|
"""Returns html for timeline keyboard navigation
|
||||||
"""
|
"""
|
||||||
calendar_str = translate['Calendar']
|
calendar_str: str = translate['Calendar']
|
||||||
if new_calendar_event:
|
if new_calendar_event:
|
||||||
calendar_str = '<strong>' + calendar_str + '</strong>'
|
calendar_str = '<strong>' + calendar_str + '</strong>'
|
||||||
dm_str = translate['DM']
|
dm_str: str = translate['DM']
|
||||||
if new_dm:
|
if new_dm:
|
||||||
dm_str = '<strong>' + dm_str + '</strong>'
|
dm_str = '<strong>' + dm_str + '</strong>'
|
||||||
replies_str = translate['Replies']
|
replies_str: str = translate['Replies']
|
||||||
if new_reply:
|
if new_reply:
|
||||||
replies_str = '<strong>' + replies_str + '</strong>'
|
replies_str = '<strong>' + replies_str + '</strong>'
|
||||||
shares_str = translate['Shares']
|
shares_str: str = translate['Shares']
|
||||||
if new_share:
|
if new_share:
|
||||||
shares_str = '<strong>' + shares_str + '</strong>'
|
shares_str = '<strong>' + shares_str + '</strong>'
|
||||||
wanted_str = translate['Wanted']
|
wanted_str: str = translate['Wanted']
|
||||||
if new_wanted:
|
if new_wanted:
|
||||||
wanted_str = '<strong>' + wanted_str + '</strong>'
|
wanted_str = '<strong>' + wanted_str + '</strong>'
|
||||||
menu_profile = \
|
menu_profile: str = \
|
||||||
html_hide_from_screen_reader('👤') + ' ' + \
|
html_hide_from_screen_reader('👤') + ' ' + \
|
||||||
translate['Switch to profile view']
|
translate['Switch to profile view']
|
||||||
menu_inbox = \
|
menu_inbox = \
|
||||||
|
|
@ -333,7 +330,7 @@ def _html_timeline_keyboard(moderator: bool, text_mode_banner: str,
|
||||||
translate['Create a new post']
|
translate['Create a new post']
|
||||||
menu_moderation = \
|
menu_moderation = \
|
||||||
html_hide_from_screen_reader('⚡️') + ' ' + translate['Mod']
|
html_hide_from_screen_reader('⚡️') + ' ' + translate['Mod']
|
||||||
nav_links = {
|
nav_links: dict = {
|
||||||
menu_profile: '/users/' + nickname,
|
menu_profile: '/users/' + nickname,
|
||||||
menu_inbox: users_path + '/inbox#timelineposts',
|
menu_inbox: users_path + '/inbox#timelineposts',
|
||||||
menu_search: users_path + '/search',
|
menu_search: users_path + '/search',
|
||||||
|
|
@ -349,7 +346,7 @@ def _html_timeline_keyboard(moderator: bool, text_mode_banner: str,
|
||||||
menu_newswire: users_path + '/newswiremobile',
|
menu_newswire: users_path + '/newswiremobile',
|
||||||
menu_links: users_path + '/linksmobile'
|
menu_links: users_path + '/linksmobile'
|
||||||
}
|
}
|
||||||
nav_access_keys = {}
|
nav_access_keys: dict = {}
|
||||||
for variable_name, key in access_keys.items():
|
for variable_name, key in access_keys.items():
|
||||||
if not locals().get(variable_name):
|
if not locals().get(variable_name):
|
||||||
continue
|
continue
|
||||||
|
|
@ -375,7 +372,7 @@ def _html_timeline_end(base_dir: str, nickname: str, domain_full: str,
|
||||||
"""Ending of the timeline, containing the right column
|
"""Ending of the timeline, containing the right column
|
||||||
"""
|
"""
|
||||||
# end of timeline-posts
|
# end of timeline-posts
|
||||||
tl_str = ' </div>\n'
|
tl_str: str = ' </div>\n'
|
||||||
|
|
||||||
# end of column-center
|
# end of column-center
|
||||||
tl_str += ' </td>\n'
|
tl_str += ' </td>\n'
|
||||||
|
|
@ -421,11 +418,11 @@ def page_number_buttons(users_path: str, box_name: str,
|
||||||
num_str: str = ''
|
num_str: str = ''
|
||||||
for page in range(min_page_number, max_page_number):
|
for page in range(min_page_number, max_page_number):
|
||||||
if num_str:
|
if num_str:
|
||||||
separator_str = \
|
separator_str: str = \
|
||||||
'<label class="pageslistDash">────</label>'
|
'<label class="pageslistDash">────</label>'
|
||||||
num_str += html_hide_from_screen_reader(separator_str)
|
num_str += html_hide_from_screen_reader(separator_str)
|
||||||
aria_page_str: str = ''
|
aria_page_str: str = ''
|
||||||
page_str = ' ' + str(page) + ' '
|
page_str: str = ' ' + str(page) + ' '
|
||||||
curr_page_str: str = ''
|
curr_page_str: str = ''
|
||||||
if page == page_number:
|
if page == page_number:
|
||||||
page_str = '[<mark>' + str(page) + '</mark>]'
|
page_str = '[<mark>' + str(page) + '</mark>]'
|
||||||
|
|
@ -495,17 +492,17 @@ def html_timeline(default_timeline: str,
|
||||||
|
|
||||||
timeline_start_time = time.time()
|
timeline_start_time = time.time()
|
||||||
|
|
||||||
account_dir = acct_dir(base_dir, nickname, domain)
|
account_dir: str = acct_dir(base_dir, nickname, domain)
|
||||||
|
|
||||||
# should the calendar icon be highlighted?
|
# should the calendar icon be highlighted?
|
||||||
new_calendar_event: bool = False
|
new_calendar_event: bool = False
|
||||||
calendar_image = 'calendar.png'
|
calendar_image: str = 'calendar.png'
|
||||||
calendar_path = '/calendar'
|
calendar_path: str = '/calendar'
|
||||||
calendar_file = account_dir + '/.newCalendar'
|
calendar_file: str = account_dir + '/.newCalendar'
|
||||||
if is_a_file(calendar_file):
|
if is_a_file(calendar_file):
|
||||||
new_calendar_event = True
|
new_calendar_event = True
|
||||||
calendar_image = 'calendar_notify.png'
|
calendar_image = 'calendar_notify.png'
|
||||||
calendar_path_str = \
|
calendar_path_str: str = \
|
||||||
load_string(calendar_file,
|
load_string(calendar_file,
|
||||||
'EX: html_timeline unable to read ' +
|
'EX: html_timeline unable to read ' +
|
||||||
calendar_file)
|
calendar_file)
|
||||||
|
|
@ -517,7 +514,7 @@ def html_timeline(default_timeline: str,
|
||||||
|
|
||||||
# should the DM button be highlighted?
|
# should the DM button be highlighted?
|
||||||
new_dm: bool = False
|
new_dm: bool = False
|
||||||
dm_file = account_dir + '/.newDM'
|
dm_file: str = account_dir + '/.newDM'
|
||||||
if is_a_file(dm_file):
|
if is_a_file(dm_file):
|
||||||
new_dm = True
|
new_dm = True
|
||||||
if box_name == 'dm':
|
if box_name == 'dm':
|
||||||
|
|
@ -526,7 +523,7 @@ def html_timeline(default_timeline: str,
|
||||||
|
|
||||||
# should the Replies button be highlighted?
|
# should the Replies button be highlighted?
|
||||||
new_reply: bool = False
|
new_reply: bool = False
|
||||||
reply_file = account_dir + '/.newReply'
|
reply_file: str = account_dir + '/.newReply'
|
||||||
if is_a_file(reply_file):
|
if is_a_file(reply_file):
|
||||||
new_reply = True
|
new_reply = True
|
||||||
if box_name == 'tlreplies':
|
if box_name == 'tlreplies':
|
||||||
|
|
@ -535,7 +532,7 @@ def html_timeline(default_timeline: str,
|
||||||
|
|
||||||
# should the Shares button be highlighted?
|
# should the Shares button be highlighted?
|
||||||
new_share: bool = False
|
new_share: bool = False
|
||||||
new_share_file = account_dir + '/.newShare'
|
new_share_file: str = account_dir + '/.newShare'
|
||||||
if is_a_file(new_share_file):
|
if is_a_file(new_share_file):
|
||||||
new_share = True
|
new_share = True
|
||||||
if box_name == 'tlshares':
|
if box_name == 'tlshares':
|
||||||
|
|
@ -545,7 +542,7 @@ def html_timeline(default_timeline: str,
|
||||||
|
|
||||||
# should the Wanted button be highlighted?
|
# should the Wanted button be highlighted?
|
||||||
new_wanted: bool = False
|
new_wanted: bool = False
|
||||||
new_wanted_file = account_dir + '/.newWanted'
|
new_wanted_file: str = account_dir + '/.newWanted'
|
||||||
if is_a_file(new_wanted_file):
|
if is_a_file(new_wanted_file):
|
||||||
new_wanted = True
|
new_wanted = True
|
||||||
if box_name == 'tlwanted':
|
if box_name == 'tlwanted':
|
||||||
|
|
@ -555,7 +552,7 @@ def html_timeline(default_timeline: str,
|
||||||
|
|
||||||
# should the Moderation/reports button be highlighted?
|
# should the Moderation/reports button be highlighted?
|
||||||
new_report: bool = False
|
new_report: bool = False
|
||||||
new_report_file = account_dir + '/.newReport'
|
new_report_file: str = account_dir + '/.newReport'
|
||||||
if is_a_file(new_report_file):
|
if is_a_file(new_report_file):
|
||||||
new_report = True
|
new_report = True
|
||||||
if box_name == 'moderation':
|
if box_name == 'moderation':
|
||||||
|
|
@ -565,7 +562,7 @@ def html_timeline(default_timeline: str,
|
||||||
|
|
||||||
# show polls/votes?
|
# show polls/votes?
|
||||||
show_vote_posts: bool = True
|
show_vote_posts: bool = True
|
||||||
show_vote_file = account_dir + '/.noVotes'
|
show_vote_file: str = account_dir + '/.noVotes'
|
||||||
if is_a_file(show_vote_file):
|
if is_a_file(show_vote_file):
|
||||||
show_vote_posts = False
|
show_vote_posts = False
|
||||||
|
|
||||||
|
|
@ -574,7 +571,7 @@ def html_timeline(default_timeline: str,
|
||||||
separator_str = html_post_separator(base_dir, None)
|
separator_str = html_post_separator(base_dir, None)
|
||||||
|
|
||||||
# the css filename
|
# the css filename
|
||||||
css_filename = base_dir + '/epicyon-profile.css'
|
css_filename: str = base_dir + '/epicyon-profile.css'
|
||||||
if is_a_file(base_dir + '/epicyon.css'):
|
if is_a_file(base_dir + '/epicyon.css'):
|
||||||
css_filename = base_dir + '/epicyon.css'
|
css_filename = base_dir + '/epicyon.css'
|
||||||
|
|
||||||
|
|
@ -647,16 +644,16 @@ def html_timeline(default_timeline: str,
|
||||||
bookmarks_button = 'buttonselected'
|
bookmarks_button = 'buttonselected'
|
||||||
|
|
||||||
# get the full domain, including any port number
|
# get the full domain, including any port number
|
||||||
full_domain = get_full_domain(domain, port)
|
full_domain: str = get_full_domain(domain, port)
|
||||||
|
|
||||||
users_path = '/users/' + nickname
|
users_path: str = '/users/' + nickname
|
||||||
actor = http_prefix + '://' + full_domain + users_path
|
actor: str = http_prefix + '://' + full_domain + users_path
|
||||||
|
|
||||||
show_individual_post_icons = True
|
show_individual_post_icons: bool = True
|
||||||
|
|
||||||
# show an icon for new follow approvals
|
# show an icon for new follow approvals
|
||||||
follow_approvals: str = ''
|
follow_approvals: str = ''
|
||||||
follow_requests_filename = \
|
follow_requests_filename: str = \
|
||||||
acct_dir(base_dir, nickname, domain) + '/followrequests.txt'
|
acct_dir(base_dir, nickname, domain) + '/followrequests.txt'
|
||||||
if is_a_file(follow_requests_filename):
|
if is_a_file(follow_requests_filename):
|
||||||
follow_requests_list: list[str] = \
|
follow_requests_list: list[str] = \
|
||||||
|
|
@ -731,13 +728,12 @@ def html_timeline(default_timeline: str,
|
||||||
'<span>' + translate['Bookmarks'] + '</span></button></a>'
|
'<span>' + translate['Bookmarks'] + '</span></button></a>'
|
||||||
|
|
||||||
# filename of the banner shown at the top
|
# filename of the banner shown at the top
|
||||||
banner_file, _ = \
|
banner_file, _ = get_banner_file(base_dir, nickname, domain, theme)
|
||||||
get_banner_file(base_dir, nickname, domain, theme)
|
banner_path: str = users_path + '/' + banner_file
|
||||||
banner_path = users_path + '/' + banner_file
|
|
||||||
|
|
||||||
# these images are pre-loaded to prevent the web page from
|
# these images are pre-loaded to prevent the web page from
|
||||||
# jumping around when rendering
|
# jumping around when rendering
|
||||||
preload_images = [
|
preload_images: list[str] = [
|
||||||
banner_path,
|
banner_path,
|
||||||
'/icons/showhide.png',
|
'/icons/showhide.png',
|
||||||
'/icons/repeat_hide.png',
|
'/icons/repeat_hide.png',
|
||||||
|
|
@ -762,9 +758,8 @@ def html_timeline(default_timeline: str,
|
||||||
'/icons/categoriesrss.png'
|
'/icons/categoriesrss.png'
|
||||||
]
|
]
|
||||||
|
|
||||||
instance_title = \
|
instance_title: str = get_config_param(base_dir, 'instanceTitle')
|
||||||
get_config_param(base_dir, 'instanceTitle')
|
tl_str: str = \
|
||||||
tl_str = \
|
|
||||||
html_header_with_external_style(css_filename, instance_title, None,
|
html_header_with_external_style(css_filename, instance_title, None,
|
||||||
preload_images)
|
preload_images)
|
||||||
|
|
||||||
|
|
@ -781,7 +776,7 @@ def html_timeline(default_timeline: str,
|
||||||
header_icons_str = '<div class="headericons">'
|
header_icons_str = '<div class="headericons">'
|
||||||
|
|
||||||
# what screen to go to when a new post is created
|
# what screen to go to when a new post is created
|
||||||
new_post_button_str = \
|
new_post_button_str: str = \
|
||||||
_html_timeline_new_post(manually_approve_followers, box_name,
|
_html_timeline_new_post(manually_approve_followers, box_name,
|
||||||
users_path, translate,
|
users_path, translate,
|
||||||
access_keys)
|
access_keys)
|
||||||
|
|
@ -1018,7 +1013,7 @@ def html_timeline(default_timeline: str,
|
||||||
if nickname in min_images_for_accounts:
|
if nickname in min_images_for_accounts:
|
||||||
minimize_all_images = True
|
minimize_all_images = True
|
||||||
|
|
||||||
no_seen_posts_filename = account_dir + '/.noSeenPosts'
|
no_seen_posts_filename: str = account_dir + '/.noSeenPosts'
|
||||||
no_seen_posts: bool = False
|
no_seen_posts: bool = False
|
||||||
if is_a_file(no_seen_posts_filename):
|
if is_a_file(no_seen_posts_filename):
|
||||||
no_seen_posts = True
|
no_seen_posts = True
|
||||||
|
|
@ -1213,7 +1208,7 @@ def html_individual_share(domain: str, share_id: str,
|
||||||
shares_file_type: str) -> str:
|
shares_file_type: str) -> str:
|
||||||
"""Returns an individual shared item as html
|
"""Returns an individual shared item as html
|
||||||
"""
|
"""
|
||||||
profile_str = '<div class="container">\n'
|
profile_str: str = '<div class="container">\n'
|
||||||
profile_str += \
|
profile_str += \
|
||||||
'<p class="share-title">' + shared_item['displayName'] + '</p>\n'
|
'<p class="share-title">' + shared_item['displayName'] + '</p>\n'
|
||||||
if shared_item.get('imageUrl'):
|
if shared_item.get('imageUrl'):
|
||||||
|
|
@ -1237,7 +1232,7 @@ def html_individual_share(domain: str, share_id: str,
|
||||||
profile_str += \
|
profile_str += \
|
||||||
'<b>' + translate['Location'] + ':</b> ' + \
|
'<b>' + translate['Location'] + ':</b> ' + \
|
||||||
shared_item['location'] + '<br>'
|
shared_item['location'] + '<br>'
|
||||||
contact_title_str = translate['Contact']
|
contact_title_str: str = translate['Contact']
|
||||||
if shared_item.get('itemPrice') and shared_item.get('itemCurrency'):
|
if shared_item.get('itemPrice') and shared_item.get('itemCurrency'):
|
||||||
if is_float(shared_item['itemPrice']):
|
if is_float(shared_item['itemPrice']):
|
||||||
if float(shared_item['itemPrice']) > 0:
|
if float(shared_item['itemPrice']) > 0:
|
||||||
|
|
@ -1247,15 +1242,15 @@ def html_individual_share(domain: str, share_id: str,
|
||||||
shared_item['itemCurrency']
|
shared_item['itemCurrency']
|
||||||
contact_title_str = translate['Buy']
|
contact_title_str = translate['Buy']
|
||||||
profile_str += '</p>\n'
|
profile_str += '</p>\n'
|
||||||
sharedesc = shared_item['displayName']
|
sharedesc: str = shared_item['displayName']
|
||||||
if '<' not in sharedesc and ';' not in sharedesc:
|
if '<' not in sharedesc and ';' not in sharedesc:
|
||||||
if show_contact:
|
if show_contact:
|
||||||
button_style_str = 'button'
|
button_style_str: str = 'button'
|
||||||
if shared_item['category'] == 'accommodation':
|
if shared_item['category'] == 'accommodation':
|
||||||
contact_title_str = translate['Request to stay']
|
contact_title_str = translate['Request to stay']
|
||||||
button_style_str = 'contactbutton'
|
button_style_str = 'contactbutton'
|
||||||
|
|
||||||
contact_actor = get_actor_from_post(shared_item)
|
contact_actor: str = get_actor_from_post(shared_item)
|
||||||
profile_str += \
|
profile_str += \
|
||||||
'<p>' + \
|
'<p>' + \
|
||||||
'<a href="' + actor + \
|
'<a href="' + actor + \
|
||||||
|
|
@ -1294,9 +1289,9 @@ def _html_shares_timeline(translate: {}, page_number: int, items_per_page: int,
|
||||||
base_dir, domain, nickname,
|
base_dir, domain, nickname,
|
||||||
max_shares_per_account,
|
max_shares_per_account,
|
||||||
shared_items_federated_domains, shares_file_type)
|
shared_items_federated_domains, shares_file_type)
|
||||||
domain_full = get_full_domain(domain, port)
|
domain_full: str = get_full_domain(domain, port)
|
||||||
actor = local_actor_url(http_prefix, nickname, domain_full)
|
actor: str = local_actor_url(http_prefix, nickname, domain_full)
|
||||||
admin_nickname = get_config_param(base_dir, 'admin')
|
admin_nickname: str = get_config_param(base_dir, 'admin')
|
||||||
admin_actor: str = ''
|
admin_actor: str = ''
|
||||||
if admin_nickname:
|
if admin_nickname:
|
||||||
admin_actor = \
|
admin_actor = \
|
||||||
|
|
@ -1318,7 +1313,7 @@ def _html_shares_timeline(translate: {}, page_number: int, items_per_page: int,
|
||||||
'" alt="' + translate['Page up'] + '"></a>\n' + \
|
'" alt="' + translate['Page up'] + '"></a>\n' + \
|
||||||
' </center>\n'
|
' </center>\n'
|
||||||
|
|
||||||
separator_str = html_post_separator(base_dir, None)
|
separator_str: str = html_post_separator(base_dir, None)
|
||||||
ctr: int = 0
|
ctr: int = 0
|
||||||
|
|
||||||
is_admin_account: bool = False
|
is_admin_account: bool = False
|
||||||
|
|
@ -1409,10 +1404,10 @@ def html_shares(default_timeline: str,
|
||||||
block_nostr: {}) -> str:
|
block_nostr: {}) -> str:
|
||||||
"""Show the shares timeline as html
|
"""Show the shares timeline as html
|
||||||
"""
|
"""
|
||||||
manually_approve_followers = \
|
manually_approve_followers: bool = \
|
||||||
follower_approval_active(base_dir, nickname, domain)
|
follower_approval_active(base_dir, nickname, domain)
|
||||||
artist = is_artist(base_dir, nickname)
|
artist: bool = is_artist(base_dir, nickname)
|
||||||
show_announces = True
|
show_announces: bool = True
|
||||||
|
|
||||||
return html_timeline(default_timeline,
|
return html_timeline(default_timeline,
|
||||||
recent_posts_cache, max_recent_posts,
|
recent_posts_cache, max_recent_posts,
|
||||||
|
|
@ -1490,10 +1485,10 @@ def html_wanted(default_timeline: str,
|
||||||
block_nostr: {}) -> str:
|
block_nostr: {}) -> str:
|
||||||
"""Show the wanted timeline as html
|
"""Show the wanted timeline as html
|
||||||
"""
|
"""
|
||||||
manually_approve_followers = \
|
manually_approve_followers: bool = \
|
||||||
follower_approval_active(base_dir, nickname, domain)
|
follower_approval_active(base_dir, nickname, domain)
|
||||||
artist = is_artist(base_dir, nickname)
|
artist: bool = is_artist(base_dir, nickname)
|
||||||
show_announces = True
|
show_announces: bool = True
|
||||||
|
|
||||||
return html_timeline(default_timeline,
|
return html_timeline(default_timeline,
|
||||||
recent_posts_cache, max_recent_posts,
|
recent_posts_cache, max_recent_posts,
|
||||||
|
|
@ -1574,9 +1569,9 @@ def html_inbox(default_timeline: str,
|
||||||
block_nostr: {}) -> str:
|
block_nostr: {}) -> str:
|
||||||
"""Show the inbox as html
|
"""Show the inbox as html
|
||||||
"""
|
"""
|
||||||
manually_approve_followers = \
|
manually_approve_followers: bool = \
|
||||||
follower_approval_active(base_dir, nickname, domain)
|
follower_approval_active(base_dir, nickname, domain)
|
||||||
artist = is_artist(base_dir, nickname)
|
artist: bool = is_artist(base_dir, nickname)
|
||||||
|
|
||||||
return html_timeline(default_timeline,
|
return html_timeline(default_timeline,
|
||||||
recent_posts_cache, max_recent_posts,
|
recent_posts_cache, max_recent_posts,
|
||||||
|
|
@ -1655,10 +1650,10 @@ def html_bookmarks(default_timeline: str,
|
||||||
block_nostr: {}) -> str:
|
block_nostr: {}) -> str:
|
||||||
"""Show the bookmarks as html
|
"""Show the bookmarks as html
|
||||||
"""
|
"""
|
||||||
manually_approve_followers = \
|
manually_approve_followers: bool = \
|
||||||
follower_approval_active(base_dir, nickname, domain)
|
follower_approval_active(base_dir, nickname, domain)
|
||||||
artist = is_artist(base_dir, nickname)
|
artist: bool = is_artist(base_dir, nickname)
|
||||||
show_announces = True
|
show_announces: bool = True
|
||||||
|
|
||||||
return html_timeline(default_timeline,
|
return html_timeline(default_timeline,
|
||||||
recent_posts_cache, max_recent_posts,
|
recent_posts_cache, max_recent_posts,
|
||||||
|
|
@ -2192,9 +2187,9 @@ def html_outbox(default_timeline: str,
|
||||||
block_nostr: {}) -> str:
|
block_nostr: {}) -> str:
|
||||||
"""Show the Outbox as html
|
"""Show the Outbox as html
|
||||||
"""
|
"""
|
||||||
manually_approve_followers = \
|
manually_approve_followers: bool = \
|
||||||
follower_approval_active(base_dir, nickname, domain)
|
follower_approval_active(base_dir, nickname, domain)
|
||||||
artist = is_artist(base_dir, nickname)
|
artist: bool = is_artist(base_dir, nickname)
|
||||||
return html_timeline(default_timeline,
|
return html_timeline(default_timeline,
|
||||||
recent_posts_cache, max_recent_posts,
|
recent_posts_cache, max_recent_posts,
|
||||||
translate, page_number,
|
translate, page_number,
|
||||||
|
|
|
||||||
238
webapp_utils.py
238
webapp_utils.py
|
|
@ -77,11 +77,11 @@ def minimizing_attached_images(base_dir: str, nickname: str, domain: str,
|
||||||
if following_nickname == nickname and following_domain == domain:
|
if following_nickname == nickname and following_domain == domain:
|
||||||
# reminder post
|
# reminder post
|
||||||
return False
|
return False
|
||||||
minimize_filename = \
|
minimize_filename: str = \
|
||||||
acct_dir(base_dir, nickname, domain) + '/followingMinimizeImages.txt'
|
acct_dir(base_dir, nickname, domain) + '/followingMinimizeImages.txt'
|
||||||
handle = following_nickname + '@' + following_domain
|
handle: str = following_nickname + '@' + following_domain
|
||||||
if not is_a_file(minimize_filename):
|
if not is_a_file(minimize_filename):
|
||||||
following_filename = \
|
following_filename: str = \
|
||||||
acct_dir(base_dir, nickname, domain) + '/following.txt'
|
acct_dir(base_dir, nickname, domain) + '/following.txt'
|
||||||
if not is_a_file(following_filename):
|
if not is_a_file(following_filename):
|
||||||
return False
|
return False
|
||||||
|
|
@ -103,21 +103,22 @@ def get_broken_link_substitute() -> str:
|
||||||
def html_following_list(base_dir: str, following_filename: str) -> str:
|
def html_following_list(base_dir: str, following_filename: str) -> str:
|
||||||
"""Returns a list of handles being followed
|
"""Returns a list of handles being followed
|
||||||
"""
|
"""
|
||||||
msg = load_string(following_filename,
|
msg: str = \
|
||||||
|
load_string(following_filename,
|
||||||
'EX: html_following_list unable to read ' +
|
'EX: html_following_list unable to read ' +
|
||||||
following_filename)
|
following_filename)
|
||||||
if msg:
|
if msg:
|
||||||
following_list = msg.split('\n')
|
following_list: list[str] = msg.split('\n')
|
||||||
following_list.sort()
|
following_list.sort()
|
||||||
if following_list:
|
if following_list:
|
||||||
css_filename = base_dir + '/epicyon-profile.css'
|
css_filename: str = base_dir + '/epicyon-profile.css'
|
||||||
if is_a_file(base_dir + '/epicyon.css'):
|
if is_a_file(base_dir + '/epicyon.css'):
|
||||||
css_filename = base_dir + '/epicyon.css'
|
css_filename = base_dir + '/epicyon.css'
|
||||||
|
|
||||||
instance_title = \
|
instance_title: str = \
|
||||||
get_config_param(base_dir, 'instanceTitle')
|
get_config_param(base_dir, 'instanceTitle')
|
||||||
preload_images: list[str] = []
|
preload_images: list[str] = []
|
||||||
following_list_html = \
|
following_list_html: str = \
|
||||||
html_header_with_external_style(css_filename,
|
html_header_with_external_style(css_filename,
|
||||||
instance_title, None,
|
instance_title, None,
|
||||||
preload_images)
|
preload_images)
|
||||||
|
|
@ -135,11 +136,12 @@ def csv_following_list(following_filename: str,
|
||||||
base_dir: str, nickname: str, domain: str) -> str:
|
base_dir: str, nickname: str, domain: str) -> str:
|
||||||
"""Returns a csv of handles being followed
|
"""Returns a csv of handles being followed
|
||||||
"""
|
"""
|
||||||
msg = load_string(following_filename,
|
msg: str = \
|
||||||
|
load_string(following_filename,
|
||||||
'EX: csv_following_list unable to read ' +
|
'EX: csv_following_list unable to read ' +
|
||||||
following_filename)
|
following_filename)
|
||||||
if msg:
|
if msg:
|
||||||
following_list = msg.split('\n')
|
following_list: list[str] = msg.split('\n')
|
||||||
following_list.sort()
|
following_list.sort()
|
||||||
if following_list:
|
if following_list:
|
||||||
following_list_csv: str = ''
|
following_list_csv: str = ''
|
||||||
|
|
@ -147,23 +149,23 @@ def csv_following_list(following_filename: str,
|
||||||
if not following_address:
|
if not following_address:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
following_nickname = \
|
following_nickname: str = \
|
||||||
get_nickname_from_actor(following_address)
|
get_nickname_from_actor(following_address)
|
||||||
following_domain, _ = \
|
following_domain, _ = \
|
||||||
get_domain_from_actor(following_address)
|
get_domain_from_actor(following_address)
|
||||||
|
|
||||||
announce_is_allowed = \
|
announce_is_allowed: bool = \
|
||||||
allowed_announce(base_dir, nickname, domain,
|
allowed_announce(base_dir, nickname, domain,
|
||||||
following_nickname,
|
following_nickname,
|
||||||
following_domain)
|
following_domain)
|
||||||
notify_on_new = 'false'
|
notify_on_new: str = 'false'
|
||||||
languages: str = ''
|
languages: str = ''
|
||||||
person_notes = \
|
person_notes: str = \
|
||||||
get_person_notes(base_dir, nickname, domain,
|
get_person_notes(base_dir, nickname, domain,
|
||||||
following_address)
|
following_address)
|
||||||
if person_notes:
|
if person_notes:
|
||||||
# make notes suitable for csv file
|
# make notes suitable for csv file
|
||||||
replacements = {
|
replacements: dict = {
|
||||||
',': ' ',
|
',': ' ',
|
||||||
'"': "'",
|
'"': "'",
|
||||||
'\n': '<br>',
|
'\n': '<br>',
|
||||||
|
|
@ -189,14 +191,14 @@ def html_hashtag_blocked(base_dir: str, translate: {}) -> str:
|
||||||
"""Show the screen for a blocked hashtag
|
"""Show the screen for a blocked hashtag
|
||||||
"""
|
"""
|
||||||
blocked_hashtag_form: str = ''
|
blocked_hashtag_form: str = ''
|
||||||
css_filename = base_dir + '/epicyon-suspended.css'
|
css_filename: str = base_dir + '/epicyon-suspended.css'
|
||||||
if is_a_file(base_dir + '/suspended.css'):
|
if is_a_file(base_dir + '/suspended.css'):
|
||||||
css_filename = base_dir + '/suspended.css'
|
css_filename = base_dir + '/suspended.css'
|
||||||
|
|
||||||
instance_title = \
|
instance_title: str = \
|
||||||
get_config_param(base_dir, 'instanceTitle')
|
get_config_param(base_dir, 'instanceTitle')
|
||||||
preload_images: list[str] = []
|
preload_images: list[str] = []
|
||||||
blocked_hashtag_form = \
|
blocked_hashtag_form: str = \
|
||||||
html_header_with_external_style(css_filename, instance_title, None,
|
html_header_with_external_style(css_filename, instance_title, None,
|
||||||
preload_images)
|
preload_images)
|
||||||
blocked_hashtag_form += '<div><center>\n'
|
blocked_hashtag_form += '<div><center>\n'
|
||||||
|
|
@ -275,7 +277,7 @@ def get_show_map_button(post_id: str, translate: {},
|
||||||
map_content: str) -> str:
|
map_content: str) -> str:
|
||||||
"""Returns the markup for a "show map" button
|
"""Returns the markup for a "show map" button
|
||||||
"""
|
"""
|
||||||
show_map_str = 'Show Map'
|
show_map_str: str = 'Show Map'
|
||||||
if translate.get('Show Map'):
|
if translate.get('Show Map'):
|
||||||
show_map_str = translate['Show Map']
|
show_map_str = translate['Show Map']
|
||||||
html_str = ' <details><summary class="cw" tabindex="10">' + \
|
html_str = ' <details><summary class="cw" tabindex="10">' + \
|
||||||
|
|
@ -289,7 +291,7 @@ def open_content_warning(text: str, translate: {}) -> str:
|
||||||
"""Opens content warning when replying to a post with a cw
|
"""Opens content warning when replying to a post with a cw
|
||||||
so that you can see what you are replying to
|
so that you can see what you are replying to
|
||||||
"""
|
"""
|
||||||
text = replace_embedded_map_with_link(text, translate)
|
text: str = replace_embedded_map_with_link(text, translate)
|
||||||
text = text.replace('<details>', '').replace('</details>', '')
|
text = text.replace('<details>', '').replace('</details>', '')
|
||||||
text = text.replace(translate['Show Map'], '', 1)
|
text = text.replace(translate['Show Map'], '', 1)
|
||||||
text = text.replace(translate['SHOW MORE'], '', 1)
|
text = text.replace(translate['SHOW MORE'], '', 1)
|
||||||
|
|
@ -303,7 +305,7 @@ def _set_actor_property_url(actor_json: {},
|
||||||
if not actor_json.get('attachment'):
|
if not actor_json.get('attachment'):
|
||||||
actor_json['attachment']: list[dict] = []
|
actor_json['attachment']: list[dict] = []
|
||||||
|
|
||||||
property_name_lower = property_name.lower()
|
property_name_lower: str = property_name.lower()
|
||||||
|
|
||||||
# remove any existing value
|
# remove any existing value
|
||||||
property_found = None
|
property_found = None
|
||||||
|
|
@ -397,17 +399,17 @@ def update_avatar_image_cache(signing_priv_key_pem: str,
|
||||||
"""
|
"""
|
||||||
if not avatar_url:
|
if not avatar_url:
|
||||||
return None
|
return None
|
||||||
actor_str = actor.replace('/', '-')
|
actor_str: str = actor.replace('/', '-')
|
||||||
avatar_image_path = base_dir + '/cache/avatars/' + actor_str
|
avatar_image_path: str = base_dir + '/cache/avatars/' + actor_str
|
||||||
|
|
||||||
# try different image types
|
# try different image types
|
||||||
image_formats = image_mime_types_dict()
|
image_formats = image_mime_types_dict()
|
||||||
avatar_image_filename = None
|
avatar_image_filename: str = None
|
||||||
session_headers = None
|
session_headers = None
|
||||||
for im_format, mime_type in image_formats.items():
|
for im_format, mime_type in image_formats.items():
|
||||||
if avatar_url.endswith('.' + im_format) or \
|
if avatar_url.endswith('.' + im_format) or \
|
||||||
'.' + im_format + '?' in avatar_url:
|
'.' + im_format + '?' in avatar_url:
|
||||||
session_headers = {
|
session_headers: dict = {
|
||||||
'Accept': 'image/' + mime_type
|
'Accept': 'image/' + mime_type
|
||||||
}
|
}
|
||||||
avatar_image_filename = avatar_image_path + '.' + im_format
|
avatar_image_filename = avatar_image_path + '.' + im_format
|
||||||
|
|
@ -454,7 +456,7 @@ def update_avatar_image_cache(signing_priv_key_pem: str,
|
||||||
except BaseException as ex:
|
except BaseException as ex:
|
||||||
print('EX: Failed to download avatar image: ' +
|
print('EX: Failed to download avatar image: ' +
|
||||||
str(avatar_url) + ' ' + str(ex))
|
str(avatar_url) + ' ' + str(ex))
|
||||||
prof = 'https://www.w3.org/ns/activitystreams'
|
prof: str = 'https://www.w3.org/ns/activitystreams'
|
||||||
if '/channel/' not in actor or '/accounts/' not in actor:
|
if '/channel/' not in actor or '/accounts/' not in actor:
|
||||||
session_headers = {
|
session_headers = {
|
||||||
'Accept': 'application/activity+json; profile="' + prof + '"'
|
'Accept': 'application/activity+json; profile="' + prof + '"'
|
||||||
|
|
@ -463,13 +465,15 @@ def update_avatar_image_cache(signing_priv_key_pem: str,
|
||||||
session_headers = {
|
session_headers = {
|
||||||
'Accept': 'application/ld+json; profile="' + prof + '"'
|
'Accept': 'application/ld+json; profile="' + prof + '"'
|
||||||
}
|
}
|
||||||
person_json = \
|
person_json: dict = \
|
||||||
get_json(signing_priv_key_pem, session, actor,
|
get_json(signing_priv_key_pem, session, actor,
|
||||||
session_headers, None,
|
session_headers, None,
|
||||||
debug, mitm_servers, __version__, http_prefix, None)
|
debug, mitm_servers, __version__, http_prefix, None)
|
||||||
if get_json_valid(person_json):
|
if get_json_valid(person_json):
|
||||||
if not person_json.get('id'):
|
if not person_json.get('id'):
|
||||||
return None
|
return None
|
||||||
|
if not isinstance(person_json['id'], str):
|
||||||
|
return None
|
||||||
pub_key, _ = get_actor_public_key_from_id(person_json, None)
|
pub_key, _ = get_actor_public_key_from_id(person_json, None)
|
||||||
if not pub_key:
|
if not pub_key:
|
||||||
return None
|
return None
|
||||||
|
|
@ -495,7 +499,7 @@ def update_avatar_image_cache(signing_priv_key_pem: str,
|
||||||
def scheduled_posts_exist(base_dir: str, nickname: str, domain: str) -> bool:
|
def scheduled_posts_exist(base_dir: str, nickname: str, domain: str) -> bool:
|
||||||
"""Returns true if there are posts scheduled to be delivered
|
"""Returns true if there are posts scheduled to be delivered
|
||||||
"""
|
"""
|
||||||
schedule_index_filename = \
|
schedule_index_filename: str = \
|
||||||
acct_dir(base_dir, nickname, domain) + '/schedule.index'
|
acct_dir(base_dir, nickname, domain) + '/schedule.index'
|
||||||
if not is_a_file(schedule_index_filename):
|
if not is_a_file(schedule_index_filename):
|
||||||
return False
|
return False
|
||||||
|
|
@ -513,27 +517,29 @@ def shares_timeline_json(actor: str, page_number: int, items_per_page: int,
|
||||||
max_shares_per_account helps to avoid one person dominating the timeline
|
max_shares_per_account helps to avoid one person dominating the timeline
|
||||||
by sharing a large number of things
|
by sharing a large number of things
|
||||||
"""
|
"""
|
||||||
all_shares_json = {}
|
all_shares_json: dict = {}
|
||||||
dir_str = data_dir(base_dir)
|
dir_str: str = data_dir(base_dir)
|
||||||
for _, dirs, files in os.walk(dir_str):
|
for _, dirs, files in os.walk(dir_str):
|
||||||
for handle in dirs:
|
for handle in dirs:
|
||||||
if not is_account_dir(handle):
|
if not is_account_dir(handle):
|
||||||
continue
|
continue
|
||||||
account_dir = acct_handle_dir(base_dir, handle)
|
account_dir: str = acct_handle_dir(base_dir, handle)
|
||||||
shares_filename = account_dir + '/' + shares_file_type + '.json'
|
shares_filename: str = \
|
||||||
|
account_dir + '/' + shares_file_type + '.json'
|
||||||
if not is_a_file(shares_filename):
|
if not is_a_file(shares_filename):
|
||||||
continue
|
continue
|
||||||
shares_json = load_json(shares_filename)
|
shares_json = load_json(shares_filename)
|
||||||
if not shares_json:
|
if not shares_json:
|
||||||
continue
|
continue
|
||||||
account_nickname = handle.split('@')[0]
|
account_nickname: str = handle.split('@')[0]
|
||||||
# Don't include shared items from blocked accounts
|
# Don't include shared items from blocked accounts
|
||||||
if account_nickname != nickname:
|
if account_nickname != nickname:
|
||||||
if is_blocked(base_dir, nickname, domain,
|
if is_blocked(base_dir, nickname, domain,
|
||||||
account_nickname, domain, None, None):
|
account_nickname, domain, None, None):
|
||||||
continue
|
continue
|
||||||
# actor who owns this share
|
# actor who owns this share
|
||||||
owner = actor.split('/users/')[0] + '/users/' + account_nickname
|
owner: str = \
|
||||||
|
actor.split('/users/')[0] + '/users/' + account_nickname
|
||||||
ctr: int = 0
|
ctr: int = 0
|
||||||
for item_id, item in shares_json.items():
|
for item_id, item in shares_json.items():
|
||||||
# assign owner to the item
|
# assign owner to the item
|
||||||
|
|
@ -546,9 +552,9 @@ def shares_timeline_json(actor: str, page_number: int, items_per_page: int,
|
||||||
break
|
break
|
||||||
if shared_items_federated_domains:
|
if shared_items_federated_domains:
|
||||||
if shares_file_type == 'shares':
|
if shares_file_type == 'shares':
|
||||||
catalogs_dir = base_dir + '/cache/catalogs'
|
catalogs_dir: str = base_dir + '/cache/catalogs'
|
||||||
else:
|
else:
|
||||||
catalogs_dir = base_dir + '/cache/wantedItems'
|
catalogs_dir: str = base_dir + '/cache/wantedItems'
|
||||||
if is_a_dir(catalogs_dir):
|
if is_a_dir(catalogs_dir):
|
||||||
for _, dirs, files in os.walk(catalogs_dir):
|
for _, dirs, files in os.walk(catalogs_dir):
|
||||||
for fname in files:
|
for fname in files:
|
||||||
|
|
@ -556,11 +562,11 @@ def shares_timeline_json(actor: str, page_number: int, items_per_page: int,
|
||||||
continue
|
continue
|
||||||
if not fname.endswith('.' + shares_file_type + '.json'):
|
if not fname.endswith('.' + shares_file_type + '.json'):
|
||||||
continue
|
continue
|
||||||
federated_domain = fname.split('.')[0]
|
federated_domain: str = fname.split('.')[0]
|
||||||
if federated_domain not in shared_items_federated_domains:
|
if federated_domain not in shared_items_federated_domains:
|
||||||
continue
|
continue
|
||||||
shares_filename = catalogs_dir + '/' + fname
|
shares_filename: str = catalogs_dir + '/' + fname
|
||||||
shares_json = load_json(shares_filename)
|
shares_json: dict = load_json(shares_filename)
|
||||||
if not shares_json:
|
if not shares_json:
|
||||||
continue
|
continue
|
||||||
ctr: int = 0
|
ctr: int = 0
|
||||||
|
|
@ -568,14 +574,15 @@ def shares_timeline_json(actor: str, page_number: int, items_per_page: int,
|
||||||
# assign owner to the item
|
# assign owner to the item
|
||||||
if '--shareditems--' not in item_id:
|
if '--shareditems--' not in item_id:
|
||||||
continue
|
continue
|
||||||
share_actor = item_id.split('--shareditems--')[0]
|
share_actor: str = item_id.split('--shareditems--')[0]
|
||||||
replacements = {
|
replacements: dict = {
|
||||||
'___': '://',
|
'___': '://',
|
||||||
'--': '/'
|
'--': '/'
|
||||||
}
|
}
|
||||||
share_actor = \
|
share_actor: str = \
|
||||||
replace_strings(share_actor, replacements)
|
replace_strings(share_actor, replacements)
|
||||||
share_nickname = get_nickname_from_actor(share_actor)
|
share_nickname: str = \
|
||||||
|
get_nickname_from_actor(share_actor)
|
||||||
if not share_nickname:
|
if not share_nickname:
|
||||||
continue
|
continue
|
||||||
if is_blocked(base_dir, nickname, domain,
|
if is_blocked(base_dir, nickname, domain,
|
||||||
|
|
@ -590,9 +597,10 @@ def shares_timeline_json(actor: str, page_number: int, items_per_page: int,
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
# sort the shared items in descending order of publication date
|
# sort the shared items in descending order of publication date
|
||||||
shares_json = OrderedDict(sorted(all_shares_json.items(), reverse=True))
|
shares_json: dict = \
|
||||||
|
OrderedDict(sorted(all_shares_json.items(), reverse=True))
|
||||||
last_page: bool = False
|
last_page: bool = False
|
||||||
start_index = items_per_page * page_number
|
start_index: int = items_per_page * page_number
|
||||||
max_index = len(shares_json.items())
|
max_index = len(shares_json.items())
|
||||||
if max_index < items_per_page:
|
if max_index < items_per_page:
|
||||||
last_page = True
|
last_page = True
|
||||||
|
|
@ -629,11 +637,11 @@ def get_shares_collection(actor: str, page_number: int, items_per_page: int,
|
||||||
shared_items_federated_domains, shares_file_type)
|
shared_items_federated_domains, shares_file_type)
|
||||||
|
|
||||||
if shares_file_type == 'shares':
|
if shares_file_type == 'shares':
|
||||||
share_type = 'offer'
|
share_type: str = 'offer'
|
||||||
collection_name = nickname + "'s Shared Items"
|
collection_name: str = nickname + "'s Shared Items"
|
||||||
else:
|
else:
|
||||||
share_type = 'request'
|
share_type: str = 'request'
|
||||||
collection_name = nickname + "'s Wanted Items"
|
collection_name: str = nickname + "'s Wanted Items"
|
||||||
|
|
||||||
for share_id, shared_item in shares_json.items():
|
for share_id, shared_item in shares_json.items():
|
||||||
shared_item['shareId'] = share_id
|
shared_item['shareId'] = share_id
|
||||||
|
|
@ -642,7 +650,7 @@ def get_shares_collection(actor: str, page_number: int, items_per_page: int,
|
||||||
if offer_item:
|
if offer_item:
|
||||||
shares_collection.append(offer_item)
|
shares_collection.append(offer_item)
|
||||||
|
|
||||||
result_json = {
|
result_json: dict = {
|
||||||
"@context": [
|
"@context": [
|
||||||
'https://www.w3.org/ns/activitystreams',
|
'https://www.w3.org/ns/activitystreams',
|
||||||
'https://w3id.org/security/v1'
|
'https://w3id.org/security/v1'
|
||||||
|
|
@ -665,6 +673,8 @@ def post_contains_public(post_json_object: {}) -> bool:
|
||||||
return contains_public
|
return contains_public
|
||||||
|
|
||||||
for to_address in post_json_object['object']['to']:
|
for to_address in post_json_object['object']['to']:
|
||||||
|
if not isinstance(to_address, str):
|
||||||
|
continue
|
||||||
if to_address.endswith('#Public') or \
|
if to_address.endswith('#Public') or \
|
||||||
to_address == 'as:Public' or \
|
to_address == 'as:Public' or \
|
||||||
to_address == 'Public':
|
to_address == 'Public':
|
||||||
|
|
@ -673,6 +683,8 @@ def post_contains_public(post_json_object: {}) -> bool:
|
||||||
if not contains_public:
|
if not contains_public:
|
||||||
if post_json_object['object'].get('cc'):
|
if post_json_object['object'].get('cc'):
|
||||||
for to_address2 in post_json_object['object']['cc']:
|
for to_address2 in post_json_object['object']['cc']:
|
||||||
|
if not isinstance(to_address2, str):
|
||||||
|
continue
|
||||||
if to_address2.endswith('#Public') or \
|
if to_address2.endswith('#Public') or \
|
||||||
to_address2 == 'as:Public' or \
|
to_address2 == 'as:Public' or \
|
||||||
to_address2 == 'Public':
|
to_address2 == 'Public':
|
||||||
|
|
@ -685,7 +697,7 @@ def get_banner_file(base_dir: str,
|
||||||
nickname: str, domain: str, theme: str) -> (str, str):
|
nickname: str, domain: str, theme: str) -> (str, str):
|
||||||
"""Gets the image for the timeline banner
|
"""Gets the image for the timeline banner
|
||||||
"""
|
"""
|
||||||
account_dir = acct_dir(base_dir, nickname, domain)
|
account_dir: str = acct_dir(base_dir, nickname, domain)
|
||||||
banner_file, banner_filename = \
|
banner_file, banner_filename = \
|
||||||
get_image_file(base_dir, 'banner', account_dir, theme)
|
get_image_file(base_dir, 'banner', account_dir, theme)
|
||||||
return banner_file, banner_filename
|
return banner_file, banner_filename
|
||||||
|
|
@ -696,7 +708,7 @@ def get_profile_background_file(base_dir: str,
|
||||||
theme: str) -> (str, str):
|
theme: str) -> (str, str):
|
||||||
"""Gets the image for the profile background
|
"""Gets the image for the profile background
|
||||||
"""
|
"""
|
||||||
account_dir = acct_dir(base_dir, nickname, domain)
|
account_dir: str = acct_dir(base_dir, nickname, domain)
|
||||||
banner_file, banner_filename = \
|
banner_file, banner_filename = \
|
||||||
get_image_file(base_dir, 'image', account_dir, theme)
|
get_image_file(base_dir, 'image', account_dir, theme)
|
||||||
return banner_file, banner_filename
|
return banner_file, banner_filename
|
||||||
|
|
@ -707,7 +719,7 @@ def get_search_banner_file(base_dir: str,
|
||||||
theme: str) -> (str, str):
|
theme: str) -> (str, str):
|
||||||
"""Gets the image for the search banner
|
"""Gets the image for the search banner
|
||||||
"""
|
"""
|
||||||
account_dir = acct_dir(base_dir, nickname, domain)
|
account_dir: str = acct_dir(base_dir, nickname, domain)
|
||||||
banner_file, banner_filename = \
|
banner_file, banner_filename = \
|
||||||
get_image_file(base_dir, 'search_banner', account_dir, theme)
|
get_image_file(base_dir, 'search_banner', account_dir, theme)
|
||||||
return banner_file, banner_filename
|
return banner_file, banner_filename
|
||||||
|
|
@ -717,7 +729,7 @@ def get_left_image_file(base_dir: str,
|
||||||
nickname: str, domain: str, theme: str) -> (str, str):
|
nickname: str, domain: str, theme: str) -> (str, str):
|
||||||
"""Gets the image for the left column
|
"""Gets the image for the left column
|
||||||
"""
|
"""
|
||||||
account_dir = acct_dir(base_dir, nickname, domain)
|
account_dir: str = acct_dir(base_dir, nickname, domain)
|
||||||
banner_file, banner_filename = \
|
banner_file, banner_filename = \
|
||||||
get_image_file(base_dir, 'left_col_image', account_dir, theme)
|
get_image_file(base_dir, 'left_col_image', account_dir, theme)
|
||||||
return banner_file, banner_filename
|
return banner_file, banner_filename
|
||||||
|
|
@ -727,7 +739,7 @@ def get_right_image_file(base_dir: str,
|
||||||
nickname: str, domain: str, theme: str) -> (str, str):
|
nickname: str, domain: str, theme: str) -> (str, str):
|
||||||
"""Gets the image for the right column
|
"""Gets the image for the right column
|
||||||
"""
|
"""
|
||||||
account_dir = acct_dir(base_dir, nickname, domain)
|
account_dir: str = acct_dir(base_dir, nickname, domain)
|
||||||
banner_file, banner_filename = \
|
banner_file, banner_filename = \
|
||||||
get_image_file(base_dir, 'right_col_image', account_dir, theme)
|
get_image_file(base_dir, 'right_col_image', account_dir, theme)
|
||||||
return banner_file, banner_filename
|
return banner_file, banner_filename
|
||||||
|
|
@ -737,8 +749,8 @@ def html_header_with_external_style(css_filename: str, instance_title: str,
|
||||||
metadata: str, preload_images: [],
|
metadata: str, preload_images: [],
|
||||||
lang: str = 'en') -> str:
|
lang: str = 'en') -> str:
|
||||||
if metadata is None:
|
if metadata is None:
|
||||||
metadata: str = ''
|
metadata = ''
|
||||||
css_file = '/' + css_filename.split('/')[-1]
|
css_file: str = '/' + css_filename.split('/')[-1]
|
||||||
pwa_theme_color, pwa_theme_background_color = \
|
pwa_theme_color, pwa_theme_background_color = \
|
||||||
get_pwa_theme_colors(css_filename)
|
get_pwa_theme_colors(css_filename)
|
||||||
preload_images_str: str = ''
|
preload_images_str: str = ''
|
||||||
|
|
@ -747,7 +759,7 @@ def html_header_with_external_style(css_filename: str, instance_title: str,
|
||||||
preload_images_str += \
|
preload_images_str += \
|
||||||
' <link rel="preload" as="image" href="' + \
|
' <link rel="preload" as="image" href="' + \
|
||||||
image_path + '">\n'
|
image_path + '">\n'
|
||||||
html_str = \
|
html_str: str = \
|
||||||
'<!DOCTYPE html>\n' + \
|
'<!DOCTYPE html>\n' + \
|
||||||
'<!--\n' + \
|
'<!--\n' + \
|
||||||
'Thankyou for using Epicyon. If you are reading this message then ' + \
|
'Thankyou for using Epicyon. If you are reading this message then ' + \
|
||||||
|
|
@ -786,7 +798,7 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
"""
|
"""
|
||||||
if not actor_json:
|
if not actor_json:
|
||||||
preload_images: list[str] = []
|
preload_images: list[str] = []
|
||||||
html_str = \
|
html_str: str = \
|
||||||
html_header_with_external_style(css_filename,
|
html_header_with_external_style(css_filename,
|
||||||
instance_title, None,
|
instance_title, None,
|
||||||
preload_images, lang)
|
preload_images, lang)
|
||||||
|
|
@ -798,7 +810,7 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
add_comma: str = ''
|
add_comma: str = ''
|
||||||
country_markup: str = ''
|
country_markup: str = ''
|
||||||
if ',' in city:
|
if ',' in city:
|
||||||
country = city.split(',', 1)[1].strip().title()
|
country: str = city.split(',', 1)[1].strip().title()
|
||||||
city = city.split(',', 1)[0]
|
city = city.split(',', 1)[0]
|
||||||
country_markup = \
|
country_markup = \
|
||||||
' "addressCountry": "' + country + '"\n'
|
' "addressCountry": "' + country + '"\n'
|
||||||
|
|
@ -813,18 +825,22 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
if actor_json.get('hasOccupation'):
|
if actor_json.get('hasOccupation'):
|
||||||
if isinstance(actor_json['hasOccupation'], list):
|
if isinstance(actor_json['hasOccupation'], list):
|
||||||
skills_markup = ' "hasOccupation": [\n'
|
skills_markup = ' "hasOccupation": [\n'
|
||||||
first_entry = True
|
first_entry: bool = True
|
||||||
for skill_dict in actor_json['hasOccupation']:
|
for skill_dict in actor_json['hasOccupation']:
|
||||||
|
if not skill_dict.get('@type'):
|
||||||
|
continue
|
||||||
|
if not isinstance(skill_dict['@type'], str):
|
||||||
|
continue
|
||||||
if skill_dict['@type'] == 'Role':
|
if skill_dict['@type'] == 'Role':
|
||||||
if not first_entry:
|
if not first_entry:
|
||||||
skills_markup += ',\n'
|
skills_markup += ',\n'
|
||||||
skl = skill_dict['hasOccupation']
|
skl: str = skill_dict['hasOccupation']
|
||||||
role_name = skl['name']
|
role_name: str = skl['name']
|
||||||
if not role_name:
|
if not role_name:
|
||||||
role_name = 'member'
|
role_name = 'member'
|
||||||
category = \
|
category: str = \
|
||||||
skl['occupationalCategory']['codeValue']
|
skl['occupationalCategory']['codeValue']
|
||||||
category_url = \
|
category_url: str = \
|
||||||
'https://www.onetonline.org/link/summary/' + category
|
'https://www.onetonline.org/link/summary/' + category
|
||||||
skills_markup += \
|
skills_markup += \
|
||||||
' {\n' + \
|
' {\n' + \
|
||||||
|
|
@ -855,11 +871,11 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
elif skill_dict['@type'] == 'Occupation':
|
elif skill_dict['@type'] == 'Occupation':
|
||||||
if not first_entry:
|
if not first_entry:
|
||||||
skills_markup += ',\n'
|
skills_markup += ',\n'
|
||||||
oc_name = skill_dict['name']
|
oc_name: str = skill_dict['name']
|
||||||
if not oc_name:
|
if not oc_name:
|
||||||
oc_name = 'member'
|
oc_name = 'member'
|
||||||
skills_list = skill_dict['skills']
|
skills_list: list[str] = skill_dict['skills']
|
||||||
skills_list_str = '['
|
skills_list_str: str = '['
|
||||||
for skill_str in skills_list:
|
for skill_str in skills_list:
|
||||||
if skills_list_str != '[':
|
if skills_list_str != '[':
|
||||||
skills_list_str += ', '
|
skills_list_str += ', '
|
||||||
|
|
@ -883,13 +899,13 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
description: str = ''
|
description: str = ''
|
||||||
if actor_json.get('summary'):
|
if actor_json.get('summary'):
|
||||||
description = remove_html(actor_json['summary'])
|
description = remove_html(actor_json['summary'])
|
||||||
name_str = remove_html(actor_json['name'])
|
name_str: str = remove_html(actor_json['name'])
|
||||||
domain_full = actor_json['id'].split('://')[1].split('/')[0]
|
domain_full: str = actor_json['id'].split('://')[1].split('/')[0]
|
||||||
handle = actor_json['preferredUsername'] + '@' + domain_full
|
handle: str = actor_json['preferredUsername'] + '@' + domain_full
|
||||||
|
|
||||||
url_str = get_url_from_post(actor_json['icon']['url'])
|
url_str: str = get_url_from_post(actor_json['icon']['url'])
|
||||||
icon_url = remove_html(url_str)
|
icon_url: str = remove_html(url_str)
|
||||||
person_markup = \
|
person_markup: str = \
|
||||||
' "about": {\n' + \
|
' "about": {\n' + \
|
||||||
' "@type" : "Person",\n' + \
|
' "@type" : "Person",\n' + \
|
||||||
' "name": "' + name_str + '",\n' + \
|
' "name": "' + name_str + '",\n' + \
|
||||||
|
|
@ -899,7 +915,7 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
' "url": "' + actor_json['id'] + '"\n' + \
|
' "url": "' + actor_json['id'] + '"\n' + \
|
||||||
' },\n'
|
' },\n'
|
||||||
|
|
||||||
profile_markup = \
|
profile_markup: str = \
|
||||||
' <script id="initial-state" type="application/ld+json">\n' + \
|
' <script id="initial-state" type="application/ld+json">\n' + \
|
||||||
' {\n' + \
|
' {\n' + \
|
||||||
' "@context":"https://schema.org",\n' + \
|
' "@context":"https://schema.org",\n' + \
|
||||||
|
|
@ -923,10 +939,10 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
' }\n' + \
|
' }\n' + \
|
||||||
' </script>\n'
|
' </script>\n'
|
||||||
|
|
||||||
description = remove_html(description)
|
description: str = remove_html(description)
|
||||||
url_str = get_url_from_post(actor_json['url'])
|
url_str: str = get_url_from_post(actor_json['url'])
|
||||||
actor2_url = remove_html(url_str)
|
actor2_url: str = remove_html(url_str)
|
||||||
og_metadata = \
|
og_metadata: str = \
|
||||||
" <meta content=\"profile\" property=\"og:type\" />\n" + \
|
" <meta content=\"profile\" property=\"og:type\" />\n" + \
|
||||||
" <meta content=\"" + description + \
|
" <meta content=\"" + description + \
|
||||||
"\" name='description'>\n" + \
|
"\" name='description'>\n" + \
|
||||||
|
|
@ -946,7 +962,7 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
" <meta content=\"" + handle + \
|
" <meta content=\"" + handle + \
|
||||||
"\" property=\"profile:username\" />\n"
|
"\" property=\"profile:username\" />\n"
|
||||||
if actor_json.get('attachment'):
|
if actor_json.get('attachment'):
|
||||||
og_tags = (
|
og_tags: list[str] = (
|
||||||
'email', 'openpgp', 'blog', 'xmpp', 'matrix', 'briar',
|
'email', 'openpgp', 'blog', 'xmpp', 'matrix', 'briar',
|
||||||
'cwtch', 'languages'
|
'cwtch', 'languages'
|
||||||
)
|
)
|
||||||
|
|
@ -958,10 +974,10 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
if not prop_value_name:
|
if not prop_value_name:
|
||||||
continue
|
continue
|
||||||
if attach_json.get('name'):
|
if attach_json.get('name'):
|
||||||
name = attach_json['name'].lower()
|
name: str = attach_json['name'].lower()
|
||||||
else:
|
else:
|
||||||
name = attach_json['schema:name'].lower()
|
name: str = attach_json['schema:name'].lower()
|
||||||
value = attach_json[prop_value_name]
|
value: str = attach_json[prop_value_name]
|
||||||
for og_tag in og_tags:
|
for og_tag in og_tags:
|
||||||
if name != og_tag:
|
if name != og_tag:
|
||||||
continue
|
continue
|
||||||
|
|
@ -970,7 +986,7 @@ def html_header_with_person_markup(css_filename: str, instance_title: str,
|
||||||
"\" property=\"og:" + og_tag + "\" />\n"
|
"\" property=\"og:" + og_tag + "\" />\n"
|
||||||
|
|
||||||
preload_images: list[str] = []
|
preload_images: list[str] = []
|
||||||
html_str = \
|
html_str: str = \
|
||||||
html_header_with_external_style(css_filename, instance_title,
|
html_header_with_external_style(css_filename, instance_title,
|
||||||
og_metadata + profile_markup,
|
og_metadata + profile_markup,
|
||||||
preload_images, lang)
|
preload_images, lang)
|
||||||
|
|
@ -983,12 +999,12 @@ def html_header_with_website_markup(css_filename: str, instance_title: str,
|
||||||
"""html header which includes website markup
|
"""html header which includes website markup
|
||||||
https://schema.org/WebSite
|
https://schema.org/WebSite
|
||||||
"""
|
"""
|
||||||
license_url = 'https://www.gnu.org/licenses/agpl-3.0.rdf'
|
license_url: str = 'https://www.gnu.org/licenses/agpl-3.0.rdf'
|
||||||
|
|
||||||
# social networking category
|
# social networking category
|
||||||
genre_url = 'http://vocab.getty.edu/aat/300312270'
|
genre_url: str = 'http://vocab.getty.edu/aat/300312270'
|
||||||
|
|
||||||
website_markup = \
|
website_markup: str = \
|
||||||
' <script id="initial-state" type="application/ld+json">\n' + \
|
' <script id="initial-state" type="application/ld+json">\n' + \
|
||||||
' {\n' + \
|
' {\n' + \
|
||||||
' "@context" : "http://schema.org",\n' + \
|
' "@context" : "http://schema.org",\n' + \
|
||||||
|
|
@ -1014,7 +1030,7 @@ def html_header_with_website_markup(css_filename: str, instance_title: str,
|
||||||
' }\n' + \
|
' }\n' + \
|
||||||
' </script>\n'
|
' </script>\n'
|
||||||
|
|
||||||
og_metadata = \
|
og_metadata: str = \
|
||||||
' <meta content="Epicyon hosted on ' + domain + \
|
' <meta content="Epicyon hosted on ' + domain + \
|
||||||
'" property="og:site_name" />\n' + \
|
'" property="og:site_name" />\n' + \
|
||||||
' <meta content="' + http_prefix + '://' + domain + \
|
' <meta content="' + http_prefix + '://' + domain + \
|
||||||
|
|
@ -1029,7 +1045,7 @@ def html_header_with_website_markup(css_filename: str, instance_title: str,
|
||||||
' <meta content="summary_large_image" property="twitter:card" />\n'
|
' <meta content="summary_large_image" property="twitter:card" />\n'
|
||||||
|
|
||||||
preload_images: list[str] = []
|
preload_images: list[str] = []
|
||||||
html_str = \
|
html_str: str = \
|
||||||
html_header_with_external_style(css_filename, instance_title,
|
html_header_with_external_style(css_filename, instance_title,
|
||||||
og_metadata + website_markup,
|
og_metadata + website_markup,
|
||||||
preload_images, system_language)
|
preload_images, system_language)
|
||||||
|
|
@ -1045,13 +1061,13 @@ def html_header_with_blog_markup(css_filename: str, instance_title: str,
|
||||||
"""html header which includes blog post markup
|
"""html header which includes blog post markup
|
||||||
https://schema.org/BlogPosting
|
https://schema.org/BlogPosting
|
||||||
"""
|
"""
|
||||||
author_url = local_actor_url(http_prefix, nickname, domain)
|
author_url: str = local_actor_url(http_prefix, nickname, domain)
|
||||||
about_url = http_prefix + '://' + domain + '/about.html'
|
about_url: str = http_prefix + '://' + domain + '/about.html'
|
||||||
|
|
||||||
# license for content on the site may be different from
|
# license for content on the site may be different from
|
||||||
# the software license
|
# the software license
|
||||||
|
|
||||||
blog_markup = \
|
blog_markup: str = \
|
||||||
' <script id="initial-state" type="application/ld+json">\n' + \
|
' <script id="initial-state" type="application/ld+json">\n' + \
|
||||||
' {\n' + \
|
' {\n' + \
|
||||||
' "@context" : "http://schema.org",\n' + \
|
' "@context" : "http://schema.org",\n' + \
|
||||||
|
|
@ -1074,7 +1090,7 @@ def html_header_with_blog_markup(css_filename: str, instance_title: str,
|
||||||
' }\n' + \
|
' }\n' + \
|
||||||
' </script>\n'
|
' </script>\n'
|
||||||
|
|
||||||
og_metadata = \
|
og_metadata: str = \
|
||||||
' <meta property="og:locale" content="' + \
|
' <meta property="og:locale" content="' + \
|
||||||
system_language + '" />\n' + \
|
system_language + '" />\n' + \
|
||||||
' <meta property="og:type" content="article" />\n' + \
|
' <meta property="og:type" content="article" />\n' + \
|
||||||
|
|
@ -1088,7 +1104,7 @@ def html_header_with_blog_markup(css_filename: str, instance_title: str,
|
||||||
modified + '" />\n'
|
modified + '" />\n'
|
||||||
|
|
||||||
preload_images: list[str] = []
|
preload_images: list[str] = []
|
||||||
html_str = \
|
html_str: str = \
|
||||||
html_header_with_external_style(css_filename, instance_title,
|
html_header_with_external_style(css_filename, instance_title,
|
||||||
og_metadata + blog_markup,
|
og_metadata + blog_markup,
|
||||||
preload_images, system_language)
|
preload_images, system_language)
|
||||||
|
|
@ -1096,7 +1112,7 @@ def html_header_with_blog_markup(css_filename: str, instance_title: str,
|
||||||
|
|
||||||
|
|
||||||
def html_footer() -> str:
|
def html_footer() -> str:
|
||||||
html_str = ' </body>\n'
|
html_str: str = ' </body>\n'
|
||||||
html_str += '</html>\n'
|
html_str += '</html>\n'
|
||||||
return html_str
|
return html_str
|
||||||
|
|
||||||
|
|
@ -1108,7 +1124,7 @@ def load_individual_post_as_html_from_cache(base_dir: str,
|
||||||
return the html text
|
return the html text
|
||||||
This is much quicker than generating the html from the json object
|
This is much quicker than generating the html from the json object
|
||||||
"""
|
"""
|
||||||
cached_post_filename = \
|
cached_post_filename: str = \
|
||||||
get_cached_post_filename(base_dir, nickname, domain, post_json_object)
|
get_cached_post_filename(base_dir, nickname, domain, post_json_object)
|
||||||
|
|
||||||
post_html: str = ''
|
post_html: str = ''
|
||||||
|
|
@ -1146,7 +1162,7 @@ def add_emoji_to_display_name(session, base_dir: str, http_prefix: str,
|
||||||
'</p>': ''
|
'</p>': ''
|
||||||
}
|
}
|
||||||
display_name = replace_strings(display_name, replacements)
|
display_name = replace_strings(display_name, replacements)
|
||||||
emoji_tags = {}
|
emoji_tags: dict = {}
|
||||||
# print('TAG: display_name before tags: ' + display_name)
|
# print('TAG: display_name before tags: ' + display_name)
|
||||||
display_name = \
|
display_name = \
|
||||||
add_html_tags(base_dir, http_prefix,
|
add_html_tags(base_dir, http_prefix,
|
||||||
|
|
@ -1176,7 +1192,7 @@ def add_emoji_to_display_name(session, base_dir: str, http_prefix: str,
|
||||||
if '://' in display_name:
|
if '://' in display_name:
|
||||||
break
|
break
|
||||||
emoji_str = display_name.split(':')[1]
|
emoji_str = display_name.split(':')[1]
|
||||||
prev_display_name = display_name
|
prev_display_name: str = display_name
|
||||||
display_name = display_name.replace(':' + emoji_str + ':', '').strip()
|
display_name = display_name.replace(':' + emoji_str + ':', '').strip()
|
||||||
if prev_display_name == display_name:
|
if prev_display_name == display_name:
|
||||||
break
|
break
|
||||||
|
|
@ -1193,8 +1209,8 @@ def _is_image_mime_type(mime_type: str) -> bool:
|
||||||
return True
|
return True
|
||||||
if not mime_type.startswith('image/'):
|
if not mime_type.startswith('image/'):
|
||||||
return False
|
return False
|
||||||
extensions = get_image_extensions()
|
extensions: list[str] = get_image_extensions()
|
||||||
ext = mime_type.split('/')[1]
|
ext: str = mime_type.split('/')[1]
|
||||||
if ext in extensions:
|
if ext in extensions:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
@ -1205,8 +1221,8 @@ def _is_video_mime_type(mime_type: str) -> bool:
|
||||||
"""
|
"""
|
||||||
if not mime_type.startswith('video/'):
|
if not mime_type.startswith('video/'):
|
||||||
return False
|
return False
|
||||||
extensions = get_video_extensions()
|
extensions: list[str] = get_video_extensions()
|
||||||
ext = mime_type.split('/')[1]
|
ext: str = mime_type.split('/')[1]
|
||||||
if ext in extensions:
|
if ext in extensions:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
@ -1219,8 +1235,8 @@ def _is_audio_mime_type(mime_type: str) -> bool:
|
||||||
return True
|
return True
|
||||||
if not mime_type.startswith('audio/'):
|
if not mime_type.startswith('audio/'):
|
||||||
return False
|
return False
|
||||||
extensions = get_audio_extensions()
|
extensions: list[str] = get_audio_extensions()
|
||||||
ext = mime_type.split('/')[1]
|
ext: str = mime_type.split('/')[1]
|
||||||
if ext in extensions:
|
if ext in extensions:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
@ -1231,13 +1247,13 @@ def _is_attached_image(attachment_url: str) -> bool:
|
||||||
"""
|
"""
|
||||||
if '.' not in attachment_url:
|
if '.' not in attachment_url:
|
||||||
return False
|
return False
|
||||||
image_ext = get_image_extensions()
|
image_ext: list[str] = get_image_extensions()
|
||||||
ext = attachment_url.split('.')[-1]
|
ext: str = attachment_url.split('.')[-1]
|
||||||
if ext in image_ext:
|
if ext in image_ext:
|
||||||
return True
|
return True
|
||||||
if '/' in attachment_url:
|
if '/' in attachment_url:
|
||||||
# this might still be an image, but without a file extension
|
# this might still be an image, but without a file extension
|
||||||
last_part = attachment_url.split('/')[-1]
|
last_part: str = attachment_url.split('/')[-1]
|
||||||
if '.' not in last_part:
|
if '.' not in last_part:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
@ -1248,10 +1264,10 @@ def _is_attached_video(attachment_filename: str) -> bool:
|
||||||
"""
|
"""
|
||||||
if '.' not in attachment_filename:
|
if '.' not in attachment_filename:
|
||||||
return False
|
return False
|
||||||
video_ext = (
|
video_ext: list[str] = (
|
||||||
'mp4', 'webm', 'ogv'
|
'mp4', 'webm', 'ogv'
|
||||||
)
|
)
|
||||||
ext = attachment_filename.split('.')[-1]
|
ext: str = attachment_filename.split('.')[-1]
|
||||||
if ext in video_ext:
|
if ext in video_ext:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
@ -1260,8 +1276,8 @@ def _is_attached_video(attachment_filename: str) -> bool:
|
||||||
def _is_nsfw(content: str) -> bool:
|
def _is_nsfw(content: str) -> bool:
|
||||||
"""Does the given content indicate nsfw?
|
"""Does the given content indicate nsfw?
|
||||||
"""
|
"""
|
||||||
content_lower = content.lower()
|
content_lower: str = content.lower()
|
||||||
nsfw_tags = (
|
nsfw_tags: list[str] = (
|
||||||
'nsfw', 'porn', 'pr0n', 'explicit', 'lewd',
|
'nsfw', 'porn', 'pr0n', 'explicit', 'lewd',
|
||||||
'nude', 'boob', 'erotic', 'sex'
|
'nude', 'boob', 'erotic', 'sex'
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue