diff --git a/conversation.py b/conversation.py index 698f523d1..b09507508 100644 --- a/conversation.py +++ b/conversation.py @@ -16,6 +16,7 @@ from utils import locate_post from utils import load_json from utils import harmless_markup from utils import get_attributed_to +from utils import get_reply_to from keys import get_instance_actor_key from session import get_json from session import get_json_valid @@ -190,11 +191,11 @@ def download_conversation_posts(authorized: bool, session, if not authorized: # only show a single post to non-authorized viewers break - if not post_json_object['object'].get('inReplyTo'): + post_id = get_reply_to(post_json_object['object']) + if not post_id: if debug: print(post_id + ' is not a reply') break - post_id = post_json_object['object']['inReplyTo'] post_id = remove_id_ending(post_id) post_filename = \ locate_post(base_dir, nickname, domain, post_id) diff --git a/desktop_client.py b/desktop_client.py index 1d789badd..f9eba5b0a 100644 --- a/desktop_client.py +++ b/desktop_client.py @@ -33,6 +33,7 @@ from utils import get_nickname_from_actor from utils import get_domain_from_actor from utils import is_pgp_encrypted from utils import local_actor_url +from utils import get_reply_to from session import create_session from speaker import speakable_text from speaker import get_speaker_pitch @@ -897,8 +898,9 @@ def _read_local_box_post(session, nickname: str, domain: str, system_language, espeak, name_str, gender) print('') - if post_json_object['object'].get('inReplyTo'): - print('Replying to ' + post_json_object['object']['inReplyTo'] + '\n') + reply_id = get_reply_to(post_json_object['object']) + if reply_id: + print('Replying to ' + reply_id + '\n') if screenreader: time.sleep(2) @@ -1181,7 +1183,8 @@ def _desktop_show_box(indent: str, # append icons to the end of the name space_added = False - if post_json_object['object'].get('inReplyTo'): + reply_id = get_reply_to(post_json_object['object']) + if reply_id: if not space_added: space_added = True name += ' ' diff --git a/inbox.py b/inbox.py index 97b54e28a..97171a8df 100644 --- a/inbox.py +++ b/inbox.py @@ -80,6 +80,7 @@ from utils import local_actor_url from utils import has_object_string_type from utils import valid_hash_tag from utils import get_attributed_to +from utils import get_reply_to from categories import get_hashtag_categories from categories import set_hashtag_category from httpsig import get_digest_algorithm_from_headers @@ -623,8 +624,9 @@ def inbox_permitted_message(domain: str, message_json: {}, if message_json['type'] not in always_allowed_types: if not has_object_dict(message_json): return True - if message_json['object'].get('inReplyTo'): - in_reply_to = message_json['object']['inReplyTo'] + reply_id = get_reply_to(message_json['object']) + if reply_id: + in_reply_to = reply_id if not isinstance(in_reply_to, str): return False if not url_permitted(in_reply_to, federation_list): @@ -737,10 +739,10 @@ def save_post_to_inbox_queue(base_dir: str, http_prefix: str, return None # is this a reply to a blocked domain or account? - if post_json_object['object'].get('inReplyTo'): - if isinstance(post_json_object['object']['inReplyTo'], str): - in_reply_to = \ - post_json_object['object']['inReplyTo'] + reply_id = get_reply_to(post_json_object['object']) + if reply_id: + if isinstance(reply_id, str): + in_reply_to = reply_id reply_domain, _ = \ get_domain_from_actor(in_reply_to) if reply_domain: @@ -1528,9 +1530,10 @@ def _valid_post_content(base_dir: str, nickname: str, domain: str, if message_json.get('id'): print('REJECT: content filtered ' + str(message_json['id'])) return False - if message_json['object'].get('inReplyTo'): - if isinstance(message_json['object']['inReplyTo'], str): - original_post_id = message_json['object']['inReplyTo'] + reply_id = get_reply_to(message_json['object']) + if reply_id: + if isinstance(reply_id, str): + original_post_id = reply_id post_post_filename = locate_post(base_dir, nickname, domain, original_post_id) if post_post_filename: @@ -2370,7 +2373,8 @@ def _receive_zot_reaction(recent_posts_cache: {}, print('DEBUG: ' + message_json['object']['type'] + ' has no "content"') return False - if not message_json['object'].get('inReplyTo'): + reply_id = get_reply_to(message_json['object']) + if not reply_id: if debug: print('DEBUG: ' + message_json['object']['type'] + ' has no "inReplyTo"') @@ -2384,7 +2388,7 @@ def _receive_zot_reaction(recent_posts_cache: {}, if debug: print('DEBUG: content is too long to be an emoji reaction') return False - if not isinstance(message_json['object']['inReplyTo'], str): + if not isinstance(reply_id, str): if debug: print('DEBUG: ' + message_json['object']['type'] + ' inReplyTo is not string') @@ -2399,7 +2403,7 @@ def _receive_zot_reaction(recent_posts_cache: {}, print('DEBUG: "users" or "profile" missing from actor in ' + message_json['object']['type']) return False - if '/statuses/' not in message_json['object']['inReplyTo']: + if '/statuses/' not in reply_id: if debug: print('DEBUG: "statuses" missing from inReplyTo in ' + message_json['object']['type']) @@ -2415,7 +2419,7 @@ def _receive_zot_reaction(recent_posts_cache: {}, handle_name = handle.split('@')[0] handle_dom = handle.split('@')[1] - post_reaction_id = message_json['object']['inReplyTo'] + post_reaction_id = get_reply_to(message_json['object']) emoji_content = remove_html(message_json['object']['content']) if not emoji_content: if debug: @@ -3417,11 +3421,11 @@ def populate_replies(base_dir: str, http_prefix: str, domain: str, return False if not has_object_dict(message_json): return False - if not message_json['object'].get('inReplyTo'): + reply_to = get_reply_to(message_json['object']) + if not reply_to: return False if not message_json['object'].get('to'): return False - reply_to = message_json['object']['inReplyTo'] if not isinstance(reply_to, str): return False if debug: @@ -3509,10 +3513,11 @@ def _obtain_avatar_for_reply_post(session, base_dir: str, http_prefix: str, if not has_object_dict(post_json_object): return - if not post_json_object['object'].get('inReplyTo'): + reply_id = get_reply_to(post_json_object['object']) + if not reply_id: return - lookup_actor = post_json_object['object']['inReplyTo'] + lookup_actor = reply_id if not lookup_actor: return @@ -4225,7 +4230,7 @@ def _is_valid_dm(base_dir: str, nickname: str, domain: str, port: int, # replies to bounce messages obj = post_json_object['object'] if obj_has_dict and \ - not obj.get('inReplyTo'): + not get_reply_to(obj): bounced_id = \ remove_id_ending(post_json_object['id']) bounce_chat = False @@ -4392,9 +4397,7 @@ def _create_reply_notification_file(base_dir: str, nickname: str, domain: str, elif post_json_object['object'].get('context'): conversation_id = post_json_object['object']['context'] - if not post_json_object['object'].get('inReplyTo'): - return is_reply_to_muted_post - in_reply_to = post_json_object['object']['inReplyTo'] + in_reply_to = get_reply_to(post_json_object['object']) if not in_reply_to: return is_reply_to_muted_post if not isinstance(in_reply_to, str): diff --git a/posts.py b/posts.py index 461fa8632..65be7d4b9 100644 --- a/posts.py +++ b/posts.py @@ -86,6 +86,7 @@ from utils import remove_html from utils import dangerous_markup from utils import acct_dir from utils import local_actor_url +from utils import get_reply_to from media import get_music_metadata from media import attach_media from media import replace_you_tube @@ -684,17 +685,17 @@ def _get_posts(session, outbox_url: str, max_posts: int, if this_item['summary']: summary = this_item['summary'] - if this_item.get('inReplyTo'): - if this_item['inReplyTo']: - if isinstance(this_item['inReplyTo'], str): - # No replies to non-permitted domains - if not url_permitted(this_item['inReplyTo'], - federation_list): - if debug: - print('url not permitted ' + - this_item['inReplyTo']) - continue - in_reply_to = this_item['inReplyTo'] + reply_id = get_reply_to(this_item) + if reply_id: + if isinstance(reply_id, str): + # No replies to non-permitted domains + if not url_permitted(reply_id, + federation_list): + if debug: + print('url not permitted ' + + reply_id) + continue + in_reply_to = reply_id if this_item.get('attachment'): if len(this_item['attachment']) > max_attachments: @@ -836,10 +837,11 @@ def get_post_domains(session, outbox_url: str, max_posts: int, debug: bool, content_str = get_base_content_from_post(item, system_language) if content_str: _update_word_frequency(content_str, word_frequency) - if item['object'].get('inReplyTo'): - if isinstance(item['object']['inReplyTo'], str): + reply_id = get_reply_to(item['object']) + if reply_id: + if isinstance(reply_id, str): post_domain, _ = \ - get_domain_from_actor(item['object']['inReplyTo']) + get_domain_from_actor(reply_id) if post_domain: if post_domain not in post_domains: post_domains.append(post_domain) @@ -900,10 +902,11 @@ def _get_posts_for_blocked_domains(base_dir: str, break if not has_object_dict(item): continue - if item['object'].get('inReplyTo'): - if isinstance(item['object']['inReplyTo'], str): + reply_id = get_reply_to(item['object']) + if reply_id: + if isinstance(reply_id, str): post_domain, _ = \ - get_domain_from_actor(item['object']['inReplyTo']) + get_domain_from_actor(reply_id) if not post_domain: continue if is_blocked_domain(base_dir, post_domain): diff --git a/question.py b/question.py index ab94e68bd..40ffec010 100644 --- a/question.py +++ b/question.py @@ -14,6 +14,7 @@ from utils import save_json from utils import has_object_dict from utils import text_in_file from utils import dangerous_markup +from utils import get_reply_to def is_vote(base_dir: str, nickname: str, domain: str, @@ -24,9 +25,10 @@ def is_vote(base_dir: str, nickname: str, domain: str, if has_object_dict(post_json_object): post_obj = post_json_object['object'] - if not post_obj.get('inReplyTo'): + reply_id = get_reply_to(post_obj) + if not reply_id: return False - if not isinstance(post_obj['inReplyTo'], str): + if not isinstance(reply_id, str): return False if not post_obj.get('name'): return False @@ -35,7 +37,7 @@ def is_vote(base_dir: str, nickname: str, domain: str, print('VOTE: ' + str(post_obj)) # is the replied to post a Question? - in_reply_to = post_obj['inReplyTo'] + in_reply_to = reply_id question_post_filename = \ locate_post(base_dir, nickname, domain, in_reply_to) if not question_post_filename: @@ -105,7 +107,7 @@ def question_update_votes(base_dir: str, nickname: str, domain: str, post_obj = reply_json['object'] reply_vote = post_obj['name'] - in_reply_to = post_obj['inReplyTo'] + in_reply_to = get_reply_to(post_obj) question_post_filename = \ locate_post(base_dir, nickname, domain, in_reply_to) if not question_post_filename: diff --git a/utils.py b/utils.py index 02929b788..873e9b432 100644 --- a/utils.py +++ b/utils.py @@ -2138,15 +2138,16 @@ def _is_reply_to_blog_post(base_dir: str, nickname: str, domain: str, """ if not has_object_dict(post_json_object): return False - if not post_json_object['object'].get('inReplyTo'): + reply_id = get_reply_to(post_json_object['object']) + if not reply_id: return False - if not isinstance(post_json_object['object']['inReplyTo'], str): + if not isinstance(reply_id, str): return False blogs_index_filename = \ acct_dir(base_dir, nickname, domain) + '/tlblogs.index' if not os.path.isfile(blogs_index_filename): return False - post_id = remove_id_ending(post_json_object['object']['inReplyTo']) + post_id = remove_id_ending(reply_id) post_id = post_id.replace('/', '#') if text_in_file(post_id, blogs_index_filename): return True @@ -3477,9 +3478,10 @@ def is_reply(post_json_object: {}, actor: str) -> bool: 'EncryptedMessage', 'ChatMessage', 'Article'): return False - if post_json_object['object'].get('inReplyTo'): - if isinstance(post_json_object['object']['inReplyTo'], str): - if post_json_object['object']['inReplyTo'].startswith(actor): + reply_id = get_reply_to(post_json_object['object']) + if reply_id: + if isinstance(reply_id, str): + if reply_id.startswith(actor): return True if not post_json_object['object'].get('tag'): return False @@ -4840,3 +4842,13 @@ def get_media_url_from_video(post_json_object: {}) -> (str, str, str, str): media_type = media_link['mediaType'] media_url = remove_html(media_link['href']) return media_type, media_url, media_torrent, media_magnet + + +def get_reply_to(post_json_object: {}) -> str: + """Returns the reply to link from a post + """ + if post_json_object.get('inReplyTo'): + return post_json_object['inReplyTo'] + if post_json_object.get('inReplyToBook'): + return post_json_object['inReplyToBook'] + return '' diff --git a/webapp_post.py b/webapp_post.py index 1c9a52a1a..aefb12e55 100644 --- a/webapp_post.py +++ b/webapp_post.py @@ -73,6 +73,7 @@ from utils import local_actor_url from utils import is_unlisted_post from utils import language_right_to_left from utils import get_attributed_to +from utils import get_reply_to from content import format_mixed_right_to_left from content import replace_remote_hashtags from content import detect_dogwhistles @@ -678,8 +679,9 @@ def _get_edit_icon_html(base_dir: str, nickname: str, domain_full: str, return edit_str reply_to = '' - if post_json_object['object'].get('inReplyTo'): - reply_to = ';replyTo=' + post_json_object['object']['inReplyTo'] + reply_id = get_reply_to(post_json_object['object']) + if reply_id: + reply_to = ';replyTo=' + reply_id first_post_str = '' if first_post_id: @@ -1482,7 +1484,7 @@ def _reply_to_unknown_html(translate: {}, """Returns the html title for a reply to an unknown handle """ replying_to_str = _replying_to_with_scope(post_json_object, translate) - post_id = post_json_object['object']['inReplyTo'] + post_id = get_reply_to(post_json_object['object']) post_link = '/users/' + nickname + '?convthread=' + \ post_id.replace('/', '--') return '