From e1b3b7a1a049977ad096848940f31e066ffffe31 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Tue, 27 May 2025 11:35:56 +0100 Subject: [PATCH] Separate module for text mode browser functions --- daemon.py | 2 +- daemon_post_profile.py | 2 +- httprequests.py | 2 +- textmode.py | 97 ++++++++++++++++++++++++++++++++++++++++++ theme.py | 69 +----------------------------- utils.py | 8 ---- webapp_column_right.py | 2 +- webapp_conversation.py | 4 +- webapp_login.py | 4 +- webapp_post.py | 4 +- webapp_profile.py | 4 +- webapp_timeline.py | 4 +- webapp_utils.py | 11 ----- 13 files changed, 113 insertions(+), 100 deletions(-) create mode 100644 textmode.py diff --git a/daemon.py b/daemon.py index b732b8797..b1158834d 100644 --- a/daemon.py +++ b/daemon.py @@ -71,8 +71,8 @@ from content import load_auto_cw_cache from content import load_dogwhistles from theme import scan_themes_for_scripts from theme import is_news_theme_name -from theme import get_text_mode_banner from theme import set_news_avatar +from textmode import get_text_mode_banner from schedule import run_post_schedule from schedule import run_post_schedule_watchdog from happening import dav_propfind_response diff --git a/daemon_post_profile.py b/daemon_post_profile.py index f8ef723c3..9aa4686b8 100644 --- a/daemon_post_profile.py +++ b/daemon_post_profile.py @@ -51,12 +51,12 @@ from content import add_html_tags from content import extract_text_fields_in_post from content import extract_media_in_form_post from content import save_media_in_form_post +from textmode import get_text_mode_banner from theme import enable_grayscale from theme import disable_grayscale from theme import get_theme from theme import is_news_theme_name from theme import set_news_avatar -from theme import get_text_mode_banner from theme import set_theme from theme import export_theme from theme import import_theme diff --git a/httprequests.py b/httprequests.py index 63c21b114..755a83dcb 100644 --- a/httprequests.py +++ b/httprequests.py @@ -7,7 +7,7 @@ __email__ = "bob@libreserver.org" __status__ = "Production" __module_group__ = "Core" -from webapp_utils import text_mode_browser +from textmode import text_mode_browser def request_csv(headers: {}) -> bool: diff --git a/textmode.py b/textmode.py new file mode 100644 index 000000000..8cb8bf279 --- /dev/null +++ b/textmode.py @@ -0,0 +1,97 @@ +__filename__ = "textmode.py" +__author__ = "Bob Mottram" +__license__ = "AGPL3+" +__version__ = "1.6.0" +__maintainer__ = "Bob Mottram" +__email__ = "bob@libreserver.org" +__status__ = "Production" +__module_group__ = "Web Interface" + +import os +from shutil import copyfile +from utils import data_dir + + +def text_mode_browser(ua_str: str) -> bool: + """Does the user agent indicate a text mode browser? + """ + if ua_str: + text_mode_agents = ('Lynx/', 'w3m/', 'Links (', 'Emacs/', 'ELinks') + for agent in text_mode_agents: + if agent in ua_str: + return True + return False + + +def text_mode_removals(text: str, translate: {}) -> str: + """Removes some elements of a post when displaying in a text mode browser + """ + text = text.replace(translate['SHOW MORE'], '') + text = text.replace(translate['mitm'], '👁 ') + return text + + +def get_text_mode_banner(base_dir: str) -> str: + """Returns the banner used for shell browsers, like Lynx + """ + text_mode_banner_filename = data_dir(base_dir) + '/banner.txt' + if os.path.isfile(text_mode_banner_filename): + with open(text_mode_banner_filename, 'r', + encoding='utf-8') as fp_text: + banner_str = fp_text.read() + if banner_str: + return banner_str.replace('\n', '
') + return None + + +def get_text_mode_logo(base_dir: str) -> str: + """Returns the login screen logo used for shell browsers, like Lynx + """ + text_mode_logo_filename = data_dir(base_dir) + '/logo.txt' + if not os.path.isfile(text_mode_logo_filename): + text_mode_logo_filename = base_dir + '/img/logo.txt' + + with open(text_mode_logo_filename, 'r', encoding='utf-8') as fp_text: + logo_str = fp_text.read() + if logo_str: + return logo_str.replace('\n', '
') + return None + + +def set_text_mode_theme(base_dir: str, name: str) -> None: + # set the text mode logo which appears on the login screen + # in browsers such as Lynx + text_mode_logo_filename = \ + base_dir + '/theme/' + name + '/logo.txt' + dir_str = data_dir(base_dir) + if os.path.isfile(text_mode_logo_filename): + try: + copyfile(text_mode_logo_filename, dir_str + '/logo.txt') + except OSError: + print('EX: set_text_mode_theme unable to copy ' + + text_mode_logo_filename + ' ' + + dir_str + '/logo.txt') + else: + dir_str = data_dir(base_dir) + try: + copyfile(base_dir + '/img/logo.txt', dir_str + '/logo.txt') + except OSError: + print('EX: set_text_mode_theme unable to copy ' + + base_dir + '/img/logo.txt ' + dir_str + '/logo.txt') + + # set the text mode banner which appears in browsers such as Lynx + text_mode_banner_filename = \ + base_dir + '/theme/' + name + '/banner.txt' + if os.path.isfile(dir_str + '/banner.txt'): + try: + os.remove(dir_str + '/banner.txt') + except OSError: + print('EX: set_text_mode_theme unable to delete ' + + dir_str + '/banner.txt') + if os.path.isfile(text_mode_banner_filename): + try: + copyfile(text_mode_banner_filename, dir_str + '/banner.txt') + except OSError: + print('EX: set_text_mode_theme unable to copy ' + + text_mode_banner_filename + ' ' + + dir_str + '/banner.txt') diff --git a/theme.py b/theme.py index 0b865e34c..4d9de4cc7 100644 --- a/theme.py +++ b/theme.py @@ -27,6 +27,7 @@ from utils import text_in_file from utils import remove_eol from utils import language_right_to_left from content import dangerous_css +from textmode import set_text_mode_theme def import_theme(base_dir: str, filename: str) -> bool: @@ -695,72 +696,6 @@ def _set_theme_fonts(base_dir: str, theme_name: str) -> None: break -def get_text_mode_banner(base_dir: str) -> str: - """Returns the banner used for shell browsers, like Lynx - """ - text_mode_banner_filename = data_dir(base_dir) + '/banner.txt' - if os.path.isfile(text_mode_banner_filename): - with open(text_mode_banner_filename, 'r', - encoding='utf-8') as fp_text: - banner_str = fp_text.read() - if banner_str: - return banner_str.replace('\n', '
') - return None - - -def get_text_mode_logo(base_dir: str) -> str: - """Returns the login screen logo used for shell browsers, like Lynx - """ - text_mode_logo_filename = data_dir(base_dir) + '/logo.txt' - if not os.path.isfile(text_mode_logo_filename): - text_mode_logo_filename = base_dir + '/img/logo.txt' - - with open(text_mode_logo_filename, 'r', encoding='utf-8') as fp_text: - logo_str = fp_text.read() - if logo_str: - return logo_str.replace('\n', '
') - return None - - -def _set_text_mode_theme(base_dir: str, name: str) -> None: - # set the text mode logo which appears on the login screen - # in browsers such as Lynx - text_mode_logo_filename = \ - base_dir + '/theme/' + name + '/logo.txt' - dir_str = data_dir(base_dir) - if os.path.isfile(text_mode_logo_filename): - try: - copyfile(text_mode_logo_filename, dir_str + '/logo.txt') - except OSError: - print('EX: _set_text_mode_theme unable to copy ' + - text_mode_logo_filename + ' ' + - dir_str + '/logo.txt') - else: - dir_str = data_dir(base_dir) - try: - copyfile(base_dir + '/img/logo.txt', dir_str + '/logo.txt') - except OSError: - print('EX: _set_text_mode_theme unable to copy ' + - base_dir + '/img/logo.txt ' + dir_str + '/logo.txt') - - # set the text mode banner which appears in browsers such as Lynx - text_mode_banner_filename = \ - base_dir + '/theme/' + name + '/banner.txt' - if os.path.isfile(dir_str + '/banner.txt'): - try: - os.remove(dir_str + '/banner.txt') - except OSError: - print('EX: _set_text_mode_theme unable to delete ' + - dir_str + '/banner.txt') - if os.path.isfile(text_mode_banner_filename): - try: - copyfile(text_mode_banner_filename, dir_str + '/banner.txt') - except OSError: - print('EX: _set_text_mode_theme unable to copy ' + - text_mode_banner_filename + ' ' + - dir_str + '/banner.txt') - - def _set_theme_images(base_dir: str, name: str) -> None: """Changes the profile background image and banner to the defaults @@ -778,7 +713,7 @@ def _set_theme_images(base_dir: str, name: str) -> None: right_col_image_filename = \ base_dir + '/theme/' + theme_name_lower + '/right_col_image.png' - _set_text_mode_theme(base_dir, theme_name_lower) + set_text_mode_theme(base_dir, theme_name_lower) background_names = ('login', 'shares', 'delete', 'follow', 'options', 'block', 'search', 'calendar', diff --git a/utils.py b/utils.py index 2ed30f841..c2415f86b 100644 --- a/utils.py +++ b/utils.py @@ -5493,14 +5493,6 @@ def save_mitm_servers(base_dir: str, mitm_servers: []) -> None: print('EX: error while saving mitm_servers.txt') -def text_mode_removals(text: str, translate: {}) -> str: - """Removes some elements of a post when displaying in a text mode browser - """ - text = text.replace(translate['SHOW MORE'], '') - text = text.replace(translate['mitm'], '👁 ') - return text - - def get_event_categories() -> []: """Returns event categories https://codeberg.org/fediverse/fep/src/branch/main/fep/8a8e/fep-8a8e.md diff --git a/webapp_column_right.py b/webapp_column_right.py index 66d9de77a..ec0e1b959 100644 --- a/webapp_column_right.py +++ b/webapp_column_right.py @@ -34,7 +34,7 @@ from webapp_utils import get_banner_file from webapp_utils import html_post_separator from webapp_utils import header_buttons_front_screen from webapp_utils import edit_text_field -from webapp_utils import text_mode_browser +from textmode import text_mode_browser def _votes_indicator(total_votes: int, positive_voting: bool) -> str: diff --git a/webapp_conversation.py b/webapp_conversation.py index d8d644944..23b124282 100644 --- a/webapp_conversation.py +++ b/webapp_conversation.py @@ -16,9 +16,9 @@ from utils import get_config_param from utils import get_nickname_from_actor from utils import get_domain_from_actor from utils import get_attributed_to -from utils import text_mode_removals +from textmode import text_mode_removals from blocking import is_blocked -from webapp_utils import text_mode_browser +from textmode import text_mode_browser from webapp_utils import html_header_with_external_style from webapp_utils import html_post_separator from webapp_utils import html_footer diff --git a/webapp_login.py b/webapp_login.py index 229895af7..60a22cad2 100644 --- a/webapp_login.py +++ b/webapp_login.py @@ -20,8 +20,8 @@ from webapp_utils import set_custom_background from webapp_utils import html_header_with_website_markup from webapp_utils import html_footer from webapp_utils import html_keyboard_navigation -from webapp_utils import text_mode_browser -from theme import get_text_mode_logo +from textmode import text_mode_browser +from textmode import get_text_mode_logo def html_get_login_credentials(login_params: str, diff --git a/webapp_post.py b/webapp_post.py index a7349e617..d64893948 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -35,8 +35,8 @@ from flags import is_news_post from flags import is_recent_post from flags import is_chat_message from flags import is_pgp_encrypted +from textmode import text_mode_removals from utils import save_json -from utils import text_mode_removals from utils import remove_header_tags from utils import get_actor_from_post_id from utils import contains_statuses @@ -102,8 +102,8 @@ from content import switch_words from content import add_auto_cw from person import is_person_snoozed from person import get_person_avatar_url +from textmode import text_mode_browser from webapp_utils import mitm_warning_html -from webapp_utils import text_mode_browser from webapp_utils import get_buy_links from webapp_utils import get_banner_file from webapp_utils import get_avatar_image_url diff --git a/webapp_profile.py b/webapp_profile.py index 09b1e8aab..1b56b0f63 100644 --- a/webapp_profile.py +++ b/webapp_profile.py @@ -18,8 +18,8 @@ from flags import is_valid_date from flags import is_premium_account from status import actor_status_expired from status import get_actor_status +from textmode import text_mode_removals from utils import get_person_icon -from utils import text_mode_removals from utils import replace_strings from utils import data_dir from utils import time_days_ago @@ -93,7 +93,7 @@ from follow import is_follower_of_person from follow import get_follower_domains from follow import is_following_actor from webapp_frontscreen import html_front_screen -from webapp_utils import text_mode_browser +from textmode import text_mode_browser from webapp_utils import html_following_dropdown from webapp_utils import edit_number_field from webapp_utils import html_keyboard_navigation diff --git a/webapp_timeline.py b/webapp_timeline.py index 4de730615..9fa947df3 100644 --- a/webapp_timeline.py +++ b/webapp_timeline.py @@ -22,11 +22,11 @@ from utils import acct_dir from utils import local_actor_url from utils import remove_eol from utils import get_actor_from_post -from utils import text_mode_removals +from textmode import text_mode_removals from follow import follower_approval_active from person import is_person_snoozed from markdown import markdown_to_html -from webapp_utils import text_mode_browser +from textmode import text_mode_browser from webapp_utils import html_keyboard_navigation from webapp_utils import html_hide_from_screen_reader from webapp_utils import html_post_separator diff --git a/webapp_utils.py b/webapp_utils.py index 70b5b4632..adeca5d29 100644 --- a/webapp_utils.py +++ b/webapp_utils.py @@ -2256,17 +2256,6 @@ def html_common_emoji(base_dir: str, no_of_emoji: int) -> str: return html_str -def text_mode_browser(ua_str: str) -> bool: - """Does the user agent indicate a text mode browser? - """ - if ua_str: - text_mode_agents = ('Lynx/', 'w3m/', 'Links (', 'Emacs/', 'ELinks') - for agent in text_mode_agents: - if agent in ua_str: - return True - return False - - def get_default_path(media_instance: bool, blogs_instance: bool, nickname: str) -> str: """Returns the default timeline