From bfda87789f645937b189960e60d941363d3b4a05 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 6 Jan 2023 15:29:34 +0000 Subject: [PATCH 1/5] Navigation links --- webapp_search.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/webapp_search.py b/webapp_search.py index 1f2920c63..86dbf3de5 100644 --- a/webapp_search.py +++ b/webapp_search.py @@ -1409,6 +1409,13 @@ def hashtag_search_json(nickname: str, domain: str, port: int, 'totalItems': 0, 'type': 'OrderedCollection' } + hashtag_json['first'] = \ + http_prefix + '://' + domain_full + '/tags/' + \ + hashtag + '?page=1' + if page_number > 1: + hashtag_json['prev'] = \ + http_prefix + '://' + domain_full + '/tags/' + \ + hashtag + '?page=' + str(page_number - 1) page_items = 0 for index, _ in enumerate(lines): post_id = lines[index].strip('\n').strip('\r') @@ -1442,6 +1449,9 @@ def hashtag_search_json(nickname: str, domain: str, port: int, hashtag_json['orderedItems'].append(id_str) hashtag_json['totalItems'] += 1 if hashtag_json['totalItems'] >= posts_per_page: + hashtag_json['next'] = \ + http_prefix + '://' + domain_full + '/tags/' + \ + hashtag + '?page=' + str(page_number + 1) break return hashtag_json From a8f0f8fb708c455950c99156480c3e1bcd9be14f Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 6 Jan 2023 17:51:45 +0000 Subject: [PATCH 2/5] Replace remote hashtag links in ssml --- speaker.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/speaker.py b/speaker.py index 7b90bd949..784ce0e1f 100644 --- a/speaker.py +++ b/speaker.py @@ -28,6 +28,7 @@ from utils import has_object_dict from utils import acct_dir from utils import local_actor_url from content import html_replace_quote_marks +from content import replace_remote_hashtags SPEAKER_REMOVE_CHARS = ('.\n', '. ', ',', ';', '?', '!') @@ -408,7 +409,7 @@ def speakable_text(base_dir: str, content: str, translate: {}) -> (str, []): def _post_to_speaker_json(base_dir: str, http_prefix: str, - nickname: str, domain_full: str, + nickname: str, domain: str, domain_full: str, post_json_object: {}, person_cache: {}, translate: {}, announcing_actor: str, theme_name: str) -> {}: @@ -431,6 +432,7 @@ def _post_to_speaker_json(base_dir: str, http_prefix: str, # replace some emoji before removing html if ' <3' in content: content = content.replace(' <3', ' ' + translate['heart']) + content = replace_remote_hashtags(content, nickname, domain) content = remove_html(html_replace_quote_marks(content)) content = speaker_replace_links(content, translate, detected_links) # replace all double spaces @@ -551,7 +553,7 @@ def update_speaker(base_dir: str, http_prefix: str, """ speaker_json = \ _post_to_speaker_json(base_dir, http_prefix, - nickname, domain_full, + nickname, domain, domain_full, post_json_object, person_cache, translate, announcing_actor, theme_name) From 7a74fd20beb52c11101c2f0aeccda59c5ffad121 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 6 Jan 2023 17:57:02 +0000 Subject: [PATCH 3/5] Tidying --- speaker.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/speaker.py b/speaker.py index 784ce0e1f..0b86a0a2c 100644 --- a/speaker.py +++ b/speaker.py @@ -223,7 +223,7 @@ def speaker_replace_links(say_text: str, translate: {}, return say_text.replace('..', '.') -def _add_ssm_lemphasis(say_text: str) -> str: +def _add_ssml_emphasis(say_text: str) -> str: """Adds emphasis to *emphasised* text """ if '*' not in say_text: @@ -342,7 +342,7 @@ def _speaker_endpoint_ssml(display_name: str, summary: str, else: gender = 'neutral' - content = _add_ssm_lemphasis(content) + content = _add_ssml_emphasis(content) voice_params = 'name="' + display_name + '" gender="' + gender + '"' if summary is None: summary = '' From 05367d1044de95a311886205a05133018209eaee Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 6 Jan 2023 18:17:34 +0000 Subject: [PATCH 4/5] Tidying --- speaker.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/speaker.py b/speaker.py index 0b86a0a2c..7b5f1066d 100644 --- a/speaker.py +++ b/speaker.py @@ -28,7 +28,6 @@ from utils import has_object_dict from utils import acct_dir from utils import local_actor_url from content import html_replace_quote_marks -from content import replace_remote_hashtags SPEAKER_REMOVE_CHARS = ('.\n', '. ', ',', ';', '?', '!') @@ -432,7 +431,6 @@ def _post_to_speaker_json(base_dir: str, http_prefix: str, # replace some emoji before removing html if ' <3' in content: content = content.replace(' <3', ' ' + translate['heart']) - content = replace_remote_hashtags(content, nickname, domain) content = remove_html(html_replace_quote_marks(content)) content = speaker_replace_links(content, translate, detected_links) # replace all double spaces From fc4de10236eca7b4db83a95e6d2e2d4c69142416 Mon Sep 17 00:00:00 2001 From: Bob Mottram Date: Fri, 6 Jan 2023 20:39:33 +0000 Subject: [PATCH 5/5] Remote hashtag links within ssml --- desktop_client.py | 57 +++++++++++++++++++++++++++++++++-------------- speaker.py | 29 +++++++++++++++++++----- tests.py | 21 ++++++++++++++++- 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/desktop_client.py b/desktop_client.py index 19d3234ba..f1e8a4326 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -807,7 +807,9 @@ def _read_local_box_post(session, nickname: str, domain: str, _text_only_content(content) content += _get_image_description(post_json_object2) message_str, _ = \ - speakable_text(base_dir, content, translate) + speakable_text(http_prefix, + nickname, domain, domain_full, + base_dir, content, translate) say_str = content _say_command(say_str, message_str, screenreader, system_language, espeak) @@ -837,7 +839,9 @@ def _read_local_box_post(session, nickname: str, domain: str, return {} content = _safe_message(content) - message_str, _ = speakable_text(base_dir, content, translate) + message_str, _ = speakable_text(http_prefix, + nickname, domain, domain_full, + base_dir, content, translate) if screenreader: time.sleep(2) @@ -870,7 +874,9 @@ def _read_local_box_post(session, nickname: str, domain: str, return post_json_object -def _desktop_show_actor(base_dir: str, actor_json: {}, translate: {}, +def _desktop_show_actor(http_prefix: str, + nickname: str, domain: str, domain_full: str, + base_dir: str, actor_json: {}, translate: {}, system_language: str, screenreader: str, espeak) -> None: """Shows information for the given actor @@ -901,16 +907,20 @@ def _desktop_show_actor(base_dir: str, actor_json: {}, translate: {}, if actor_json.get('summary'): say_str = html.unescape(remove_html(actor_json['summary'])) say_str = say_str.replace('"', "'") - say_str2 = speakable_text(base_dir, say_str, translate)[0] + say_str2 = speakable_text(http_prefix, + nickname, domain, domain_full, + base_dir, say_str, translate)[0] _say_command(say_str, say_str2, screenreader, system_language, espeak) -def _desktop_show_profile(session, nickname: str, domain: str, +def _desktop_show_profile(session, nickname: str, + domain: str, domain_full: str, base_dir: str, index: int, box_json: {}, system_language: str, screenreader: str, espeak, translate: {}, post_json_object: {}, - signing_priv_key_pem: str) -> {}: + signing_priv_key_pem: str, + http_prefix: str) -> {}: """Shows the profile of the actor for the given post Returns the actor json """ @@ -947,17 +957,21 @@ def _desktop_show_profile(session, nickname: str, domain: str, get_actor_json(domain, actor, is_http, is_gnunet, is_ipfs, is_ipns, False, True, signing_priv_key_pem, session) - _desktop_show_actor(base_dir, actor_json, translate, + _desktop_show_actor(http_prefix, + nickname, domain, domain_full, + base_dir, actor_json, translate, system_language, screenreader, espeak) return actor_json -def _desktop_show_profile_from_handle(session, domain: str, base_dir: str, +def _desktop_show_profile_from_handle(session, nickname: str, domain: str, + domain_full: str, base_dir: str, handle: str, system_language: str, screenreader: str, espeak, translate: {}, - signing_priv_key_pem: str) -> {}: + signing_priv_key_pem: str, + http_prefix: str) -> {}: """Shows the profile for a handle Returns the actor json """ @@ -966,7 +980,8 @@ def _desktop_show_profile_from_handle(session, domain: str, base_dir: str, False, True, signing_priv_key_pem, session) - _desktop_show_actor(base_dir, actor_json, translate, + _desktop_show_actor(http_prefix, nickname, domain, domain_full, + base_dir, actor_json, translate, system_language, screenreader, espeak) return actor_json @@ -1733,14 +1748,16 @@ def run_desktop_client(base_dir: str, proxy_type: str, http_prefix: str, if command_str == 'profile': if post_json_object: actor_json = \ - _desktop_show_profile(session, nickname, domain, + _desktop_show_profile(session, nickname, + domain, domain_full, base_dir, post_index, box_json, system_language, screenreader, espeak, translate, post_json_object, - signing_priv_key_pem) + signing_priv_key_pem, + http_prefix) else: post_index_str = '1' else: @@ -1750,13 +1767,15 @@ def run_desktop_client(base_dir: str, proxy_type: str, http_prefix: str, profile_handle = post_index_str _desktop_clear_screen() _desktop_show_banner() - _desktop_show_profile_from_handle(session, domain, + _desktop_show_profile_from_handle(session, nickname, + domain, domain_full, base_dir, profile_handle, system_language, screenreader, espeak, translate, - signing_priv_key_pem) + signing_priv_key_pem, + http_prefix) say_str = 'Press Enter to continue...' say_str2 = _highlight_text(say_str) _say_command(say_str2, say_str, @@ -1771,12 +1790,14 @@ def run_desktop_client(base_dir: str, proxy_type: str, http_prefix: str, post_index_str = "1" post_index = int(post_index_str) actor_json = \ - _desktop_show_profile(session, nickname, domain, + _desktop_show_profile(session, nickname, + domain, domain_full, base_dir, post_index, box_json, system_language, screenreader, espeak, translate, - None, signing_priv_key_pem) + None, signing_priv_key_pem, + http_prefix) say_str = 'Press Enter to continue...' say_str2 = _highlight_text(say_str) _say_command(say_str2, say_str, @@ -2553,7 +2574,9 @@ def run_desktop_client(base_dir: str, proxy_type: str, http_prefix: str, get_base_content_from_post(post_json_object, system_language) message_str, detected_links = \ - speakable_text(base_dir, content, translate) + speakable_text(http_prefix, + nickname, domain, domain_full, + base_dir, content, translate) link_opened = False for url in detected_links: if '://' in url: diff --git a/speaker.py b/speaker.py index 7b5f1066d..3d4cc34cd 100644 --- a/speaker.py +++ b/speaker.py @@ -170,7 +170,9 @@ def _speaker_pronounce(base_dir: str, say_text: str, translate: {}) -> str: return say_text -def speaker_replace_links(say_text: str, translate: {}, +def speaker_replace_links(http_prefix: str, nickname: str, + orig_domain: str, orig_domain_full: str, + say_text: str, translate: {}, detected_links: []) -> str: """Replaces any links in the given text with "link to [domain]". Instead of reading out potentially very long and meaningless links @@ -181,6 +183,7 @@ def speaker_replace_links(say_text: str, translate: {}, text = text.replace(char, ' ') text = text.replace('__v=', '?v=') replacements = {} + replacements_hashtags = {} words_list = text.split(' ') if translate.get('Linked'): linked_str = translate['Linked'] @@ -216,9 +219,17 @@ def speaker_replace_links(say_text: str, translate: {}, if domain.startswith('www.'): domain = domain.replace('www.', '') replacements[domain_full] = '. ' + linked_str + ' ' + domain + '.' - detected_links.append(domain_full) + if '/tags/' in domain_full and domain != orig_domain: + remote_hashtag_link = \ + http_prefix + '://' + orig_domain_full + '/users/' + \ + nickname + '?remotetag=' + domain_full.replace('/', '--') + detected_links.append(remote_hashtag_link) + else: + detected_links.append(domain_full) for replace_str, new_str in replacements.items(): say_text = say_text.replace(replace_str, new_str) + for replace_str, new_str in replacements_hashtags.items(): + say_text = say_text.replace(replace_str, new_str) return say_text.replace('..', '.') @@ -382,9 +393,11 @@ def get_ssml_box(base_dir: str, path: str, gender, box_name) -def speakable_text(base_dir: str, content: str, translate: {}) -> (str, []): +def speakable_text(http_prefix: str, + nickname: str, domain: str, domain_full: str, + base_dir: str, content: str, translate: {}) -> (str, []): """Convert the given text to a speakable version - which includes changes for prononciation + which includes changes for pronunciation """ content = str(content) if is_pgp_encrypted(content): @@ -395,7 +408,9 @@ def speakable_text(base_dir: str, content: str, translate: {}) -> (str, []): content = content.replace(' <3', ' ' + translate['heart']) content = remove_html(html_replace_quote_marks(content)) detected_links = [] - content = speaker_replace_links(content, translate, detected_links) + content = speaker_replace_links(http_prefix, + nickname, domain, domain_full, + content, translate, detected_links) # replace all double spaces while ' ' in content: content = content.replace(' ', ' ') @@ -432,7 +447,9 @@ def _post_to_speaker_json(base_dir: str, http_prefix: str, if ' <3' in content: content = content.replace(' <3', ' ' + translate['heart']) content = remove_html(html_replace_quote_marks(content)) - content = speaker_replace_links(content, translate, detected_links) + content = speaker_replace_links(http_prefix, + nickname, domain, domain_full, + content, translate, detected_links) # replace all double spaces while ' ' in content: content = content.replace(' ', ' ') diff --git a/tests.py b/tests.py index 478700958..994cfa108 100644 --- a/tests.py +++ b/tests.py @@ -5960,6 +5960,11 @@ def _test_extract_text_fields_from_post(): def _test_speaker_replace_link(): + http_prefix = 'https' + nickname = 'mynick' + domain = 'mydomain' + domain_full = domain + print('testSpeakerReplaceLinks') text = 'The Tor Project: For Snowflake volunteers: If you use ' + \ 'Firefox, Brave, or Chrome, our Snowflake extension turns ' + \ @@ -5970,13 +5975,27 @@ def _test_speaker_replace_link(): 'how-to-help-running-snowflake/' detected_links = [] result = \ - speaker_replace_links(text, {'Linked': 'Web link'}, detected_links) + speaker_replace_links(http_prefix, nickname, domain, domain_full, + text, {'Linked': 'Web link'}, detected_links) assert len(detected_links) == 1 assert detected_links[0] == \ 'https://support.torproject.org/censorship/' + \ 'how-to-help-running-snowflake/' assert 'Web link support.torproject.org' in result + remote_link = 'https://somedomain/tags/sometag' + text = 'Test with a hashtag ' + remote_link + ' link' + detected_links = [] + result = \ + speaker_replace_links(http_prefix, nickname, domain, domain_full, + text, {'Linked': 'Web link'}, detected_links) + assert len(detected_links) == 1 + local_link = \ + 'https://' + domain_full + '/users/' + nickname + \ + '?remotetag=' + remote_link.replace('/', '--') + assert detected_links[0] == local_link + assert 'Web link somedomain' in result + def _test_camel_case_split(): print('test_camel_case_split')