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')